TSocket.cxx

Go to the documentation of this file.
00001 // @(#)root/net:$Id: TSocket.cxx 35826 2010-09-28 09:38:08Z rdm $
00002 // Author: Fons Rademakers   18/12/96
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 // TSocket                                                              //
00015 //                                                                      //
00016 // This class implements client sockets. A socket is an endpoint for    //
00017 // communication between two machines.                                  //
00018 // The actual work is done via the TSystem class (either TUnixSystem    //
00019 // or TWinNTSystem).                                                    //
00020 //                                                                      //
00021 //////////////////////////////////////////////////////////////////////////
00022 
00023 #include "Bytes.h"
00024 #include "NetErrors.h"
00025 #include "TEnv.h"
00026 #include "TError.h"
00027 #include "TMessage.h"
00028 #include "TPSocket.h"
00029 #include "TPluginManager.h"
00030 #include "TROOT.h"
00031 #include "TString.h"
00032 #include "TSystem.h"
00033 #include "TUrl.h"
00034 #include "TVirtualAuth.h"
00035 #include "TStreamerInfo.h"
00036 #include "TProcessID.h"
00037 
00038 ULong64_t TSocket::fgBytesSent = 0;
00039 ULong64_t TSocket::fgBytesRecv = 0;
00040 
00041 //
00042 // Client "protocol changes"
00043 //
00044 // This was in TNetFile and TAuthenticate before, but after the introduction
00045 // of TSocket::CreateAuthSocket the common place for all the clients is TSocket,
00046 // so this seems to be the right place for a version number
00047 //
00048 // 7: added support for ReOpen(), kROOTD_BYE and kROOTD_PROTOCOL2
00049 // 8: added support for update being a create (open stat = 2 and not 1)
00050 // 9: added new authentication features (see README.AUTH)
00051 // 10: added support for authenticated socket via TSocket::CreateAuthSocket(...)
00052 // 11: modified SSH protocol + support for server 'no authentication' mode
00053 // 12: add random tags to avoid reply attacks (password+token)
00054 // 13: authentication re-organization; cleanup in PROOF
00055 // 14: support for SSH authentication via SSH tunnel
00056 // 15: cope with fixes in TUrl::GetFile
00057 // 16: add env setup message exchange
00058 // 17: optmized Globus/GSI protocol exchange
00059 //
00060 Int_t TSocket::fgClientProtocol = 17;  // increase when client protocol changes
00061 
00062 TVirtualMutex *gSocketAuthMutex = 0;
00063 
00064 ClassImp(TSocket)
00065 
00066 //______________________________________________________________________________
00067 TSocket::TSocket(TInetAddress addr, const char *service, Int_t tcpwindowsize)
00068          : TNamed(addr.GetHostName(), service)
00069 {
00070    // Create a socket. Connect to the named service at address addr.
00071    // Use tcpwindowsize to specify the size of the receive buffer, it has
00072    // to be specified here to make sure the window scale option is set (for
00073    // tcpwindowsize > 65KB and for platforms supporting window scaling).
00074    // Returns when connection has been accepted by remote side. Use IsValid()
00075    // to check the validity of the socket. Every socket is added to the TROOT
00076    // sockets list which will make sure that any open sockets are properly
00077    // closed on program termination.
00078 
00079    R__ASSERT(gROOT);
00080    R__ASSERT(gSystem);
00081 
00082    fService = service;
00083    fSecContext = 0;
00084    fRemoteProtocol= -1;
00085    fServType = kSOCKD;
00086    if (fService.Contains("root"))
00087       fServType = kROOTD;
00088    if (fService.Contains("proof"))
00089       fServType = kPROOFD;
00090    fAddress = addr;
00091    fAddress.fPort = gSystem->GetServiceByName(service);
00092    fBytesSent = 0;
00093    fBytesRecv = 0;
00094    fCompress = 0;
00095    fTcpWindowSize = tcpwindowsize;
00096    fUUIDs = 0;
00097    fLastUsageMtx = 0;
00098 
00099    if (fAddress.GetPort() != -1) {
00100       fSocket = gSystem->OpenConnection(addr.GetHostName(), fAddress.GetPort(),
00101                                         tcpwindowsize);
00102 
00103       if (fSocket != -1) {
00104          R__LOCKGUARD2(gROOTMutex);
00105          gROOT->GetListOfSockets()->Add(this);
00106       }
00107    } else
00108       fSocket = -1;
00109 
00110 }
00111 
00112 //______________________________________________________________________________
00113 TSocket::TSocket(TInetAddress addr, Int_t port, Int_t tcpwindowsize)
00114          : TNamed(addr.GetHostName(), "")
00115 {
00116    // Create a socket. Connect to the specified port # at address addr.
00117    // Use tcpwindowsize to specify the size of the receive buffer, it has
00118    // to be specified here to make sure the window scale option is set (for
00119    // tcpwindowsize > 65KB and for platforms supporting window scaling).
00120    // Returns when connection has been accepted by remote side. Use IsValid()
00121    // to check the validity of the socket. Every socket is added to the TROOT
00122    // sockets list which will make sure that any open sockets are properly
00123    // closed on program termination.
00124 
00125    R__ASSERT(gROOT);
00126    R__ASSERT(gSystem);
00127 
00128    fService = gSystem->GetServiceByPort(port);
00129    fSecContext = 0;
00130    fRemoteProtocol= -1;
00131    fServType = kSOCKD;
00132    if (fService.Contains("root"))
00133       fServType = kROOTD;
00134    if (fService.Contains("proof"))
00135       fServType = kPROOFD;
00136    fAddress = addr;
00137    fAddress.fPort = port;
00138    SetTitle(fService);
00139    fBytesSent = 0;
00140    fBytesRecv = 0;
00141    fCompress = 0;
00142    fTcpWindowSize = tcpwindowsize;
00143    fUUIDs = 0;
00144    fLastUsageMtx = 0;
00145 
00146    fSocket = gSystem->OpenConnection(addr.GetHostName(), fAddress.GetPort(),
00147                                      tcpwindowsize);
00148    if (fSocket == -1)
00149       fAddress.fPort = -1;
00150    else {
00151       R__LOCKGUARD2(gROOTMutex);
00152       gROOT->GetListOfSockets()->Add(this);
00153    }
00154 }
00155 
00156 //______________________________________________________________________________
00157 TSocket::TSocket(const char *host, const char *service, Int_t tcpwindowsize)
00158          : TNamed(host, service)
00159 {
00160    // Create a socket. Connect to named service on the remote host.
00161    // Use tcpwindowsize to specify the size of the receive buffer, it has
00162    // to be specified here to make sure the window scale option is set (for
00163    // tcpwindowsize > 65KB and for platforms supporting window scaling).
00164    // Returns when connection has been accepted by remote side. Use IsValid()
00165    // to check the validity of the socket. Every socket is added to the TROOT
00166    // sockets list which will make sure that any open sockets are properly
00167    // closed on program termination.
00168 
00169    R__ASSERT(gROOT);
00170    R__ASSERT(gSystem);
00171 
00172    fService = service;
00173    fSecContext = 0;
00174    fRemoteProtocol= -1;
00175    fServType = kSOCKD;
00176    if (fService.Contains("root"))
00177       fServType = kROOTD;
00178    if (fService.Contains("proof"))
00179       fServType = kPROOFD;
00180    fAddress = gSystem->GetHostByName(host);
00181    fAddress.fPort = gSystem->GetServiceByName(service);
00182    SetName(fAddress.GetHostName());
00183    fBytesSent = 0;
00184    fBytesRecv = 0;
00185    fCompress = 0;
00186    fTcpWindowSize = tcpwindowsize;
00187    fUUIDs = 0;
00188    fLastUsageMtx = 0;
00189 
00190    if (fAddress.GetPort() != -1) {
00191       fSocket = gSystem->OpenConnection(host, fAddress.GetPort(), tcpwindowsize);
00192       if (fSocket != -1) {
00193          R__LOCKGUARD2(gROOTMutex);
00194          gROOT->GetListOfSockets()->Add(this);
00195       }
00196    } else
00197       fSocket = -1;
00198 }
00199 
00200 //______________________________________________________________________________
00201 TSocket::TSocket(const char *url, Int_t port, Int_t tcpwindowsize)
00202          : TNamed(TUrl(url).GetHost(), "")
00203 {
00204    // Create a socket; see CreateAuthSocket for the form of url.
00205    // Connect to the specified port # on the remote host.
00206    // If user is specified in url, try authentication as user.
00207    // Use tcpwindowsize to specify the size of the receive buffer, it has
00208    // to be specified here to make sure the window scale option is set (for
00209    // tcpwindowsize > 65KB and for platforms supporting window scaling).
00210    // Returns when connection has been accepted by remote side. Use IsValid()
00211    // to check the validity of the socket. Every socket is added to the TROOT
00212    // sockets list which will make sure that any open sockets are properly
00213    // closed on program termination.
00214 
00215    R__ASSERT(gROOT);
00216    R__ASSERT(gSystem);
00217 
00218    fUrl = TString(url);
00219    TString host(TUrl(fUrl).GetHost());
00220 
00221    fService = gSystem->GetServiceByPort(port);
00222    fSecContext = 0;
00223    fRemoteProtocol= -1;
00224    fServType = kSOCKD;
00225    if (fUrl.Contains("root"))
00226       fServType = kROOTD;
00227    if (fUrl.Contains("proof"))
00228       fServType = kPROOFD;
00229    fAddress = gSystem->GetHostByName(host);
00230    fAddress.fPort = port;
00231    SetName(fAddress.GetHostName());
00232    SetTitle(fService);
00233    fBytesSent = 0;
00234    fBytesRecv = 0;
00235    fCompress = 0;
00236    fTcpWindowSize = tcpwindowsize;
00237    fUUIDs = 0;
00238    fLastUsageMtx = 0;
00239 
00240    fSocket = gSystem->OpenConnection(host, fAddress.GetPort(), tcpwindowsize);
00241    if (fSocket == -1) {
00242       fAddress.fPort = -1;
00243    } else {
00244       R__LOCKGUARD2(gROOTMutex);
00245       gROOT->GetListOfSockets()->Add(this);
00246    }
00247 }
00248 
00249 //______________________________________________________________________________
00250 TSocket::TSocket(const char *sockpath) : TNamed(sockpath, "")
00251 {
00252    // Create a socket in the Unix domain on 'sockpath'.
00253    // Returns when connection has been accepted by the server. Use IsValid()
00254    // to check the validity of the socket. Every socket is added to the TROOT
00255    // sockets list which will make sure that any open sockets are properly
00256    // closed on program termination.
00257 
00258    R__ASSERT(gROOT);
00259    R__ASSERT(gSystem);
00260 
00261    fUrl = sockpath;
00262 
00263    fService = "unix";
00264    fSecContext = 0;
00265    fRemoteProtocol= -1;
00266    fServType = kSOCKD;
00267    fAddress.fPort = -1;
00268    fName.Form("unix:%s", sockpath);
00269    SetTitle(fService);
00270    fBytesSent = 0;
00271    fBytesRecv = 0;
00272    fCompress  = 0;
00273    fTcpWindowSize = -1;
00274    fUUIDs = 0;
00275    fLastUsageMtx  = 0;
00276 
00277    fSocket = gSystem->OpenConnection(sockpath, -1, -1);
00278    if (fSocket > 0) {
00279       R__LOCKGUARD2(gROOTMutex);
00280       gROOT->GetListOfSockets()->Add(this);
00281    }
00282 }
00283 
00284 //______________________________________________________________________________
00285 TSocket::TSocket(Int_t desc) : TNamed("", "")
00286 {
00287    // Create a socket. The socket will adopt previously opened TCP socket with
00288    // descriptor desc.
00289 
00290    R__ASSERT(gROOT);
00291    R__ASSERT(gSystem);
00292 
00293    fSecContext     = 0;
00294    fRemoteProtocol = 0;
00295    fService        = (char *)kSOCKD;
00296    fServType       = kSOCKD;
00297    fBytesSent      = 0;
00298    fBytesRecv      = 0;
00299    fCompress       = 0;
00300    fTcpWindowSize = -1;
00301    fUUIDs          = 0;
00302    fLastUsageMtx   = 0;
00303 
00304    if (desc >= 0) {
00305       fSocket  = desc;
00306       fAddress = gSystem->GetPeerName(fSocket);
00307       R__LOCKGUARD2(gROOTMutex);
00308       gROOT->GetListOfSockets()->Add(this);
00309    } else
00310       fSocket = -1;
00311 }
00312 
00313 //______________________________________________________________________________
00314 TSocket::TSocket(Int_t desc, const char *sockpath) : TNamed(sockpath, "")
00315 {
00316    // Create a socket. The socket will adopt previously opened Unix socket with
00317    // descriptor desc. The sockpath arg is for info purposes only. Use
00318    // this method to adopt e.g. a socket created via socketpair().
00319 
00320    R__ASSERT(gROOT);
00321    R__ASSERT(gSystem);
00322 
00323    fUrl = sockpath;
00324 
00325    fService = "unix";
00326    fSecContext = 0;
00327    fRemoteProtocol= -1;
00328    fServType = kSOCKD;
00329    fAddress.fPort = -1;
00330    fName.Form("unix:%s", sockpath);
00331    SetTitle(fService);
00332    fBytesSent = 0;
00333    fBytesRecv = 0;
00334    fCompress  = 0;
00335    fTcpWindowSize = -1;
00336    fUUIDs = 0;
00337    fLastUsageMtx  = 0;
00338 
00339    if (desc >= 0) {
00340       fSocket  = desc;
00341       R__LOCKGUARD2(gROOTMutex);
00342       gROOT->GetListOfSockets()->Add(this);
00343    } else
00344       fSocket = -1;
00345 }
00346 
00347 
00348 //______________________________________________________________________________
00349 TSocket::TSocket(const TSocket &s) : TNamed(s)
00350 {
00351    // TSocket copy ctor.
00352 
00353    fSocket         = s.fSocket;
00354    fService        = s.fService;
00355    fAddress        = s.fAddress;
00356    fLocalAddress   = s.fLocalAddress;
00357    fBytesSent      = s.fBytesSent;
00358    fBytesRecv      = s.fBytesRecv;
00359    fCompress       = s.fCompress;
00360    fSecContext     = s.fSecContext;
00361    fRemoteProtocol = s.fRemoteProtocol;
00362    fServType       = s.fServType;
00363    fUUIDs          = 0;
00364    fLastUsageMtx   = 0;
00365 
00366    if (fSocket != -1) {
00367       R__LOCKGUARD2(gROOTMutex);
00368       gROOT->GetListOfSockets()->Add(this);
00369    }
00370 }
00371 
00372 //______________________________________________________________________________
00373 void TSocket::Close(Option_t *option)
00374 {
00375    // Close the socket. If option is "force", calls shutdown(id,2) to
00376    // shut down the connection. This will close the connection also
00377    // for the parent of this process. Also called via the dtor (without
00378    // option "force", call explicitely Close("force") if this is desired).
00379 
00380    Bool_t force = option ? (!strcmp(option, "force") ? kTRUE : kFALSE) : kFALSE;
00381 
00382    if (fSocket != -1) {
00383       gSystem->CloseConnection(fSocket, force);
00384       R__LOCKGUARD2(gROOTMutex);
00385       gROOT->GetListOfSockets()->Remove(this);
00386    }
00387    fSocket = -1;
00388 
00389    SafeDelete(fUUIDs);
00390    SafeDelete(fLastUsageMtx);
00391 }
00392 
00393 //______________________________________________________________________________
00394 TInetAddress TSocket::GetLocalInetAddress()
00395 {
00396    // Return internet address of local host to which the socket is bound.
00397    // In case of error TInetAddress::IsValid() returns kFALSE.
00398 
00399    if (IsValid()) {
00400       if (fLocalAddress.GetPort() == -1)
00401          fLocalAddress = gSystem->GetSockName(fSocket);
00402       return fLocalAddress;
00403    }
00404    return TInetAddress();
00405 }
00406 
00407 //______________________________________________________________________________
00408 Int_t TSocket::GetLocalPort()
00409 {
00410    // Return the local port # to which the socket is bound.
00411    // In case of error return -1.
00412 
00413    if (IsValid()) {
00414       if (fLocalAddress.GetPort() == -1)
00415          GetLocalInetAddress();
00416       return fLocalAddress.GetPort();
00417    }
00418    return -1;
00419 }
00420 
00421 //______________________________________________________________________________
00422 Int_t TSocket::Select(Int_t interest, Long_t timeout)
00423 {
00424    // Waits for this socket to change status. If interest=kRead,
00425    // the socket will be watched to see if characters become available for
00426    // reading; if interest=kWrite the socket will be watched to
00427    // see if a write will not block.
00428    // The argument 'timeout' specifies a maximum time to wait in millisec.
00429    // Default no timeout.
00430    // Returns 1 if a change of status of interest has been detected within
00431    // timeout; 0 in case of timeout; < 0 if an error occured.
00432 
00433    Int_t rc = 1;
00434 
00435    // Associate a TFileHandler to this socket
00436    TFileHandler fh(fSocket, interest);
00437 
00438    // Wait for an event now
00439    rc = gSystem->Select(&fh, timeout);
00440 
00441    return rc;
00442 }
00443 
00444 //______________________________________________________________________________
00445 Int_t TSocket::Send(Int_t kind)
00446 {
00447    // Send a single message opcode. Use kind (opcode) to set the
00448    // TMessage "what" field. Returns the number of bytes that were sent
00449    // (always sizeof(Int_t)) and -1 in case of error. In case the kind has
00450    // been or'ed with kMESS_ACK, the call will only return after having
00451    // received an acknowledgement, making the sending process synchronous.
00452 
00453    TMessage mess(kind);
00454 
00455    Int_t nsent;
00456    if ((nsent = Send(mess)) < 0)
00457       return -1;
00458 
00459    return nsent;
00460 }
00461 
00462 //______________________________________________________________________________
00463 Int_t TSocket::Send(Int_t status, Int_t kind)
00464 {
00465    // Send a status and a single message opcode. Use kind (opcode) to set the
00466    // TMessage "what" field. Returns the number of bytes that were sent
00467    // (always 2*sizeof(Int_t)) and -1 in case of error. In case the kind has
00468    // been or'ed with kMESS_ACK, the call will only return after having
00469    // received an acknowledgement, making the sending process synchronous.
00470 
00471    TMessage mess(kind);
00472    mess << status;
00473 
00474    Int_t nsent;
00475    if ((nsent = Send(mess)) < 0)
00476       return -1;
00477 
00478    return nsent;
00479 }
00480 
00481 //______________________________________________________________________________
00482 Int_t TSocket::Send(const char *str, Int_t kind)
00483 {
00484    // Send a character string buffer. Use kind to set the TMessage "what" field.
00485    // Returns the number of bytes in the string str that were sent and -1 in
00486    // case of error. In case the kind has been or'ed with kMESS_ACK, the call
00487    // will only return after having received an acknowledgement, making the
00488    // sending process synchronous.
00489 
00490    TMessage mess(kind);
00491    if (str) mess.WriteString(str);
00492 
00493    Int_t nsent;
00494    if ((nsent = Send(mess)) < 0)
00495       return -1;
00496 
00497    return nsent - sizeof(Int_t);    // - TMessage::What()
00498 }
00499 
00500 //______________________________________________________________________________
00501 Int_t TSocket::Send(const TMessage &mess)
00502 {
00503    // Send a TMessage object. Returns the number of bytes in the TMessage
00504    // that were sent and -1 in case of error. In case the TMessage::What
00505    // has been or'ed with kMESS_ACK, the call will only return after having
00506    // received an acknowledgement, making the sending process synchronous.
00507    // Returns -4 in case of kNoBlock and errno == EWOULDBLOCK.
00508    // Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
00509    // support for streaming TStreamerInfo added by Rene Brun May 2008
00510    // support for streaming TProcessID added by Rene Brun June 2008
00511 
00512    TSystem::ResetErrno();
00513 
00514    if (fSocket == -1) return -1;
00515 
00516    if (mess.IsReading()) {
00517       Error("Send", "cannot send a message used for reading");
00518       return -1;
00519    }
00520 
00521    // send streamer infos in case schema evolution is enabled in the TMessage
00522    SendStreamerInfos(mess);
00523 
00524    // send the process id's so TRefs work
00525    SendProcessIDs(mess);
00526 
00527    mess.SetLength();   //write length in first word of buffer
00528 
00529    if (fCompress > 0 && mess.GetCompressionLevel() == 0)
00530       const_cast<TMessage&>(mess).SetCompressionLevel(fCompress);
00531 
00532    if (mess.GetCompressionLevel() > 0)
00533       const_cast<TMessage&>(mess).Compress();
00534 
00535    char *mbuf = mess.Buffer();
00536    Int_t mlen = mess.Length();
00537    if (mess.CompBuffer()) {
00538       mbuf = mess.CompBuffer();
00539       mlen = mess.CompLength();
00540    }
00541 
00542    Int_t nsent;
00543    if ((nsent = gSystem->SendRaw(fSocket, mbuf, mlen, 0)) <= 0) {
00544       if (nsent == -5) {
00545          // Connection reset by peer or broken
00546          Close();
00547       }
00548       return nsent;
00549    }
00550 
00551    fBytesSent  += nsent;
00552    fgBytesSent += nsent;
00553 
00554    // If acknowledgement is desired, wait for it
00555    if (mess.What() & kMESS_ACK) {
00556       TSystem::ResetErrno();
00557       char buf[2];
00558       Int_t n = 0;
00559       if ((n = gSystem->RecvRaw(fSocket, buf, sizeof(buf), 0)) < 0) {
00560          if (n == -5) {
00561             // Connection reset by peer or broken
00562             Close();
00563          } else
00564             n = -1;
00565          return n;
00566       }
00567       if (strncmp(buf, "ok", 2)) {
00568          Error("Send", "bad acknowledgement");
00569          return -1;
00570       }
00571       fBytesRecv  += 2;
00572       fgBytesRecv += 2;
00573    }
00574 
00575    Touch();  // update usage timestamp
00576 
00577    return nsent - sizeof(UInt_t);  //length - length header
00578 }
00579 
00580 //______________________________________________________________________________
00581 Int_t TSocket::SendObject(const TObject *obj, Int_t kind)
00582 {
00583    // Send an object. Returns the number of bytes sent and -1 in case of error.
00584    // In case the "kind" has been or'ed with kMESS_ACK, the call will only
00585    // return after having received an acknowledgement, making the sending
00586    // synchronous.
00587 
00588    //stream object to message buffer
00589    TMessage mess(kind);
00590    mess.WriteObject(obj);
00591 
00592    //now sending the object itself
00593    Int_t nsent;
00594    if ((nsent = Send(mess)) < 0)
00595       return -1;
00596 
00597    return nsent;
00598 }
00599 
00600 //______________________________________________________________________________
00601 Int_t TSocket::SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt)
00602 {
00603    // Send a raw buffer of specified length. Using option kOob one can send
00604    // OOB data. Returns the number of bytes sent or -1 in case of error.
00605    // Returns -4 in case of kNoBlock and errno == EWOULDBLOCK.
00606    // Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
00607 
00608    TSystem::ResetErrno();
00609 
00610    if (fSocket == -1) return -1;
00611 
00612    Int_t nsent;
00613 
00614    if ((nsent = gSystem->SendRaw(fSocket, buffer, length, (int) opt)) <= 0) {
00615       if (nsent == -5) {
00616          // Connection reset or broken: close
00617          Close();
00618       }
00619       return nsent;
00620    }
00621 
00622    fBytesSent  += nsent;
00623    fgBytesSent += nsent;
00624 
00625    Touch();  // update usage timestamp
00626 
00627    return nsent;
00628 }
00629 
00630 //______________________________________________________________________________
00631 void TSocket::SendStreamerInfos(const TMessage &mess)
00632 {
00633    // Check if TStreamerInfo must be sent. The list of TStreamerInfo of classes
00634    // in the object in the message is in the fInfos list of the message.
00635    // We send only the TStreamerInfos not yet sent on this socket.
00636 
00637    if (mess.fInfos && mess.fInfos->GetEntries()) {
00638       TIter next(mess.fInfos);
00639       TStreamerInfo *info;
00640       TList *minilist = 0;
00641       while ((info = (TStreamerInfo*)next())) {
00642          Int_t uid = info->GetNumber();
00643          if (fBitsInfo.TestBitNumber(uid))
00644             continue; //TStreamerInfo had already been sent
00645          fBitsInfo.SetBitNumber(uid);
00646          if (!minilist)
00647             minilist = new TList();
00648          if (gDebug > 0)
00649             Info("SendStreamerInfos", "sending TStreamerInfo: %s, version = %d",
00650                  info->GetName(),info->GetClassVersion());
00651          minilist->Add(info);
00652       }
00653       if (minilist) {
00654          TMessage messinfo(kMESS_STREAMERINFO);
00655          messinfo.WriteObject(minilist);
00656          delete minilist;
00657          if (messinfo.fInfos)
00658             messinfo.fInfos->Clear();
00659          Send(messinfo);
00660       }
00661    }
00662 }
00663 
00664 //______________________________________________________________________________
00665 void TSocket::SendProcessIDs(const TMessage &mess)
00666 {
00667    // Check if TProcessIDs must be sent. The list of TProcessIDs
00668    // in the object in the message is found by looking in the TMessage bits.
00669    // We send only the TProcessIDs not yet send on this socket.
00670 
00671    if (mess.TestBitNumber(0)) {
00672       TObjArray *pids = TProcessID::GetPIDs();
00673       Int_t npids = pids->GetEntries();
00674       TProcessID *pid;
00675       TList *minilist = 0;
00676       for (Int_t ipid = 0; ipid < npids; ipid++) {
00677          pid = (TProcessID*)pids->At(ipid);
00678          if (!pid || !mess.TestBitNumber(pid->GetUniqueID()+1))
00679             continue;
00680          //check if a pid with this title has already been sent through the socket
00681          //if not add it to the fUUIDs list
00682          if (!fUUIDs) {
00683             fUUIDs = new TList();
00684          } else {
00685             if (fUUIDs->FindObject(pid->GetTitle()))
00686                continue;
00687          }
00688          fUUIDs->Add(new TObjString(pid->GetTitle()));
00689          if (!minilist)
00690             minilist = new TList();
00691          if (gDebug > 0)
00692             Info("SendProcessIDs", "sending TProcessID: %s", pid->GetTitle());
00693          minilist->Add(pid);
00694       }
00695       if (minilist) {
00696          TMessage messpid(kMESS_PROCESSID);
00697          messpid.WriteObject(minilist);
00698          delete minilist;
00699          Send(messpid);
00700       }
00701    }
00702 }
00703 
00704 //______________________________________________________________________________
00705 Int_t TSocket::Recv(char *str, Int_t max)
00706 {
00707    // Receive a character string message of maximum max length. The expected
00708    // message must be of type kMESS_STRING. Returns length of received string
00709    // (can be 0 if otherside of connection is closed) or -1 in case of error
00710    // or -4 in case a non-blocking socket would block (i.e. there is nothing
00711    // to be read).
00712 
00713    Int_t n, kind;
00714 
00715    if ((n = Recv(str, max, kind)) <= 0) {
00716       if (n == -5)
00717          n = -1;
00718       return n;
00719    }
00720 
00721    if (kind != kMESS_STRING) {
00722       Error("Recv", "got message of wrong kind (expected %d, got %d)",
00723             kMESS_STRING, kind);
00724       return -1;
00725    }
00726 
00727    return n;
00728 }
00729 
00730 //______________________________________________________________________________
00731 Int_t TSocket::Recv(char *str, Int_t max, Int_t &kind)
00732 {
00733    // Receive a character string message of maximum max length. Returns in
00734    // kind the message type. Returns length of received string+4 (can be 0 if
00735    // other side of connection is closed) or -1 in case of error or -4 in
00736    // case a non-blocking socket would block (i.e. there is nothing to be read).
00737 
00738    Int_t     n;
00739    TMessage *mess;
00740 
00741    if ((n = Recv(mess)) <= 0) {
00742       if (n == -5)
00743          n = -1;
00744       return n;
00745    }
00746 
00747    kind = mess->What();
00748    if (str) {
00749       if (mess->BufferSize() > (Int_t)sizeof(Int_t)) // if mess contains more than kind
00750          mess->ReadString(str, max);
00751       else
00752          str[0] = 0;
00753    }
00754 
00755    delete mess;
00756 
00757    return n;   // number of bytes read (len of str + sizeof(kind)
00758 }
00759 
00760 //______________________________________________________________________________
00761 Int_t TSocket::Recv(Int_t &status, Int_t &kind)
00762 {
00763    // Receives a status and a message type. Returns length of received
00764    // integers, 2*sizeof(Int_t) (can be 0 if other side of connection
00765    // is closed) or -1 in case of error or -4 in case a non-blocking
00766    // socket would block (i.e. there is nothing to be read).
00767 
00768    Int_t     n;
00769    TMessage *mess;
00770 
00771    if ((n = Recv(mess)) <= 0) {
00772       if (n == -5)
00773          n = -1;
00774       return n;
00775    }
00776 
00777    kind = mess->What();
00778    (*mess) >> status;
00779 
00780    delete mess;
00781 
00782    return n;   // number of bytes read (2 * sizeof(Int_t)
00783 }
00784 
00785 //______________________________________________________________________________
00786 Int_t TSocket::Recv(TMessage *&mess)
00787 {
00788    // Receive a TMessage object. The user must delete the TMessage object.
00789    // Returns length of message in bytes (can be 0 if other side of connection
00790    // is closed) or -1 in case of error or -4 in case a non-blocking socket
00791    // would block (i.e. there is nothing to be read) or -5 if pipe broken
00792    // or reset by peer (EPIPE || ECONNRESET). In those case mess == 0.
00793 
00794    TSystem::ResetErrno();
00795 
00796    if (fSocket == -1) {
00797       mess = 0;
00798       return -1;
00799    }
00800 
00801 oncemore:
00802    Int_t  n;
00803    UInt_t len;
00804    if ((n = gSystem->RecvRaw(fSocket, &len, sizeof(UInt_t), 0)) <= 0) {
00805       if (n == 0 || n == -5) {
00806          // Connection closed, reset or broken
00807          Close();
00808       }
00809       mess = 0;
00810       return n;
00811    }
00812    len = net2host(len);  //from network to host byte order
00813 
00814    char *buf = new char[len+sizeof(UInt_t)];
00815    if ((n = gSystem->RecvRaw(fSocket, buf+sizeof(UInt_t), len, 0)) <= 0) {
00816       if (n == 0 || n == -5) {
00817          // Connection closed, reset or broken
00818          Close();
00819       }
00820       delete [] buf;
00821       mess = 0;
00822       return n;
00823    }
00824 
00825    fBytesRecv  += n + sizeof(UInt_t);
00826    fgBytesRecv += n + sizeof(UInt_t);
00827 
00828    mess = new TMessage(buf, len+sizeof(UInt_t));
00829 
00830    // receive any streamer infos
00831    if (RecvStreamerInfos(mess))
00832       goto oncemore;
00833 
00834    // receive any process ids
00835    if (RecvProcessIDs(mess))
00836       goto oncemore;
00837 
00838    if (mess->What() & kMESS_ACK) {
00839       char ok[2] = { 'o', 'k' };
00840       Int_t n2 = 0;
00841       if ((n2 = gSystem->SendRaw(fSocket, ok, sizeof(ok), 0)) < 0) {
00842          if (n2 == -5) {
00843             // Connection reset or broken
00844             Close();
00845          }
00846          delete mess;
00847          mess = 0;
00848          return n2;
00849       }
00850       mess->SetWhat(mess->What() & ~kMESS_ACK);
00851 
00852       fBytesSent  += 2;
00853       fgBytesSent += 2;
00854    }
00855 
00856    Touch();  // update usage timestamp
00857 
00858    return n;
00859 }
00860 
00861 //______________________________________________________________________________
00862 Int_t TSocket::RecvRaw(void *buffer, Int_t length, ESendRecvOptions opt)
00863 {
00864    // Receive a raw buffer of specified length bytes. Using option kPeek
00865    // one can peek at incoming data. Returns number of received bytes.
00866    // Returns -1 in case of error. In case of opt == kOob: -2 means
00867    // EWOULDBLOCK and -3 EINVAL. In case of non-blocking mode (kNoBlock)
00868    // -4 means EWOULDBLOCK. Returns -5 if pipe broken or reset by
00869    // peer (EPIPE || ECONNRESET).
00870 
00871    TSystem::ResetErrno();
00872 
00873    if (fSocket == -1) return -1;
00874    if (length == 0) return 0;
00875 
00876    Int_t n;
00877 
00878    if ((n = gSystem->RecvRaw(fSocket, buffer, length, (int) opt)) <= 0) {
00879       if (n == 0 || n == -5) {
00880          // Connection closed, reset or broken
00881          Close();
00882       }
00883       return n;
00884    }
00885 
00886    fBytesRecv  += n;
00887    fgBytesRecv += n;
00888 
00889    Touch();  // update usage timestamp
00890 
00891    return n;
00892 }
00893 
00894 //______________________________________________________________________________
00895 Bool_t TSocket::RecvStreamerInfos(TMessage *mess)
00896 {
00897    // Receive a message containing streamer infos. In case the message contains
00898    // streamer infos they are imported, the message will be deleted and the
00899    // method returns kTRUE.
00900 
00901    if (mess->What() == kMESS_STREAMERINFO) {
00902       TList *list = (TList*)mess->ReadObject(TList::Class());
00903       TIter next(list);
00904       TStreamerInfo *info;
00905       TObjLink *lnk = list->FirstLink();
00906       // First call BuildCheck for regular class
00907       while (lnk) {
00908          info = (TStreamerInfo*)lnk->GetObject();
00909          TObject *element = info->GetElements()->UncheckedAt(0);
00910          Bool_t isstl = element && strcmp("This",element->GetName())==0;
00911          if (!isstl) {
00912             info->BuildCheck();
00913             if (gDebug > 0)
00914                Info("RecvStreamerInfos", "importing TStreamerInfo: %s, version = %d",
00915                     info->GetName(), info->GetClassVersion());
00916          }
00917          lnk = lnk->Next();
00918       }
00919       // Then call BuildCheck for stl class
00920       lnk = list->FirstLink();
00921       while (lnk) {
00922          info = (TStreamerInfo*)lnk->GetObject();
00923          TObject *element = info->GetElements()->UncheckedAt(0);
00924          Bool_t isstl = element && strcmp("This",element->GetName())==0;
00925          if (isstl) {
00926             info->BuildCheck();
00927             if (gDebug > 0)
00928                Info("RecvStreamerInfos", "importing TStreamerInfo: %s, version = %d",
00929                     info->GetName(), info->GetClassVersion());
00930          }
00931          lnk = lnk->Next();
00932      }
00933       delete list;
00934       delete mess;
00935 
00936       return kTRUE;
00937    }
00938    return kFALSE;
00939 }
00940 
00941 //______________________________________________________________________________
00942 Bool_t TSocket::RecvProcessIDs(TMessage *mess)
00943 {
00944    // Receive a message containing process ids. In case the message contains
00945    // process ids they are imported, the message will be deleted and the
00946    // method returns kTRUE.
00947 
00948    if (mess->What() == kMESS_PROCESSID) {
00949       TList *list = (TList*)mess->ReadObject(TList::Class());
00950       TIter next(list);
00951       TProcessID *pid;
00952       while ((pid = (TProcessID*)next())) {
00953          // check that a similar pid is not already registered in fgPIDs
00954          TObjArray *pidslist = TProcessID::GetPIDs();
00955          TIter nextpid(pidslist);
00956          TProcessID *p;
00957          while ((p = (TProcessID*)nextpid())) {
00958             if (!strcmp(p->GetTitle(), pid->GetTitle())) {
00959                delete pid;
00960                pid = 0;
00961                break;
00962             }
00963          }
00964          if (pid) {
00965             if (gDebug > 0)
00966                Info("RecvProcessIDs", "importing TProcessID: %s", pid->GetTitle());
00967             pid->IncrementCount();
00968             pidslist->Add(pid);
00969             Int_t ind = pidslist->IndexOf(pid);
00970             pid->SetUniqueID((UInt_t)ind);
00971          }
00972       }
00973       delete list;
00974       delete mess;
00975 
00976       return kTRUE;
00977    }
00978    return kFALSE;
00979 }
00980 
00981 //______________________________________________________________________________
00982 Int_t TSocket::SetOption(ESockOptions opt, Int_t val)
00983 {
00984    // Set socket options.
00985 
00986    if (fSocket == -1) return -1;
00987 
00988    return gSystem->SetSockOpt(fSocket, opt, val);
00989 }
00990 
00991 //______________________________________________________________________________
00992 Int_t TSocket::GetOption(ESockOptions opt, Int_t &val)
00993 {
00994    // Get socket options. Returns -1 in case of error.
00995 
00996    if (fSocket == -1) return -1;
00997 
00998    return gSystem->GetSockOpt(fSocket, opt, &val);
00999 }
01000 
01001 //______________________________________________________________________________
01002 Int_t TSocket::GetErrorCode() const
01003 {
01004    // Returns error code. Meaning depends on context where it is called.
01005    // If no error condition returns 0 else a value < 0.
01006    // For example see TServerSocket ctor.
01007 
01008    if (!IsValid())
01009       return fSocket;
01010 
01011    return 0;
01012 }
01013 
01014 //______________________________________________________________________________
01015 void TSocket::SetCompressionLevel(Int_t level)
01016 {
01017    // Set the message compression level. Can be between 0 and 9 with 0
01018    // being no compression and 9 maximum compression. In general the default
01019    // level of 1 is the best compromise between achieved compression and
01020    // cpu time. Compression will only happen when the message is > 256 bytes.
01021 
01022    if (level < 0) level = 0;
01023    if (level > 9) level = 9;
01024 
01025    fCompress = level;
01026 }
01027 
01028 //______________________________________________________________________________
01029 Bool_t TSocket::Authenticate(const char *user)
01030 {
01031    // Authenticated the socket with specified user.
01032 
01033    Bool_t rc = kFALSE;
01034 
01035    // Parse protocol name, for PROOF, send message with server role
01036    TString sproto = TUrl(fUrl).GetProtocol();
01037    if (sproto.Contains("sockd")) {
01038       fServType = kSOCKD;
01039    } else if (sproto.Contains("rootd")) {
01040       fServType = kROOTD;
01041    } else if (sproto.Contains("proofd")) {
01042       fServType = kPROOFD;
01043       // Parse options
01044       TString opt(TUrl(fUrl).GetOptions());
01045       //First letter in Opt describes type of proofserv to invoke
01046       if (!strncasecmp(opt, "S", 1)) {
01047          Send("slave");
01048       } else if (!strncasecmp(opt, "M", 1)) {
01049          Send("master");
01050       } else {
01051          Warning("Authenticate",
01052                  "called by TSlave: unknown option '%c' %s",
01053                  opt[0], " - assuming Slave");
01054          Send("slave");
01055       }
01056    }
01057    if (gDebug > 2)
01058       Info("Authenticate","Local protocol: %s",sproto.Data());
01059 
01060    // Get server protocol level
01061    Int_t kind = kROOTD_PROTOCOL;
01062    // Warning: for backward compatibility reasons here we have to
01063    // send exactly 4 bytes: for fgClientClientProtocol > 99
01064    // the space in the format must be dropped
01065    if (fRemoteProtocol == -1) {
01066       Send(Form(" %d", fgClientProtocol), kROOTD_PROTOCOL);
01067       Recv(fRemoteProtocol, kind);
01068       //
01069       // If we are talking to an old rootd server we get a fatal
01070       // error here and we need to reopen the connection,
01071       // communicating first the size of the parallel socket
01072       if (kind == kROOTD_ERR) {
01073          fRemoteProtocol = 9;
01074          return kFALSE;
01075       }
01076    }
01077 
01078    // Find out whether authentication is required
01079    Bool_t runauth = kTRUE;
01080    if (fRemoteProtocol > 1000) {
01081       // Authentication not required by the remote server
01082       runauth = kFALSE;
01083       fRemoteProtocol %= 1000;
01084    }
01085 
01086    // If authentication is required, we need to find out which library
01087    // has to be loaded (preparation for near future, 9/7/05)
01088    TString host = GetInetAddress().GetHostName();
01089    if (runauth) {
01090 
01091       // Default (future)
01092       TString alib = "Xrd";
01093       if (fRemoteProtocol < 100) {
01094          // Standard Authentication lib
01095          alib = "Root";
01096       }
01097 
01098       // Load the plugin
01099       TPluginHandler *h =
01100          gROOT->GetPluginManager()->FindHandler("TVirtualAuth", alib);
01101       if (!h || h->LoadPlugin() != 0) {
01102          Error("Authenticate",
01103                "could not load properly %s authentication plugin", alib.Data());
01104          return rc;
01105       }
01106 
01107       // Get an instance of the interface class
01108       TVirtualAuth *auth = (TVirtualAuth *)(h->ExecPlugin(0));
01109       if (!auth) {
01110          Error("Authenticate", "could not instantiate the interface class");
01111          return rc;
01112       }
01113       if (gDebug > 1)
01114          Info("Authenticate", "class for '%s' authentication loaded", alib.Data());
01115 
01116       Option_t *opts = (gROOT->IsProofServ()) ? "P" : "";
01117       if (!(auth->Authenticate(this, host, user, opts))) {
01118          Error("Authenticate",
01119                "authentication attempt failed for %s@%s", user, host.Data());
01120       } else {
01121          rc = kTRUE;
01122       }
01123    } else {
01124 
01125       // Communicate who we are and our target user
01126       UserGroup_t *u = gSystem->GetUserInfo();
01127       if (u) {
01128          Send(Form("%s %s", u->fUser.Data(), user), kROOTD_USER);
01129          delete u;
01130       } else
01131          Send(Form("-1 %s", user), kROOTD_USER);
01132 
01133       rc = kFALSE;
01134 
01135       // Receive confirmation that everything went well
01136       Int_t stat;
01137       if (Recv(stat, kind) > 0) {
01138 
01139          if (kind == kROOTD_ERR) {
01140             if (gDebug > 0)
01141                TSocket::NetError("TSocket::Authenticate", stat);
01142          } else if (kind == kROOTD_AUTH) {
01143 
01144             // Authentication was not required: create inactive
01145             // security context for consistency
01146             fSecContext = new TSecContext(user, host, 0, -4, 0, 0);
01147             if (gDebug > 3)
01148                Info("Authenticate", "no authentication required remotely");
01149 
01150             // Set return flag;
01151             rc = 1;
01152          } else {
01153             if (gDebug > 0)
01154                Info("Authenticate", "expected message type %d, received %d",
01155                     kROOTD_AUTH, kind);
01156          }
01157       } else {
01158          if (gDebug > 0)
01159             Info("Authenticate", "error receiving message");
01160       }
01161 
01162    }
01163 
01164    return rc;
01165 }
01166 
01167 //______________________________________________________________________________
01168 TSocket *TSocket::CreateAuthSocket(const char *url, Int_t size,
01169                                    Int_t tcpwindowsize, TSocket *opensock)
01170 {
01171    // Creates a socket or a parallel socket and authenticates to the
01172    // remote server.
01173    //
01174    // url: [[proto][p][auth]://][user@]host[:port][/service][?options]
01175    //
01176    // where  proto = "sockd", "rootd", "proofd"
01177    //                indicates the type of remote server;
01178    //                if missing "sockd" is assumed ("sockd" indicates
01179    //                any remote server session using TServerSocket)
01180    //          [p] = for parallel sockets (forced internally for
01181    //                rootd; ignored for proofd)
01182    //       [auth] = "up", "s", "k", "g", "h", "ug" to force UsrPwd,
01183    //                SRP, Krb5, Globus, SSH or UidGid authentication
01184    //       [port] = is the remote port number
01185    //    [service] = service name used to determine the port
01186    //                (for backward compatibility, specification of
01187    //                 port as priority)
01188    //     options  = "m" or "s", when proto=proofd indicates whether
01189    //                we are master or slave (used internally by
01190    //                TSlave)
01191    //
01192    // An already opened connection can be used by passing its socket
01193    // in opensock.
01194    //
01195    // Example:
01196    //
01197    //   TSocket::CreateAuthSocket("rootds://qwerty@machine.fq.dn:5051")
01198    //
01199    //   creates an authenticated socket to a rootd server running
01200    //   on remote machine machine.fq.dn on port 5051; "parallel" sockets
01201    //   are forced internally because rootd expects
01202    //   parallel sockets; however a simple socket will be created
01203    //   in this case because the size is 0 (the default);
01204    //   authentication will attempt protocol SRP first.
01205    //
01206    //   TSocket::CreateAuthSocket("pk://qwerty@machine.fq.dn:5052",3)
01207    //
01208    //   creates an authenticated parallel socket of size 3 to a sockd
01209    //   server running on remote machine machine.fq.dn on port 5052;
01210    //   authentication will attempt protocol Kerberos first.
01211    //
01212    // NB: may hang if the remote server is not of the correct type;
01213    //     at present TSocket has no way to find out the type of the
01214    //     remote server automatically
01215    //
01216    // Returns pointer to an authenticated socket or 0 if creation or
01217    // authentication is unsuccessful.
01218 
01219    R__LOCKGUARD2(gSocketAuthMutex);
01220 
01221    // Url to be passed to choosen constructor
01222    TString eurl(url);
01223 
01224    // Parse protocol, if any
01225    Bool_t parallel = kFALSE;
01226    TString proto(TUrl(url).GetProtocol());
01227    TString protosave = proto;
01228 
01229    // Get rid of authentication suffix
01230    TString asfx = "";
01231    if (proto.EndsWith("up") || proto.EndsWith("ug")) {
01232       asfx = proto;
01233       asfx.Remove(0,proto.Length()-2);
01234       proto.Resize(proto.Length()-2);
01235    } else if (proto.EndsWith("s") || proto.EndsWith("k") ||
01236               proto.EndsWith("g") || proto.EndsWith("h")) {
01237       asfx = proto;
01238       asfx.Remove(0,proto.Length()-1);
01239       proto.Resize(proto.Length()-1);
01240    }
01241 
01242    // Find out if parallel (ignore if proofd, force if rootd)
01243    if (((proto.EndsWith("p") || size > 1) &&
01244                !proto.BeginsWith("proof")) ||
01245          proto.BeginsWith("root") ) {
01246       parallel = kTRUE;
01247       if (proto.EndsWith("p"))
01248          proto.Resize(proto.Length()-1);
01249    }
01250 
01251    // Force "sockd" if the rest is not recognized
01252    if (!proto.BeginsWith("sock") && !proto.BeginsWith("proof") &&
01253        !proto.BeginsWith("root"))
01254       proto = "sockd";
01255 
01256    // Substitute this for original proto in eurl
01257    protosave += "://";
01258    proto += asfx;
01259    proto += "://";
01260    eurl.ReplaceAll(protosave,proto);
01261 
01262    // Create the socket now
01263 
01264    TSocket *sock = 0;
01265    if (!parallel) {
01266 
01267       // Simple socket
01268       if (opensock && opensock->IsValid())
01269          sock = opensock;
01270       else
01271          sock = new TSocket(eurl, TUrl(url).GetPort(), tcpwindowsize);
01272 
01273       // Authenticate now
01274       if (sock && sock->IsValid()) {
01275          if (!sock->Authenticate(TUrl(url).GetUser())) {
01276             sock->Close();
01277             delete sock;
01278             sock = 0;
01279          }
01280       }
01281 
01282    } else {
01283 
01284       // Tell TPSocket that we want authentication, which has to
01285       // be done using the original socket before creation of set
01286       // of parallel sockets
01287       if (eurl.Contains("?"))
01288          eurl.Resize(eurl.Index("?"));
01289       eurl += "?A";
01290 
01291       // Parallel socket
01292       if (opensock && opensock->IsValid())
01293          sock = new TPSocket(eurl, TUrl(url).GetPort(), size, opensock);
01294       else
01295          sock = new TPSocket(eurl, TUrl(url).GetPort(), size, tcpwindowsize);
01296 
01297       // Cleanup if failure ...
01298       if (sock && !sock->IsAuthenticated()) {
01299          // Nothing to do except setting sock to NULL
01300          if (sock->IsValid())
01301             // And except when the sock is valid; this typically
01302             // happens when talking to a old server, because the
01303             // the parallel socket system is open before authentication
01304             delete sock;
01305          sock = 0;
01306       }
01307    }
01308 
01309    return sock;
01310 }
01311 
01312 //______________________________________________________________________________
01313 TSocket *TSocket::CreateAuthSocket(const char *user, const char *url,
01314                                    Int_t port, Int_t size, Int_t tcpwindowsize,
01315                                    TSocket *opensock)
01316 {
01317    // Creates a socket or a parallel socket and authenticates to the
01318    // remote server specified in 'url' on remote 'port' as 'user'.
01319    //
01320    // url: [[proto][p][auth]://]host[/?options]
01321    //
01322    // where  proto = "sockd", "rootd", "proofd"
01323    //                indicates the type of remote server
01324    //                if missing "sockd" is assumed ("sockd" indicates
01325    //                any remote server session using TServerSocket)
01326    //          [p] = for parallel sockets (forced internally for
01327    //                rootd)
01328    //       [auth] = "up", "s", "k", "g", "h", "ug" to force UsrPwd,
01329    //                SRP, Krb5, Globus, SSH or UidGid authentication
01330    //    [options] = "m" or "s", when proto=proofd indicates whether
01331    //                we are master or slave (used internally by TSlave)
01332    //
01333    // An already opened connection can be used by passing its socket
01334    // in opensock.
01335    //
01336    // Example:
01337    //
01338    //   TSocket::CreateAuthSocket("qwerty","rootdps://machine.fq.dn",5051)
01339    //
01340    //   creates an authenticated socket to a rootd server running
01341    //   on remote machine machine.fq.dn on port 5051; "parallel"
01342    //   sockets are forced internally because rootd expects
01343    //   parallel sockets; however a simple socket will be created
01344    //   in this case because the size is 0 (the default);
01345    //   authentication will attempt protocol SRP first.
01346    //
01347    //   TSocket::CreateAuthSocket("qwerty","pk://machine.fq.dn:5052",3)
01348    //
01349    //   creates an authenticated parallel socket of size 3 to a sockd
01350    //   server running on remote machine machine.fq.dn on port 5052;
01351    //   authentication will attempt protocol Kerberos first.
01352    //
01353    // NB: may hang if the remote server is not of the correct type;
01354    //     at present TSocket has no way to find out the type of the
01355    //     remote server automatically
01356    //
01357    // Returns pointer to an authenticated socket or 0 if creation or
01358    // authentication is unsuccessful.
01359 
01360    R__LOCKGUARD2(gSocketAuthMutex);
01361 
01362    // Extended url to be passed to base call
01363    TString eurl;
01364 
01365    // Add protocol, if any
01366    if (TString(TUrl(url).GetProtocol()).Length() > 0) {
01367       eurl += TString(TUrl(url).GetProtocol());
01368       eurl += TString("://");
01369    }
01370    // Add user, if any
01371    if (!user || strlen(user) > 0) {
01372       eurl += TString(user);
01373       eurl += TString("@");
01374    }
01375    // Add host
01376    eurl += TString(TUrl(url).GetHost());
01377    // Add port
01378    eurl += TString(":");
01379    eurl += (port > 0 ? port : 0);
01380    // Add options, if any
01381    if (TString(TUrl(url).GetOptions()).Length() > 0) {
01382       eurl += TString("/?");
01383       eurl += TString(TUrl(url).GetOptions());
01384    }
01385 
01386    // Create the socket and return it
01387    return TSocket::CreateAuthSocket(eurl,size,tcpwindowsize,opensock);
01388 }
01389 
01390 //______________________________________________________________________________
01391 Int_t TSocket::GetClientProtocol()
01392 {
01393    // Static method returning supported client protocol.
01394 
01395    return fgClientProtocol;
01396 }
01397 
01398 //______________________________________________________________________________
01399 void TSocket::NetError(const char *where, Int_t err)
01400 {
01401    // Print error string depending on error code.
01402 
01403    // Make sure it is in range
01404    err = (err < kErrError) ? ((err > -1) ? err : 0) : kErrError;
01405 
01406    if (gDebug > 0)
01407       ::Error(where, "%s", gRootdErrStr[err]);
01408 }
01409 
01410 //______________________________________________________________________________
01411 ULong64_t TSocket::GetSocketBytesSent()
01412 {
01413    // Get total number of bytes sent via all sockets.
01414 
01415    return fgBytesSent;
01416 }
01417 
01418 //______________________________________________________________________________
01419 ULong64_t TSocket::GetSocketBytesRecv()
01420 {
01421    // Get total number of bytes received via all sockets.
01422 
01423    return fgBytesRecv;
01424 }

Generated on Tue Jul 5 14:46:11 2011 for ROOT_528-00b_version by  doxygen 1.5.1