XrdProofConn.cxx

Go to the documentation of this file.
00001 // @(#)root/proofd:$Id: XrdProofConn.cxx 32192 2010-02-03 08:50:20Z ganis $
00002 // Author: Gerardo Ganis  12/12/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, 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 // XrdProofConn                                                         //
00015 //                                                                      //
00016 // Authors: G. Ganis, CERN, 2005                                        //
00017 //                                                                      //
00018 // Low level handler of connections to xproofd.                         //
00019 //                                                                      //
00020 //////////////////////////////////////////////////////////////////////////
00021 
00022 #ifdef OLDXRDOUC
00023 #  include "XrdSysToOuc.h"
00024 #  include "XrdOuc/XrdOucError.hh"
00025 #  include "XrdOuc/XrdOucPlugin.hh"
00026 #  include "XrdOuc/XrdOucPthread.hh"
00027 #else
00028 #  include "XrdSys/XrdSysError.hh"
00029 #  include "XrdSys/XrdSysPlugin.hh"
00030 #  include "XrdSys/XrdSysPthread.hh"
00031 #endif
00032 
00033 #include "XrdProofConn.h"
00034 #include "XProofProtocol.h"
00035 
00036 #include "XrdClient/XrdClientConnMgr.hh"
00037 #include "XrdClient/XrdClientConst.hh"
00038 #include "XrdClient/XrdClientDebug.hh"
00039 #include "XrdClient/XrdClientEnv.hh"
00040 #include "XrdClient/XrdClientLogConnection.hh"
00041 #include "XrdClient/XrdClientPhyConnection.hh"
00042 #include "XrdClient/XrdClientMessage.hh"
00043 #include "XrdClient/XrdClientUrlInfo.hh"
00044 #include "XrdNet/XrdNetDNS.hh"
00045 #include "XrdOuc/XrdOucErrInfo.hh"
00046 #include "XrdOuc/XrdOucString.hh"
00047 #include "XrdSec/XrdSecInterface.hh"
00048 
00049 // Dynamic libs
00050 // Bypass Solaris ELF madness
00051 #if (defined(SUNCC) || defined(SUN))
00052 #include <sys/isa_defs.h>
00053 #if defined(_ILP32) && (_FILE_OFFSET_BITS != 32)
00054 #undef  _FILE_OFFSET_BITS
00055 #define _FILE_OFFSET_BITS 32
00056 #undef  _LARGEFILE_SOURCE
00057 #endif
00058 #endif
00059 
00060 #ifndef WIN32
00061 #include <dlfcn.h>
00062 #if !defined(__APPLE__)
00063 #include <link.h>
00064 #endif
00065 #endif
00066 
00067 // Tracing utils
00068 #include "XrdProofdTrace.h"
00069 
00070 #ifndef WIN32
00071 #include <sys/socket.h>
00072 #include <sys/types.h>
00073 #include <pwd.h>
00074 #else
00075 #include <process.h>
00076 #include <Winsock2.h>
00077 #endif
00078 
00079 // Security handle
00080 typedef XrdSecProtocol *(*XrdSecGetProt_t)(const char *, const struct sockaddr &,
00081                                            const XrdSecParameters &, XrdOucErrInfo *);
00082 
00083 XrdClientConnectionMgr *XrdProofConn::fgConnMgr = 0;
00084 
00085 // Retry controllers
00086 int XrdProofConn::fgMaxTry = 5;
00087 int XrdProofConn::fgTimeWait = 2;  // seconds
00088 
00089 XrdSysPlugin *XrdProofConn::fgSecPlugin = 0;       // Sec library plugin
00090 void         *XrdProofConn::fgSecGetProtocol = 0;  // Sec protocol getter
00091 
00092 #ifndef SafeDelete
00093 #define SafeDelete(x) { if (x) { delete x; x = 0; } }
00094 #endif
00095 #define URLTAG "["<<fUrl.Host<<":"<<fUrl.Port<<"]"
00096 
00097 //_____________________________________________________________________________
00098 XrdProofConn::XrdProofConn(const char *url, char m, int psid, char capver,
00099                            XrdClientAbsUnsolMsgHandler *uh, const char *logbuf)
00100    : fMode(m), fConnected(0), fLogConnID(-1), fStreamid(0), fRemoteProtocol(-1),
00101      fServerProto(-1), fServerType(kSTNone), fSessionID(psid),
00102      fLastErr(kXR_Unsupported), fCapVer(capver), fLoginBuffer(logbuf), fMutex(0),
00103      fConnectInterruptMtx(0), fConnectInterrupt(0),
00104      fPhyConn(0), fUnsolMsgHandler(uh), fSender(0), fSenderArg(0)
00105 {
00106    // Constructor. Open the connection to a remote XrdProofd instance.
00107    // The mode 'm' indicates the role of this connection:
00108    //     'a'      Administrator; used by an XPD to contact the head XPD
00109    //     'i'      Internal; used by a TXProofServ to call back its creator
00110    //              (see XrdProofUnixConn)
00111    //     'M'      Client contacting a top master
00112    //     'm'      Top master contacting a submaster
00113    //     's'      Master contacting a slave
00114    // The buffer 'logbuf' is a null terminated string to be sent over at
00115    // login. In case of need, internally it is overwritten with a token
00116    // needed during redirection.
00117    XPDLOC(ALL, "XrdProofConn")
00118 
00119    // Mutex
00120    fMutex = new XrdSysRecMutex();
00121    fConnectInterruptMtx = new XrdSysRecMutex();
00122 
00123    // Initialization
00124    if (url && !Init(url)) {
00125       if (GetServType() != kSTProofd)
00126          TRACE(XERR, "XrdProofConn: severe error occurred while opening a"
00127                      " connection" << " to server "<<URLTAG);
00128    }
00129 
00130    return;
00131 }
00132 
00133 //_____________________________________________________________________________
00134 void XrdProofConn::GetRetryParam(int &maxtry, int &timewait)
00135 {
00136    // Retrieve current values of the retry control parameters, numer of retries
00137    // and wait time between attempts (in seconds).
00138 
00139    maxtry = fgMaxTry;
00140    timewait = fgTimeWait;
00141 }
00142 
00143 //_____________________________________________________________________________
00144 void XrdProofConn::SetRetryParam(int maxtry, int timewait)
00145 {
00146    // Change values of the retry control parameters, numer of retries
00147    // and wait time between attempts (in seconds).
00148 
00149    fgMaxTry = maxtry;
00150    fgTimeWait = timewait;
00151 }
00152 
00153 //_____________________________________________________________________________
00154 bool XrdProofConn::Init(const char *url)
00155 {
00156    // Initialization
00157    XPDLOC(ALL, "Conn::Init")
00158 
00159    // Init connection manager (only once)
00160    if (!fgConnMgr) {
00161       if (!(fgConnMgr = new XrdClientConnectionMgr())) {
00162          TRACE(XERR,"error initializing connection manager");
00163          return 0;
00164       }
00165    }
00166 
00167    // Parse Url
00168    fUrl.TakeUrl(XrdOucString(url));
00169    fUser = fUrl.User.c_str();
00170    // Get username from Url
00171    if (fUser.length() <= 0) {
00172       // If not specified, use local username
00173 #ifndef WIN32
00174       struct passwd *pw = getpwuid(getuid());
00175       fUser = pw ? pw->pw_name : "";
00176 #else
00177       char  name[256];
00178       DWORD length = sizeof (name);
00179       ::GetUserName(name, &length);
00180       if (strlen(name) > 1)
00181          fUser = name;
00182 #endif
00183    }
00184    fHost = fUrl.Host.c_str();
00185    fPort = fUrl.Port;
00186 
00187    // Run the connection attempts: the result is stored in fConnected
00188    Connect();
00189 
00190    // We are done
00191    return fConnected;
00192 }
00193 
00194 //_____________________________________________________________________________
00195 void XrdProofConn::Connect()
00196 {
00197    // Run the connection attempts: the result is stored in fConnected
00198    XPDLOC(ALL, "Conn::Connect")
00199 
00200    // Max number of tries and timeout
00201    int maxTry = (fgMaxTry > -1) ? fgMaxTry : EnvGetLong(NAME_FIRSTCONNECTMAXCNT);
00202    int timeWait = (fgTimeWait > -1) ? fgTimeWait : EnvGetLong(NAME_CONNECTTIMEOUT);
00203 
00204    fConnected = 0;
00205    int logid = -1;
00206    int i = 0;
00207    for (; (i < maxTry) && (!fConnected); i++) {
00208 
00209       // Try connection
00210       logid = TryConnect();
00211 
00212       // Check if interrupted
00213       if (ConnectInterrupt()) {
00214          TRACE(ALL, "got an interrupt while connecting - aborting attempts");
00215          break;
00216       }
00217 
00218       // We are connected to a host. Let's handshake with it.
00219       if (fConnected) {
00220 
00221          // Set the port used
00222          fPort = fUrl.Port;
00223 
00224          if (fPhyConn->IsLogged() == kNo) {
00225             // Now the have the logical Connection ID, that we can use as streamid for
00226             // communications with the server
00227             TRACE(DBG, "new logical connection ID: "<<logid);
00228 
00229             // Get access to server
00230             if (!GetAccessToSrv()) {
00231                if (GetServType() == kSTProofd) {
00232                   fConnected = 0;
00233                   return;
00234                }
00235                if (fLastErr == kXR_NotAuthorized || fLastErr == kXR_InvalidRequest) {
00236                   // Auth error or invalid request: does not make much sense to retry
00237                   Close("P");
00238                   XrdOucString msg = fLastErrMsg;
00239                   msg.erase(msg.rfind(":"));
00240                   TRACE(XERR, "failure: " << msg);
00241                   return;
00242                } else {
00243                   TRACE(XERR, "access to server failed (" << fLastErrMsg << ")");
00244                }
00245                fConnected = 0;
00246                continue;
00247             }
00248          }
00249 
00250          // Notify
00251          TRACE(DBG, "connection successfully created");
00252          break;
00253 
00254       }
00255 
00256       // Reset
00257       TRACE(REQ, "disconnecting");
00258       Close();
00259 
00260       // And we wait a bit before retrying
00261       if (i < maxTry - 1) {
00262          TRACE(DBG, "connection attempt failed: sleep " << timeWait << " secs");
00263          sleep(timeWait);
00264       }
00265 
00266    } //for connect try
00267 
00268    // Notify failure
00269    if (!fConnected) {
00270       TRACE(XERR, "failed to connect to " << fUrl.GetUrl());
00271    }
00272 }
00273 
00274 //_____________________________________________________________________________
00275 XrdProofConn::~XrdProofConn()
00276 {
00277    // Destructor
00278 
00279    // Disconnect from remote server (the connection manager is
00280    // responsible of the underlying physical connection, so we do not
00281    // force its closing)
00282    if (fRemoteProtocol > 1004) {
00283       // We may be into a reconnection attempt: interrupt it ...
00284       SetConnectInterrupt();
00285       // ... and wait for the OK
00286       XrdClientPhyConnLocker pcl(fPhyConn);
00287       // Can close now
00288       Close();
00289    } else {
00290       Close();
00291    }
00292 
00293    // Cleanup mutex
00294    SafeDelete(fMutex);
00295    SafeDelete(fConnectInterruptMtx);
00296 }
00297 
00298 //_____________________________________________________________________________
00299 void XrdProofConn::ReConnect()
00300 {
00301    // Perform a reconnection attempt when a connection is not valid any more
00302    XPDLOC(ALL, "Conn::ReConnect")
00303 
00304    if (!IsValid()) {
00305       if (fRemoteProtocol > 1004) {
00306 
00307          // Block any other attempt to use this connection
00308          XrdClientPhyConnLocker pcl(fPhyConn);
00309 
00310          Close();
00311          int maxtry, timewait;
00312          XrdProofConn::GetRetryParam(maxtry, timewait);
00313          XrdProofConn::SetRetryParam(300, 1);
00314          Connect();
00315          XrdProofConn::SetRetryParam();
00316 
00317       } else {
00318          TRACE(DBG, "server does not support reconnections (protocol: %d" <<
00319                     fRemoteProtocol << " < 1005)");
00320       }
00321    }
00322 }
00323 
00324 //_____________________________________________________________________________
00325 int XrdProofConn::TryConnect()
00326 {
00327    // Connect to remote server
00328    XPDLOC(ALL, "Conn::TryConnect")
00329 
00330    int logid;
00331    logid = -1;
00332 
00333    // Resolve the DNS information
00334    char *haddr[10] = {0}, *hname[10] = {0};
00335    int naddr = XrdNetDNS::getAddrName(fUrl.Host.c_str(), 10, haddr, hname);
00336 
00337    int i = 0;
00338    for (; i < naddr; i++ ) {
00339       // Address
00340       fUrl.HostAddr = (const char *) haddr[i];
00341       // Name
00342       fUrl.Host = (const char *) hname[i];
00343       // Notify
00344       TRACE(HDBG, "found host "<<fUrl.Host<<" with addr " << fUrl.HostAddr);
00345    }
00346 
00347    // Set port: the first time find the default
00348    static int servdef = -1;
00349    if (servdef < 0) {
00350       struct servent *ent = getservbyname("proofd", "tcp");
00351       servdef = (ent) ? (int)ntohs(ent->s_port) : 1093;
00352    }
00353    fUrl.Port = (fUrl.Port <= 0) ? servdef : fUrl.Port;
00354 
00355    // Connect
00356    if ((logid = fgConnMgr->Connect(fUrl)) < 0) {
00357       TRACE(DBG, "failure creating logical connection to " <<URLTAG);
00358       fLogConnID = logid;
00359       fConnected = 0;
00360       return -1;
00361    }
00362 
00363    // Set some vars
00364    fLogConnID = logid;
00365    fStreamid = fgConnMgr->GetConnection(fLogConnID)->Streamid();
00366    fPhyConn = fgConnMgr->GetConnection(fLogConnID)->GetPhyConnection();
00367    fConnected = 1;
00368 
00369    TRACE(DBG, "connect to "<<URLTAG<<" returned {"<<fLogConnID<<", "<< fStreamid<<"}");
00370 
00371    // Fill in the remote protocol: either it was received during handshake
00372    // or it was saved in the underlying physical connection
00373    if (fRemoteProtocol < 0)
00374       fRemoteProtocol = fPhyConn->fServerProto;
00375 
00376    // Handle asynchronous requests
00377    SetAsync(fUnsolMsgHandler);
00378 
00379    // We are done
00380    return logid;
00381 }
00382 
00383 //_____________________________________________________________________________
00384 void XrdProofConn::Close(const char *opt)
00385 {
00386    // Close connection.
00387    XPDLOC(ALL, "Conn::Close")
00388 
00389    // Make sure we are connected
00390    if (!fConnected)
00391       return;
00392 
00393    // Close also theunderlying physical connection ?
00394    bool closephys = (opt[0] == 'P') ? 1 : 0;
00395    TRACE(DBG, URLTAG <<": closing also physical connection ? "<< closephys);
00396 
00397    // Close connection
00398    if (fgConnMgr)
00399       fgConnMgr->Disconnect(GetLogConnID(), closephys);
00400 
00401    // Flag this action
00402    fConnected = 0;
00403 
00404    // We are done
00405    return;
00406 }
00407 
00408 //_____________________________________________________________________________
00409 UnsolRespProcResult XrdProofConn::ProcessUnsolicitedMsg(XrdClientUnsolMsgSender *,
00410                                                         XrdClientMessage *m)
00411 {
00412    // We are here if an unsolicited response comes from a logical conn
00413    // The response comes in the form of an XrdClientMessage *, that must NOT be
00414    // destroyed after processing. It is destroyed by the first sender.
00415    // Remember that we are in a separate thread, since unsolicited
00416    // responses are asynchronous by nature.
00417    XPDLOC(ALL, "Conn::ProcessUnsolicitedMsg")
00418 
00419    TRACE(DBG,"processing unsolicited response");
00420 
00421    if (!m || m->IsError()) {
00422       TRACE(XERR, "Got empty or error unsolicited message");
00423    } else {
00424       // Check length
00425       int len = 0;
00426       if ((len = m->DataLen()) < (int)sizeof(kXR_int32)) {
00427          TRACE(XERR, "empty or bad-formed message - ignoring");
00428          return kUNSOL_KEEP;
00429       }
00430       // The first 4 bytes contain the action code
00431       kXR_int32 acod = 0;
00432       memcpy(&acod, m->GetData(), sizeof(kXR_int32));
00433       //
00434       // Update pointer to data
00435       void *pdata = (void *)((char *)(m->GetData()) + sizeof(kXR_int32));
00436       //
00437       // Only interested in service messages
00438       if (acod == kXPD_srvmsg) {
00439          // The next 4 bytes may contain a flag to control the way the message is displayed
00440          kXR_int32 opt = 0;
00441          memcpy(&opt, pdata, sizeof(kXR_int32));
00442          opt = ntohl(opt);
00443          if (opt == 0 || opt == 1 || opt == 2) {
00444             // Update pointer to data
00445             pdata = (void *)((char *)pdata + sizeof(kXR_int32));
00446             len -= sizeof(kXR_int32);
00447          } else {
00448             opt = 1;
00449          }
00450          // Send up, if required
00451          if (fSender) {
00452             (*fSender)((const char *)pdata, len, fSenderArg);
00453          }
00454       }
00455    }
00456 
00457    return kUNSOL_KEEP;
00458 }
00459 
00460 //_____________________________________________________________________________
00461 void XrdProofConn::SetAsync(XrdClientAbsUnsolMsgHandler *uh,
00462                             XrdProofConnSender_t sender, void *arg)
00463 {
00464    // Set handler of unsolicited responses
00465 
00466    if (fgConnMgr && (fLogConnID > -1)  && fgConnMgr->GetConnection(fLogConnID))
00467       fgConnMgr->GetConnection(fLogConnID)->UnsolicitedMsgHandler = uh;
00468 
00469    // Set also the sender method and its argument, if required
00470    fSender = sender;
00471    fSenderArg = arg;
00472 }
00473 
00474 //_____________________________________________________________________________
00475 XrdClientMessage *XrdProofConn::ReadMsg()
00476 {
00477    // Pickup message from the queue
00478 
00479    return (fgConnMgr ? fgConnMgr->ReadMsg(fLogConnID) : (XrdClientMessage *)0);
00480 }
00481 
00482 //_____________________________________________________________________________
00483 XrdClientMessage *XrdProofConn::SendRecv(XPClientRequest *req, const void *reqData,
00484                                          char **answData)
00485 {
00486    // SendRecv sends a command to the server and to get a response.
00487    // The header of the last response is returned as pointer to a XrdClientMessage.
00488    // The data, if any, are returned in *answData; if *answData == 0 in input,
00489    // the buffer is internally allocated and must be freed by the caller.
00490    // If (*answData != 0) the program assumes that the caller has allocated
00491    // enough bytes to contain the reply.
00492    XPDLOC(ALL, "Conn::SendRecv")
00493 
00494    XrdClientMessage *xmsg = 0;
00495 
00496    // We have to unconditionally set the streamid inside the
00497    // header, because, in case of 'rebouncing here', the Logical Connection
00498    // ID might have changed, while in the header to write it remained the
00499    // same as before, not valid anymore
00500    SetSID(req->header.streamid);
00501 
00502    // Notify what we are going to send
00503    if (TRACING(HDBG))
00504       XPD::smartPrintClientHeader(req);
00505 
00506    // We need the right order
00507    int reqDataLen = req->header.dlen;
00508    if (XPD::clientMarshall(req) != 0) {
00509       TRACE(XERR, "problems marshalling "<<URLTAG);
00510       return xmsg;
00511    }
00512    if (LowWrite(req, reqData, reqDataLen) != kOK) {
00513       TRACE(XERR, "problems sending request to server "<<URLTAG);
00514       return xmsg;
00515    }
00516 
00517    // Check if the client has already allocated the buffer
00518    bool needalloc = (answData && !(*answData));
00519 
00520    // Read from server the answer
00521    // Note that the answer can be composed by many reads, in the case that
00522    // the status field of the responses is kXR_oksofar
00523    size_t dataRecvSize = 0;
00524    do {
00525       //
00526       // NB: Xmsg contains ALSO the information about the result of
00527       // the communication at low level.
00528       kXR_int16 xst = kXR_error;
00529       if (!(xmsg = ReadMsg()) || xmsg->IsError()) {
00530          TRACE(XERR, "reading msg from connmgr (server "<<URLTAG<<")");
00531       } else {
00532          // Dump header, if required
00533          if (TRACING(HDBG))
00534             XPD::smartPrintServerHeader(&(xmsg->fHdr));
00535          // Get the status
00536          xst = xmsg->HeaderStatus();
00537       }
00538 
00539       // We save the result, if the caller wants so. In any case
00540       // we update the counters
00541       if ((xst == kXR_ok) || (xst == kXR_oksofar) || (xst == kXR_authmore)) {
00542          if (answData && xmsg->DataLen() > 0) {
00543             if (needalloc) {
00544                *answData = (char *) realloc(*answData, dataRecvSize + xmsg->DataLen());
00545                if (!(*answData)) {
00546                   // Memory resources exhausted
00547                   TRACE(XERR, "reallocating "<<dataRecvSize<<" bytes");
00548                   free((void *) *answData);
00549                   *answData = 0;
00550                   SafeDelete(xmsg);
00551                   return xmsg;
00552                }
00553             }
00554             // Now we copy the content of the Xmsg to the buffer where
00555             // the data are needed
00556             memcpy((*answData)+dataRecvSize,
00557                    xmsg->GetData(), xmsg->DataLen());
00558             //
00559             // Dump the buffer *answData, if requested
00560             if (TRACING(HDBG)) {
00561                TRACE(DBG, "dumping read data ...");
00562                for (int jj = 0; jj < xmsg->DataLen(); jj++) {
00563                   printf("0x%.2x ", *(((kXR_char *)xmsg->GetData())+jj));
00564                   if (!(jj%10)) printf("\n");
00565                }
00566             }
00567          }
00568          // Update counters
00569          dataRecvSize += xmsg->DataLen();
00570 
00571       } else if (xst != kXR_error) {
00572          //
00573          // Status unknown: protocol error?
00574          TRACE(XERR, "status in reply is unknown ["<<
00575                XPD::convertRespStatusToChar(xmsg->fHdr.status)<<
00576                "] (server "<<URLTAG<<") - Abort");
00577          // We cannot continue
00578          SafeDelete(xmsg);
00579          return xmsg;
00580       }
00581       // The last message may be empty: not an error
00582       if (xmsg && (xst == kXR_oksofar) && (xmsg->DataLen() == 0))
00583          return xmsg;
00584 
00585    } while (xmsg && (xmsg->HeaderStatus() == kXR_oksofar));
00586 
00587    // We might have collected multiple partial response also in a given mem block
00588    if (xmsg)
00589       xmsg->fHdr.dlen = dataRecvSize;
00590 
00591    return xmsg;
00592 }
00593 
00594 //_____________________________________________________________________________
00595 XrdClientMessage *XrdProofConn::SendReq(XPClientRequest *req, const void *reqData,
00596                                         char **answData, const char *CmdName,
00597                                         bool notifyerr)
00598 {
00599    // SendReq tries to send a single command for a number of times
00600    XPDLOC(ALL, "Conn::SendReq")
00601 
00602    XrdClientMessage *answMex = 0;
00603 
00604    TRACE(DBG,"len: "<<req->sendrcv.dlen);
00605 
00606    int retry = 0;
00607    bool resp = 0, abortcmd = 0;
00608    int maxTry = (fgMaxTry > -1) ? fgMaxTry : kXR_maxReqRetry;
00609 
00610    // We need the unmarshalled request for retries
00611    XPClientRequest reqsave;
00612    memcpy(&reqsave, req, sizeof(XPClientRequest));
00613 
00614    while (!abortcmd && !resp) {
00615 
00616       TRACE(HDBG, this << " locking phyconn: "<<fPhyConn);
00617 
00618       // Ok, now we can try
00619       abortcmd = 0;
00620 
00621       // Make sure we have the unmarshalled request
00622       memcpy(req, &reqsave, sizeof(XPClientRequest));
00623 
00624       // Send the cmd, dealing automatically with redirections and
00625       // redirections on error
00626       TRACE(DBG,"calling SendRecv");
00627       answMex = SendRecv(req, reqData, answData);
00628 
00629       // On serious communication error we retry for a number of times,
00630       // waiting for the server to come back
00631       retry++;
00632       if (!answMex || answMex->IsError()) {
00633 
00634          TRACE(DBG, "communication error detected with "<<URLTAG);
00635          if (retry > maxTry) {
00636             TRACE(XERR,"max number of retries reached - Abort");
00637             abortcmd = 1;
00638          } else {
00639             if (!IsValid()) {
00640                // Connection is gone: try to reconnect and if this fails, give up
00641                ReConnect();
00642                if (!IsValid()) {
00643                   TRACE(XERR,"not connected: nothing to do");
00644                   break;
00645                }
00646             }
00647             abortcmd = 0;
00648             // Restore the unmarshalled request
00649             memcpy(req, &reqsave, sizeof(XPClientRequest));
00650          }
00651       } else {
00652 
00653          // We are here if we got an answer for the command, so
00654          // the server (original or redirected) is alive
00655          resp = CheckResp(&(answMex->fHdr), CmdName, notifyerr);
00656 
00657          // If the answer was not (or not totally) positive, we must
00658          // investigate on the result
00659          if (!resp)
00660             abortcmd = CheckErrorStatus(answMex, retry, CmdName, notifyerr);
00661 
00662          if (retry > maxTry) {
00663             TRACE(XERR,"max number of retries reached - Abort");
00664             abortcmd = 1;
00665          }
00666       }
00667       if (abortcmd) {
00668          // Cleanup if failed
00669          SafeDelete(answMex);
00670       } else if (!resp) {
00671          // Sleep a while before retrying
00672          int sleeptime = 1;
00673          TRACE(DBG,"sleep "<<sleeptime<<" secs ...");
00674          sleep(sleeptime);
00675       }
00676    }
00677 
00678    // We are done
00679    return answMex;
00680 }
00681 
00682 //_____________________________________________________________________________
00683 bool XrdProofConn::CheckResp(struct ServerResponseHeader *resp,
00684                              const char *method, bool notifyerr)
00685 {
00686    // Checks if the server's response is ours.
00687    // If the response's status is "OK" returns 1; if the status is "redirect", it
00688    // means that the max number of redirections has been achieved, so returns 0.
00689    XPDLOC(ALL, "Conn::CheckResp")
00690 
00691    if (MatchStreamID(resp)) {
00692 
00693       if (resp->status != kXR_ok && resp->status != kXR_authmore &&
00694           resp->status != kXR_wait) {
00695          if (notifyerr) {
00696             TRACE(XERR,"server "<<URLTAG<<
00697                        " did not return OK replying to last request");
00698          }
00699          return 0;
00700       }
00701       return 1;
00702 
00703    } else {
00704       if (notifyerr) {
00705          TRACE(XERR, method << " return message not belonging to this client"
00706                                " - protocol error");
00707       }
00708       return 0;
00709    }
00710 }
00711 
00712 //_____________________________________________________________________________
00713 bool XrdProofConn::MatchStreamID(struct ServerResponseHeader *ServerResponse)
00714 {
00715    // Check stream ID matching
00716 
00717    char sid[2];
00718 
00719    memcpy(sid, &fStreamid, sizeof(sid));
00720 
00721    // Matches the streamid contained in the server's response with the ours
00722    return (memcmp(ServerResponse->streamid, sid, sizeof(sid)) == 0 );
00723 }
00724 
00725 //_____________________________________________________________________________
00726 void XrdProofConn::SetSID(kXR_char *sid) {
00727    // Set our stream id, to match against that one in the server's response.
00728 
00729    memcpy((void *)sid, (const void*)&fStreamid, 2);
00730 }
00731 
00732 //_____________________________________________________________________________
00733 XReqErrorType XrdProofConn::LowWrite(XPClientRequest *req, const void* reqData,
00734                                      int reqDataLen)
00735 {
00736    // Send request to server
00737    // (NB: req is marshalled at this point, so we need also the plain reqDataLen)
00738    XPDLOC(ALL, "Conn::LowWrite")
00739 
00740    // Strong mutual exclusion over the physical channel
00741    XrdClientPhyConnLocker pcl(fPhyConn);
00742    int wc = 0;
00743 
00744    //
00745    // Send header info first
00746    int len = sizeof(req->header);
00747    if ((wc = WriteRaw(req, len)) != len) {
00748       TRACE(XERR, "sending header to server "<<URLTAG<<" (rc="<<wc<<")");
00749       return kWRITE;
00750    }
00751 
00752    //
00753    // Send data next, if any
00754    if (reqDataLen > 0) {
00755       //
00756       if ((wc = WriteRaw(reqData, reqDataLen)) != reqDataLen) {
00757          TRACE(XERR, "sending data ("<<reqDataLen<<" bytes) to server "<<URLTAG<<
00758                     " (rc="<<wc<<")");
00759          return kWRITE;
00760       }
00761    }
00762 
00763    return kOK;
00764 }
00765 
00766 //_____________________________________________________________________________
00767 bool XrdProofConn::CheckErrorStatus(XrdClientMessage *mex, int &Retry,
00768                                     const char *CmdName, bool notifyerr)
00769 {
00770    // Check error status
00771    XPDLOC(ALL, "Conn::CheckErrorStatus")
00772 
00773    TRACE(DBG, "parsing reply from server "<<URLTAG);
00774 
00775    if (mex->HeaderStatus() == kXR_error) {
00776       //
00777       // The server declared an error.
00778       // In this case it's better to exit, unhandled error
00779 
00780       struct ServerResponseBody_Error *body_err;
00781 
00782       body_err = (struct ServerResponseBody_Error *)mex->GetData();
00783 
00784       if (body_err) {
00785          fLastErr = (XErrorCode)ntohl(body_err->errnum);
00786          fLastErrMsg = body_err->errmsg;
00787          if (notifyerr) {
00788             // Print out the error information, as received by the server
00789             if (fLastErr == (XErrorCode)kXP_reconnecting) {
00790                TRACE(XERR, fLastErrMsg);
00791             } else {
00792                TRACE(XERR,"error "<<fLastErr<<": '"<<fLastErrMsg<<"'");
00793             }
00794          }
00795       }
00796       if (fLastErr == (XErrorCode)kXP_reconnecting)
00797          return 0;
00798       return 1;
00799    }
00800 
00801    if (mex->HeaderStatus() == kXR_wait) {
00802       //
00803       // We have to wait for a specified number of seconds and then
00804       // retry the same cmd
00805 
00806       struct ServerResponseBody_Wait *body_wait;
00807 
00808       body_wait = (struct ServerResponseBody_Wait *)mex->GetData();
00809 
00810       if (body_wait) {
00811          int sleeptime = ntohl(body_wait->seconds);
00812          if (mex->DataLen() > 4) {
00813             TRACE(DBG,"wait request ("<<sleeptime<<
00814                   " secs); message: "<<(const char*)body_wait->infomsg);
00815          } else {
00816             TRACE(DBG,"wait request ("<<sleeptime<<" secs)");
00817          }
00818          sleep(sleeptime);
00819       }
00820 
00821       // We don't want kxr_wait to count as an error
00822       Retry--;
00823       return 0;
00824    }
00825 
00826    // We don't understand what the server said. Better investigate on it...
00827    TRACE(XERR,"after: "<<CmdName<<": server reply not recognized - protocol error");
00828 
00829    return 1;
00830 }
00831 
00832 //_____________________________________________________________________________
00833 bool XrdProofConn::GetAccessToSrv()
00834 {
00835    // Gets access to the connected server.
00836    // The login and authorization steps are performed here.
00837    XPDLOC(ALL, "Conn::GetAccessToSrv")
00838 
00839    // Now we are connected and we ask for the kind of the server
00840    {  XrdClientPhyConnLocker pcl(fPhyConn);
00841       fServerType = DoHandShake();
00842    }
00843 
00844    switch (fServerType) {
00845 
00846    case kSTXProofd:
00847 
00848       TRACE(DBG,"found server at "<<URLTAG);
00849 
00850       // Now we can start the reader thread in the physical connection, if needed
00851       fPhyConn->StartReader();
00852       fPhyConn->fServerType = kSTBaseXrootd;
00853       break;
00854 
00855    case kSTProofd:
00856       TRACE(DBG,"server at "<<URLTAG<<" is a proofd");
00857       // Close correctly this connection to proofd
00858       kXR_int32 dum[2];
00859       dum[0] = (kXR_int32)htonl(0);
00860       dum[1] = (kXR_int32)htonl(2034);
00861       WriteRaw(&dum[0], sizeof(dum));
00862       Close("P");
00863       return 0;
00864 
00865    case kSTError:
00866       TRACE(XERR,"handShake failed with server "<<URLTAG);
00867       Close("P");
00868       return 0;
00869 
00870    case kSTNone:
00871       TRACE(XERR,"server at "<<URLTAG<<" is unknown");
00872       Close("P");
00873       return 0;
00874    }
00875 
00876    bool ok = (fPhyConn->IsLogged() == kNo) ? Login() : 1;
00877    if (!ok) {
00878       TRACE(XERR,"client could not login at "<<URLTAG);
00879       return ok;
00880    }
00881 
00882    // We are done
00883    return ok;
00884 }
00885 
00886 //_____________________________________________________________________________
00887 int XrdProofConn::WriteRaw(const void *buf, int len)
00888 {
00889    // Low level write call
00890 
00891    if (fgConnMgr)
00892       return fgConnMgr->WriteRaw(fLogConnID, buf, len, 0);
00893 
00894    // No connection open
00895    return -1;
00896 }
00897 
00898 //_____________________________________________________________________________
00899 int XrdProofConn::ReadRaw(void *buf, int len)
00900 {
00901    // Low level receive call
00902 
00903    if (fgConnMgr)
00904       return fgConnMgr->ReadRaw(fLogConnID, buf, len);
00905 
00906    // No connection open
00907    return -1;
00908 }
00909 
00910 //_____________________________________________________________________________
00911 XrdProofConn::ESrvType XrdProofConn::DoHandShake()
00912 {
00913    // Performs initial hand-shake with the server in order to understand which
00914    // kind of server is there at the other side
00915    XPDLOC(ALL, "Conn::DoHandShake")
00916 
00917    // Nothing to do if already connected
00918    if (fPhyConn->fServerType == kSTBaseXrootd) {
00919 
00920       TRACE(DBG,"already connected to a PROOF server "<<URLTAG);
00921       return kSTXProofd;
00922    }
00923 
00924    // Set field in network byte order
00925    struct ClientInitHandShake initHS;
00926    memset(&initHS, 0, sizeof(initHS));
00927    initHS.third  = (kXR_int32)htonl((int)1);
00928 
00929    // Send to the server the initial hand-shaking message asking for the
00930    // kind of server
00931    int len = sizeof(initHS);
00932    TRACE(HDBG, "step 1: sending "<<len<<" bytes to server "<<URLTAG);
00933 
00934    int writeCount = WriteRaw(&initHS, len);
00935    if (writeCount != len) {
00936       TRACE(XERR, "sending "<<len<<" bytes to server "<<URLTAG);
00937       return kSTError;
00938    }
00939 
00940    // These 8 bytes are need by 'proofd' and discarded by XPD
00941    kXR_int32 dum[2];
00942    dum[0] = (kXR_int32)htonl(4);
00943    dum[1] = (kXR_int32)htonl(2012);
00944    writeCount = WriteRaw(&dum[0], sizeof(dum));
00945    if (writeCount != sizeof(dum)) {
00946       TRACE(XERR, "sending "<<sizeof(dum)<<" bytes to server "<<URLTAG);
00947       return kSTError;
00948    }
00949 
00950    // Read from server the first 4 bytes
00951    ServerResponseType type;
00952    len = sizeof(type);
00953    TRACE(HDBG, "step 2: reading "<<len<<" bytes from server "<<URLTAG);
00954 
00955    // Read returns the return value of TSocket->RecvRaw... that returns the
00956    // return value of recv (unix low level syscall)
00957    int readCount = ReadRaw(&type, len); // 4(2+2) bytes
00958    if (readCount != len) {
00959       if (readCount == (int)TXSOCK_ERR_TIMEOUT) {
00960          TRACE(ALL,"-----------------------");
00961          TRACE(ALL,"TimeOut condition reached reading from remote server.");
00962          TRACE(ALL,"This may indicate that the server is a 'proofd', version <= 12");
00963          TRACE(ALL,"Retry commenting the 'Plugin.TSlave' line in system.rootrc or adding");
00964          TRACE(ALL,"Plugin.TSlave: ^xpd  TSlave Proof \"TSlave(const char *,const char"
00965                " *,int,const char *, TProof *,ESlaveType,const char *,const char *)\"");
00966          TRACE(ALL,"to your $HOME/.rootrc .");
00967          TRACE(ALL,"-----------------------");
00968       } else {
00969          TRACE(XERR, "reading "<<len<<" bytes from server "<<URLTAG);
00970       }
00971       return kSTError;
00972    }
00973 
00974    // to host byte order
00975    type = ntohl(type);
00976 
00977    // Check if the server is the eXtended proofd
00978    if (type == 0) {
00979 
00980       struct ServerInitHandShake xbody;
00981 
00982       // ok
00983       len = sizeof(xbody);
00984       TRACE(HDBG, "step 3: reading "<<len<<" bytes from server "<<URLTAG);
00985 
00986       readCount = ReadRaw(&xbody, len); // 12(4+4+4) bytes
00987       if (readCount != len) {
00988          TRACE(XERR, "reading "<<len<<" bytes from server "<<URLTAG);
00989          return kSTError;
00990       }
00991 
00992       XPD::ServerInitHandShake2HostFmt(&xbody);
00993 
00994       fRemoteProtocol = xbody.protover;
00995       if (fPhyConn->fServerProto <= 0)
00996          fPhyConn->fServerProto = fRemoteProtocol;
00997 
00998       return kSTXProofd;
00999 
01000    } else if (type == 8) {
01001       // Standard proofd
01002       return kSTProofd;
01003    } else {
01004       // We don't know the server type
01005       TRACE(XERR, "unknown server type ("<<type<<")");
01006       return kSTNone;
01007    }
01008 }
01009 
01010 //_____________________________________________________________________________
01011 int XrdProofConn::GetLowSocket()
01012 {
01013    // Return the socket descriptor of the underlying connection
01014 
01015    return (fPhyConn ? fPhyConn->GetSocket() : -1);
01016 }
01017 
01018 //_____________________________________________________________________________
01019 bool XrdProofConn::Login()
01020 {
01021    // This method perform the loggin-in into the server just after the
01022    // hand-shake. It also calls the Authenticate() method
01023    XPDLOC(ALL, "Conn::Login")
01024 
01025    XPClientRequest reqhdr, reqsave;
01026 
01027    // We fill the header struct containing the request for login
01028    memset( &reqhdr, 0, sizeof(reqhdr));
01029 
01030    reqhdr.login.pid = getpid();
01031 
01032    // User[:group] info (url's password field used for the group)
01033    XrdOucString ug = fUser;
01034    if (fUrl.Passwd.length() > 0) {
01035       ug += ":";
01036       ug += fUrl.Passwd;
01037    }
01038 
01039    // Fill login username
01040    if (ug.length() > 8) {
01041       // The name must go in the attached buffer because the login structure
01042       // can accomodate at most 8 chars
01043       strcpy( (char *)reqhdr.login.username, "?>buf" );
01044       // Add the name to the login buffer, if not already done during
01045       // a previous login (for example if we are reconnecting ...)
01046       if (fLoginBuffer.find("|usr:") == STR_NPOS) {
01047          fLoginBuffer += "|usr:";
01048          fLoginBuffer += ug;
01049       }
01050    } else if (ug.length() >= 0) {
01051       memcpy((void *)reqhdr.login.username, (void *)(ug.c_str()), ug.length());
01052       if (ug.length() < 8) reqhdr.login.username[ug.length()] = '\0';
01053    } else {
01054       strcpy((char *)reqhdr.login.username, "????" );
01055    }
01056 
01057    // This is the place to send a token for fast authentication
01058    // or id to the server (or any other information)
01059    const void *buf = (const void *)(fLoginBuffer.c_str());
01060    reqhdr.header.dlen = fLoginBuffer.length();
01061 
01062    // Set the connection mode (see constructor header)
01063    reqhdr.login.role[0] = fMode;
01064 
01065    // For normal connections this is the PROOF protocol version run by the client.
01066    // For internal connections this is the id of the session we want to be
01067    // connected.
01068    short int sessID = fSessionID;
01069    // We use the 2 reserved bytes
01070    memcpy(&reqhdr.login.reserved[0], &sessID, 2);
01071 
01072    // Send also a capability (protocol) version number
01073    reqhdr.login.capver[0] = fCapVer;
01074 
01075    // We call SendReq, the function devoted to sending commands.
01076    if (TRACING(DBG)) {
01077       XrdOucString usr((const char *)&reqhdr.login.username[0], 8);
01078       TRACE(DBG, "logging into server "<<URLTAG<<"; pid="<<reqhdr.login.pid<<
01079                  "; uid=" << usr);
01080    }
01081 
01082    // Finish to fill up and ...
01083    SetSID(reqhdr.header.streamid);
01084    reqhdr.header.requestid = kXP_login;
01085    // ... saved it unmarshalled for retrials, if any
01086    memcpy(&reqsave, &reqhdr, sizeof(XPClientRequest));
01087 
01088    // Reset logged state
01089    fPhyConn->SetLogged(kNo);
01090 
01091    bool notdone = 1;
01092    bool resp = 1;
01093 
01094 
01095    // If positive answer
01096    XrdSecProtocol *secp = 0;
01097    while (notdone) {
01098 
01099       // server response header
01100       char *pltmp = 0;
01101 
01102       // Make sure we have the unmarshalled version
01103       memcpy(&reqhdr, &reqsave, sizeof(XPClientRequest));
01104 
01105       XrdClientMessage *xrsp = SendReq(&reqhdr, buf,
01106                                        &pltmp, "XrdProofConn::Login");
01107       // If positive answer
01108       secp = 0;
01109       char *plref = pltmp;
01110       if (xrsp) {
01111          //
01112          // Pointer to data
01113          int len = xrsp->DataLen();
01114          if (len >= (int)sizeof(kXR_int32)) {
01115             // The first 4 bytes contain the remote daemon version
01116             kXR_int32 vers = 0;
01117             memcpy(&vers, pltmp, sizeof(kXR_int32));
01118             fRemoteProtocol = ntohl(vers);
01119             pltmp = (char *)((char *)pltmp + sizeof(kXR_int32));
01120             len -= sizeof(kXR_int32);
01121          }
01122          // Check if we need to authenticate
01123          if (pltmp && (len > 0)) {
01124             //
01125             // Reset the result
01126             resp = 0;
01127             //
01128             // Set some environment variables: debug
01129             char *s = 0;
01130             if (EnvGetLong(NAME_DEBUG) > 0) {
01131                s = new char [strlen("XrdSecDEBUG")+20];
01132                sprintf(s, "XrdSecDEBUG=%ld", EnvGetLong(NAME_DEBUG));
01133                putenv(s);
01134             }
01135             // user name
01136             s = new char [strlen("XrdSecUSER")+fUser.length()+2];
01137             sprintf(s, "XrdSecUSER=%s", fUser.c_str());
01138             putenv(s);
01139             // host name
01140             s = new char [strlen("XrdSecHOST")+fHost.length()+2];
01141             sprintf(s, "XrdSecHOST=%s", fHost.c_str());
01142             putenv(s);
01143             // netrc file
01144             XrdOucString netrc;
01145 #ifndef WIN32
01146             struct passwd *pw = getpwuid(getuid());
01147             if (pw) {
01148                netrc = pw->pw_dir;
01149                netrc += "/.rootnetrc";
01150             }
01151 #endif
01152             if (netrc.length() > 0) {
01153                s = new char [strlen("XrdSecNETRC")+netrc.length()+2];
01154                sprintf(s, "XrdSecNETRC=%s", netrc.c_str());
01155                putenv(s);
01156             }
01157             //
01158             // Null-terminate server reply
01159             char *plist = new char[len+1];
01160             memcpy(plist, pltmp, len);
01161             plist[len] = 0;
01162             TRACE(DBG, "server requires authentication");
01163 
01164             secp = Authenticate(plist, (int)(len+1));
01165             resp = (secp != 0) ? 1 : 0;
01166 
01167             if (!resp)
01168                // We failed the aythentication attempt: cannot continue
01169                notdone = 0;
01170 
01171             if (plist)
01172                delete[] plist;
01173          } else {
01174             // We are successfully done
01175             resp = 1;
01176             notdone = 0;
01177          }
01178          // Cleanup
01179          SafeDelete(xrsp);
01180       } else {
01181          // We failed but we are done with this attempt
01182          resp = 0;
01183          notdone = 0;
01184          // Print error msg, if any
01185          if (GetLastErr())
01186             XPDPRT(fHost << ": "<< GetLastErr());
01187       }
01188 
01189       // Cleanup
01190       if (plref)
01191          free(plref);
01192 
01193    }
01194 
01195    // Flag success if everything went ok
01196    if (resp) {
01197       fPhyConn->SetLogged(kYes);
01198       fPhyConn->SetSecProtocol(secp);
01199    }
01200 
01201    // We are done
01202    return resp;
01203 }
01204 
01205 //_____________________________________________________________________________
01206 XrdSecProtocol *XrdProofConn::Authenticate(char *plist, int plsiz)
01207 {
01208    // Negotiate authentication with the remote server. Tries in turn
01209    // all available protocols proposed by the server (in plist),
01210    // starting from the first.
01211    XPDLOC(ALL, "Conn::Authenticate")
01212 
01213    XrdSecProtocol *protocol = (XrdSecProtocol *)0;
01214 
01215    if (!plist || plsiz <= 0)
01216       return protocol;
01217 
01218    TRACE(DBG, "host "<<URLTAG<< " sent a list of "<<plsiz<<" bytes");
01219    //
01220    // Prepare host/IP information of the remote xrootd. This is required
01221    // for the authentication.
01222    struct sockaddr_in netaddr;
01223    char **hosterrmsg = 0;
01224    if (XrdNetDNS::getHostAddr((char *)fUrl.HostAddr.c_str(),
01225                                 (struct sockaddr &)netaddr, hosterrmsg) <= 0) {
01226       TRACE(XERR, "getHostAddr: "<< *hosterrmsg);
01227       return protocol;
01228    }
01229    netaddr.sin_port   = fUrl.Port;
01230    //
01231    // Variables for negotiation
01232    XrdSecParameters  *secToken = 0;
01233    XrdSecCredentials *credentials = 0;
01234 
01235    //
01236    // Prepare the parms object
01237    char *bpar = (char *)malloc(plsiz + 1);
01238    if (bpar)
01239       memcpy(bpar, plist, plsiz);
01240    bpar[plsiz] = 0;
01241    XrdSecParameters Parms(bpar, plsiz + 1);
01242 
01243    // We need to load the protocol getter the first time we are here
01244    if (!fgSecGetProtocol) {
01245       static XrdSysError err(0, "XrdProofConn_");
01246       // Initialize the security library plugin, if needed
01247       if (!fgSecPlugin)
01248          fgSecPlugin = new XrdSysPlugin(&err, "libXrdSec.so");
01249 
01250       // Get the client protocol getter
01251       if (!(fgSecGetProtocol = fgSecPlugin->getPlugin("XrdSecGetProtocol"))) {
01252          TRACE(XERR, "unable to load XrdSecGetProtocol()");
01253          return protocol;
01254       }
01255    }
01256    //
01257    // Cycle through the security protocols accepted by the server
01258    while ((protocol = (*((XrdSecGetProt_t)fgSecGetProtocol))((char *)fUrl.Host.c_str(),
01259                                           (const struct sockaddr &)netaddr, Parms, 0))) {
01260       //
01261       // Protocol name
01262       XrdOucString protname = protocol->Entity.prot;
01263       //
01264       // Once we have the protocol, get the credentials
01265       XrdOucErrInfo ei;
01266       credentials = protocol->getCredentials(0, &ei);
01267       if (!credentials) {
01268          TRACE(XERR, "cannot obtain credentials (protocol: "<<protname<<")");
01269          // Set error, in case of need
01270          fLastErr = kXR_NotAuthorized;
01271          if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
01272          fLastErrMsg += "cannot obtain credentials for protocol: ";
01273          fLastErrMsg += ei.getErrText();
01274          protocol->Delete();
01275          protocol = 0;
01276          continue;
01277       } else {
01278          TRACE(HDBG, "credentials size: " << credentials->size);
01279       }
01280       //
01281       // We fill the header struct containing the request for login
01282       XPClientRequest reqhdr;
01283       memset(reqhdr.auth.reserved, 0, 12);
01284       memset(reqhdr.auth.credtype, 0, 4);
01285       memcpy(reqhdr.auth.credtype, protname.c_str(), protname.length());
01286 
01287       bool failed = 0;
01288       int status = kXR_authmore;
01289       int dlen = 0;
01290       char *srvans = 0;
01291       XrdClientMessage *xrsp = 0;
01292       while (status == kXR_authmore) {
01293          //
01294          // Length of the credentials buffer
01295          SetSID(reqhdr.header.streamid);
01296          reqhdr.header.requestid = kXP_auth;
01297          reqhdr.header.dlen = (credentials) ? credentials->size : 0;
01298          char *credbuf = (credentials) ? credentials->buffer : 0;
01299          xrsp = SendReq(&reqhdr, credbuf, &srvans, "XrdProofConn::Authenticate");
01300          SafeDelete(credentials);
01301          status = (xrsp) ? xrsp->HeaderStatus() : kXR_error;
01302          dlen = (xrsp) ? xrsp->DataLen() : 0;
01303          TRACE(HDBG, "server reply: status: "<<status<<" dlen: "<<dlen);
01304 
01305          if (xrsp && (status == kXR_authmore)) {
01306             //
01307             // We are required to send additional information
01308             // First assign the security token that we have received
01309             // at the login request
01310             secToken = new XrdSecParameters(srvans, dlen);
01311             //
01312             // then get next part of the credentials
01313             credentials = protocol->getCredentials(secToken, &ei);
01314             SafeDelete(secToken); // nb: srvans is released here
01315             srvans = 0;
01316             if (!credentials) {
01317                TRACE(XERR, "cannot obtain credentials");
01318                // Set error, in case of need
01319                fLastErr = kXR_NotAuthorized;
01320                if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
01321                fLastErrMsg += "cannot obtain credentials: ";
01322                fLastErrMsg += ei.getErrText();
01323                protocol->Delete();
01324                protocol = 0;
01325                // Server does not implement yet full cycling, so we are
01326                // allowed to try the handshake only for one protocol; we
01327                // cleanup the message and fail;
01328                SafeDelete(xrsp);
01329                failed = 1;
01330                break;
01331             } else {
01332                TRACE(HDBG, "credentials size " << credentials->size);
01333             }
01334          } else if (status != kXR_ok) {
01335             // Unexpected reply; print error msg, if any
01336             if (GetLastErr())
01337                TRACE(XERR, fHost << ": "<< GetLastErr());
01338             if (protocol) {
01339                protocol->Delete();
01340                protocol = 0;
01341             }
01342          }
01343          // Cleanup message
01344          SafeDelete(xrsp);
01345       }
01346 
01347       // If we are done
01348       if (protocol) {
01349          fLastErr = kXR_Unsupported;
01350          fLastErrMsg = "";
01351          break;
01352       }
01353       // Server does not implement yet full cycling, so we are
01354       // allowed to try the handshake only for one protocol; we
01355       if (failed) break;
01356    }
01357    if (!protocol) {
01358       TRACE(XERR, "unable to get protocol object.");
01359       // Set error, in case of need
01360       fLastErr = kXR_NotAuthorized;
01361       if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
01362       fLastErrMsg += "unable to get protocol object.";
01363    }
01364 
01365    // Return the result of the negotiation
01366    //
01367    return protocol;
01368 }
01369 
01370 //_____________________________________________________________________________
01371 void XrdProofConn::SetInterrupt()
01372 {
01373    // Interrupt the underlying socket
01374 
01375    if (fPhyConn)
01376       fPhyConn->SetInterrupt();
01377 }
01378 
01379 //_____________________________________________________________________________
01380 void XrdProofConn::SetConnectInterrupt()
01381 {
01382    // Interrupt connection attempts
01383 
01384    XrdSysMutexHelper mhp(fConnectInterruptMtx);
01385    fConnectInterrupt = 1;
01386 }
01387 
01388 //_____________________________________________________________________________
01389 bool XrdProofConn::ConnectInterrupt()
01390 {
01391    // Check if interrupted during connect
01392 
01393    bool rc = 0;
01394    {  XrdSysMutexHelper mhp(fConnectInterruptMtx);
01395       rc = fConnectInterrupt;
01396       // Reset the interrupt
01397       fConnectInterrupt = 0;
01398    }
01399    // Done
01400    return rc;
01401 }
01402 
01403 //_____________________________________________________________________________
01404 bool XrdProofConn::IsValid() const
01405 {
01406    // Test validity of this connection
01407 
01408    if (fConnected)
01409       if (fPhyConn && fPhyConn->IsValid())
01410          return 1;
01411    // Invalid
01412    return 0;
01413 }
01414 

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