Logo ROOT   6.08/07
Reference Guide
XrdProofConn.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 
15 // XrdProofConn //
16 // //
17 // Authors: G. Ganis, CERN, 2005 //
18 // //
19 // Low level handler of connections to xproofd. //
20 // //
21 //////////////////////////////////////////////////////////////////////////
22 #include "XrdProofdXrdVers.h"
23 
24 #ifndef ROOT_XrdFour
25 #include "XpdSysDNS.h"
26 #else
27 #include "XrdNet/XrdNetAddr.hh"
28 #endif
29 
30 #include "XpdSysError.h"
31 #include "XpdSysPlugin.h"
32 #include "XpdSysPthread.h"
33 
34 #include "XrdProofConn.h"
35 #include "XrdProofdAux.h"
36 #include "XProofProtocol.h"
37 
45 #include "XrdOuc/XrdOucErrInfo.hh"
46 #include "XrdOuc/XrdOucString.hh"
47 #include "XrdSec/XrdSecInterface.hh"
48 #include "XrdSys/XrdSysLogger.hh"
49 #include "XrdSys/XrdSysPlatform.hh"
50 
51 // Dynamic libs
52 // Bypass Solaris ELF madness
53 #if (defined(SUNCC) || defined(SUN))
54 #include <sys/isa_defs.h>
55 #if defined(_ILP32) && (_FILE_OFFSET_BITS != 32)
56 #undef _FILE_OFFSET_BITS
57 #define _FILE_OFFSET_BITS 32
58 #undef _LARGEFILE_SOURCE
59 #endif
60 #endif
61 
62 #ifndef WIN32
63 #include <dlfcn.h>
64 #if !defined(__APPLE__)
65 #include <link.h>
66 #endif
67 #endif
68 
69 // Tracing utils
70 #include "XrdProofdTrace.h"
71 
72 #ifndef WIN32
73 #ifndef ROOT_XrdFour
74 # include <sys/socket.h>
75 #endif
76 #include <sys/types.h>
77 #include <netdb.h>
78 #include <pwd.h>
79 #else
80 #include <process.h>
81 #include <Winsock2.h>
82 #endif
83 
84 // Security handle
85 typedef XrdSecProtocol *(*secGetProt_t)(const char *, const struct sockaddr &,
86  const XrdSecParameters &, XrdOucErrInfo *);
87 
89 
90 // Retry controllers
92 int XrdProofConn::fgTimeWait = 2; // seconds
93 
94 XrdSysPlugin *XrdProofConn::fgSecPlugin = 0; // Sec library plugin
95 void *XrdProofConn::fgSecGetProtocol = 0; // Sec protocol getter
96 
97 #define URLTAG "["<<fUrl.Host<<":"<<fUrl.Port<<"]"
98 
99 ////////////////////////////////////////////////////////////////////////////////
100 /// Constructor. Open the connection to a remote XrdProofd instance.
101 /// The mode 'm' indicates the role of this connection:
102 /// 'a' Administrator; used by an XPD to contact the head XPD
103 /// 'i' Internal; used by a TXProofServ to call back its creator
104 /// (see XrdProofUnixConn)
105 /// 'M' Client contacting a top master
106 /// 'm' Top master contacting a submaster
107 /// 's' Master contacting a slave
108 /// The buffer 'logbuf' is a null terminated string to be sent over at
109 /// login. In case of need, internally it is overwritten with a token
110 /// needed during redirection.
111 
112 XrdProofConn::XrdProofConn(const char *url, char m, int psid, char capver,
113  XrdClientAbsUnsolMsgHandler *uh, const char *logbuf)
114  : fMode(m), fConnected(0), fLogConnID(-1), fStreamid(0), fRemoteProtocol(-1),
115  fServerProto(-1), fServerType(kSTNone), fSessionID(psid), fPort(-1),
116  fLastErr(kXR_noErrorYet), fCapVer(capver), fLoginBuffer(logbuf), fMutex(0),
117  fConnectInterruptMtx(0), fConnectInterrupt(0), fPhyConn(0),
118  fOpenSockFD(-1), fUnsolMsgHandler(uh), fSender(0), fSenderArg(0)
119 {
120  XPDLOC(ALL, "XrdProofConn")
121 
122  // Mutex
123  fMutex = new XrdSysRecMutex();
125 
126  // Initialization
127  if (url && !Init(url)) {
128  if (GetServType() != kSTProofd && !(fLastErr == kXR_NotAuthorized))
129  TRACE(XERR, "XrdProofConn: severe error occurred while opening a"
130  " connection" << " to server "<<URLTAG);
131  }
132 
133  return;
134 }
135 
136 ////////////////////////////////////////////////////////////////////////////////
137 /// Retrieve current values of the retry control parameters, numer of retries
138 /// and wait time between attempts (in seconds).
139 
140 void XrdProofConn::GetRetryParam(int &maxtry, int &timewait)
141 {
142  maxtry = fgMaxTry;
143  timewait = fgTimeWait;
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Change values of the retry control parameters, numer of retries
148 /// and wait time between attempts (in seconds).
149 
150 void XrdProofConn::SetRetryParam(int maxtry, int timewait)
151 {
152  fgMaxTry = maxtry;
153  fgTimeWait = timewait;
154 }
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Initialization
158 
159 bool XrdProofConn::Init(const char *url, int)
160 {
161  XPDLOC(ALL, "Conn::Init")
162 
163  // Init connection manager (only once)
164  if (!fgConnMgr) {
165  if (!(fgConnMgr = new XrdClientConnectionMgr())) {
166  TRACE(XERR,"error initializing connection manager");
167  return 0;
168  }
169  }
170 
171  // Parse Url
172  fUrl.TakeUrl(XrdOucString(url));
173  fUser = fUrl.User.c_str();
174  // Get username from Url
175  if (fUser.length() <= 0) {
176  // If not specified, use local username
177 #ifndef WIN32
178  struct passwd *pw = getpwuid(getuid());
179  fUser = pw ? pw->pw_name : "";
180 #else
181  char name[256];
182  DWORD length = sizeof (name);
183  ::GetUserName(name, &length);
184  if (strlen(name) > 1)
185  fUser = name;
186 #endif
187  }
188  fHost = fUrl.Host.c_str();
189  fPort = fUrl.Port;
190 
191  // Run the connection attempts: the result is stored in fConnected
192  Connect();
193 
194  // We are done
195  return fConnected;
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// Run the connection attempts: the result is stored in fConnected
200 
202 {
203  XPDLOC(ALL, "Conn::Connect")
204 
205  // Max number of tries and timeout
206  int maxTry = (fgMaxTry > -1) ? fgMaxTry : EnvGetLong(NAME_FIRSTCONNECTMAXCNT);
207  int timeWait = (fgTimeWait > -1) ? fgTimeWait : EnvGetLong(NAME_CONNECTTIMEOUT);
208 
209  fConnected = 0;
210  int logid = -1;
211  int i = 0;
212  for (; (i < maxTry) && (!fConnected); i++) {
213 
214  // Try connection
215  logid = TryConnect();
216 
217  // Check if interrupted
218  if (ConnectInterrupt()) {
219  TRACE(ALL, "got an interrupt while connecting - aborting attempts");
220  break;
221  }
222 
223  // We are connected to a host. Let's handshake with it.
224  if (fConnected) {
225 
226  // Set the port used
227  fPort = fUrl.Port;
228 
229  if (fPhyConn->IsLogged() == kNo) {
230  // Now the have the logical Connection ID, that we can use as streamid for
231  // communications with the server
232  TRACE(DBG, "new logical connection ID: "<<logid);
233 
234  // Get access to server
235  if (!GetAccessToSrv()) {
236  if (GetServType() == kSTProofd) {
237  fConnected = 0;
238  return;
239  }
240  if (fLastErr == kXR_NotAuthorized || fLastErr == kXR_InvalidRequest) {
241  // Auth error or invalid request: does not make much sense to retry
242  Close("P");
243  if (fLastErr == kXR_InvalidRequest) {
244  XrdOucString msg = fLastErrMsg;
245  msg.erase(msg.rfind(":"));
246  TRACE(XERR, "failure: " << msg);
247  }
248  return;
249  } else {
250  TRACE(XERR, "access to server failed (" << fLastErrMsg << ")");
251  }
252  fConnected = 0;
253  continue;
254  }
255  }
256 
257  // Notify
258  TRACE(DBG, "connection successfully created");
259  break;
260 
261  }
262 
263  // Reset
264  TRACE(REQ, "disconnecting");
265  Close();
266 
267  // And we wait a bit before retrying
268  if (i < maxTry - 1) {
269  TRACE(DBG, "connection attempt failed: sleep " << timeWait << " secs");
270  if (fUrl.Host == "lite" || fUrl.Host == "pod") {
271  const char *cdef = (fUrl.Host == "lite") ? " (or \"\": check 'Proof.LocalDefault')" : "";
272  const char *cnow = (fUrl.Host == "lite") ? "now " : "";
273  const char *cses = (fUrl.Host == "lite") ? "PROOF-Lite" : "PoD";
274  TRACE(ALL, "connection attempt to server \""<<fUrl.Host<<"\" failed. We are going to retry after some sleep,");
275  TRACE(ALL, "but if you intended to start a "<<cses<<" session instead, please note that you must");
276  TRACE(ALL, cnow<<"use \""<<fUrl.Host<<"://\" as connection string"<<cdef);
277  }
278  sleep(timeWait);
279  }
280 
281  } //for connect try
282 
283  // Notify failure
284  if (!fConnected) {
285  TRACE(XERR, "failed to connect to " << fUrl.GetUrl());
286  }
287 }
288 
289 ////////////////////////////////////////////////////////////////////////////////
290 /// Destructor
291 
293 {
294  // Disconnect from remote server (the connection manager is
295  // responsible of the underlying physical connection, so we do not
296  // force its closing)
297  if (fRemoteProtocol > 1004) {
298  // We may be into a reconnection attempt: interrupt it ...
300  // ... and wait for the OK
302  // Can close now
303  Close();
304  } else {
305  Close();
306  }
307 
308  // Cleanup mutex
309  SafeDel(fMutex);
311 }
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// Perform a reconnection attempt when a connection is not valid any more
315 
317 {
318  XPDLOC(ALL, "Conn::ReConnect")
319 
320  if (!IsValid()) {
321  if (fRemoteProtocol > 1004) {
322 
323  // Block any other attempt to use this connection
325 
326  Close();
327  int maxtry, timewait;
328  XrdProofConn::GetRetryParam(maxtry, timewait);
330  Connect();
332 
333  } else {
334  TRACE(DBG, "server does not support reconnections (protocol: %d" <<
335  fRemoteProtocol << " < 1005)");
336  }
337  }
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Connect to remote server
342 
344 {
345  XPDLOC(ALL, "Conn::TryConnect")
346 
347  int logid;
348  logid = -1;
349 
350  // The first time find the default port
351  static int servdef = -1;
352  if (servdef < 0) {
353  struct servent *ent = getservbyname("proofd", "tcp");
354  servdef = (ent) ? (int)ntohs(ent->s_port) : 1093;
355  }
356 
357  // Resolve the DNS information
358 #ifndef ROOT_XrdFour
359  char *haddr[10] = {0}, *hname[10] = {0};
360  int naddr = XrdSysDNS::getAddrName(fUrl.Host.c_str(), 10, haddr, hname);
361 
362  int i = 0;
363  for (; i < naddr; i++ ) {
364  // Address
365  fUrl.HostAddr = (const char *) haddr[i];
366  // Name
367  fUrl.Host = (const char *) hname[i];
368  // Notify
369  TRACE(HDBG, "found host "<<fUrl.Host<<" with addr " << fUrl.HostAddr);
370  }
371 
372 #else
373  XrdNetAddr aNA;
374  aNA.Set(fUrl.Host.c_str());
375  fUrl.Host = (const char *) aNA.Name();
376  char ha[256] = {0};
377  if (aNA.Format(ha, 256) <= 0) {
378  TRACE(DBG, "failure resolving address name " <<URLTAG);
379  fLogConnID = logid;
380  fConnected = 0;
381  return -1;
382  }
383  fUrl.HostAddr = (const char *) ha; //
384  // Notify
385  TRACE(HDBG, "found host "<<fUrl.Host<<" with addr " << fUrl.HostAddr);
386 #endif
387 
388  // Set the port
389  fUrl.Port = (fUrl.Port <= 0) ? servdef : fUrl.Port;
390 
391  // Connect
392  if ((logid = fgConnMgr->Connect(fUrl)) < 0) {
393  TRACE(DBG, "failure creating logical connection to " <<URLTAG);
394  fLogConnID = logid;
395  fConnected = 0;
396  return -1;
397  }
398 
399  // Set some vars
400  fLogConnID = logid;
403  fConnected = 1;
404 
405  TRACE(DBG, "connect to "<<URLTAG<<" returned {"<<fLogConnID<<", "<< fStreamid<<"}");
406 
407  // Fill in the remote protocol: either it was received during handshake
408  // or it was saved in the underlying physical connection
409  if (fRemoteProtocol < 0)
411 
412  // Handle asynchronous requests
414 
415  // We are done
416  return logid;
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 /// Close connection.
421 
422 void XrdProofConn::Close(const char *opt)
423 {
424  XPDLOC(ALL, "Conn::Close")
425 
426  // Make sure we are connected
427  if (!fConnected)
428  return;
429 
430  // Close also theunderlying physical connection ?
431  bool closephys = (opt[0] == 'P') ? 1 : 0;
432  TRACE(DBG, URLTAG <<": closing also physical connection ? "<< closephys);
433 
434  // Close connection
435  if (fgConnMgr)
436  fgConnMgr->Disconnect(GetLogConnID(), closephys);
437 
438  // Flag this action
439  fConnected = 0;
440 
441  // We are done
442  return;
443 }
444 
445 ////////////////////////////////////////////////////////////////////////////////
446 /// We are here if an unsolicited response comes from a logical conn
447 /// The response comes in the form of an XrdClientMessage *, that must NOT be
448 /// destroyed after processing. It is destroyed by the first sender.
449 /// Remember that we are in a separate thread, since unsolicited
450 /// responses are asynchronous by nature.
451 
454 {
455  XPDLOC(ALL, "Conn::ProcessUnsolicitedMsg")
456 
457  TRACE(DBG,"processing unsolicited response");
458 
459  if (!m || m->IsError()) {
460  TRACE(XERR, "Got empty or error unsolicited message");
461  } else {
462  // Check length
463  int len = 0;
464  if ((len = m->DataLen()) < (int)sizeof(kXR_int32)) {
465  TRACE(XERR, "empty or bad-formed message - ignoring");
466  return kUNSOL_KEEP;
467  }
468  // The first 4 bytes contain the action code
469  kXR_int32 acod = 0;
470  memcpy(&acod, m->GetData(), sizeof(kXR_int32));
471  //
472  // Update pointer to data
473  void *pdata = (void *)((char *)(m->GetData()) + sizeof(kXR_int32));
474  //
475  // Only interested in service messages
476  if (acod == kXPD_srvmsg) {
477  // The next 4 bytes may contain a flag to control the way the message is displayed
478  kXR_int32 opt = 0;
479  memcpy(&opt, pdata, sizeof(kXR_int32));
480  opt = ntohl(opt);
481  if (opt == 0 || opt == 1 || opt == 2) {
482  // Update pointer to data
483  pdata = (void *)((char *)pdata + sizeof(kXR_int32));
484  len -= sizeof(kXR_int32);
485  } else {
486  opt = 1;
487  }
488  // Send up, if required
489  if (fSender) {
490  (*fSender)((const char *)pdata, len, fSenderArg);
491  }
492  }
493  }
494 
495  return kUNSOL_KEEP;
496 }
497 
498 ////////////////////////////////////////////////////////////////////////////////
499 /// Set handler of unsolicited responses
500 
502  XrdProofConnSender_t sender, void *arg)
503 {
506 
507  // Set also the sender method and its argument, if required
508  fSender = sender;
509  fSenderArg = arg;
510 }
511 
512 ////////////////////////////////////////////////////////////////////////////////
513 /// Pickup message from the queue
514 
516 {
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// SendRecv sends a command to the server and to get a response.
522 /// The header of the last response is returned as pointer to a XrdClientMessage.
523 /// The data, if any, are returned in *answData; if *answData == 0 in input,
524 /// the buffer is internally allocated and must be freed by the caller.
525 /// If (*answData != 0) the program assumes that the caller has allocated
526 /// enough bytes to contain the reply.
527 
529  char **answData)
530 {
531  XPDLOC(ALL, "Conn::SendRecv")
532 
533  XrdClientMessage *xmsg = 0;
534 
535  // We have to unconditionally set the streamid inside the
536  // header, because, in case of 'rebouncing here', the Logical Connection
537  // ID might have changed, while in the header to write it remained the
538  // same as before, not valid anymore
539  SetSID(req->header.streamid);
540 
541  // Notify what we are going to send
542  if (TRACING(HDBG))
544 
545  // We need the right order
546  int reqDataLen = req->header.dlen;
547  if (XPD::clientMarshall(req) != 0) {
548  TRACE(XERR, "problems marshalling "<<URLTAG);
549  return xmsg;
550  }
551  if (LowWrite(req, reqData, reqDataLen) != kOK) {
552  TRACE(XERR, "problems sending request to server "<<URLTAG);
553  return xmsg;
554  }
555 
556  // Check if the client has already allocated the buffer
557  bool needalloc = (answData && !(*answData));
558 
559  // Read from server the answer
560  // Note that the answer can be composed by many reads, in the case that
561  // the status field of the responses is kXR_oksofar
562  size_t dataRecvSize = 0;
563  do {
564  //
565  // NB: Xmsg contains ALSO the information about the result of
566  // the communication at low level.
567  kXR_int16 xst = kXR_error;
568  if (!(xmsg = ReadMsg()) || xmsg->IsError()) {
569  TRACE(XERR, "reading msg from connmgr (server "<<URLTAG<<")");
570  } else {
571  // Dump header, if required
572  if (TRACING(HDBG))
574  // Get the status
575  xst = xmsg->HeaderStatus();
576  }
577 
578  // We save the result, if the caller wants so. In any case
579  // we update the counters
580  if ((xst == kXR_ok) || (xst == kXR_oksofar) || (xst == kXR_authmore)) {
581  if (answData && xmsg->DataLen() > 0) {
582  if (needalloc) {
583  *answData = (char *) realloc(*answData, dataRecvSize + xmsg->DataLen());
584  if (!(*answData)) {
585  // Memory resources exhausted
586  TRACE(XERR, "reallocating "<<dataRecvSize<<" bytes");
587  free((void *) *answData);
588  *answData = 0;
589  SafeDel(xmsg);
590  return xmsg;
591  }
592  }
593  // Now we copy the content of the Xmsg to the buffer where
594  // the data are needed
595  memcpy((*answData)+dataRecvSize,
596  xmsg->GetData(), xmsg->DataLen());
597  //
598  // Dump the buffer *answData, if requested
599  if (TRACING(HDBG)) {
600  TRACE(DBG, "dumping read data ...");
601  for (int jj = 0; jj < xmsg->DataLen(); jj++) {
602  printf("0x%.2x ", *(((kXR_char *)xmsg->GetData())+jj));
603  if (!(jj%10)) printf("\n");
604  }
605  }
606  }
607  // Update counters
608  dataRecvSize += xmsg->DataLen();
609 
610  } else if (xst != kXR_error) {
611  //
612  // Status unknown: protocol error?
613  TRACE(XERR, "status in reply is unknown ["<<
614  XPD::convertRespStatusToChar(xmsg->fHdr.status)<<
615  "] (server "<<URLTAG<<") - Abort");
616  // We cannot continue
617  SafeDel(xmsg);
618  return xmsg;
619  }
620  // The last message may be empty: not an error
621  if (xmsg && (xst == kXR_oksofar) && (xmsg->DataLen() == 0))
622  return xmsg;
623 
624  } while (xmsg && (xmsg->HeaderStatus() == kXR_oksofar));
625 
626  // We might have collected multiple partial response also in a given mem block
627  if (xmsg)
628  xmsg->fHdr.dlen = dataRecvSize;
629 
630  return xmsg;
631 }
632 
633 ////////////////////////////////////////////////////////////////////////////////
634 /// SendReq tries to send a single command for a number of times
635 
637  char **answData, const char *CmdName,
638  bool notifyerr)
639 {
640  XPDLOC(ALL, "Conn::SendReq")
641 
642  XrdClientMessage *answMex = 0;
643 
644  TRACE(DBG,"len: "<<req->sendrcv.dlen);
645 
646  int retry = 0;
647  bool resp = 0, abortcmd = 0;
648  int maxTry = (fgMaxTry > -1) ? fgMaxTry : kXR_maxReqRetry;
649 
650  // We need the unmarshalled request for retries
651  XPClientRequest reqsave;
652  memcpy(&reqsave, req, sizeof(XPClientRequest));
653 
654  while (!abortcmd && !resp) {
655 
656  TRACE(HDBG, this << " locking phyconn: "<<fPhyConn);
657 
658  // Ok, now we can try
659  abortcmd = 0;
660 
661  // Make sure we have the unmarshalled request
662  memcpy(req, &reqsave, sizeof(XPClientRequest));
663 
664  // Send the cmd, dealing automatically with redirections and
665  // redirections on error
666  TRACE(DBG,"calling SendRecv");
667  answMex = SendRecv(req, reqData, answData);
668 
669  // On serious communication error we retry for a number of times,
670  // waiting for the server to come back
671  retry++;
672  if (!answMex || answMex->IsError()) {
673 
674  TRACE(DBG, "communication error detected with "<<URLTAG);
675  if (retry > maxTry) {
676  TRACE(XERR,"max number of retries reached - Abort");
677  abortcmd = 1;
678  } else {
679  if (!IsValid()) {
680  // Connection is gone: try to reconnect and if this fails, give up
681  ReConnect();
682  if (!IsValid()) {
683  TRACE(XERR,"not connected: nothing to do");
684  break;
685  }
686  }
687  abortcmd = 0;
688  // Restore the unmarshalled request
689  memcpy(req, &reqsave, sizeof(XPClientRequest));
690  }
691  } else {
692 
693  // We are here if we got an answer for the command, so
694  // the server (original or redirected) is alive
695  resp = CheckResp(&(answMex->fHdr), CmdName, notifyerr);
696 
697  // If the answer was not (or not totally) positive, we must
698  // investigate on the result
699  if (!resp)
700  abortcmd = CheckErrorStatus(answMex, retry, CmdName, notifyerr);
701 
702  if (retry > maxTry) {
703  TRACE(XERR,"max number of retries reached - Abort");
704  abortcmd = 1;
705  }
706  }
707  if (abortcmd) {
708  // Cleanup if failed
709  SafeDel(answMex);
710  } else if (!resp) {
711  // Sleep a while before retrying
712  int sleeptime = 1;
713  TRACE(DBG,"sleep "<<sleeptime<<" secs ...");
714  sleep(sleeptime);
715  }
716  }
717 
718  // We are done
719  return answMex;
720 }
721 
722 ////////////////////////////////////////////////////////////////////////////////
723 /// Checks if the server's response is ours.
724 /// If the response's status is "OK" returns 1; if the status is "redirect", it
725 /// means that the max number of redirections has been achieved, so returns 0.
726 
727 bool XrdProofConn::CheckResp(struct ServerResponseHeader *resp,
728  const char *method, bool notifyerr)
729 {
730  XPDLOC(ALL, "Conn::CheckResp")
731 
732  if (MatchStreamID(resp)) {
733 
734  if (resp->status != kXR_ok && resp->status != kXR_authmore &&
735  resp->status != kXR_wait) {
736  if (notifyerr) {
737  TRACE(XERR,"server "<<URLTAG<<
738  " did not return OK replying to last request");
739  }
740  return 0;
741  }
742  return 1;
743 
744  } else {
745  if (notifyerr) {
746  TRACE(XERR, method << " return message not belonging to this client"
747  " - protocol error");
748  }
749  return 0;
750  }
751 }
752 
753 ////////////////////////////////////////////////////////////////////////////////
754 /// Check stream ID matching
755 
756 bool XrdProofConn::MatchStreamID(struct ServerResponseHeader *ServerResponse)
757 {
758  char sid[2];
759 
760  memcpy(sid, &fStreamid, sizeof(sid));
761 
762  // Matches the streamid contained in the server's response with the ours
763  return (memcmp(ServerResponse->streamid, sid, sizeof(sid)) == 0 );
764 }
765 
766 ////////////////////////////////////////////////////////////////////////////////
767 /// Set our stream id, to match against that one in the server's response.
768 
769 void XrdProofConn::SetSID(kXR_char *sid) {
770  memcpy((void *)sid, (const void*)&fStreamid, 2);
771 }
772 
773 ////////////////////////////////////////////////////////////////////////////////
774 /// Send request to server
775 /// (NB: req is marshalled at this point, so we need also the plain reqDataLen)
776 
777 XReqErrorType XrdProofConn::LowWrite(XPClientRequest *req, const void* reqData,
778  int reqDataLen)
779 {
780  XPDLOC(ALL, "Conn::LowWrite")
781 
782  // Strong mutual exclusion over the physical channel
784  int wc = 0;
785 
786  //
787  // Send header info first
788  int len = sizeof(req->header);
789  if ((wc = WriteRaw(req, len)) != len) {
790  TRACE(XERR, "sending header to server "<<URLTAG<<" (rc="<<wc<<")");
791  return kWRITE;
792  }
793 
794  //
795  // Send data next, if any
796  if (reqDataLen > 0) {
797  //
798  if ((wc = WriteRaw(reqData, reqDataLen)) != reqDataLen) {
799  TRACE(XERR, "sending data ("<<reqDataLen<<" bytes) to server "<<URLTAG<<
800  " (rc="<<wc<<")");
801  return kWRITE;
802  }
803  }
804 
805  return kOK;
806 }
807 
808 ////////////////////////////////////////////////////////////////////////////////
809 /// Check error status
810 
812  const char *CmdName, bool notifyerr)
813 {
814  XPDLOC(ALL, "Conn::CheckErrorStatus")
815 
816  TRACE(DBG, "parsing reply from server "<<URLTAG);
817 
818  if (mex->HeaderStatus() == kXR_error) {
819  //
820  // The server declared an error.
821  // In this case it's better to exit, unhandled error
822 
823  struct ServerResponseBody_Error *body_err;
824 
825  body_err = (struct ServerResponseBody_Error *)mex->GetData();
826 
827  if (body_err) {
828  fLastErr = (XErrorCode)ntohl(body_err->errnum);
829  fLastErrMsg = body_err->errmsg;
830  if (notifyerr) {
831  // Print out the error information, as received by the server
832  if (fLastErr == (XErrorCode)kXP_reconnecting) {
833  TRACE(XERR, fLastErrMsg);
834  } else {
835  TRACE(XERR,"error "<<fLastErr<<": '"<<fLastErrMsg<<"'");
836  }
837  }
838  }
839  if (fLastErr == (XErrorCode)kXP_reconnecting)
840  return 0;
841  return 1;
842  }
843 
844  if (mex->HeaderStatus() == kXR_wait) {
845  //
846  // We have to wait for a specified number of seconds and then
847  // retry the same cmd
848 
849  struct ServerResponseBody_Wait *body_wait;
850 
851  body_wait = (struct ServerResponseBody_Wait *)mex->GetData();
852 
853  if (body_wait) {
854  int sleeptime = ntohl(body_wait->seconds);
855  if (mex->DataLen() > 4) {
856  TRACE(DBG,"wait request ("<<sleeptime<<
857  " secs); message: "<<(const char*)body_wait->infomsg);
858  } else {
859  TRACE(DBG,"wait request ("<<sleeptime<<" secs)");
860  }
861  sleep(sleeptime);
862  }
863 
864  // We don't want kxr_wait to count as an error
865  Retry--;
866  return 0;
867  }
868 
869  // We don't understand what the server said. Better investigate on it...
870  TRACE(XERR,"after: "<<CmdName<<": server reply not recognized - protocol error");
871 
872  return 1;
873 }
874 
875 ////////////////////////////////////////////////////////////////////////////////
876 /// Gets access to the connected server.
877 /// The login and authorization steps are performed here.
878 
880 {
881  XPDLOC(ALL, "Conn::GetAccessToSrv")
882 
883  XrdClientPhyConnection *phyconn = (p) ? p : fPhyConn;
884  // Now we are connected and we ask for the kind of the server
885  { XrdClientPhyConnLocker pcl(phyconn);
887  }
888 
889  switch (fServerType) {
890 
891  case kSTXProofd:
892 
893  TRACE(DBG,"found server at "<<URLTAG);
894 
895  // Now we can start the reader thread in the physical connection, if needed
896  if (phyconn == fPhyConn) fPhyConn->StartReader();
898  break;
899 
900  case kSTProofd:
901  TRACE(DBG,"server at "<<URLTAG<<" is a proofd");
902  // Close correctly this connection to proofd
903  kXR_int32 dum[2];
904  dum[0] = (kXR_int32)htonl(0);
905  dum[1] = (kXR_int32)htonl(2034);
906  WriteRaw(&dum[0], sizeof(dum), p);
907  Close("P");
908  return 0;
909 
910  case kSTError:
911  TRACE(XERR,"handshake failed with server "<<URLTAG);
912  Close("P");
913  return 0;
914 
915  case kSTNone:
916  TRACE(XERR,"server at "<<URLTAG<<" is unknown");
917  Close("P");
918  return 0;
919  }
920 
921  bool ok = (phyconn == fPhyConn && fPhyConn->IsLogged() == kNo) ? Login() : 1;
922  if (!ok) {
923  TRACE(XERR,"client could not login at "<<URLTAG);
924  return ok;
925  }
926 
927  // We are done
928  return ok;
929 }
930 
931 ////////////////////////////////////////////////////////////////////////////////
932 /// Low level write call
933 
934 int XrdProofConn::WriteRaw(const void *buf, int len, XrdClientPhyConnection *phyconn)
935 {
936  if (phyconn && phyconn->IsValid()) {
937  phyconn->WriteRaw(buf, len, 0);
938  } else if (fgConnMgr) {
939  return fgConnMgr->WriteRaw(fLogConnID, buf, len, 0);
940  }
941 
942  // No connection open
943  return -1;
944 }
945 
946 ////////////////////////////////////////////////////////////////////////////////
947 /// Low level receive call
948 
949 int XrdProofConn::ReadRaw(void *buf, int len, XrdClientPhyConnection *phyconn)
950 {
951  if (phyconn && phyconn->IsValid()) {
952  phyconn->ReadRaw(buf, len);
953  } else if (fgConnMgr) {
954  return fgConnMgr->ReadRaw(fLogConnID, buf, len);
955  }
956 
957  // No connection open
958  return -1;
959 }
960 
961 ////////////////////////////////////////////////////////////////////////////////
962 /// Performs initial hand-shake with the server in order to understand which
963 /// kind of server is there at the other side
964 
966 {
967  XPDLOC(ALL, "Conn::DoHandShake")
968 
969  XrdClientPhyConnection *phyconn = (p) ? p : fPhyConn;
970 
971  // Nothing to do if already connected
972  if (phyconn->fServerType == kSTBaseXrootd) {
973 
974  TRACE(DBG,"already connected to a PROOF server "<<URLTAG);
975  return kSTXProofd;
976  }
977 
978  // Set field in network byte order
979  struct ClientInitHandShake initHS;
980  memset(&initHS, 0, sizeof(initHS));
981  initHS.third = (kXR_int32)htonl((int)1);
982 
983  // Send to the server the initial hand-shaking message asking for the
984  // kind of server
985  int len = sizeof(initHS);
986  TRACE(HDBG, "step 1: sending "<<len<<" bytes to server "<<URLTAG);
987 
988  int writeCount = WriteRaw(&initHS, len, p);
989  if (writeCount != len) {
990  TRACE(XERR, "sending "<<len<<" bytes to server "<<URLTAG);
991  return kSTError;
992  }
993 
994  // These 8 bytes are need by 'proofd' and discarded by XPD
995  kXR_int32 dum[2];
996  dum[0] = (kXR_int32)htonl(4);
997  dum[1] = (kXR_int32)htonl(2012);
998  writeCount = WriteRaw(&dum[0], sizeof(dum), p);
999  if (writeCount != sizeof(dum)) {
1000  TRACE(XERR, "sending "<<sizeof(dum)<<" bytes to server "<<URLTAG);
1001  return kSTError;
1002  }
1003 
1004  // Read from server the first 4 bytes
1005  ServerResponseType type;
1006  len = sizeof(type);
1007  TRACE(HDBG, "step 2: reading "<<len<<" bytes from server "<<URLTAG);
1008 
1009  // Read returns the return value of TSocket->RecvRaw... that returns the
1010  // return value of recv (unix low level syscall)
1011  int readCount = ReadRaw(&type, len, p); // 4(2+2) bytes
1012  if (readCount != len) {
1013  if (readCount == (int)TXSOCK_ERR_TIMEOUT) {
1014  TRACE(ALL,"-----------------------");
1015  TRACE(ALL,"TimeOut condition reached reading from remote server.");
1016  TRACE(ALL,"This may indicate that the server is a 'proofd', version <= 12");
1017  TRACE(ALL,"Retry commenting the 'Plugin.TSlave' line in system.rootrc or adding");
1018  TRACE(ALL,"Plugin.TSlave: ^xpd TSlave Proof \"TSlave(const char *,const char"
1019  " *,int,const char *, TProof *,ESlaveType,const char *,const char *)\"");
1020  TRACE(ALL,"to your $HOME/.rootrc .");
1021  TRACE(ALL,"-----------------------");
1022  } else {
1023  TRACE(XERR, "reading "<<len<<" bytes from server "<<URLTAG);
1024  }
1025  return kSTError;
1026  }
1027 
1028  // to host byte order
1029  type = ntohl(type);
1030 
1031  // Check if the server is the eXtended proofd
1032  if (type == 0) {
1033 
1034  struct ServerInitHandShake xbody;
1035 
1036  // ok
1037  len = sizeof(xbody);
1038  TRACE(HDBG, "step 3: reading "<<len<<" bytes from server "<<URLTAG);
1039 
1040  readCount = ReadRaw(&xbody, len, p); // 12(4+4+4) bytes
1041  if (readCount != len) {
1042  TRACE(XERR, "reading "<<len<<" bytes from server "<<URLTAG);
1043  return kSTError;
1044  }
1045 
1047 
1048  fRemoteProtocol = xbody.protover;
1049  if (fPhyConn->fServerProto <= 0)
1051 
1052  return kSTXProofd;
1053 
1054  } else if (type == 8) {
1055  // Standard proofd
1056  return kSTProofd;
1057  } else {
1058  // We don't know the server type
1059  TRACE(XERR, "unknown server type ("<<type<<")");
1060  return kSTNone;
1061  }
1062 }
1063 
1064 ////////////////////////////////////////////////////////////////////////////////
1065 /// Return the socket descriptor of the underlying connection
1066 
1068 {
1069  return (fPhyConn ? fPhyConn->GetSocket() : -1);
1070 }
1071 
1072 ////////////////////////////////////////////////////////////////////////////////
1073 /// This method perform the loggin-in into the server just after the
1074 /// hand-shake. It also calls the Authenticate() method
1075 
1077 {
1078  XPDLOC(ALL, "Conn::Login")
1079 
1080  XPClientRequest reqhdr, reqsave;
1081 
1082  // We fill the header struct containing the request for login
1083  memset( &reqhdr, 0, sizeof(reqhdr));
1084 
1085  reqhdr.login.pid = getpid();
1086 
1087  // User[:group] info (url's password field used for the group)
1088  XrdOucString ug = fUser;
1089  if (fUrl.Passwd.length() > 0) {
1090  ug += ":";
1091  ug += fUrl.Passwd;
1092  }
1093 
1094  // Fill login username
1095  if (ug.length() > 8) {
1096  // The name must go in the attached buffer because the login structure
1097  // can accomodate at most 8 chars
1098  strncpy( (char *)reqhdr.login.username, "?>buf", sizeof(reqhdr.login.username));
1099  // Add the name to the login buffer, if not already done during
1100  // a previous login (for example if we are reconnecting ...)
1101  if (fLoginBuffer.find("|usr:") == STR_NPOS) {
1102  fLoginBuffer += "|usr:";
1103  fLoginBuffer += ug;
1104  }
1105  } else if (ug.length() >= 0) {
1106  memcpy((void *)reqhdr.login.username, (void *)(ug.c_str()), ug.length());
1107  if (ug.length() < 8) reqhdr.login.username[ug.length()] = '\0';
1108  } else {
1109  strncpy((char *)reqhdr.login.username, "????", sizeof(reqhdr.login.username));
1110  }
1111 
1112  // This is the place to send a token for fast authentication
1113  // or id to the server (or any other information)
1114  const void *buf = (const void *)(fLoginBuffer.c_str());
1115  reqhdr.header.dlen = fLoginBuffer.length();
1116 
1117  // Set the connection mode (see constructor header)
1118  reqhdr.login.role[0] = fMode;
1119 
1120  // For normal connections this is the PROOF protocol version run by the client.
1121  // For internal connections this is the id of the session we want to be
1122  // connected.
1123  short int sessID = fSessionID;
1124  // We use the 2 reserved bytes
1125  memcpy(&reqhdr.login.reserved[0], &sessID, 2);
1126 
1127  // Send also a capability (protocol) version number
1128  reqhdr.login.capver[0] = fCapVer;
1129 
1130  // We call SendReq, the function devoted to sending commands.
1131  if (TRACING(DBG)) {
1132  XrdOucString usr((const char *)&reqhdr.login.username[0], 8);
1133  TRACE(DBG, "logging into server "<<URLTAG<<"; pid="<<reqhdr.login.pid<<
1134  "; uid=" << usr);
1135  }
1136 
1137  // Finish to fill up and ...
1138  SetSID(reqhdr.header.streamid);
1139  reqhdr.header.requestid = kXP_login;
1140  // ... saved it unmarshalled for retrials, if any
1141  memcpy(&reqsave, &reqhdr, sizeof(XPClientRequest));
1142 
1143  // Reset logged state
1145 
1146  bool notdone = 1;
1147  bool resp = 1;
1148 
1149 
1150  // If positive answer
1151  XrdSecProtocol *secp = 0;
1152  while (notdone) {
1153 
1154  // server response header
1155  char *pltmp = 0;
1156 
1157  // Make sure we have the unmarshalled version
1158  memcpy(&reqhdr, &reqsave, sizeof(XPClientRequest));
1159 
1160  XrdClientMessage *xrsp = SendReq(&reqhdr, buf,
1161  &pltmp, "XrdProofConn::Login", 0);
1162  // If positive answer
1163  secp = 0;
1164  char *plref = pltmp;
1165  if (xrsp) {
1166  //
1167  // Pointer to data
1168  int len = xrsp->DataLen();
1169  if (len >= (int)sizeof(kXR_int32)) {
1170  // The first 4 bytes contain the remote daemon version
1171  kXR_int32 vers = 0;
1172  memcpy(&vers, pltmp, sizeof(kXR_int32));
1173  fRemoteProtocol = ntohl(vers);
1174  pltmp = (char *)((char *)pltmp + sizeof(kXR_int32));
1175  len -= sizeof(kXR_int32);
1176  }
1177  // Check if we need to authenticate
1178  if (pltmp && (len > 0)) {
1179  //
1180  // Reset the result
1181  resp = 0;
1182  //
1183  // Set some environment variables: debug
1184  char *s = 0;
1185  if (EnvGetLong(NAME_DEBUG) > 0) {
1186  s = new char [strlen("XrdSecDEBUG")+20];
1187  sprintf(s, "XrdSecDEBUG=%ld", EnvGetLong(NAME_DEBUG));
1188  putenv(s);
1189  }
1190  // user name
1191  s = new char [strlen("XrdSecUSER")+fUser.length()+2];
1192  sprintf(s, "XrdSecUSER=%s", fUser.c_str());
1193  putenv(s);
1194  // host name
1195  s = new char [strlen("XrdSecHOST")+fHost.length()+2];
1196  sprintf(s, "XrdSecHOST=%s", fHost.c_str());
1197  putenv(s);
1198  // netrc file
1199  XrdOucString netrc;
1200 #ifndef WIN32
1201  struct passwd *pw = getpwuid(getuid());
1202  if (pw) {
1203  netrc = pw->pw_dir;
1204  netrc += "/.rootnetrc";
1205  }
1206 #endif
1207  if (netrc.length() > 0) {
1208  s = new char [strlen("XrdSecNETRC")+netrc.length()+2];
1209  sprintf(s, "XrdSecNETRC=%s", netrc.c_str());
1210  putenv(s);
1211  }
1212  //
1213  // Null-terminate server reply
1214  char *plist = new char[len+1];
1215  memcpy(plist, pltmp, len);
1216  plist[len] = 0;
1217  TRACE(DBG, "server requires authentication");
1218 
1219  secp = Authenticate(plist, (int)(len+1));
1220  resp = (secp != 0) ? 1 : 0;
1221 
1222  if (!resp)
1223  // We failed the aythentication attempt: cannot continue
1224  notdone = 0;
1225 
1226  delete[] plist;
1227  } else {
1228  // We are successfully done
1229  resp = 1;
1230  notdone = 0;
1231  }
1232  // Cleanup
1233  SafeDel(xrsp);
1234  } else {
1235  // We failed but we are done with this attempt
1236  resp = 0;
1237  notdone = 0;
1238  // Print error msg, if any
1239  if (GetLastErr())
1240  XPDPRT(fHost << ": "<< GetLastErr());
1241  }
1242 
1243  // Cleanup
1244  if (plref)
1245  free(plref);
1246 
1247  }
1248 
1249  // Flag success if everything went ok
1250  if (resp) {
1252  fPhyConn->SetSecProtocol(secp);
1253  }
1254 
1255  // We are done
1256  return resp;
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////////
1260 /// Negotiate authentication with the remote server. Tries in turn
1261 /// all available protocols proposed by the server (in plist),
1262 /// starting from the first.
1263 
1264 XrdSecProtocol *XrdProofConn::Authenticate(char *plist, int plsiz)
1265 {
1266  XPDLOC(ALL, "Conn::Authenticate")
1267 
1268  XrdSecProtocol *protocol = (XrdSecProtocol *)0;
1269 
1270  if (!plist || plsiz <= 0)
1271  return protocol;
1272 
1273  TRACE(DBG, "host "<<URLTAG<< " sent a list of "<<plsiz<<" bytes");
1274  //
1275  // Prepare host/IP information of the remote xrootd. This is required
1276  // for the authentication.
1277  struct sockaddr_in netaddr;
1278 #ifndef ROOT_XrdFour
1279  char **hosterrmsg = 0;
1280  if (XrdSysDNS::getHostAddr((char *)fUrl.HostAddr.c_str(),
1281  (struct sockaddr &)netaddr, hosterrmsg) <= 0) {
1282  TRACE(XERR, "getHostAddr: "<< *hosterrmsg);
1283  return protocol;
1284  }
1285 #else
1286  XrdNetAddr aNA;
1287  aNA.Set(fUrl.HostAddr.c_str());
1288  memcpy(&netaddr, aNA.NetAddr(), sizeof(struct sockaddr_in));
1289 #endif
1290  netaddr.sin_port = fUrl.Port;
1291  //
1292  // Variables for negotiation
1293  XrdSecParameters *secToken = 0;
1294  XrdSecCredentials *credentials = 0;
1295 
1296  //
1297  // Prepare the parms object
1298  char *bpar = (char *)malloc(plsiz + 1);
1299  if (bpar)
1300  memcpy(bpar, plist, plsiz);
1301  bpar[plsiz] = 0;
1302  XrdSecParameters Parms(bpar, plsiz + 1);
1303 
1304  // We need to load the protocol getter the first time we are here
1305  if (!fgSecGetProtocol) {
1306  static XrdSysLogger log;
1307  static XrdSysError err(&log, "XrdProofConn_");
1308  // Initialize the security library plugin, if needed
1309  XrdOucString libsec;
1310  if (!fgSecPlugin) {
1311 #if !defined(ROOT_XrdNoUtils)
1312  libsec = "libXrdSec";
1313  libsec += LT_MODULE_EXT;
1314 #else
1315  libsec = "libXrdSec.so";
1316 #endif
1317  fgSecPlugin = new XrdSysPlugin(&err, libsec.c_str());
1318  }
1319 
1320  // Get the client protocol getter
1321  if (!(fgSecGetProtocol = fgSecPlugin->getPlugin("XrdSecGetProtocol"))) {
1322  TRACE(XERR, "unable to load XrdSecGetProtocol()");
1323  return protocol;
1324  }
1325  }
1326  //
1327  // Cycle through the security protocols accepted by the server
1328  while ((protocol = (*((secGetProt_t)fgSecGetProtocol))((char *)fUrl.Host.c_str(),
1329  (const struct sockaddr &)netaddr, Parms, 0))) {
1330  //
1331  // Protocol name
1332  XrdOucString protname = protocol->Entity.prot;
1333  //
1334  // Once we have the protocol, get the credentials
1335  XrdOucErrInfo ei;
1336  credentials = protocol->getCredentials(0, &ei);
1337  if (!credentials) {
1338  TRACE(XERR, "cannot obtain credentials (protocol: "<<protname<<")");
1339  // Set error, in case of need
1340  fLastErr = kXR_NotAuthorized;
1341  if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
1342  fLastErrMsg += "cannot obtain credentials for protocol: ";
1343  fLastErrMsg += ei.getErrText();
1344  protocol->Delete();
1345  protocol = 0;
1346  continue;
1347  } else {
1348  TRACE(HDBG, "credentials size: " << credentials->size);
1349  }
1350  //
1351  // We fill the header struct containing the request for login
1352  XPClientRequest reqhdr;
1353  memset(reqhdr.auth.reserved, 0, 12);
1354  memset(reqhdr.auth.credtype, 0, 4);
1355  memcpy(reqhdr.auth.credtype, protname.c_str(), protname.length());
1356 
1357  bool failed = 0;
1358  int status = kXR_authmore;
1359  int dlen = 0;
1360  char *srvans = 0;
1361  XrdClientMessage *xrsp = 0;
1362  while (status == kXR_authmore) {
1363  //
1364  // Length of the credentials buffer
1365  SetSID(reqhdr.header.streamid);
1366  reqhdr.header.requestid = kXP_auth;
1367  reqhdr.header.dlen = (credentials) ? credentials->size : 0;
1368  char *credbuf = (credentials) ? credentials->buffer : 0;
1369  xrsp = SendReq(&reqhdr, credbuf, &srvans, "XrdProofConn::Authenticate");
1370  SafeDel(credentials);
1371  status = (xrsp) ? xrsp->HeaderStatus() : kXR_error;
1372  dlen = (xrsp) ? xrsp->DataLen() : 0;
1373  TRACE(HDBG, "server reply: status: "<<status<<" dlen: "<<dlen);
1374 
1375  if (xrsp && (status == kXR_authmore)) {
1376  //
1377  // We are required to send additional information
1378  // First assign the security token that we have received
1379  // at the login request
1380  secToken = new XrdSecParameters(srvans, dlen);
1381  //
1382  // then get next part of the credentials
1383  credentials = protocol->getCredentials(secToken, &ei);
1384  SafeDel(secToken); // nb: srvans is released here
1385  srvans = 0;
1386  if (!credentials) {
1387  TRACE(XERR, "cannot obtain credentials");
1388  // Set error, in case of need
1389  fLastErr = kXR_NotAuthorized;
1390  if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
1391  fLastErrMsg += "cannot obtain credentials: ";
1392  fLastErrMsg += ei.getErrText();
1393  protocol->Delete();
1394  protocol = 0;
1395  // Server does not implement yet full cycling, so we are
1396  // allowed to try the handshake only for one protocol; we
1397  // cleanup the message and fail;
1398  SafeDel(xrsp);
1399  failed = 1;
1400  break;
1401  } else {
1402  TRACE(HDBG, "credentials size " << credentials->size);
1403  }
1404  } else if (status != kXR_ok) {
1405  // Unexpected reply; print error msg, if any
1406  if (GetLastErr())
1407  TRACE(XERR, fHost << ": "<< GetLastErr());
1408  if (protocol) {
1409  protocol->Delete();
1410  protocol = 0;
1411  }
1412  }
1413  // Cleanup message
1414  SafeDel(xrsp);
1415  }
1416 
1417  // If we are done
1418  if (protocol) {
1419  fLastErr = kXR_noErrorYet;
1420  fLastErrMsg = "";
1421  break;
1422  }
1423  // Server does not implement yet full cycling, so we are
1424  // allowed to try the handshake only for one protocol; we
1425  if (failed) break;
1426  }
1427  if (!protocol) {
1428  TRACE(XERR, "unable to get protocol object.");
1429  // Set error, in case of need
1430  fLastErr = kXR_NotAuthorized;
1431  if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
1432  fLastErrMsg += "unable to get protocol object.";
1433  TRACE(XERR, fLastErrMsg.c_str());
1434  }
1435 
1436  // Return the result of the negotiation
1437  //
1438  return protocol;
1439 }
1440 
1441 ////////////////////////////////////////////////////////////////////////////////
1442 /// Interrupt the underlying socket
1443 
1445 {
1446  if (fPhyConn)
1448 }
1449 
1450 ////////////////////////////////////////////////////////////////////////////////
1451 /// Interrupt connection attempts
1452 
1454 {
1456  fConnectInterrupt = 1;
1457 }
1458 
1459 ////////////////////////////////////////////////////////////////////////////////
1460 /// Check if interrupted during connect
1461 
1463 {
1464  bool rc = 0;
1466  rc = fConnectInterrupt;
1467  // Reset the interrupt
1468  fConnectInterrupt = 0;
1469  }
1470  // Done
1471  return rc;
1472 }
1473 
1474 ////////////////////////////////////////////////////////////////////////////////
1475 /// Test validity of this connection
1476 
1478 {
1479  if (fConnected)
1480  if (fPhyConn && fPhyConn->IsValid())
1481  return 1;
1482  // Invalid
1483  return 0;
1484 }
1485 
virtual bool GetAccessToSrv(XrdClientPhyConnection *p=0)
Gets access to the connected server.
virtual ~XrdProofConn()
Destructor.
#define XrdSysLogger
Definition: XpdSysLogger.h:8
#define SafeDel(x)
Definition: XrdProofdAux.h:335
void TakeUrl(XrdOucString url)
kXR_unt16 fStreamid
Definition: XrdProofConn.h:73
#define TRACING(x)
int GetServType() const
Definition: XrdProofConn.h:143
virtual XrdClientMessage * ReadMsg()
Pickup message from the queue.
int GetLogConnID() const
Definition: XrdProofConn.h:140
virtual void Connect(int=-1)
Run the connection attempts: the result is stored in fConnected.
void SetLogged(ELoginState status)
static int fgTimeWait
Definition: XrdProofConn.h:107
#define XrdSysRecMutex
Definition: XrdSysToOuc.h:18
bool ConnectInterrupt()
Check if interrupted during connect.
static void SetRetryParam(int maxtry=5, int timewait=2)
Change values of the retry control parameters, numer of retries and wait time between attempts (in se...
#define TRACE(Flag, Args)
Definition: TGHtml.h:124
XrdClientMessage * SendReq(XPClientRequest *req, const void *reqData, char **answData, const char *CmdName, bool notifyerr=1)
SendReq tries to send a single command for a number of times.
XrdOucString fLoginBuffer
Definition: XrdProofConn.h:86
ServerResponseHeader fHdr
char * convertRespStatusToChar(kXR_int16 status)
void SetSID(kXR_char *sid)
Set our stream id, to match against that one in the server&#39;s response.
#define NAME_DEBUG
#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...
#define malloc
Definition: civetweb.c:818
#define URLTAG
void SetInterrupt()
Interrupt the underlying socket.
#define EnvGetLong(x)
Definition: XrdClientEnv.hh:44
short fSessionID
Definition: XrdProofConn.h:78
#define XPDPRT(x)
struct ClientRequestHdr header
virtual int WriteRaw(const void *buf, int len, XrdClientPhyConnection *p=0)
Low level write call.
bool MatchStreamID(struct ServerResponseHeader *resp)
Check stream ID matching.
XrdClientMessage * SendRecv(XPClientRequest *req, const void *reqData, char **answData)
SendRecv sends a command to the server and to get a response.
static XrdClientConnectionMgr * fgConnMgr
Definition: XrdProofConn.h:104
const char * GetLastErr()
Definition: XrdProofConn.h:146
XrdSysRecMutex * fMutex
Definition: XrdProofConn.h:88
char * pw_name
Definition: TWinNTSystem.h:50
int(* XrdProofConnSender_t)(const char *, int, void *)
Definition: XrdProofConn.h:56
#define realloc
Definition: civetweb.c:820
int fRemoteProtocol
Definition: XrdProofConn.h:74
bool Login()
This method perform the loggin-in into the server just after the hand-shake.
XrdProofConnSender_t fSender
Definition: XrdProofConn.h:99
int ReadRaw(void *buffer, int BufferLength, int substreamid=-1, int *usedsubstreamid=0)
virtual int TryConnect(int=-1)
Connect to remote server.
struct XPClientSendRcvRequest sendrcv
#define XPDLOC(d, x)
XrdSecProtocol * Authenticate(char *plist, int lsiz)
Negotiate authentication with the remote server.
XrdSysRecMutex * fConnectInterruptMtx
Definition: XrdProofConn.h:90
bool CheckErrorStatus(XrdClientMessage *, int &, const char *, bool)
Check error status.
virtual bool Init(const char *url=0, int=-1)
Initialization.
UnsolRespProcResult
static XrdSysPlugin * fgSecPlugin
Definition: XrdProofConn.h:109
ELoginState IsLogged()
static int fgMaxTry
Definition: XrdProofConn.h:106
#define XrdSysMutexHelper
Definition: XrdSysToOuc.h:17
#define XrdSysError
Definition: XpdSysError.h:8
#define XrdSysPlugin
Definition: XpdSysPlugin.h:8
TMarker * m
Definition: textangle.C:8
void smartPrintServerHeader(struct ServerResponseHeader *hdr)
bool fConnectInterrupt
Definition: XrdProofConn.h:91
int clientMarshall(XPClientRequest *str)
This function applies the network byte order on those parts of the 16-bytes buffer, only if it is composed by some binary part Return 0 if OK, -1 in case the ID is unknown.
void SetConnectInterrupt()
Interrupt connection attempts.
XrdOucString Passwd
struct ClientAuthRequest auth
bool CheckResp(struct ServerResponseHeader *resp, const char *met, bool)
Checks if the server&#39;s response is ours.
XrdOucString fUser
Definition: XrdProofConn.h:79
XrdClientUrlInfo fUrl
Definition: XrdProofConn.h:102
XrdOucString GetUrl()
int WriteRaw(int LogConnectionID, const void *buffer, int BufferLength, int substreamid)
static void GetRetryParam(int &maxtry, int &timewait)
Retrieve current values of the retry control parameters, numer of retries and wait time between attem...
int GetLowSocket()
Return the socket descriptor of the underlying connection.
XrdProofConn(const char *url, char mode='M', int psid=-1, char ver=-1, XrdClientAbsUnsolMsgHandler *uh=0, const char *logbuf=0)
Constructor.
XrdOucString fHost
Definition: XrdProofConn.h:80
#define NAME_CONNECTTIMEOUT
int type
Definition: TGX11.cxx:120
#define free
Definition: civetweb.c:821
virtual void Close(const char *opt="")
Close connection.
XrdClientPhyConnection * fPhyConn
Definition: XrdProofConn.h:93
XrdOucString fLastErrMsg
Definition: XrdProofConn.h:82
virtual void SetAsync(XrdClientAbsUnsolMsgHandler *uh, XrdProofConnSender_t=0, void *=0)
Set handler of unsolicited responses.
void SetSecProtocol(XrdSecProtocol *sp)
XrdClientMessage * ReadMsg(int LogConnectionID)
void ReConnect()
Perform a reconnection attempt when a connection is not valid any more.
struct XPClientLoginRequest login
XrdClientPhyConnection * GetPhyConnection()
int ReadRaw(int LogConnectionID, void *buffer, int BufferLength)
R__EXTERN C unsigned int sleep(unsigned int seconds)
void * fSenderArg
Definition: XrdProofConn.h:100
void ServerInitHandShake2HostFmt(struct ServerInitHandShake *srh)
void smartPrintClientHeader(XPClientRequest *hdr)
#define TXSOCK_ERR_TIMEOUT
char * pw_dir
Definition: TWinNTSystem.h:56
int WriteRaw(const void *buffer, int BufferLength, int substreamid=0)
XrdClientAbsUnsolMsgHandler * UnsolicitedMsgHandler
XReqErrorType LowWrite(XPClientRequest *, const void *, int)
Send request to server (NB: req is marshalled at this point, so we need also the plain reqDataLen) ...
bool IsValid() const
Test validity of this connection.
int Connect(XrdClientUrlInfo RemoteAddress)
ESrvType fServerType
Definition: XrdProofConn.h:76
static void * fgSecGetProtocol
Definition: XrdProofConn.h:110
XrdClientLogConnection * GetConnection(int LogConnectionID)
void Disconnect(int LogConnectionID, bool ForcePhysicalDisc)
char name[80]
Definition: TGX11.cxx:109
double log(double)
virtual int ReadRaw(void *buf, int len, XrdClientPhyConnection *p=0)
Low level receive call.
if(line.BeginsWith("/*"))
Definition: HLFactory.cxx:443
XrdOucString HostAddr
XrdClientAbsUnsolMsgHandler * fUnsolMsgHandler
Definition: XrdProofConn.h:97
XrdSecProtocol *(* secGetProt_t)(const char *, const struct sockaddr &, const XrdSecParameters &, XrdOucErrInfo *)
virtual UnsolRespProcResult ProcessUnsolicitedMsg(XrdClientUnsolMsgSender *s, XrdClientMessage *m)
We are here if an unsolicited response comes from a logical conn The response comes in the form of an...