00001 // @(#)root/net:$Id: TPServerSocket.cxx 23091 2008-04-09 15:04:27Z rdm $ 00002 // Author: Fons Rademakers 19/1/2001 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 ////////////////////////////////////////////////////////////////////////// 00013 // // 00014 // TPServerSocket // 00015 // // 00016 // This class implements parallel server sockets. A parallel server // 00017 // socket waits for requests to come in over the network. It performs // 00018 // some operation based on that request and then possibly returns a // 00019 // full duplex parallel socket to the requester. The actual work is // 00020 // done via the TSystem class (either TUnixSystem or TWinNTSystem). // 00021 // // 00022 ////////////////////////////////////////////////////////////////////////// 00023 00024 #include "TPServerSocket.h" 00025 #include "TPSocket.h" 00026 #include "TROOT.h" 00027 #include "TVirtualMutex.h" 00028 00029 ClassImp(TPServerSocket) 00030 00031 //______________________________________________________________________________ 00032 TPServerSocket::TPServerSocket(Int_t port, Bool_t reuse, Int_t backlog, 00033 Int_t tcpwindowsize) : 00034 TServerSocket(port, reuse, backlog, tcpwindowsize) 00035 { 00036 // Create a parallel server socket object on a specified port. Set reuse 00037 // to true to force reuse of the server socket (i.e. do not wait for the 00038 // time out to pass). Using backlog one can set the desirable queue length 00039 // for pending connections. 00040 // Use tcpwindowsize to specify the size of the receive buffer, it has 00041 // to be specified here to make sure the window scale option is set (for 00042 // tcpwindowsize > 65KB and for platforms supporting window scaling). 00043 // Use IsValid() to check the validity of the 00044 // server socket. In case server socket is not valid use GetErrorCode() 00045 // to obtain the specific error value. These values are: 00046 // 0 = no error (socket is valid) 00047 // -1 = low level socket() call failed 00048 // -2 = low level bind() call failed 00049 // -3 = low level listen() call failed 00050 // Every valid server socket is added to the TROOT sockets list which 00051 // will make sure that any open sockets are properly closed on 00052 // program termination. 00053 00054 fTcpWindowSize = tcpwindowsize; 00055 SetName("PServerSocket"); 00056 } 00057 00058 //______________________________________________________________________________ 00059 TPServerSocket::TPServerSocket(const char *service, Bool_t reuse, Int_t backlog, 00060 Int_t tcpwindowsize) : 00061 TServerSocket(service, reuse, backlog, tcpwindowsize) 00062 { 00063 // Create a parallel server socket object for a named service. Set reuse 00064 // to true to force reuse of the server socket (i.e. do not wait for the 00065 // time out to pass). Using backlog one can set the desirable queue length 00066 // for pending connections. 00067 // Use tcpwindowsize to specify the size of the receive buffer, it has 00068 // to be specified here to make sure the window scale option is set (for 00069 // tcpwindowsize > 65KB and for platforms supporting window scaling). 00070 // Use IsValid() to check the validity of the 00071 // server socket. In case server socket is not valid use GetErrorCode() 00072 // to obtain the specific error value. These values are: 00073 // 0 = no error (socket is valid) 00074 // -1 = low level socket() call failed 00075 // -2 = low level bind() call failed 00076 // -3 = low level listen() call failed 00077 // Every valid server socket is added to the TROOT sockets list which 00078 // will make sure that any open sockets are properly closed on 00079 // program termination. 00080 00081 fTcpWindowSize = tcpwindowsize; 00082 SetName("PServerSocket"); 00083 } 00084 00085 //______________________________________________________________________________ 00086 TSocket *TPServerSocket::Accept(UChar_t Opt) 00087 { 00088 // Accept a connection on a parallel server socket. Returns a full-duplex 00089 // parallel communication TPSocket object. If no pending connections are 00090 // present on the queue and nonblocking mode has not been enabled 00091 // with SetOption(kNoBlock,1) the call blocks until a connection is 00092 // present. The returned socket must be deleted by the user. The socket 00093 // is also added to the TROOT sockets list which will make sure that 00094 // any open sockets are properly closed on program termination. 00095 // In case of error 0 is returned and in case non-blocking I/O is 00096 // enabled and no connections are available -1 is returned. 00097 00098 TSocket *setupSocket = 0; 00099 TSocket **pSockets; 00100 TPSocket *newPSocket = 0; 00101 00102 Int_t size, port; 00103 00104 // wait for the incoming connections to the server and accept them 00105 setupSocket = TServerSocket::Accept(Opt); 00106 00107 if (setupSocket <= 0) return 0; 00108 00109 // receive the port number and number of parallel sockets from the 00110 // client and establish 'n' connections 00111 setupSocket->Recv(port, size); 00112 00113 // Check if client is running in single mode 00114 if (size == 0) { 00115 pSockets = new TSocket*[1]; 00116 00117 pSockets[0] = setupSocket; 00118 00119 // create TPSocket object with the original socket 00120 newPSocket = new TPSocket(pSockets, 1); 00121 00122 } else { 00123 pSockets = new TSocket*[size]; 00124 00125 for (int i = 0; i < size; i++) { 00126 pSockets[i] = new TSocket(setupSocket->GetInetAddress(), 00127 port, fTcpWindowSize); 00128 R__LOCKGUARD2(gROOTMutex); 00129 gROOT->GetListOfSockets()->Remove(pSockets[i]); 00130 } 00131 00132 // create TPSocket object with all the accepted sockets 00133 newPSocket = new TPSocket(pSockets, size); 00134 00135 } 00136 00137 // Transmit authentication information, if any 00138 if (setupSocket->IsAuthenticated()) 00139 newPSocket->SetSecContext(setupSocket->GetSecContext()); 00140 00141 // clean up, if needed 00142 if (size > 0) 00143 delete setupSocket; 00144 00145 // return the TSocket object 00146 return newPSocket; 00147 } 00148