Logo ROOT   6.08/07
Reference Guide
TServerSocket.cxx
Go to the documentation of this file.
1 // @(#)root/net:$Id$
2 // Author: Fons Rademakers 18/12/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TServerSocket //
15 // //
16 // This class implements server sockets. A server socket waits for //
17 // requests to come in over the network. It performs some operation //
18 // based on that request and then possibly returns a full duplex socket //
19 // to the requester. The actual work is done via the TSystem class //
20 // (either TUnixSystem or TWinNTSystem). //
21 // //
22 //////////////////////////////////////////////////////////////////////////
23 
24 #include "TServerSocket.h"
25 #include "TSocket.h"
26 #include "TSystem.h"
27 #include "TROOT.h"
28 #include "TError.h"
29 #include <string>
30 #include "TVirtualMutex.h"
31 
32 // Hook to server authentication wrapper
35 
36 // Defaul options for accept
38 
40 
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Kind of macro to parse input options
45 /// Modify opt according to modifier mod.
46 
47 static void SetAuthOpt(UChar_t &opt, UChar_t mod)
48 {
49  R__LOCKGUARD2(gSrvAuthenticateMutex);
50 
51  if (!mod) return;
52 
53  if ((mod & kSrvAuth)) opt |= kSrvAuth;
54  if ((mod & kSrvNoAuth)) opt &= ~kSrvAuth;
55 }
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// Create a server socket object for a named service. Set reuse to true
59 /// to force reuse of the server socket (i.e. do not wait for the time
60 /// out to pass). Using backlog one can set the desirable queue length
61 /// for pending connections.
62 /// Use tcpwindowsize to specify the size of the receive buffer, it has
63 /// to be specified here to make sure the window scale option is set (for
64 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
65 /// Use IsValid() to check the validity of the
66 /// server socket. In case server socket is not valid use GetErrorCode()
67 /// to obtain the specific error value. These values are:
68 /// 0 = no error (socket is valid)
69 /// -1 = low level socket() call failed
70 /// -2 = low level bind() call failed
71 /// -3 = low level listen() call failed
72 /// Every valid server socket is added to the TROOT sockets list which
73 /// will make sure that any open sockets are properly closed on
74 /// program termination.
75 
76 TServerSocket::TServerSocket(const char *service, Bool_t reuse, Int_t backlog,
77  Int_t tcpwindowsize)
78 {
81 
82  SetName("ServerSocket");
83 
84  fSecContext = 0;
85  fSecContexts = new TList;
86 
87  // If this is a local path, try announcing a UNIX socket service
89  if (service && (!gSystem->AccessPathName(service) ||
90 #ifndef WIN32
91  service[0] == '/')) {
92 #else
93  service[0] == '/' || (service[1] == ':' && service[2] == '/'))) {
94 #endif
96  fService = "unix:";
97  fService += service;
98  fSocket = gSystem->AnnounceUnixService(service, backlog);
99  if (fSocket >= 0) {
101  gROOT->GetListOfSockets()->Add(this);
102  }
103  } else {
104  // TCP / UDP socket
105  fService = service;
106  int port = gSystem->GetServiceByName(service);
107  if (port != -1) {
108  fSocket = gSystem->AnnounceTcpService(port, reuse, backlog, tcpwindowsize);
109  if (fSocket >= 0) {
111  gROOT->GetListOfSockets()->Add(this);
112  }
113  } else {
114  fSocket = -1;
115  }
116  }
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Create a server socket object on a specified port. Set reuse to true
121 /// to force reuse of the server socket (i.e. do not wait for the time
122 /// out to pass). Using backlog one can set the desirable queue length
123 /// for pending connections. If port is 0 a port scan will be done to
124 /// find a free port. This option is mutual exlusive with the reuse option.
125 /// Use tcpwindowsize to specify the size of the receive buffer, it has
126 /// to be specified here to make sure the window scale option is set (for
127 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
128 /// Use IsValid() to check the validity of the
129 /// server socket. In case server socket is not valid use GetErrorCode()
130 /// to obtain the specific error value. These values are:
131 /// 0 = no error (socket is valid)
132 /// -1 = low level socket() call failed
133 /// -2 = low level bind() call failed
134 /// -3 = low level listen() call failed
135 /// Every valid server socket is added to the TROOT sockets list which
136 /// will make sure that any open sockets are properly closed on
137 /// program termination.
138 
140  Int_t tcpwindowsize)
141 {
142  R__ASSERT(gROOT);
144 
145  SetName("ServerSocket");
146 
147  fSecContext = 0;
148  fSecContexts = new TList;
151 
152  fSocket = gSystem->AnnounceTcpService(port, reuse, backlog, tcpwindowsize);
153  if (fSocket >= 0) {
155  gROOT->GetListOfSockets()->Add(this);
156  }
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Destructor: cleanup authentication stuff (if any) and close
161 
163 {
164  R__LOCKGUARD2(gSrvAuthenticateMutex);
165  if (fSecContexts) {
166  if (fgSrvAuthClupHook) {
167  // Cleanup the security contexts
168  (*fgSrvAuthClupHook)(fSecContexts);
169  }
170  // Remove the list
171  fSecContexts->Delete();
173  fSecContexts = 0;
174  }
175 
176  Close();
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// Accept a connection on a server socket. Returns a full-duplex
181 /// communication TSocket object. If no pending connections are
182 /// present on the queue and nonblocking mode has not been enabled
183 /// with SetOption(kNoBlock,1) the call blocks until a connection is
184 /// present. The returned socket must be deleted by the user. The socket
185 /// is also added to the TROOT sockets list which will make sure that
186 /// any open sockets are properly closed on program termination.
187 /// In case of error 0 is returned and in case non-blocking I/O is
188 /// enabled and no connections are available -1 is returned.
189 ///
190 /// The opt can be used to require client authentication; valid options are
191 ///
192 /// kSrvAuth = require client authentication
193 /// kSrvNoAuth = force no client authentication
194 ///
195 /// Example: use Opt = kSrvAuth to require client authentication.
196 ///
197 /// Default options are taken from fgAcceptOpt and are initially
198 /// equivalent to kSrvNoAuth; they can be changed with the static
199 /// method TServerSocket::SetAcceptOptions(Opt).
200 /// The active defaults can be visualized using the static method
201 /// TServerSocket::ShowAcceptOptions().
202 ///
203 
205 {
206  if (fSocket == -1) { return 0; }
207 
208  TSocket *socket = new TSocket;
209 
211  if (soc == -1) { delete socket; return 0; }
212  if (soc == -2) { delete socket; return (TSocket*) -1; }
213 
214  // Parse Opt
215  UChar_t acceptOpt = fgAcceptOpt;
216  SetAuthOpt(acceptOpt, opt);
217  Bool_t auth = (Bool_t)(acceptOpt & kSrvAuth);
218 
219  socket->fSocket = soc;
220  socket->fSecContext = 0;
221  socket->fService = fService;
223  socket->fAddress = gSystem->GetPeerName(socket->fSocket);
224  if (socket->fSocket >= 0) {
226  gROOT->GetListOfSockets()->Add(socket);
227  }
228 
229  // Perform authentication, if required
230  if (auth) {
231  if (!Authenticate(socket)) {
232  delete socket;
233  socket = 0;
234  }
235  }
236 
237  return socket;
238 }
239 
240 ////////////////////////////////////////////////////////////////////////////////
241 /// Return internet address of host to which the server socket is bound,
242 /// i.e. the local host. In case of error TInetAddress::IsValid() returns
243 /// kFALSE.
244 
246 {
247  if (fSocket != -1) {
248  if (fAddress.GetPort() == -1)
250  return fAddress;
251  }
252  return TInetAddress();
253 }
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 /// Get port # to which server socket is bound. In case of error returns -1.
257 
259 {
260  if (fSocket != -1) {
261  if (fAddress.GetPort() == -1)
263  return fAddress.GetPort();
264  }
265  return -1;
266 }
267 
268 
269 ////////////////////////////////////////////////////////////////////////////////
270 /// Return default options for Accept
271 
273 {
274  return fgAcceptOpt;
275 }
276 
277 ////////////////////////////////////////////////////////////////////////////////
278 /// Set default options for Accept according to modifier 'mod'.
279 /// Use:
280 /// kSrvAuth require client authentication
281 /// kSrvNoAuth do not require client authentication
282 
284 {
285  SetAuthOpt(fgAcceptOpt, mod);
286 }
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 /// Print default options for Accept.
290 
292 {
293  ::Info("ShowAcceptOptions", "Use authentication: %s", (fgAcceptOpt & kSrvAuth) ? "yes" : "no");
294 }
295 
296 ////////////////////////////////////////////////////////////////////////////////
297 /// Check authentication request from the client on new
298 /// open connection
299 
301 {
302  if (!fgSrvAuthHook) {
303  R__LOCKGUARD2(gSrvAuthenticateMutex);
304 
305  // Load libraries needed for (server) authentication ...
306  TString srvlib = "libSrvAuth";
307  char *p = 0;
308  // The generic one
309  if ((p = gSystem->DynamicPathName(srvlib, kTRUE))) {
310  delete[] p;
311  if (gSystem->Load(srvlib) == -1) {
312  Error("Authenticate", "can't load %s",srvlib.Data());
313  return kFALSE;
314  }
315  } else {
316  Error("Authenticate", "can't locate %s",srvlib.Data());
317  return kFALSE;
318  }
319  //
320  // Locate SrvAuthenticate
321  Func_t f = gSystem->DynFindSymbol(srvlib,"SrvAuthenticate");
322  if (f)
323  fgSrvAuthHook = (SrvAuth_t)(f);
324  else {
325  Error("Authenticate", "can't find SrvAuthenticate");
326  return kFALSE;
327  }
328  //
329  // Locate SrvAuthCleanup
330  f = gSystem->DynFindSymbol(srvlib,"SrvAuthCleanup");
331  if (f)
333  else {
334  Warning("Authenticate", "can't find SrvAuthCleanup");
335  }
336  }
337 
338  TString confdir;
339 #ifndef ROOTPREFIX
340  // try to guess the config directory...
341  if (gSystem->Getenv("ROOTSYS")) {
342  confdir = TString(gSystem->Getenv("ROOTSYS"));
343  } else {
344  // Try to guess it from 'root.exe' path
345  char *rootexe = gSystem->Which(gSystem->Getenv("PATH"),
346  "root.exe", kExecutePermission);
347  confdir = rootexe;
348  confdir.Resize(confdir.Last('/'));
349  delete [] rootexe;
350  }
351 #else
352  confdir = TString(ROOTPREFIX);
353 #endif
354  if (!confdir.Length()) {
355  Error("Authenticate", "config dir undefined");
356  return kFALSE;
357  }
358 
359  // dir for temporary files
360  TString tmpdir = TString(gSystem->TempDirectory());
362  tmpdir = TString("/tmp");
363 
364  // Get Host name
365  TString openhost(sock->GetInetAddress().GetHostName());
366  if (gDebug > 2)
367  Info("Authenticate","OpenHost = %s", openhost.Data());
368 
369  // Run Authentication now
370  std::string user;
371  Int_t meth = -1;
372  Int_t auth = 0;
373  Int_t type = 0;
374  std::string ctkn = "";
375  if (fgSrvAuthHook)
376  auth = (*fgSrvAuthHook)(sock, confdir, tmpdir, user,
377  meth, type, ctkn, fSecContexts);
378 
379  if (gDebug > 2)
380  Info("Authenticate","auth = %d, type= %d, ctkn= %s",
381  auth, type, ctkn.c_str());
382 
383  return auth;
384 }
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1266
virtual ~TServerSocket()
Destructor: cleanup authentication stuff (if any) and close.
Int_t fSocket
Definition: TSocket.h:100
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:899
const char * GetHostName() const
Definition: TInetAddress.h:75
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:157
static void SetAuthOpt(UChar_t &opt, UChar_t mod)
Kind of macro to parse input options Modify opt according to modifier mod.
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
virtual Int_t GetLocalPort()
Get port # to which server socket is bound. In case of error returns -1.
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:40
This class implements a mutex interface.
Definition: TVirtualMutex.h:34
#define R__ASSERT(e)
Definition: TError.h:98
#define gROOT
Definition: TROOT.h:364
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1819
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1512
TInetAddress fAddress
Definition: TSocket.h:90
static void SetAcceptOptions(UChar_t Opt)
Set default options for Accept according to modifier &#39;mod&#39;.
virtual TInetAddress GetPeerName(int sock)
Get Internet Protocol (IP) address of remote host and port #.
Definition: TSystem.cxx:2282
virtual char * GetServiceByPort(int port)
Get name of internet service.
Definition: TSystem.cxx:2309
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
virtual void Delete(Option_t *option="")=0
Delete this object.
#define SafeDelete(p)
Definition: RConfig.h:507
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1628
Int_t GetPort() const
Definition: TInetAddress.h:77
TString fService
Definition: TSocket.h:98
virtual TSocket * Accept(UChar_t Opt=0)
Accept a connection on a server socket.
virtual const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Definition: TSystem.cxx:1448
const UChar_t kSrvAuth
Definition: TServerSocket.h:41
Int_t(* SrvAuth_t)(TSocket *sock, const char *, const char *, std::string &, Int_t &, Int_t &, std::string &, TSeqCollection *)
Definition: TServerSocket.h:35
const UChar_t kSrvNoAuth
Definition: TServerSocket.h:42
TSeqCollection * fSecContexts
Definition: TServerSocket.h:47
A doubly linked list.
Definition: TList.h:47
virtual void Close(Option_t *opt="")
Close the socket.
Definition: TSocket.cxx:388
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
virtual int AcceptConnection(int sock)
Accept a connection.
Definition: TSystem.cxx:2363
virtual int AnnounceTcpService(int port, Bool_t reuse, int backlog, int tcpwindowsize=-1)
Announce TCP/IP service.
Definition: TSystem.cxx:2327
static UChar_t fgAcceptOpt
Definition: TServerSocket.h:50
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
Ssiz_t Length() const
Definition: TString.h:390
TSocket()
Definition: TSocket.h:114
virtual TInetAddress GetLocalInetAddress()
Return internet address of host to which the server socket is bound, i.e.
#define R__LOCKGUARD2(mutex)
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
virtual Func_t DynFindSymbol(const char *module, const char *entry)
Find specific entry point in specified library.
Definition: TSystem.cxx:1983
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:865
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:1959
int type
Definition: TGX11.cxx:120
Int_t(* SrvClup_t)(TSeqCollection *)
Definition: TServerSocket.h:38
virtual TInetAddress GetSockName(int sock)
Get Internet Protocol (IP) address of host and port #.
Definition: TSystem.cxx:2291
Bool_t Authenticate(TSocket *)
Check authentication request from the client on new open connection.
static UChar_t GetAcceptOptions()
Return default options for Accept.
virtual int GetServiceByName(const char *service)
Get port # of internet service.
Definition: TSystem.cxx:2300
virtual int AnnounceUnixService(int port, int backlog)
Announce unix domain service.
Definition: TSystem.cxx:2345
static void ShowAcceptOptions()
Print default options for Accept.
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
static SrvAuth_t fgSrvAuthHook
Definition: TServerSocket.h:48
TInetAddress GetInetAddress() const
Definition: TSocket.h:143
static SrvClup_t fgSrvAuthClupHook
Definition: TServerSocket.h:49
void ResetBit(UInt_t f)
Definition: TObject.h:156
unsigned char UChar_t
Definition: RtypesCore.h:34
TVirtualMutex * gSrvAuthenticateMutex
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911
TSecContext * fSecContext
Definition: TSocket.h:96
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1059
const char * Data() const
Definition: TString.h:349