Logo ROOT   6.10/09
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 = TROOT::GetRootSys();
339  if (!confdir.Length()) {
340  Error("Authenticate", "config dir undefined");
341  return kFALSE;
342  }
343 
344  // dir for temporary files
345  TString tmpdir = TString(gSystem->TempDirectory());
347  tmpdir = TString("/tmp");
348 
349  // Get Host name
350  TString openhost(sock->GetInetAddress().GetHostName());
351  if (gDebug > 2)
352  Info("Authenticate","OpenHost = %s", openhost.Data());
353 
354  // Run Authentication now
355  std::string user;
356  Int_t meth = -1;
357  Int_t auth = 0;
358  Int_t type = 0;
359  std::string ctkn = "";
360  if (fgSrvAuthHook)
361  auth = (*fgSrvAuthHook)(sock, confdir, tmpdir, user,
362  meth, type, ctkn, fSecContexts);
363 
364  if (gDebug > 2)
365  Info("Authenticate","auth = %d, type= %d, ctkn= %s",
366  auth, type, ctkn.c_str());
367 
368  return auth;
369 }
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:1272
virtual ~TServerSocket()
Destructor: cleanup authentication stuff (if any) and close.
Int_t fSocket
Definition: TSocket.h:84
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:847
const char * GetHostName() const
Definition: TInetAddress.h:71
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
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:36
This class implements a mutex interface.
Definition: TVirtualMutex.h:32
#define R__ASSERT(e)
Definition: TError.h:96
#define gROOT
Definition: TROOT.h:375
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1825
Basic string class.
Definition: TString.h:129
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
static const TString & GetRootSys()
Get the rootsys directory in the installation. Static utility function.
Definition: TROOT.cxx:2707
TInetAddress fAddress
Definition: TSocket.h:74
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:2276
virtual char * GetServiceByPort(int port)
Get name of internet service.
Definition: TSystem.cxx:2303
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:687
virtual void Delete(Option_t *option="")=0
Delete this object.
#define SafeDelete(p)
Definition: RConfig.h:499
Int_t GetPort() const
Definition: TInetAddress.h:73
TString fService
Definition: TSocket.h:82
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:1454
const UChar_t kSrvAuth
Definition: TServerSocket.h:39
Int_t(* SrvAuth_t)(TSocket *sock, const char *, const char *, std::string &, Int_t &, Int_t &, std::string &, TSeqCollection *)
Definition: TServerSocket.h:33
const UChar_t kSrvNoAuth
Definition: TServerSocket.h:40
TSeqCollection * fSecContexts
Definition: TServerSocket.h:45
A doubly linked list.
Definition: TList.h:43
virtual void Close(Option_t *opt="")
Close the socket.
Definition: TSocket.cxx:388
R__EXTERN TSystem * gSystem
Definition: TSystem.h:539
virtual int AcceptConnection(int sock)
Accept a connection.
Definition: TSystem.cxx:2357
virtual int AnnounceTcpService(int port, Bool_t reuse, int backlog, int tcpwindowsize=-1)
Announce TCP/IP service.
Definition: TSystem.cxx:2321
static UChar_t fgAcceptOpt
Definition: TServerSocket.h:48
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:873
Ssiz_t Length() const
Definition: TString.h:388
TSocket()
Definition: TSocket.h:98
virtual TInetAddress GetLocalInetAddress()
Return internet address of host to which the server socket is bound, i.e.
#define R__LOCKGUARD2(mutex)
const Bool_t kFALSE
Definition: RtypesCore.h:92
#define ClassImp(name)
Definition: Rtypes.h:336
double f(double x)
virtual Func_t DynFindSymbol(const char *module, const char *entry)
Find specific entry point in specified library.
Definition: TSystem.cxx:1977
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:1953
int type
Definition: TGX11.cxx:120
Int_t(* SrvClup_t)(TSeqCollection *)
Definition: TServerSocket.h:36
virtual TInetAddress GetSockName(int sock)
Get Internet Protocol (IP) address of host and port #.
Definition: TSystem.cxx:2285
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:2294
virtual int AnnounceUnixService(int port, int backlog)
Announce unix domain service.
Definition: TSystem.cxx:2339
static void ShowAcceptOptions()
Print default options for Accept.
R__EXTERN Int_t gDebug
Definition: Rtypes.h:83
static SrvAuth_t fgSrvAuthHook
Definition: TServerSocket.h:46
TInetAddress GetInetAddress() const
Definition: TSocket.h:127
static SrvClup_t fgSrvAuthClupHook
Definition: TServerSocket.h:47
void ResetBit(UInt_t f)
Definition: TObject.h:158
unsigned char UChar_t
Definition: RtypesCore.h:34
TVirtualMutex * gSrvAuthenticateMutex
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
const Bool_t kTRUE
Definition: RtypesCore.h:91
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:859
TSecContext * fSecContext
Definition: TSocket.h:80
const char * Data() const
Definition: TString.h:347