Logo ROOT   6.18/05
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
85typedef XrdSecProtocol *(*secGetProt_t)(const char *, const struct sockaddr &,
86 const XrdSecParameters &, XrdOucErrInfo *);
87
89
90// Retry controllers
92int XrdProofConn::fgTimeWait = 2; // seconds
93
94XrdSysPlugin *XrdProofConn::fgSecPlugin = 0; // Sec library plugin
95void *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
112XrdProofConn::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
140void 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
150void XrdProofConn::SetRetryParam(int maxtry, int timewait)
151{
152 fgMaxTry = maxtry;
153 fgTimeWait = timewait;
154}
155
156////////////////////////////////////////////////////////////////////////////////
157/// Initialization
158
159bool 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
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
422void 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
727bool 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
756bool 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
769void 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
777XReqErrorType 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
934int 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
949int 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
1264XrdSecProtocol *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 TRACE(XERR, "unable to allocate buffer for parameters");
1301 return protocol;
1302 }
1303
1304 memcpy(bpar, plist, plsiz);
1305 bpar[plsiz] = 0;
1306 XrdSecParameters Parms(bpar, plsiz + 1);
1307
1308 // We need to load the protocol getter the first time we are here
1309 if (!fgSecGetProtocol) {
1310 static XrdSysLogger log;
1311 static XrdSysError err(&log, "XrdProofConn_");
1312 // Initialize the security library plugin, if needed
1313 XrdOucString libsec;
1314 if (!fgSecPlugin) {
1315#if !defined(ROOT_XrdNoUtils)
1316 libsec = "libXrdSec";
1317 libsec += LT_MODULE_EXT;
1318#else
1319 libsec = "libXrdSec.so";
1320#endif
1321 fgSecPlugin = new XrdSysPlugin(&err, libsec.c_str());
1322 }
1323
1324 // Get the client protocol getter
1325 if (!(fgSecGetProtocol = fgSecPlugin->getPlugin("XrdSecGetProtocol"))) {
1326 TRACE(XERR, "unable to load XrdSecGetProtocol()");
1327 return protocol;
1328 }
1329 }
1330 //
1331 // Cycle through the security protocols accepted by the server
1332 while ((protocol = (*((secGetProt_t)fgSecGetProtocol))((char *)fUrl.Host.c_str(),
1333 (const struct sockaddr &)netaddr, Parms, 0))) {
1334 //
1335 // Protocol name
1336 XrdOucString protname = protocol->Entity.prot;
1337 //
1338 // Once we have the protocol, get the credentials
1339 XrdOucErrInfo ei;
1340 credentials = protocol->getCredentials(0, &ei);
1341 if (!credentials) {
1342 TRACE(XERR, "cannot obtain credentials (protocol: "<<protname<<")");
1343 // Set error, in case of need
1344 fLastErr = kXR_NotAuthorized;
1345 if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
1346 fLastErrMsg += "cannot obtain credentials for protocol: ";
1347 fLastErrMsg += ei.getErrText();
1348 protocol->Delete();
1349 protocol = 0;
1350 continue;
1351 } else {
1352 TRACE(HDBG, "credentials size: " << credentials->size);
1353 }
1354 //
1355 // We fill the header struct containing the request for login
1356 XPClientRequest reqhdr;
1357 memset(reqhdr.auth.reserved, 0, 12);
1358 memset(reqhdr.auth.credtype, 0, 4);
1359 memcpy(reqhdr.auth.credtype, protname.c_str(), protname.length());
1360
1361 bool failed = 0;
1362 int status = kXR_authmore;
1363 int dlen = 0;
1364 char *srvans = 0;
1365 XrdClientMessage *xrsp = 0;
1366 while (status == kXR_authmore) {
1367 //
1368 // Length of the credentials buffer
1369 SetSID(reqhdr.header.streamid);
1370 reqhdr.header.requestid = kXP_auth;
1371 reqhdr.header.dlen = (credentials) ? credentials->size : 0;
1372 char *credbuf = (credentials) ? credentials->buffer : 0;
1373 xrsp = SendReq(&reqhdr, credbuf, &srvans, "XrdProofConn::Authenticate");
1374 SafeDel(credentials);
1375 status = (xrsp) ? xrsp->HeaderStatus() : kXR_error;
1376 dlen = (xrsp) ? xrsp->DataLen() : 0;
1377 TRACE(HDBG, "server reply: status: "<<status<<" dlen: "<<dlen);
1378
1379 if (xrsp && (status == kXR_authmore)) {
1380 //
1381 // We are required to send additional information
1382 // First assign the security token that we have received
1383 // at the login request
1384 secToken = new XrdSecParameters(srvans, dlen);
1385 //
1386 // then get next part of the credentials
1387 credentials = protocol->getCredentials(secToken, &ei);
1388 SafeDel(secToken); // nb: srvans is released here
1389 srvans = 0;
1390 if (!credentials) {
1391 TRACE(XERR, "cannot obtain credentials");
1392 // Set error, in case of need
1393 fLastErr = kXR_NotAuthorized;
1394 if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
1395 fLastErrMsg += "cannot obtain credentials: ";
1396 fLastErrMsg += ei.getErrText();
1397 protocol->Delete();
1398 protocol = 0;
1399 // Server does not implement yet full cycling, so we are
1400 // allowed to try the handshake only for one protocol; we
1401 // cleanup the message and fail;
1402 SafeDel(xrsp);
1403 failed = 1;
1404 break;
1405 } else {
1406 TRACE(HDBG, "credentials size " << credentials->size);
1407 }
1408 } else if (status != kXR_ok) {
1409 // Unexpected reply; print error msg, if any
1410 if (GetLastErr())
1411 TRACE(XERR, fHost << ": "<< GetLastErr());
1412 if (protocol) {
1413 protocol->Delete();
1414 protocol = 0;
1415 }
1416 }
1417 // Cleanup message
1418 SafeDel(xrsp);
1419 }
1420
1421 // If we are done
1422 if (protocol) {
1423 fLastErr = kXR_noErrorYet;
1424 fLastErrMsg = "";
1425 break;
1426 }
1427 // Server does not implement yet full cycling, so we are
1428 // allowed to try the handshake only for one protocol; we
1429 if (failed) break;
1430 }
1431 if (!protocol) {
1432 TRACE(XERR, "unable to get protocol object.");
1433 // Set error, in case of need
1434 fLastErr = kXR_NotAuthorized;
1435 if (fLastErrMsg.length() > 0) fLastErrMsg += ":";
1436 fLastErrMsg += "unable to get protocol object.";
1437 TRACE(XERR, fLastErrMsg.c_str());
1438 }
1439
1440 // Return the result of the negotiation
1441 //
1442 return protocol;
1443}
1444
1445////////////////////////////////////////////////////////////////////////////////
1446/// Interrupt the underlying socket
1447
1449{
1450 if (fPhyConn)
1452}
1453
1454////////////////////////////////////////////////////////////////////////////////
1455/// Interrupt connection attempts
1456
1458{
1461}
1462
1463////////////////////////////////////////////////////////////////////////////////
1464/// Check if interrupted during connect
1465
1467{
1468 bool rc = 0;
1470 rc = fConnectInterrupt;
1471 // Reset the interrupt
1473 }
1474 // Done
1475 return rc;
1476}
1477
1478////////////////////////////////////////////////////////////////////////////////
1479/// Test validity of this connection
1480
1482{
1483 if (fConnected)
1484 if (fPhyConn && fPhyConn->IsValid())
1485 return 1;
1486 // Invalid
1487 return 0;
1488}
1489
#define TRACE(Flag, Args)
Definition: TGHtml.h:120
char name[80]
Definition: TGX11.cxx:109
int type
Definition: TGX11.cxx:120
double log(double)
R__EXTERN C unsigned int sleep(unsigned int seconds)
@ kXP_auth
@ kXP_login
@ kXP_reconnecting
@ kXPD_srvmsg
#define XrdSysError
Definition: XpdSysError.h:8
#define XrdSysLogger
Definition: XpdSysLogger.h:8
#define XrdSysPlugin
Definition: XpdSysPlugin.h:8
#define NAME_CONNECTTIMEOUT
#define NAME_DEBUG
#define TXSOCK_ERR_TIMEOUT
#define NAME_FIRSTCONNECTMAXCNT
#define EnvGetLong(x)
Definition: XrdClientEnv.hh:44
UnsolRespProcResult
@ kUNSOL_KEEP
XrdSecProtocol *(* secGetProt_t)(const char *, const struct sockaddr &, const XrdSecParameters &, XrdOucErrInfo *)
#define URLTAG
int(* XrdProofConnSender_t)(const char *, int, void *)
Definition: XrdProofConn.h:46
#define SafeDel(x)
Definition: XrdProofdAux.h:332
#define XPDPRT(x)
#define XPDLOC(d, x)
#define TRACING(x)
#define XrdSysMutexHelper
Definition: XrdSysToOuc.h:17
#define XrdSysRecMutex
Definition: XrdSysToOuc.h:18
#define realloc
Definition: civetweb.c:1538
#define free
Definition: civetweb.c:1539
#define malloc
Definition: civetweb.c:1536
int Connect(XrdClientUrlInfo RemoteAddress)
XrdClientMessage * ReadMsg(int LogConnectionID)
int WriteRaw(int LogConnectionID, const void *buffer, int BufferLength, int substreamid)
void Disconnect(int LogConnectionID, bool ForcePhysicalDisc)
int ReadRaw(int LogConnectionID, void *buffer, int BufferLength)
XrdClientLogConnection * GetConnection(int LogConnectionID)
XrdClientPhyConnection * GetPhyConnection()
ServerResponseHeader fHdr
int ReadRaw(void *buffer, int BufferLength, int substreamid=-1, int *usedsubstreamid=0)
int WriteRaw(const void *buffer, int BufferLength, int substreamid=0)
ELoginState IsLogged()
void SetLogged(ELoginState status)
void SetSecProtocol(XrdSecProtocol *sp)
XrdClientAbsUnsolMsgHandler * UnsolicitedMsgHandler
void TakeUrl(XrdOucString url)
XrdOucString HostAddr
XrdOucString Passwd
XrdOucString GetUrl()
ESrvType DoHandShake(XrdClientPhyConnection *p=0)
Performs initial hand-shake with the server in order to understand which kind of server is there at t...
virtual int TryConnect(int=-1)
Connect to remote server.
static void GetRetryParam(int &maxtry, int &timewait)
Retrieve current values of the retry control parameters, numer of retries and wait time between attem...
static int fgTimeWait
Definition: XrdProofConn.h:97
XrdClientPhyConnection * fPhyConn
Definition: XrdProofConn.h:83
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.
ESrvType fServerType
Definition: XrdProofConn.h:66
static void * fgSecGetProtocol
Definition: XrdProofConn.h:100
virtual bool Init(const char *url=0, int=-1)
Initialization.
int fRemoteProtocol
Definition: XrdProofConn.h:64
static int fgMaxTry
Definition: XrdProofConn.h:96
XrdSecProtocol * Authenticate(char *plist, int lsiz)
Negotiate authentication with the remote server.
bool ConnectInterrupt()
Check if interrupted during connect.
bool CheckErrorStatus(XrdClientMessage *, int &, const char *, bool)
Check error status.
virtual void SetAsync(XrdClientAbsUnsolMsgHandler *uh, XrdProofConnSender_t=0, void *=0)
Set handler of unsolicited responses.
XrdProofConnSender_t fSender
Definition: XrdProofConn.h:89
virtual bool GetAccessToSrv(XrdClientPhyConnection *p=0)
Gets access to the connected server.
bool MatchStreamID(struct ServerResponseHeader *resp)
Check stream ID matching.
int GetLogConnID() const
Definition: XrdProofConn.h:130
short fSessionID
Definition: XrdProofConn.h:68
XrdClientAbsUnsolMsgHandler * fUnsolMsgHandler
Definition: XrdProofConn.h:87
XErrorCode fLastErr
Definition: XrdProofConn.h:73
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...
XrdSysRecMutex * fMutex
Definition: XrdProofConn.h:78
bool IsValid() const
Test validity of this connection.
virtual int WriteRaw(const void *buf, int len, XrdClientPhyConnection *p=0)
Low level write call.
bool CheckResp(struct ServerResponseHeader *resp, const char *met, bool)
Checks if the server's response is ours.
virtual void Close(const char *opt="")
Close connection.
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:94
XrdClientUrlInfo fUrl
Definition: XrdProofConn.h:92
kXR_unt16 fStreamid
Definition: XrdProofConn.h:63
virtual ~XrdProofConn()
Destructor.
virtual XrdClientMessage * ReadMsg()
Pickup message from the queue.
void SetSID(kXR_char *sid)
Set our stream id, to match against that one in the server's response.
XrdOucString fUser
Definition: XrdProofConn.h:69
XrdOucString fLastErrMsg
Definition: XrdProofConn.h:72
XReqErrorType LowWrite(XPClientRequest *, const void *, int)
Send request to server (NB: req is marshalled at this point, so we need also the plain reqDataLen)
const char * GetLastErr()
Definition: XrdProofConn.h:136
void * fSenderArg
Definition: XrdProofConn.h:90
virtual void Connect(int=-1)
Run the connection attempts: the result is stored in fConnected.
XrdOucString fLoginBuffer
Definition: XrdProofConn.h:76
static XrdSysPlugin * fgSecPlugin
Definition: XrdProofConn.h:99
XrdSysRecMutex * fConnectInterruptMtx
Definition: XrdProofConn.h:80
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.
bool Login()
This method perform the loggin-in into the server just after the hand-shake.
void ReConnect()
Perform a reconnection attempt when a connection is not valid any more.
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...
virtual int ReadRaw(void *buf, int len, XrdClientPhyConnection *p=0)
Low level receive call.
int GetServType() const
Definition: XrdProofConn.h:133
bool fConnectInterrupt
Definition: XrdProofConn.h:81
XrdOucString fHost
Definition: XrdProofConn.h:70
void SetInterrupt()
Interrupt the underlying socket.
void SetConnectInterrupt()
Interrupt connection attempts.
static constexpr double s
void smartPrintClientHeader(XPClientRequest *hdr)
char * convertRespStatusToChar(kXR_int16 status)
void ServerInitHandShake2HostFmt(struct ServerInitHandShake *srh)
void smartPrintServerHeader(struct ServerResponseHeader *hdr)
int clientMarshall(XPClientRequest *str)
This function applies the network byte order on those parts of the 16-bytes buffer,...
char * pw_name
Definition: TWinNTSystem.h:48
char * pw_dir
Definition: TWinNTSystem.h:54
auto * m
Definition: textangle.C:8
struct XPClientLoginRequest login
struct ClientRequestHdr header
struct ClientAuthRequest auth
struct XPClientSendRcvRequest sendrcv