Logo ROOT   6.08/07
Reference Guide
XrdProofPhyConn.cxx
Go to the documentation of this file.
1 // @(#)root/proofd:$Id$
2 // Author: Gerardo Ganis 12/12/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // XrdProofPhyConn //
15 // //
16 // Authors: G. Ganis, CERN, 2005 //
17 // //
18 // XrdProofConn implementation using a simple physical connection //
19 // (Unix or Tcp) //
20 //////////////////////////////////////////////////////////////////////////
21 
22 #include "XrdProofPhyConn.h"
23 #include "XpdSysDNS.h"
24 
25 #include "XrdVersion.hh"
31 #include "XrdSec/XrdSecInterface.hh"
32 
33 #ifndef WIN32
34 #ifndef ROOT_XrdFour
35 # include <sys/socket.h>
36 #endif
37 #include <sys/types.h>
38 #include <netdb.h>
39 #include <pwd.h>
40 #else
41 #include <Winsock2.h>
42 #endif
43 
44 // Tracing utils
45 #include "XrdProofdTrace.h"
46 
47 #define URLTAG "["<<fUrl.Host<<":"<<fUrl.Port<<"]"
48 
49 ////////////////////////////////////////////////////////////////////////////////
50 /// Constructor. Open a direct connection (Unix or Tcp) to a remote
51 /// XrdProofd instance. Does not use the connection manager.
52 
53 XrdProofPhyConn::XrdProofPhyConn(const char *url, int psid, char capver,
54  XrdClientAbsUnsolMsgHandler *uh, bool tcp, int fd)
55  : XrdProofConn(0, 'i', psid, capver, uh)
56 {
57  XPDLOC(ALL, "PhyConn")
58 
59  fTcp = tcp;
60 
61  // Mutex
62  fMutex = new XrdSysRecMutex();
63 
64  // Initialization
65  if (url && !Init(url, fd)) {
66  TRACE(XERR, "severe error occurred while"
67  " opening a connection" << " to server "<<URLTAG);
68  return;
69  }
70 }
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 /// Initialization
74 
75 bool XrdProofPhyConn::Init(const char *url, int fd)
76 {
77  XPDLOC(ALL, "PhyConn::Init")
78 
79  // Save url
80  fUrl.TakeUrl(XrdOucString(url));
81 
82  // Get user
83  fUser = fUrl.User.c_str();
84  if (fUser.length() <= 0) {
85  // Use local username, if not specified
86 #ifndef WIN32
87  struct passwd *pw = getpwuid(getuid());
88  fUser = pw ? pw->pw_name : "";
89 #else
90  char lname[256];
91  DWORD length = sizeof (lname);
92  ::GetUserName(lname, &length);
93  fUser = lname;
94 #endif
95  }
96 
97  // Host and Port
98  if (!fTcp) {
99  char *hn = XrdSysDNS::getHostName(((fUrl.Host.length() > 0) ?
100  fUrl.Host.c_str() : "localhost"));
101  fHost = hn;
102  free(hn);
103  fPort = -1;
104  fUrl.Host = "";
105  fUrl.User = "";
106  } else {
107 
108  fHost = fUrl.Host.c_str();
109  fPort = fUrl.Port;
110  // Check port
111  if (fPort <= 0) {
112  struct servent *sent = getservbyname("proofd", "tcp");
113  if (!sent) {
114  TRACE(XERR, "service 'proofd' not found by getservbyname" <<
115  ": using default IANA assigned tcp port 1093");
116  fPort = 1093;
117  } else {
118  fPort = (int)ntohs(sent->s_port);
119  // Update port in url
120  fUrl.Port = fPort;
121  TRACE(XERR, "getservbyname found tcp port " << fPort <<
122  " for service 'proofd'");
123  }
124  }
125  }
126 
127  // Run the connection attempts: the result is stored in fConnected
128  Connect(fd);
129 
130  // We are done
131  return fConnected;
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Run the connection attempts: the result is stored in fConnected
136 
138 {
139  XPDLOC(ALL, "PhyConn::Connect")
140 
141  int maxTry = -1, timeWait = -1;
142  // Max number of tries and timeout; use current settings, if any
143  XrdProofConn::GetRetryParam(maxTry, timeWait);
144  maxTry = (maxTry > -1) ? maxTry : EnvGetLong(NAME_FIRSTCONNECTMAXCNT);
145  timeWait = (timeWait > -1) ? timeWait : EnvGetLong(NAME_CONNECTTIMEOUT);
146 
147  int logid = -1;
148  int i = 0;
149  for (; (i < maxTry) && (!fConnected); i++) {
150 
151  // Try connection
152  logid = TryConnect(fd);
153 
154  // We are connected to a host. Let's handshake with it.
155  if (fConnected) {
156 
157  // Now the have the logical Connection ID, that we can use as streamid for
158  // communications with the server
159  TRACE(DBG, "new logical connection ID: "<<logid);
160 
161  // Get access to server
162  if (!GetAccessToSrv()) {
163  if (fLastErr == kXR_NotAuthorized) {
164  // Authentication error: does not make much sense to retry
165  Close("P");
166  XrdOucString msg = fLastErrMsg;
167  msg.erase(msg.rfind(":"));
168  TRACE(XERR, "authentication failure: " << msg);
169  return;
170  } else {
171  TRACE(XERR, "access to server failed (" << fLastErrMsg << ")");
172  }
173  continue;
174  } else {
175 
176  // Manager call in client: no need to create or attach: just notify
177  TRACE(DBG, "access to server granted.");
178  break;
179  }
180  }
181 
182  // We force a physical disconnection in this special case
183  TRACE(DBG, "disconnecting");
184  Close("P");
185 
186  // And we wait a bit before retrying
187  TRACE(DBG, "connection attempt failed: sleep " << timeWait << " secs");
188 #ifndef WIN32
189  sleep(timeWait);
190 #else
191  Sleep(timeWait * 1000);
192 #endif
193 
194  } //for connect try
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Connect to remote server
199 
201 {
202  XPDLOC(ALL, "PhyConn::TryConnect")
203 
204  const char *ctype[2] = {"UNIX", "TCP"};
205 
206  // Create physical connection
207  fPhyConn = new XrdClientPhyConnection(this, 0);
208 
209  // Connect
210  bool isUnix = (fTcp) ? 0 : 1;
211 #if ROOTXRDVERS <= ROOT_PhyConnNoReuse
212  if (fd > 0) {
213  TRACE(XERR, "Reusing an existing connection (descriptor "<<fd<<
214  ") not supported by the xroot client version (requires xrootd >= 3.0.3)");
215  fLogConnID = -1;
216  fConnected = 0;
217  return -1;
218  }
219  if (!(fPhyConn->Connect(fUrl, isUnix))) {
220 #else
221  if (!(fPhyConn->Connect(fUrl, isUnix, fd))) {
222 #endif
223  TRACE(XERR, "creating "<<ctype[fTcp]<<" connection to "<<URLTAG);
224  fLogConnID = -1;
225  fConnected = 0;
226  return -1;
227  }
228  TRACE(DBG, ctype[fTcp]<<"-connected to "<<URLTAG);
229 
230  // Set some vars
231  fLogConnID = 0;
232  fStreamid = 1;
233  fConnected = 1;
234 
235  // Replies are processed asynchronously
237 
238  // We are done
239  return fLogConnID;
240 }
241 
242 ////////////////////////////////////////////////////////////////////////////////
243 /// Close the connection.
244 
245 void XrdProofPhyConn::Close(const char *)
246 {
247  // Make sure we are connected
248  if (!fConnected)
249  return;
250 
251  // Close connection
252  if (fPhyConn)
253  fPhyConn->Disconnect();
254 
255  // Flag this action
256  fConnected = 0;
257 
258  // We are done
259  return;
260 }
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 /// Set handler of unsolicited responses
264 
266  XrdProofConnSender_t, void *)
267 {
268  if (fPhyConn)
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// Pickup message from the queue
274 
276 {
278 }
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 /// Gets access to the connected server.
282 /// The login and authorization steps are performed here.
283 
285 {
286  XPDLOC(ALL, "PhyConn::GetAccessToSrv")
287 
288  // Now we are connected and we ask for the kind of the server
291  }
292 
293  switch (fServerType) {
294 
295  case kSTXProofd:
296  TRACE(DBG, "found server at "<<URLTAG);
297 
298  // Now we can start the reader thread in the physical connection, if needed
301  break;
302 
303  case kSTError:
304  TRACE(XERR, "handshake failed with server "<<URLTAG);
305  Close();
306  return 0;
307 
308  case kSTProofd:
309  case kSTNone:
310  default:
311  TRACE(XERR, "server at "<<URLTAG<< " is unknown : protocol error");
312  Close();
313  return 0;
314  }
315 
316  // Execute a login
317  if (fPhyConn->IsLogged() != kNo) {
318  TRACE(XERR, "client already logged-in at "<<URLTAG<<" (!): protocol error!");
319  return 0;
320  }
321 
322  // Login
323  return Login();
324 }
325 
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 /// Low level write call
329 
330 int XrdProofPhyConn::WriteRaw(const void *buf, int len, XrdClientPhyConnection *)
331 {
332  if (fPhyConn)
333  return fPhyConn->WriteRaw(buf, len);
334 
335  // No connection open
336  return -1;
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// Low level write call
341 
343 {
344  if (fPhyConn)
345  return fPhyConn->ReadRaw(buf, len);
346 
347  // No connection open
348  return -1;
349 }
int WriteRaw(const void *buf, int len, XrdClientPhyConnection *=0)
Low level write call.
void TakeUrl(XrdOucString url)
kXR_unt16 fStreamid
Definition: XrdProofConn.h:73
void Close(const char *opt="")
Close the connection.
#define XrdSysRecMutex
Definition: XrdSysToOuc.h:18
#define URLTAG
#define TRACE(Flag, Args)
Definition: TGHtml.h:124
#define NAME_FIRSTCONNECTMAXCNT
XErrorCode fLastErr
Definition: XrdProofConn.h:83
ESrvType DoHandShake(XrdClientPhyConnection *p=0)
Performs initial hand-shake with the server in order to understand which kind of server is there at t...
void SetAsync(XrdClientAbsUnsolMsgHandler *uh, XrdProofConnSender_t=0, void *=0)
Set handler of unsolicited responses.
#define EnvGetLong(x)
Definition: XrdClientEnv.hh:44
bool Init(const char *url, int fd=-1)
Initialization.
XrdSysRecMutex * fMutex
Definition: XrdProofConn.h:88
bool GetAccessToSrv(XrdClientPhyConnection *=0)
Gets access to the connected server.
char * pw_name
Definition: TWinNTSystem.h:50
int(* XrdProofConnSender_t)(const char *, int, void *)
Definition: XrdProofConn.h:56
bool Login()
This method perform the loggin-in into the server just after the hand-shake.
int ReadRaw(void *buffer, int BufferLength, int substreamid=-1, int *usedsubstreamid=0)
#define XPDLOC(d, x)
bool Connect(XrdClientUrlInfo RemoteHost, bool isUnix=0)
ELoginState IsLogged()
XrdClientMessage * ReadMsg()
Pickup message from the queue.
XrdOucString fUser
Definition: XrdProofConn.h:79
XrdClientUrlInfo fUrl
Definition: XrdProofConn.h:102
static void GetRetryParam(int &maxtry, int &timewait)
Retrieve current values of the retry control parameters, numer of retries and wait time between attem...
void Connect(int fd=-1)
Run the connection attempts: the result is stored in fConnected.
XrdOucString fHost
Definition: XrdProofConn.h:80
#define NAME_CONNECTTIMEOUT
int TryConnect(int fd=-1)
Connect to remote server.
#define free
Definition: civetweb.c:821
XrdClientPhyConnection * fPhyConn
Definition: XrdProofConn.h:93
XrdOucString fLastErrMsg
Definition: XrdProofConn.h:82
R__EXTERN C unsigned int sleep(unsigned int seconds)
int WriteRaw(const void *buffer, int BufferLength, int substreamid=0)
XrdClientAbsUnsolMsgHandler * UnsolicitedMsgHandler
ESrvType fServerType
Definition: XrdProofConn.h:76
int ReadRaw(void *buf, int len, XrdClientPhyConnection *=0)
Low level write call.
XrdProofPhyConn(const char *url, int psid=-1, char ver=-1, XrdClientAbsUnsolMsgHandler *uh=0, bool tcp=0, int fd=-1)
Constructor.
XrdClientMessage * ReadMessage(int streamid)
XrdClientAbsUnsolMsgHandler * fUnsolMsgHandler
Definition: XrdProofConn.h:97