XrdProofPhyConn.cxx

Go to the documentation of this file.
00001 // @(#)root/proofd:$Id: XrdProofPhyConn.cxx 29510 2009-07-17 12:04:40Z 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 // XrdProofPhyConn                                                      //
00015 //                                                                      //
00016 // Authors: G. Ganis, CERN, 2005                                        //
00017 //                                                                      //
00018 //  XrdProofConn implementation using a simple physical connection      //
00019 // (Unix or Tcp)                                                        //
00020 //////////////////////////////////////////////////////////////////////////
00021 
00022 #include "XrdProofPhyConn.h"
00023 
00024 #include "XrdVersion.hh"
00025 #include "XrdClient/XrdClientEnv.hh"
00026 #include "XrdClient/XrdClientConnMgr.hh"
00027 #include "XrdClient/XrdClientConst.hh"
00028 #include "XrdClient/XrdClientLogConnection.hh"
00029 #include "XrdClient/XrdClientMessage.hh"
00030 #include "XrdNet/XrdNetDNS.hh"
00031 #include "XrdSec/XrdSecInterface.hh"
00032 
00033 #ifndef WIN32
00034 #include <sys/socket.h>
00035 #include <sys/types.h>
00036 #include <pwd.h>
00037 #else
00038 #include <Winsock2.h>
00039 #endif
00040 
00041 // Tracing utils
00042 #include "XrdProofdTrace.h"
00043 
00044 #define URLTAG "["<<fUrl.Host<<":"<<fUrl.Port<<"]"
00045 
00046 //_____________________________________________________________________________
00047 XrdProofPhyConn::XrdProofPhyConn(const char *url, int psid, char capver,
00048                                  XrdClientAbsUnsolMsgHandler *uh, bool tcp)
00049    : XrdProofConn(0, 'i', psid, capver, uh)
00050 {
00051    // Constructor. Open a direct connection (Unix or Tcp) to a remote
00052    // XrdProofd instance. Does not use the connection manager.
00053    XPDLOC(ALL, "PhyConn")
00054 
00055    fTcp = tcp;
00056 
00057    // Mutex
00058    fMutex = new XrdSysRecMutex();
00059 
00060    // Initialization
00061    if (url && !Init(url)) {
00062       TRACE(XERR, "severe error occurred while"
00063                   " opening a connection" << " to server "<<URLTAG);
00064       return;
00065    }
00066 }
00067 
00068 //_____________________________________________________________________________
00069 bool XrdProofPhyConn::Init(const char *url)
00070 {
00071    // Initialization
00072    XPDLOC(ALL, "PhyConn::Init")
00073 
00074    // Save url
00075    fUrl.TakeUrl(XrdOucString(url));
00076 
00077    // Get user
00078    fUser = fUrl.User.c_str();
00079    if (fUser.length() <= 0) {
00080       // Use local username, if not specified
00081 #ifndef WIN32
00082       struct passwd *pw = getpwuid(getuid());
00083       fUser = pw ? pw->pw_name : "";
00084 #else
00085       char  lname[256];
00086       DWORD length = sizeof (lname);
00087       ::GetUserName(lname, &length);
00088       fUser = lname;
00089 #endif
00090    }
00091 
00092    // Host and Port
00093    if (!fTcp) {
00094       fHost = XrdNetDNS::getHostName(((fUrl.Host.length() > 0) ?
00095                                        fUrl.Host.c_str() : "localhost"));
00096       fPort = -1;
00097       fUrl.Host = "";
00098       fUrl.User = "";
00099    } else {
00100 
00101       fHost = fUrl.Host.c_str();
00102       fPort = fUrl.Port;
00103       // Check port
00104       if (fPort <= 0) {
00105          struct servent *sent = getservbyname("proofd", "tcp");
00106          if (!sent) {
00107             TRACE(XERR, "service 'proofd' not found by getservbyname" <<
00108                         ": using default IANA assigned tcp port 1093");
00109             fPort = 1093;
00110          } else {
00111             fPort = (int)ntohs(sent->s_port);
00112             // Update port in url
00113             fUrl.Port = fPort;
00114             TRACE(XERR, "getservbyname found tcp port " << fPort <<
00115                         " for service 'proofd'");
00116          }
00117       }
00118    }
00119 
00120    // Run the connection attempts: the result is stored in fConnected
00121    Connect();
00122 
00123    // We are done
00124    return fConnected;
00125 }
00126 
00127 //_____________________________________________________________________________
00128 void XrdProofPhyConn::Connect()
00129 {
00130    // Run the connection attempts: the result is stored in fConnected
00131    XPDLOC(ALL, "PhyConn::Connect")
00132 
00133    int maxTry = -1, timeWait = -1;
00134    // Max number of tries and timeout; use current settings, if any
00135    XrdProofConn::GetRetryParam(maxTry, timeWait);
00136    maxTry = (maxTry > -1) ? maxTry : EnvGetLong(NAME_FIRSTCONNECTMAXCNT);
00137    timeWait = (timeWait > -1) ? timeWait : EnvGetLong(NAME_CONNECTTIMEOUT);
00138 
00139    int logid = -1;
00140    int i = 0;
00141    for (; (i < maxTry) && (!fConnected); i++) {
00142 
00143       // Try connection
00144       logid = TryConnect();
00145 
00146       // We are connected to a host. Let's handshake with it.
00147       if (fConnected) {
00148 
00149          // Now the have the logical Connection ID, that we can use as streamid for
00150          // communications with the server
00151          TRACE(DBG, "new logical connection ID: "<<logid);
00152 
00153          // Get access to server
00154          if (!GetAccessToSrv()) {
00155             if (fLastErr == kXR_NotAuthorized) {
00156                // Authentication error: does not make much sense to retry
00157                Close("P");
00158                XrdOucString msg = fLastErrMsg;
00159                msg.erase(msg.rfind(":"));
00160                TRACE(XERR, "authentication failure: " << msg);
00161                return;
00162             } else {
00163                TRACE(XERR, "access to server failed (" << fLastErrMsg << ")");
00164             }
00165             continue;
00166          } else {
00167 
00168             // Manager call in client: no need to create or attach: just notify
00169             TRACE(DBG, "access to server granted.");
00170             break;
00171          }
00172       }
00173 
00174       // We force a physical disconnection in this special case
00175       TRACE(DBG, "disconnecting");
00176       Close("P");
00177 
00178       // And we wait a bit before retrying
00179       TRACE(DBG, "connection attempt failed: sleep " << timeWait << " secs");
00180 #ifndef WIN32
00181       sleep(timeWait);
00182 #else
00183       Sleep(timeWait * 1000);
00184 #endif
00185 
00186    } //for connect try
00187 }
00188 
00189 //_____________________________________________________________________________
00190 int XrdProofPhyConn::TryConnect()
00191 {
00192    // Connect to remote server
00193    XPDLOC(ALL, "PhyConn::TryConnect")
00194 
00195    const char *ctype[2] = {"UNIX", "TCP"};
00196 
00197    // Create physical connection
00198 #ifdef OLDXRCPHYCONN
00199    fPhyConn = new XrdClientPhyConnection(this);
00200 #else
00201    fPhyConn = new XrdClientPhyConnection(this, 0);
00202 #endif
00203 
00204    // Connect
00205    bool isUnix = (fTcp) ? 0 : 1;
00206    if (!(fPhyConn->Connect(fUrl, isUnix))) {
00207       TRACE(XERR, "creating "<<ctype[fTcp]<<" connection to "<<URLTAG);
00208       fLogConnID = -1;
00209       fConnected = 0;
00210       return -1;
00211    }
00212    TRACE(DBG, ctype[fTcp]<<"-connected to "<<URLTAG);
00213 
00214    // Set some vars
00215    fLogConnID = 0;
00216    fStreamid = 1;
00217    fConnected = 1;
00218 
00219    // Replies are processed asynchronously
00220    SetAsync(fUnsolMsgHandler);
00221 
00222    // We are done
00223    return fLogConnID;
00224 }
00225 
00226 //_____________________________________________________________________________
00227 void XrdProofPhyConn::Close(const char *)
00228 {
00229    // Close the connection.
00230 
00231    // Make sure we are connected
00232    if (!fConnected)
00233       return;
00234 
00235    // Close connection
00236    if (fPhyConn)
00237       fPhyConn->Disconnect();
00238 
00239    // Flag this action
00240    fConnected = 0;
00241 
00242    // We are done
00243    return;
00244 }
00245 
00246 //_____________________________________________________________________________
00247 void XrdProofPhyConn::SetAsync(XrdClientAbsUnsolMsgHandler *uh,
00248                                XrdProofConnSender_t, void *)
00249 {
00250    // Set handler of unsolicited responses
00251 
00252    if (fPhyConn)
00253       fPhyConn->UnsolicitedMsgHandler = uh;
00254 }
00255 
00256 //_____________________________________________________________________________
00257 XrdClientMessage *XrdProofPhyConn::ReadMsg()
00258 {
00259    // Pickup message from the queue
00260 
00261    return (fPhyConn ? fPhyConn->ReadMessage(fStreamid) : (XrdClientMessage *)0);
00262 }
00263 
00264 //_____________________________________________________________________________
00265 bool XrdProofPhyConn::GetAccessToSrv()
00266 {
00267    // Gets access to the connected server.
00268    // The login and authorization steps are performed here.
00269    XPDLOC(ALL, "PhyConn::GetAccessToSrv")
00270 
00271    // Now we are connected and we ask for the kind of the server
00272    { XrdClientPhyConnLocker pcl(fPhyConn);
00273    fServerType = DoHandShake();
00274    }
00275 
00276    switch (fServerType) {
00277 
00278    case kSTXProofd:
00279       TRACE(DBG, "found server at "<<URLTAG);
00280 
00281       // Now we can start the reader thread in the physical connection, if needed
00282       fPhyConn->StartReader();
00283       fPhyConn->fServerType = kSTBaseXrootd;
00284       break;
00285 
00286    case kSTError:
00287       TRACE(XERR, "handShake failed with server "<<URLTAG);
00288       Close();
00289       return 0;
00290 
00291    case kSTProofd:
00292    case kSTNone:
00293    default:
00294       TRACE(XERR, "server at "<<URLTAG<< " is unknown : protocol error");
00295       Close();
00296       return 0;
00297    }
00298 
00299    // Execute a login
00300    if (fPhyConn->IsLogged() != kNo) {
00301       TRACE(XERR, "client already logged-in at "<<URLTAG<<" (!): protocol error!");
00302       return 0;
00303    }
00304 
00305    // Login
00306    return Login();
00307 }
00308 
00309 
00310 //_____________________________________________________________________________
00311 int XrdProofPhyConn::WriteRaw(const void *buf, int len)
00312 {
00313    // Low level write call
00314 
00315    if (fPhyConn)
00316       return fPhyConn->WriteRaw(buf, len);
00317 
00318    // No connection open
00319    return -1;
00320 }
00321 
00322 //_____________________________________________________________________________
00323 int XrdProofPhyConn::ReadRaw(void *buf, int len)
00324 {
00325    // Low level write call
00326 
00327    if (fPhyConn)
00328       return fPhyConn->ReadRaw(buf, len);
00329 
00330    // No connection open
00331    return -1;
00332 }

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