XRootD
XrdXrootdProtocol.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d X r o o t d P r o t o c o l . c c */
4 /* */
5 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <poll.h>
31 
32 #include "XrdVersion.hh"
33 
34 #include "XProtocol/XProtocol.hh"
35 
36 #include "Xrd/XrdBuffer.hh"
37 #include "Xrd/XrdLink.hh"
38 #include "XrdNet/XrdNetIF.hh"
39 #include "XrdOuc/XrdOucEnv.hh"
40 #include "XrdOuc/XrdOucUtils.hh"
41 #include "XrdOuc/XrdOucStream.hh"
42 #include "XrdOuc/XrdOucString.hh"
43 #include "XrdOuc/XrdOucUtils.hh"
44 #include "XrdSec/XrdSecProtect.hh"
45 #include "XrdSfs/XrdSfsFlags.hh"
47 #include "XrdSys/XrdSysAtomics.hh"
48 #include "XrdSys/XrdSysTimer.hh"
49 #include "XrdTls/XrdTls.hh"
61 
62 /******************************************************************************/
63 /* G l o b a l s */
64 /******************************************************************************/
65 
66 namespace XrdXrootd
67 {
68 XrdSysError eLog(0, "Xrootd");
72 }
73 
75 
76 /******************************************************************************/
77 /* S t a t i c M e m b e r s */
78 /******************************************************************************/
79 
100 
101 char *XrdXrootdProtocol::Notify = 0;
102 const char *XrdXrootdProtocol::myCName= 0;
109 int XrdXrootdProtocol::redirIPHold = 8*60*60; // 8 Hours
114 
115 int XrdXrootdProtocol::hcMax = 28657; // const for now
117 int XrdXrootdProtocol::maxTransz = 262144; // 256KB
120 int XrdXrootdProtocol::as_maxperlnk = 8; // Max ops per link
121 int XrdXrootdProtocol::as_maxperreq = 8; // Max ops per request
122 int XrdXrootdProtocol::as_maxpersrv = 4096;// Max ops per server
126 #ifdef __solaris__
128 #else
130 #endif
132 short XrdXrootdProtocol::as_okstutter = 1; // For 64K unit
134 bool XrdXrootdProtocol::as_force = false;
135 bool XrdXrootdProtocol::as_aioOK = true;
136 bool XrdXrootdProtocol::as_nosf = false;
137 bool XrdXrootdProtocol::as_syncw = false;
138 
139 const char *XrdXrootdProtocol::myInst = 0;
140 const char *XrdXrootdProtocol::TraceID = "Protocol";
142 int XrdXrootdProtocol::myPID = static_cast<int>(getpid());
143 
146 
147 gid_t XrdXrootdProtocol::myGID = 0;
148 uid_t XrdXrootdProtocol::myUID = 0;
151 const char *XrdXrootdProtocol::myGName= "?";
152 const char *XrdXrootdProtocol::myUName= "?";
153 time_t XrdXrootdProtocol::keepT = 86400; // 24 hours
154 
156 bool XrdXrootdProtocol::PrepareAlt = false;
158 
162 bool XrdXrootdProtocol::OD_Bypass= false;
163 bool XrdXrootdProtocol::OD_Redir = false;
164 
165 bool XrdXrootdProtocol::CL_Redir = false;
166 
167 bool XrdXrootdProtocol::isProxy = false;
168 
172 
175 
177 
178 /******************************************************************************/
179 /* P r o t o c o l M a n a g e m e n t S t a c k s */
180 /******************************************************************************/
181 
183  XrdXrootdProtocol::ProtStack("ProtStack",
184  "xroot protocol anchor");
185 
186 /******************************************************************************/
187 /* P r o t o c o l L o a d e r */
188 /* X r d g e t P r o t o c o l */
189 /******************************************************************************/
190 
191 // This protocol can live in a shared library. The interface below is used by
192 // the protocol driver to obtain a copy of the protocol object that can be used
193 // to decide whether or not a link is talking a particular protocol.
194 //
196 
197 extern "C"
198 {
199 XrdProtocol *XrdgetProtocol(const char *pname, char *parms,
200  XrdProtocol_Config *pi)
201 {
202  XrdProtocol *pp = 0;
203  const char *txt = "completed.";
204 
205 // Put up the banner
206 //
207  pi->eDest->Say("Copr. 2012 Stanford University, xroot protocol "
208  kXR_PROTOCOLVSTRING, " version ", XrdVERSION);
209  pi->eDest->Say("++++++ xroot protocol initialization started.");
210 
211 // Return the protocol object to be used if static init succeeds
212 //
213  if (XrdXrootdProtocol::Configure(parms, pi))
214  pp = (XrdProtocol *)new XrdXrootdProtocol();
215  else txt = "failed.";
216  pi->eDest->Say("------ xroot protocol initialization ", txt);
217  return pp;
218 }
219 }
220 
221 /******************************************************************************/
222 /* P r o t o c o l P o r t D e t e r m i n a t i o n */
223 /* X r d g e t P r o t o c o l P o r t */
224 /******************************************************************************/
225 
226 // This function is called early on to determine the port we need to use. The
227 // default is ostensibly 1094 but can be overridden; which we allow.
228 //
230 
231 extern "C"
232 {
233 int XrdgetProtocolPort(const char *pname, char *parms, XrdProtocol_Config *pi)
234 {
235 
236 // Figure out what port number we should return. In practice only one port
237 // number is allowed. However, we could potentially have a clustered port
238 // and several unclustered ports. So, we let this practicality slide.
239 //
240  if (pi->Port < 0) return 1094;
241  return pi->Port;
242 }
243 }
244 
245 /******************************************************************************/
246 /* X r d P r o t o c o l X r o o t d C l a s s */
247 /******************************************************************************/
248 
249 namespace
250 {
253 }
254 
255 /******************************************************************************/
256 /* C o n s t r u c t o r */
257 /******************************************************************************/
258 
260  : XrdProtocol("xroot protocol handler"),
261  XrdSfsXio(SfsXioImpl),
262  ProtLink(this), Entity(0), AppName(0)
263 {
264  Reset();
265 }
266 
267 /******************************************************************************/
268 /* protected: g e t S I D */
269 /******************************************************************************/
270 
272 {
273  static XrdSysMutex SidMutex;
274  static unsigned int Sid = 1;
275  unsigned int theSid;
276 
277 // Generate unqiue number for this server instance
278 //
279  AtomicBeg(SidMutex);
280  theSid = AtomicInc(Sid);
281  AtomicEnd(SidMutex);
282  return theSid;
283 }
284 
285 /******************************************************************************/
286 /* M a t c h */
287 /******************************************************************************/
288 
289 #define TRACELINK lp
290 
292 {
293 static const int hsSZ = sizeof(ClientInitHandShake);
294  char hsbuff[hsSZ];
295  struct ClientInitHandShake *hsData = (ClientInitHandShake *)hsbuff;
296 
297 static struct hs_response
298  {kXR_unt16 streamid;
299  kXR_unt16 status;
300  kXR_unt32 rlen; // Specified as kXR_int32 in doc!
301  kXR_unt32 pval; // Specified as kXR_int32 in doc!
302  kXR_unt32 styp; // Specified as kXR_int32 in doc!
303  } hsresp={0, 0, htonl(8), htonl(kXR_PROTOCOLVERSION),
304  (isRedir ? htonl((unsigned int)kXR_LBalServer)
305  : htonl((unsigned int)kXR_DataServer))};
307 int dlen, rc;
308 
309 // Peek at the first 20 bytes of data
310 //
311  if ((dlen = lp->Peek(hsbuff, hsSZ, hailWait)) < hsSZ)
312  {if (dlen <= 0) lp->setEtext("handshake not received");
313  return (XrdProtocol *)0;
314  }
315 
316 // Trace the data
317 //
318 // TRACEI(REQ, "received: " <<Trace->bin2hex(hsbuff,dlen));
319 
320 // Verify that this is our protocol
321 //
322  hsData->fourth = ntohl(hsData->fourth);
323  hsData->fifth = ntohl(hsData->fifth);
324  if (hsData->first || hsData->second || hsData->third
325  || hsData->fourth != 4 || hsData->fifth != ROOTD_PQ) return 0;
326 
327 // Send the handshake response. We used optimize the subsequent protocol
328 // request sent with handshake but the protocol request is now overloaded.
329 //
330  rc = lp->Send((char *)&hsresp, sizeof(hsresp));
331 
332 // Verify that our handshake response was actually sent
333 //
334  if (!rc)
335  {lp->setEtext("handshake failed");
336  return (XrdProtocol *)0;
337  }
338 
339 // We can now read all 20 bytes and discard them (no need to wait for it)
340 //
341  if (lp->Recv(hsbuff, hsSZ) != hsSZ)
342  {lp->setEtext("reread failed");
343  return (XrdProtocol *)0;
344  }
345 
346 // Get a protocol object off the stack (if none, allocate a new one)
347 //
348  if (!(xp = ProtStack.Pop())) xp = new XrdXrootdProtocol();
349 
350 // Bind the protocol to the link and return the protocol
351 //
352  SI->Bump(SI->Count);
353  xp->Link = lp;
354  xp->Response.Set(lp);
355  strcpy(xp->Entity.prot, "host");
356  xp->Entity.host = (char *)lp->Host();
357  xp->Entity.addrInfo = lp->AddrInfo();
358  return (XrdProtocol *)xp;
359 }
360 
361 /******************************************************************************/
362 /* P r o c e s s */
363 /******************************************************************************/
364 
365 #undef TRACELINK
366 #define TRACELINK Link
367 
368 int XrdXrootdProtocol::Process(XrdLink *lp) // We ignore the argument here
369 {
370  int rc;
371  kXR_unt16 reqID;
372 
373 // Check if we are servicing a slow link
374 //
375  if (Resume)
376  {if (myBlen && (rc = getData("data", myBuff, myBlen)) != 0) return rc;
377  else if ((rc = (*this.*Resume)()) != 0) return rc;
378  else {Resume = 0; return 0;}
379  }
380 
381 // Read the next request header
382 //
383  if ((rc=getData("request",(char *)&Request,sizeof(Request))) != 0) return rc;
384 
385 // Check if we need to copy the request prior to unmarshalling it
386 //
387  reqID = ntohs(Request.header.requestid);
388  if (reqID != kXR_sigver && NEED2SECURE(Protect)(Request))
389  {memcpy(&sigReq2Ver, &Request, sizeof(ClientRequest));
390  sigNeed = true;
391  }
392 
393 // Deserialize the data
394 //
395  Request.header.requestid = reqID;
398  TRACEP(REQ, "req=" <<XProtocol::reqName(reqID)
399  <<" dlen=" <<Request.header.dlen);
400 
401 // Every request has an associated data length. It better be >= 0 or we won't
402 // be able to know how much data to read.
403 //
404  if (Request.header.dlen < 0)
405  {Response.Send(kXR_ArgInvalid, "Invalid request data length");
406  return Link->setEtext("protocol data length error");
407  }
408 
409 // Process sigver requests now as they appear ahead of a request
410 //
411  if (reqID == kXR_sigver) return ProcSig();
412 
413 // Read any argument data at this point, except when the request is a write.
414 // The argument may have to be segmented and we're not prepared to do that here.
415 //
416  if (reqID != kXR_write && reqID != kXR_pgwrite && Request.header.dlen)
417  {if (!argp || Request.header.dlen+1 > argp->bsize)
418  {if (argp) BPool->Release(argp);
419  if (!(argp = BPool->Obtain(Request.header.dlen+1)))
420  {Response.Send(kXR_ArgTooLong, "Request argument is too long");
421  return 0;
422  }
423  hcNow = hcPrev; halfBSize = argp->bsize >> 1;
424  }
425  argp->buff[Request.header.dlen] = '\0';
426  if ((rc = getData("arg", argp->buff, Request.header.dlen)))
427  {Resume = &XrdXrootdProtocol::Process2; return rc;}
428  }
429 
430 // Continue with request processing at the resume point
431 //
432  return Process2();
433 }
434 
435 /******************************************************************************/
436 /* p r i v a t e P r o c e s s 2 */
437 /******************************************************************************/
438 
440 {
441 // If we are verifying requests, see if this request needs to be verified
442 //
443  if (sigNeed)
444  {const char *eText = "Request not signed";
445  if (!sigHere || (eText = Protect->Verify(sigReq,sigReq2Ver,argp->buff)))
446  {Response.Send(kXR_SigVerErr, eText);
448  <<" verification failed; " <<eText);
449  SI->Bump(SI->badSCnt);
450  return Link->setEtext(eText);
451  } else {
452  SI->Bump(SI->aokSCnt);
453  sigNeed = sigHere = false;
454  }
455  } else {
456  if (sigHere)
458  <<" unneeded signature discarded.");
459  if (sigWarn)
460  {eDest.Emsg("Protocol","Client is needlessly signing requests.");
461  sigWarn = false;
462  }
463  SI->Bump(SI->ignSCnt);
464  sigHere = false;
465  }
466  }
467 
468 // If the user is not yet logged in, restrict what the user can do
469 //
470  if (!Status)
471  switch(Request.header.requestid)
472  {case kXR_login: return do_Login();
473  case kXR_protocol: return do_Protocol();
474  case kXR_bind: return do_Bind();
476  "Invalid request; user not logged in");
477  return Link->setEtext("request without login");
478  }
479 
480 // Help the compiler, select the the high activity requests (the ones with
481 // file handles) in a separate switch statement. A special case exists for
482 // sync() which return with a callback, so handle it here. Note that stat(fh)
483 // normally never does a callback but historically we allowed it to do so.
484 // We maintain that capability even when it's likely never used.
485 //
486  switch(Request.header.requestid) // First, the ones with file handles
487  {case kXR_read: return do_Read();
488  case kXR_readv: return do_ReadV();
489  case kXR_write: return do_Write();
490  case kXR_writev: return do_WriteV();
491  case kXR_pgread: return do_PgRead();
492  case kXR_pgwrite: return do_PgWrite();
494  return do_Sync();
496  return do_Close();
497  case kXR_stat: if (!Request.header.dlen)
499  return do_Stat();
500  }
501  break;
503  if (!Request.header.dlen) return do_Truncate();
504  break;
505  case kXR_query: if (!Request.header.dlen) return do_Qfh();
506  break;
507  case kXR_chkpoint: return do_ChkPnt();
508  case kXR_clone: return do_Clone();
509  default: break;
510  }
511 
512 // Now select the requests that do not need authentication
513 //
514  switch(Request.header.requestid)
515  {case kXR_protocol: return do_Protocol(); // dlen ignored
516  case kXR_ping: return do_Ping(); // dlen ignored
517  default: break;
518  }
519 
520 // Force authentication at this point, if need be
521 //
522  if (Status & XRD_NEED_AUTH)
523  {int rc;
524  if (Request.header.requestid == kXR_auth) rc = do_Auth();
526  "Invalid request; user not authenticated");
527  rc = -1;
528  }
530  return rc;
531  }
532 
533 // Construct request ID as the following functions are async eligible
534 //
536 
537 // Process items that don't need arguments but may have them
538 //
539  switch(Request.header.requestid)
540  {case kXR_endsess: return do_Endsess();
541  default: break;
542  }
543 
544 // All remaining requests require an argument. Make sure we have one
545 //
546  if (!argp || !Request.header.dlen)
547  {Response.Send(kXR_ArgMissing, "Required argument not present");
548  return 0;
549  }
550 
551 // All of the subsequent requests can be redirected and are subject to
552 // prefunctory redirection which we check here.
553 //
554  if (CL_Redir && !Link->hasBridge())
555  {bool doRdr = false;
556  if (Link->AddrInfo()->isPrivate()) rdType = 1;
557  if (RouteClient.pvtIP && rdType) doRdr = true;
559  doRdr = true;
560  else if (RouteClient.DomCnt)
561  {XrdOucString hName = Link->Host();
562  for (int i = 0; i < RouteClient.DomCnt; i++)
563  {if (hName.endswith(RouteClient.Domain[i]))
564  {doRdr = true; break;}
565  }
566  }
567  if (doRdr)
568  {Response.Send(kXR_redirect,Route[RD_client].Port[rdType],
569  Route[RD_client].Host[rdType]);
570  return -1;
571  }
572  }
573 
574 // Process items that keep own statistics
575 //
576  switch(Request.header.requestid)
577  {case kXR_open: return do_Open();
578  case kXR_gpfile: return do_gpFile();
579  default: break;
580  }
581 
582 // Update misc stats count
583 //
584  SI->Bump(SI->miscCnt);
585 
586 // Now process whatever we have
587 //
588  switch(Request.header.requestid)
589  {case kXR_chmod: return do_Chmod();
590  case kXR_dirlist: return do_Dirlist();
591  case kXR_fattr: return do_FAttr();
592  case kXR_locate: return do_Locate();
593  case kXR_mkdir: return do_Mkdir();
594  case kXR_mv: return do_Mv();
595  case kXR_query: return do_Query();
596  case kXR_prepare: return do_Prepare();
597  case kXR_rm: return do_Rm();
598  case kXR_rmdir: return do_Rmdir();
599  case kXR_set: return do_Set();
600  case kXR_stat: return do_Stat();
601  case kXR_statx: return do_Statx();
602  case kXR_truncate: return do_Truncate();
603  default: break;
604  }
605 
606 // Whatever we have, it's not valid
607 //
608  Response.Send(kXR_InvalidRequest, "Invalid request code");
609  return 0;
610 }
611 
612 /******************************************************************************/
613 /* P r o c S i g */
614 /******************************************************************************/
615 
617 {
618  int rc;
619 
620 // Check if we completed reading the signature and if so, we are done
621 //
622  if (sigRead)
623  {sigRead = false;
624  sigHere = true;
625  return 0;
626  }
627 
628 // Verify that the hash is not longer that what we support and is present
629 //
630  if (Request.header.dlen <= 0
631  || Request.header.dlen > (int)sizeof(sigBuff))
632  {Response.Send(kXR_ArgInvalid, "Invalid signature data length");
633  return Link->setEtext("signature data length error");
634  }
635 
636 // Save relevant information for the next round
637 //
638  memcpy(&sigReq, &Request, sizeof(ClientSigverRequest));
639  sigReq.header.dlen = htonl(Request.header.dlen);
640 
641 // Now read in the signature
642 //
643  sigRead = true;
644  if ((rc = getData("arg", sigBuff, Request.header.dlen)))
645  {Resume = &XrdXrootdProtocol::ProcSig; return rc;}
646  sigRead = false;
647 
648 // All done
649 //
650  sigHere = true;
651  return 0;
652 }
653 
654 /******************************************************************************/
655 /* R e c y c l e */
656 /******************************************************************************/
657 
658 #undef TRACELINK
659 #define TRACELINK Link
660 
661 void XrdXrootdProtocol::Recycle(XrdLink *lp, int csec, const char *reason)
662 {
663  char *sfxp, ctbuff[24], buff[128], Flags = (reason ? XROOTD_MON_FORCED : 0);
664  const char *What;
665  XrdSysMutexHelper recycleHelper(unbindMutex);
666 
667 // Check for disconnect or unbind
668 //
669  if (Status == XRD_BOUNDPATH) {What = "unbind"; Flags |= XROOTD_MON_BOUNDP;}
670  else What = "disc";
671 
672 // Document the disconnect or undind
673 //
674  if (lp)
675  {XrdSysTimer::s2hms(csec, ctbuff, sizeof(ctbuff));
676  if (reason && strcmp(reason, "hangup"))
677  {snprintf(buff, sizeof(buff), "%s (%s)", ctbuff, reason);
678  sfxp = buff;
679  } else sfxp = ctbuff;
680 
681  eDest.Log(SYS_LOG_02, "Xeq", lp->ID, (char *)What, sfxp);
682  }
683 
684 // Handle any waiting read on this link. This is a tricky proposition because
685 // we don't know if the thread is waiting to run or not. However, we will
686 // indicate that gdFail was already called and should the thread run, it will
687 // promptly exit should it ever run again. That way, we handle the cleanup.
688 //
692 
693 // If this is a bound stream then we cannot release the resources until
694 // all activity ceases on this stream (i.e., lp == 0). This is only relevant for
695 // writes that read from the link. if we are still tagged as active and not
696 // waiting for link activity then ask to be signalled once activity stops.
697 // Otherwise, redrive the parallel I/O so that it cleans up.
698 //
699  if (lp && Status == XRD_BOUNDPATH)
700  {streamMutex.Lock();
701  isNOP = true;
702  if (isActive)
703  {if (isLinkWT)
704  {streamMutex.UnLock();
705  do_OffloadIO();
706  } else {
707  while(isActive)
708  {XrdSysCondVar2 aioDone(streamMutex);
709  endNote = &aioDone;
710  aioDone.Wait();
711  endNote = 0;
712  }
714  }
715  } else streamMutex.UnLock();
716  boundRecycle->Post();
717  if (lp) return; // Async close
718  }
719 
720 // Release all appendages
721 //
722  Cleanup();
723 
724 // If we are monitoring logins then we are also monitoring disconnects. We do
725 // this after cleanup so that close records can be generated before we cut a
726 // disconnect record. This then requires we clear the monitor object here.
727 // We and the destrcutor are the only ones who call cleanup and a deletion
728 // will call the monitor clear method. So, we won't leak memeory.
729 //
730  if (Monitor.Logins()) Monitor.Agent->Disc(Monitor.Did, csec, Flags);
732  Monitor.Clear();
733 
734 // Set fields to starting point (debugging mostly)
735 //
736  Reset();
737 
738 // Push ourselves on the stack
739 //
740  if (Response.isOurs()) ProtStack.Push(&ProtLink);
741 }
742 
743 /******************************************************************************/
744 /* S t a t G e n */
745 /******************************************************************************/
746 
747 int XrdXrootdProtocol::StatGen(struct stat &buf, char *xxBuff, int xxLen,
748  bool xtnd)
749 {
750  const mode_t isReadable = (S_IRUSR | S_IRGRP | S_IROTH);
751  const mode_t isWritable = (S_IWUSR | S_IWGRP | S_IWOTH);
752  const mode_t isExecable = (S_IXUSR | S_IXGRP | S_IXOTH);
753  uid_t theuid;
754  gid_t thegid;
755  union {long long uuid; struct {int hi; int lo;} id;} Dev;
756  long long fsz;
757  int m, n, flags = 0;
758 
759 // Get the right uid/gid
760 //
761  theuid = (Client && Client->uid ? Client->uid : myUID);
762  thegid = (Client && Client->gid ? Client->gid : myGID);
763 
764 // Compute the unique id
765 //
766  Dev.id.lo = buf.st_ino;
767  Dev.id.hi = buf.st_dev;
768 
769 // Compute correct setting of the readable flag
770 //
771  if (buf.st_mode & isReadable
772  &&((buf.st_mode & S_IRUSR && theuid == buf.st_uid)
773  || (buf.st_mode & S_IRGRP && thegid == buf.st_gid)
774  || buf.st_mode & S_IROTH)) flags |= kXR_readable;
775 
776 // Compute correct setting of the writable flag
777 //
778  if (buf.st_mode & isWritable
779  &&((buf.st_mode & S_IWUSR && theuid == buf.st_uid)
780  || (buf.st_mode & S_IWGRP && thegid == buf.st_gid)
781  || buf.st_mode & S_IWOTH)) flags |= kXR_writable;
782 
783 // Compute correct setting of the execable flag
784 //
785  if (buf.st_mode & isExecable
786  &&((buf.st_mode & S_IXUSR && theuid == buf.st_uid)
787  || (buf.st_mode & S_IXGRP && thegid == buf.st_gid)
788  || buf.st_mode & S_IXOTH)) flags |= kXR_xset;
789 
790 // Compute the other flag settings
791 //
792  if (!Dev.uuid) flags |= kXR_offline;
793  if (S_ISDIR(buf.st_mode)) flags |= kXR_isDir;
794  else if (!S_ISREG(buf.st_mode)) flags |= kXR_other;
795  else{if (buf.st_mode & XRDSFS_POSCPEND) flags |= kXR_poscpend;
796  if ((buf.st_rdev & XRDSFS_RDVMASK) == 0)
797  {if (buf.st_rdev & XRDSFS_OFFLINE) flags |= kXR_offline;
798  if (buf.st_rdev & XRDSFS_HASBKUP) flags |= kXR_bkpexist;
799  }
800  }
801  if ((fsFeatures & XrdSfs::hasCACH) != 0 && buf.st_atime != 0)
802  flags |= kXR_cachersp;
803  fsz = static_cast<long long>(buf.st_size);
804 
805 // Format the default response: <devid> <size> <flags> <mtime>
806 //
807  m = snprintf(xxBuff, xxLen, "%lld %lld %d %lld",
808  Dev.uuid, fsz, flags, (long long) buf.st_mtime);
809 // if (!xtnd || m >= xxLen) return xxLen;
810 //
811 
812 // Format extended response: <ctime> <atime> <mode>
813 //
814  char *origP = xxBuff;
815  char *nullP = xxBuff + m++;
816  xxBuff += m; xxLen -= m;
817  n = snprintf(xxBuff, xxLen, "%lld %lld %04o ",
818  (long long) buf.st_ctime, (long long) buf.st_atime,
819  buf.st_mode&07777);
820  if (n >= xxLen) return m;
821  xxBuff += n; xxLen -= n;
822 
823 // Tack on owner
824 //
825  if (buf.st_uid == myUID)
826  {if (myUNLen >= xxLen) return m;
827  strcpy(xxBuff, myUName);
828  n = myUNLen;
829  } else {
830  if (!(n = XrdOucUtils::UidName(buf.st_uid,xxBuff,xxLen,keepT))) return m;
831  }
832  xxBuff += n;
833  *xxBuff++ = ' ';
834  xxLen -= (n+1);
835 
836 // Tack on group
837 //
838  if (buf.st_gid == myGID)
839  {if (myGNLen >= xxLen) return m;
840  strcpy(xxBuff, myGName);
841  n = myGNLen;
842  } else {
843  if (!(n = XrdOucUtils::GidName(buf.st_gid,xxBuff,xxLen,keepT))) return m;
844  }
845  xxBuff += n+1;
846 
847 // All done, return full response
848 //
849  *nullP = ' ';
850  return xxBuff - origP;
851 }
852 
853 /******************************************************************************/
854 /* S t a t s */
855 /******************************************************************************/
856 
857 int XrdXrootdProtocol::Stats(char *buff, int blen, int do_sync)
858 {
859 // Synchronize statistics if need be
860 //
861  if (do_sync)
862  {SI->statsMutex.Lock();
863  SI->readCnt += numReads;
864  cumReads += numReads; numReads = 0;
865  SI->prerCnt += numReadP;
866  cumReadP += numReadP; numReadP = 0;
867 
868  SI->rvecCnt += numReadV;
869  cumReadV += numReadV; numReadV = 0;
870  SI->rsegCnt += numSegsV;
871  cumSegsV += numSegsV; numSegsV = 0;
872 
873  SI->wvecCnt += numWritV;
874  cumWritV += numWritV; numWritV = 0;
875  SI->wsegCnt += numSegsW;
876  cumSegsW += numSegsW, numSegsW = 0;
877 
878  SI->writeCnt += numWrites;
880  SI->statsMutex.UnLock();
881  }
882 
883 // Now return the statistics
884 //
885  return SI->Stats(buff, blen, do_sync);
886 }
887 
888 /******************************************************************************/
889 /* X r d S f s X i o M e t h o d s */
890 /******************************************************************************/
891 /******************************************************************************/
892 /* Static: B u f f e r */
893 /******************************************************************************/
894 
896 {
897  XrdBuffer *xbP = (XrdBuffer *)h;
898 
899  if (h)
900  {if (bsz) *bsz = xbP->bsize;
901  return xbP->buff;
902  }
903  if (bsz) *bsz = 0;
904  return 0;
905 }
906 
907 /******************************************************************************/
908 /* C l a i m */
909 /******************************************************************************/
910 
911 XrdSfsXioHandle XrdXrootdProtocol::Claim(const char *buff, int datasz,
912  int minasz)
913 {
914 
915 // Qualify swap choice
916 //
917  if (minasz >= argp->bsize || datasz >= argp->bsize/2) return Swap(buff);
918  errno = 0;
919  return 0;
920 }
921 
922 /******************************************************************************/
923 /* Static: R e c l a i m */
924 /******************************************************************************/
925 
927 {
928 
929  if (h) BPool->Release((XrdBuffer *)h);
930 }
931 
932 /******************************************************************************/
933 /* S t r e a m N O P */
934 /******************************************************************************/
935 
937 {
938 
939 // Mark this stream as not operation if it is not the control strea,
940 //
941  if (PathID)
942  {streamMutex.Lock();
943  isNOP = true;
945  }
946 }
947 
948 /******************************************************************************/
949 /* S w a p */
950 /******************************************************************************/
951 
953 {
954  XrdBuffer *oldBP = argp;
955 
956 // Verify the context and linkage and if OK, swap buffers
957 //
958  if (Request.header.requestid != kXR_write) errno = ENOTSUP;
959  else if (buff != argp->buff) errno = EINVAL;
960  else {if (h)
961  {argp = (XrdBuffer *)h;
962  return oldBP;
963  } else {
964  argp = BPool->Obtain(argp->bsize);
965  if (argp) return oldBP;
966  argp = oldBP;
967  errno = ENOBUFS;
968  }
969  }
970  return 0;
971 }
972 
973 /******************************************************************************/
974 /* V e r i f y S t r e a m */
975 /******************************************************************************/
976 
978 {
979  XrdXrootdProtocol *pp;
980 
981 // Verify that the path actually exists
982 //
983  if (pID >= maxStreams || !(pp = Stream[pID]))
984  {rc = Response.Send(kXR_ArgInvalid, "invalid path ID");
985  return 0;
986  }
987 
988 // Verify that this path is still functional
989 //
990  pp->streamMutex.Lock();
991  if (pp->isNOP)
992  {pp->streamMutex.UnLock();
993  rc = Response.Send(kXR_ArgInvalid, "path ID is not operational");
994  return 0;
995  }
996 
997 // All done!
998 //
999  if (!lok) pp->streamMutex.UnLock();
1000  return pp;
1001 }
1002 
1003 /******************************************************************************/
1004 /* P r i v a t e M e t h o d s */
1005 /******************************************************************************/
1006 /******************************************************************************/
1007 /* C h e c k S u m */
1008 /******************************************************************************/
1009 
1010 int XrdXrootdProtocol::CheckSum(XrdOucStream *Stream, char **argv, int argc)
1011 {
1012  int rc, ecode;
1013 
1014 // The arguments must have <name> <cstype> <path> <tident> [name] (argc >= 4)
1015 //
1016  if (argc < 4)
1017  {Stream->PutLine("Internal error; not enough checksum args!");
1018  return 8;
1019  }
1020 
1021 // Construct the error information
1022 //
1023  XrdOucEnv myEnv;
1024  XrdOucErrInfo myInfo(argv[3], &myEnv);
1025 
1026 // Add username, if present
1027 //
1028  if (argc > 4 && *argv[4]) myEnv.Put("request.name", argv[4]);
1029 
1030 // Issue the checksum calculation (that's all we do here).
1031 //
1032  rc = osFS->chksum(XrdSfsFileSystem::csCalc, argv[1], argv[2], myInfo);
1033 
1034 // Return result regardless of what it is
1035 //
1036  Stream->PutLine(myInfo.getErrText(ecode));
1037  if (rc) {SI->errorCnt++;
1038  if (ecode) rc = ecode;
1039  }
1040  return rc;
1041 }
1042 
1043 /******************************************************************************/
1044 /* C l e a n u p */
1045 /******************************************************************************/
1046 
1047 void XrdXrootdProtocol::Cleanup()
1048 {
1049  XrdXrootdPio *pioP;
1050  int i;
1051 
1052 // Handle parallel stream cleanup. The session stream cannot be closed if
1053 // there is any queued activity on subordinate streams. A subordinate
1054 // can either be closed from the session stream or asynchronously only if
1055 // it is active. Which means they could be running while we are running.
1056 // So, we first call RequestClose. If this returns true it will inhibit the
1057 // asynchronous close and we call close(). Otherwise the asynchronous close
1058 // already hapened. Either way we wait for the boundRecycle semaphore to
1059 // confirm the first pass through Recycle (via close) and then we trigger
1060 // the actual recycle of the object.
1061 //
1062  if (Status != XRD_BOUNDPATH)
1063  {streamMutex.Lock();
1064  for (i = 1; i < maxStreams; i++)
1065  if (Stream[i])
1066  {Stream[i]->Stream[0] = 0;
1067  const bool doCl = Stream[i]->RequestClose();
1068  if (doCl) Stream[i]->Link->Close();
1069  Stream[i]->boundRecycle->Wait();
1070  Stream[i]->Recycle(0, 0, 0);
1071  Stream[i] = 0;
1072  }
1073  streamMutex.UnLock();
1074  }
1075 
1076 // Handle packet parking (needs to be done before deleting other stuff)
1077 //
1078  if (pmHandle) delete pmHandle;
1079 
1080 // Release any internal monitoring information
1081 //
1082  if (Entity.moninfo) {free(Entity.moninfo); Entity.moninfo = 0;}
1083 
1084 // If we have a buffer, release it
1085 //
1086  if (argp) {BPool->Release(argp); argp = 0;}
1087 
1088 // Notify the filesystem of a disconnect prior to deleting file tables
1089 //
1090  if (Status != XRD_BOUNDPATH) osFS->Disc(Client);
1091 
1092 // Handle parallel I/O appendages. We need to do this first as these have
1093 // referenced open files and we need to deref them before we cleanup the ftab.
1094 //
1095  while((pioP = pioFirst))
1096  {pioP->IO.File->Ref(-1); pioFirst = pioP->Next; pioP->Recycle();}
1097  while((pioP = pioFree )) {pioFree = pioP->Next; pioP->Recycle();}
1098 
1099 // Delete the FTab if we have it
1100 //
1101  if (FTab)
1102  {FTab->Recycle(Monitor.Files() ? Monitor.Agent : 0);
1103  FTab = 0;
1104  }
1105 
1106 // Handle statistics
1107 //
1108  SI->statsMutex.Lock();
1110  SI->statsMutex.UnLock();
1111 
1112 // Handle authentication protocol
1113 //
1114  if (AuthProt) {AuthProt->Delete(); AuthProt = 0;}
1115  if (Protect) {Protect->Delete(); Protect = 0;}
1116 
1117 // Handle writev appendage
1118 //
1119  if (wvInfo) {free(wvInfo); wvInfo = 0;}
1120 
1121 // Release aplication name
1122 //
1123  if (AppName) {free(AppName); AppName = 0;}
1124 
1125 // Release the pagewrite control object
1126 //
1127  if (pgwCtl) delete pgwCtl;
1128 
1129 // Release the recycle semaphore for bound connections
1130 //
1131  if (boundRecycle) { delete boundRecycle; boundRecycle = 0; }
1132 }
1133 
1134 /******************************************************************************/
1135 /* g e t D a t a */
1136 /******************************************************************************/
1137 
1138 int XrdXrootdProtocol::getData(const char *dtype, char *buff, int blen)
1139 {
1140  int rlen;
1141 
1142 // Read the data but reschedule he link if we have not received all of the
1143 // data within the timeout interval.
1144 //
1145  rlen = Link->Recv(buff, blen, readWait);
1146  if (rlen < 0)
1147  {if (rlen != -ENOMSG) return Link->setEtext("link read error");
1148  else return -1;
1149  }
1150  if (rlen < blen)
1151  {myBuff = buff+rlen; myBlen = blen-rlen;
1152  TRACEP(REQ, dtype <<" timeout; read " <<rlen <<" of " <<blen <<" bytes");
1153  return 1;
1154  }
1155  return 0;
1156 }
1157 
1158 /******************************************************************************/
1159 
1161  const char *dtype, char *buff, int blen)
1162 {
1163  bool inCB = (gdCtl.Status == GetDataCtl::inCallBk);
1164 
1165 // Setup the control information to direct the vector read
1166 //
1167  memset((char *)&gdCtl, 0, sizeof(gdCtl));
1168  gdCtl.BuffLen = blen; // Buffer length (bytes to read)
1169  gdCtl.Buffer = buff; // The actual buffer
1170  gdCtl.CallBack= cbP; // Method to callback upon success
1171  gdCtl.ioDType = dtype; // Name of the data being read for tracing
1173 
1174 // Effect the read. We prevent recursive calls if this was called while
1175 // we were in a callback, which is possible due to I/O continuations.
1176 //
1177  if (inCB)
1178  {gdCtl.useCB = true;
1179  return 1;
1180  }
1181  return getDataCont();
1182 }
1183 
1184 /******************************************************************************/
1185 namespace {int consumed = 0;}
1186 
1188  const char *dtype, struct iovec *iov, int iovn)
1189 {
1190  bool inCB = (gdCtl.Status == GetDataCtl::inCallBk);
1191 
1192 // Setup the control information to direct the vector read
1193 //
1194  memset((char *)&gdCtl, 0, sizeof(gdCtl));
1195  gdCtl.iovNum = iovn; // Number of original elements
1196  gdCtl.iovVec = iov; // The actual vector
1197  gdCtl.CallBack= cbP; // Method to callback upon success
1198  gdCtl.ioDType = dtype; // Name of the data being read for tracing
1200 
1201 // Effect the read. We prevent recursive calls if this was called while
1202 // we were in a callback, which is possible due to I/O continuations.
1203 //
1204  if (inCB)
1205  {gdCtl.useCB = true;
1206  return 1;
1207  }
1208 consumed = 0;
1209  return getDataIovCont();
1210 }
1211 
1212 /******************************************************************************/
1213 /* g e t D a t a C o n t */
1214 /******************************************************************************/
1215 
1216 int XrdXrootdProtocol::getDataCont()
1217 {
1218  int rlen;
1219 
1220 // Check if we need to terminate because the link died or we can proceed.
1221 //
1223  return -EINPROGRESS;
1224 
1225 // I/O continuations may occur either via entry or an attempt to continue a new
1226 // operation via the callback. This takes care of it here.
1227 //
1228 do{if ((rlen = Link->Recv(gdCtl.Buffer, gdCtl.BuffLen, readWait)) < 0) break;
1229  gdCtl.Buffer += rlen;
1230  gdCtl.BuffLen -= rlen;
1231 
1232 // If we completed the read then either return or use the callback. Note that
1233 // we convert recursive call for more data into an iterative continuation.
1234 //
1235  if (!gdCtl.BuffLen)
1236  {if (gdCtl.useCB)
1238  if (int(gdCtl.stalls) > as_okstutter)
1240  rlen = gdCtl.CallBack->gdDone();
1241  if (rlen < 0) break;
1242  if (gdCtl.Status == GetDataCtl::inData) continue;
1243  if (gdCtl.Status == GetDataCtl::inDataIov) return getDataIovCont();
1244  if (gdCtl.Status == GetDataCtl::inDump) return getDumpCont();
1246  return rlen;
1247  }
1249  return 0;
1250  }
1251 
1252 // Make sure we don't have an over-run
1253 //
1254  if (gdCtl.BuffLen < 0)
1255  {rlen = Link->setEtext("link excessive read length error");
1256  break;
1257  }
1258 
1259 // Record where we stopped and setup to resume here when more data arrives. We
1260 // must set myBlen to zero to avoid calling the other GetData() method. We want
1261 // to resume and perform the GetData() function here.
1262 //
1263  Resume = &XrdXrootdProtocol::getDataCont;
1264  myBlen = 0;
1265  gdCtl.useCB = true;
1267  if (gdCtl.stalls < 255) gdCtl.stalls++;
1268 
1269 // Return indicating we need more data
1270 //
1271  TRACEP(REQ, gdCtl.ioDType <<" timeout; read " <<rlen <<" bytes "
1272  <<gdCtl.BuffLen <<" remaining");
1273  return 1;
1274 
1275  } while(true);
1276 
1277 // If got here then we had a link failure or some other fatal issue
1278 //
1279  if (rlen != -ENOMSG) return Link->setEtext("link read error");
1280 
1281 // Use callback, if need be.
1282 //
1283  if (gdCtl.useCB)
1285  gdCtl.CallBack->gdFail();
1286  }
1288  return -1;
1289 }
1290 
1291 /******************************************************************************/
1292 /* g e t D a t I o v C o n t */
1293 /******************************************************************************/
1294 
1295 int XrdXrootdProtocol::getDataIovCont()
1296 {
1297  int rc;
1298 
1299 // Check if we need to terminate because the link died or we can proceed.
1300 //
1302  return -EINPROGRESS;
1303 
1304 // I/O continuations may occur either via entry or an attempt to continue a new
1305 // operation via the callback. This takes care of it here.
1306 //
1307 do{struct iovec *ioV = gdCtl.iovVec;
1308  int i, rlen, iovN = gdCtl.iovNum, iNow = gdCtl.iovNow;
1309 
1310 // Read as much data as we can. Handle any link error. Note that when a link
1311 // error occurs we return failure whether or not the callback wants to do more.
1312 //
1313  rlen = Link->Recv(&ioV[iNow], iovN - iNow, readWait);
1314  if (rlen < 0)
1315  {if (rlen != -ENOMSG) Link->setEtext("link read error");
1316  if (gdCtl.iovAdj)
1317  {ioV[iNow].iov_base = ((char *)ioV[iNow].iov_base) - gdCtl.iovAdj;
1318  ioV[iNow].iov_len += gdCtl.iovAdj;
1319  gdCtl.iovAdj = 0;
1320  }
1321  rc = -1;
1322  break;
1323  }
1324 
1325 // Compute where we finished in the iovec.
1326 //
1327  for (i = iNow; i < iovN && (int)ioV[i].iov_len <= rlen; i++)
1328  rlen -= ioV[i].iov_len;
1329 
1330 // Before proceeding, restore any changes we made to a completed iovec element
1331 //
1332  if (i != iNow && gdCtl.iovAdj)
1333  {ioV[iNow].iov_base = ((char *)ioV[iNow].iov_base) - gdCtl.iovAdj;
1334  ioV[iNow].iov_len += gdCtl.iovAdj;
1335  gdCtl.iovAdj = 0;
1336  }
1337 
1338 // If the vector is complete then effect the callback unless this was the
1339 // initial call, we simply return to prevent recursive continuations by
1340 // converting a recursive call to an iterative continuation!
1341 //
1342  if (i >= iovN)
1343  {if (!rlen)
1344  {if (gdCtl.useCB)
1346  if (int(gdCtl.stalls) > as_okstutter)
1348  rc = gdCtl.CallBack->gdDone();
1349  if (rc < 0) break;
1350  if (gdCtl.Status == GetDataCtl::inDataIov) continue;
1351  if (gdCtl.Status == GetDataCtl::inDump) return getDumpCont();
1353  return rc;
1354  }
1356  return 0;
1357  }
1358  rc = Link->setEtext("link iov read length error");
1359  break;
1360  }
1361 
1362 // Record where we stopped and adjust the iovec element address and length if
1363 // needed. Record the change made so that it can be undone as we progress.
1364 //
1365  gdCtl.iovNow = i;
1366  if (rlen)
1367  {if (gdCtl.iovAdj == 0) gdCtl.iovNow = i;
1368  gdCtl.iovAdj += rlen;
1369  ioV[i].iov_base = ((char *)ioV[i].iov_base) + rlen;
1370  ioV[i].iov_len -= rlen;
1371  }
1372 
1373 // Setup to resume here when more data arrives. We must set myBlen to zero to
1374 // avoid calling the other GetData() method as we want to resume here.
1375 //
1376  Resume = &XrdXrootdProtocol::getDataIovCont;
1377  myBlen = 0;
1378  gdCtl.useCB = true;
1380  if (gdCtl.stalls < 255) gdCtl.stalls++;
1381 
1382 // Return indicating we need more data
1383 //
1384  TRACEP(REQ, gdCtl.ioDType<<" read timeout; "<<iovN-i<<" of "
1385  <<gdCtl.iovNum <<" iov elements left");
1386  return 1;
1387 
1388  } while(true);
1389 
1390 // If got here then we had a link failure or some other fatal issue
1391 //
1392  if (gdCtl.useCB)
1394  gdCtl.CallBack->gdFail();
1395  }
1397  return rc;
1398 }
1399 
1400 /******************************************************************************/
1401 /* g e t D u m p */
1402 /******************************************************************************/
1403 
1404 int XrdXrootdProtocol::getDump(const char *dtype, int dlen)
1405 {
1406  bool inCB = (gdCtl.Status == GetDataCtl::inCallBk);
1407 
1408 // Setup the control information to direct the vector read
1409 //
1410  memset((char *)&gdCtl, 0, sizeof(gdCtl));
1411  gdCtl.DumpLen = dlen; // Bytes left to drain
1412  gdCtl.ioDType = dtype; // Name of the data being read for tracing
1414 
1415 // Effect the read. We prevent recursive calls if this was called while
1416 // we were in a callback, which is possible due to I/O continuations.
1417 //
1418  return (inCB ? 1 : getDumpCont());
1419 }
1420 
1421 /******************************************************************************/
1422 /* Private: g e t D u m p C o n t */
1423 /******************************************************************************/
1424 
1425 int XrdXrootdProtocol::getDumpCont()
1426 {
1427  int rlen = 0, rwant;
1428  char buff[65536];
1429 
1430  TRACEP(REQ, gdCtl.ioDType<<" discarding "<<gdCtl.DumpLen<<" bytes.");
1431 
1432 // Read data and discard it
1433 //
1434  while(gdCtl.DumpLen > 0)
1435  {if (gdCtl.DumpLen <= (int)sizeof(buff)) rwant = gdCtl.DumpLen;
1436  else rwant = sizeof(buff);
1437  if ((rlen = Link->Recv(buff, rwant, readWait)) <= 0) break;
1438  gdCtl.DumpLen -= rlen;
1439  }
1440 
1441 // Check if we failed
1442 //
1443  if (rlen < 0 || gdCtl.DumpLen < 0)
1444  {if (gdCtl.DumpLen < 0) Link->setEtext("link read overrun error");
1445  else if (rlen != -ENOMSG) Link->setEtext("link read error");
1447  return -1;
1448  }
1449 
1450 // Check if we completed
1451 //
1452  if (gdCtl.DumpLen == 0)
1454  return 0;
1455  }
1456 
1457 // Wait until more data arrives. We will now need to use the callback.
1458 //
1459  Resume = &XrdXrootdProtocol::getDumpCont;
1460  myBlen = 0;
1461 
1462  TRACEP(REQ, gdCtl.ioDType<<" read timeout; "<<gdCtl.DumpLen
1463  <<" bytes left to discard");
1464  return 1;
1465 }
1466 
1467 /******************************************************************************/
1468 /* R e s e t */
1469 /******************************************************************************/
1470 
1471 void XrdXrootdProtocol::Reset()
1472 {
1473  Status = 0;
1474  argp = 0;
1475  Link = 0;
1476  FTab = 0;
1477  pmHandle = 0;
1478  ResumePio = 0;
1479  Resume = 0;
1480  myBuff = (char *)&Request;
1481  myBlen = sizeof(Request);
1482  myBlast = 0;
1483  myStalls = 0;
1484  pgwCtl = 0;
1485  memset(&IO, 0, sizeof(IO));
1486  wvInfo = 0;
1487  numReads = 0;
1488  numReadP = 0;
1489  numReadV = 0;
1490  numSegsV = 0;
1491  numWritV = 0;
1492  numSegsW = 0;
1493  numWrites = 0;
1494  numFiles = 0;
1495  cumReads = 0;
1496  cumReadV = 0;
1497  cumSegsV = 0;
1498  cumWritV = 0;
1499  cumSegsW = 0;
1500  cumWrites = 0;
1501  totReadP = 0;
1502  hcPrev =13;
1503  hcNext =21;
1504  hcNow =13;
1505  Client = 0;
1506  AuthProt = 0;
1507  Protect = 0;
1508  mySID = 0;
1509  CapVer = 0;
1510  CloseRequested = false;
1511  clientPV = 0;
1512  clientRN = 0;
1513  pmDone = false;
1514  reTry = 0;
1515  boundRecycle = 0;
1516  endNote = 0;
1517  PathID = 0;
1518  newPio = false;
1519  rvSeq = 0;
1520  wvSeq = 0;
1521  doTLS = tlsNot; // Assume client is not capable. This will be
1522  ableTLS = false; // resolved during the kXR_protocol interchange.
1523  isTLS = false; // Made true when link converted to TLS
1524  linkAioReq = 0;
1525  pioFree = pioFirst = pioLast = 0;
1526  isActive = isLinkWT= isNOP = false;
1527  sigNeed = sigHere = sigRead = false;
1528  sigWarn = true;
1529  rdType = 0;
1530  Entity.Reset(0);
1531  memset(Stream, 0, sizeof(Stream));
1532  memset((char *)&gdCtl, 0, sizeof(gdCtl));
1533  PrepareCount = 0;
1534  if (AppName) {free(AppName); AppName = 0;}
1535 }
1536 
1537 /******************************************************************************/
1538 /* C l o s e R e q u e s t C b */
1539 /******************************************************************************/
1540 
1542 {
1543  XrdXrootdProtocol *pp = (XrdXrootdProtocol*)cbarg;
1544  return pp->RequestClose();
1545 }
1546 
1547 /******************************************************************************/
1548 /* D o C l o s e R e q u e s t e d */
1549 /******************************************************************************/
1550 
1552 {
1554  if (CloseRequested) return false;
1555  CloseRequested = true;
1556  return true;
1557 }
@ kXR_ArgInvalid
Definition: XProtocol.hh:1032
@ kXR_InvalidRequest
Definition: XProtocol.hh:1038
@ kXR_ArgMissing
Definition: XProtocol.hh:1033
@ kXR_SigVerErr
Definition: XProtocol.hh:1054
@ kXR_ArgTooLong
Definition: XProtocol.hh:1034
struct ClientRequestHdr header
Definition: XProtocol.hh:923
kXR_char streamid[2]
Definition: XProtocol.hh:158
@ kXR_redirect
Definition: XProtocol.hh:946
struct ClientRequestHdr header
Definition: XProtocol.hh:887
#define kXR_PROTOCOLVSTRING
Definition: XProtocol.hh:76
kXR_int32 fourth
Definition: XProtocol.hh:88
kXR_unt16 requestid
Definition: XProtocol.hh:159
@ kXR_read
Definition: XProtocol.hh:126
@ kXR_open
Definition: XProtocol.hh:123
@ kXR_writev
Definition: XProtocol.hh:144
@ kXR_clone
Definition: XProtocol.hh:145
@ kXR_readv
Definition: XProtocol.hh:138
@ kXR_mkdir
Definition: XProtocol.hh:121
@ kXR_sync
Definition: XProtocol.hh:129
@ kXR_chmod
Definition: XProtocol.hh:115
@ kXR_bind
Definition: XProtocol.hh:137
@ kXR_dirlist
Definition: XProtocol.hh:117
@ kXR_sigver
Definition: XProtocol.hh:142
@ kXR_fattr
Definition: XProtocol.hh:133
@ kXR_rm
Definition: XProtocol.hh:127
@ kXR_query
Definition: XProtocol.hh:114
@ kXR_write
Definition: XProtocol.hh:132
@ kXR_gpfile
Definition: XProtocol.hh:118
@ kXR_login
Definition: XProtocol.hh:120
@ kXR_auth
Definition: XProtocol.hh:113
@ kXR_endsess
Definition: XProtocol.hh:136
@ kXR_set
Definition: XProtocol.hh:131
@ kXR_rmdir
Definition: XProtocol.hh:128
@ kXR_statx
Definition: XProtocol.hh:135
@ kXR_truncate
Definition: XProtocol.hh:141
@ kXR_protocol
Definition: XProtocol.hh:119
@ kXR_mv
Definition: XProtocol.hh:122
@ kXR_ping
Definition: XProtocol.hh:124
@ kXR_stat
Definition: XProtocol.hh:130
@ kXR_pgread
Definition: XProtocol.hh:143
@ kXR_chkpoint
Definition: XProtocol.hh:125
@ kXR_locate
Definition: XProtocol.hh:140
@ kXR_close
Definition: XProtocol.hh:116
@ kXR_pgwrite
Definition: XProtocol.hh:139
@ kXR_prepare
Definition: XProtocol.hh:134
@ kXR_faMaxVlen
Definition: XProtocol.hh:312
@ kXR_faMaxNlen
Definition: XProtocol.hh:311
#define kXR_LBalServer
Definition: XProtocol.hh:1193
#define kXR_PROTOCOLVERSION
Definition: XProtocol.hh:70
#define kXR_DataServer
Definition: XProtocol.hh:1192
@ kXR_readable
Definition: XProtocol.hh:1266
@ kXR_isDir
Definition: XProtocol.hh:1263
@ kXR_offline
Definition: XProtocol.hh:1265
@ kXR_bkpexist
Definition: XProtocol.hh:1269
@ kXR_other
Definition: XProtocol.hh:1264
@ kXR_poscpend
Definition: XProtocol.hh:1268
@ kXR_writable
Definition: XProtocol.hh:1267
@ kXR_cachersp
Definition: XProtocol.hh:1270
@ kXR_xset
Definition: XProtocol.hh:1262
kXR_int32 dlen
Definition: XProtocol.hh:161
kXR_int32 second
Definition: XProtocol.hh:86
unsigned int kXR_unt32
Definition: XPtypes.hh:90
unsigned short kXR_unt16
Definition: XPtypes.hh:67
#define stat(a, b)
Definition: XrdPosix.hh:105
#define NEED2SECURE(protP)
This class implements the XRootD protocol security protection.
static const dev_t XRDSFS_HASBKUP
Definition: XrdSfsFlags.hh:105
static const dev_t XRDSFS_RDVMASK
Definition: XrdSfsFlags.hh:107
#define XRDSFS_POSCPEND
Definition: XrdSfsFlags.hh:92
static const dev_t XRDSFS_OFFLINE
Definition: XrdSfsFlags.hh:103
class XrdBuffer * XrdSfsXioHandle
Definition: XrdSfsXio.hh:46
#define AtomicInc(x)
#define AtomicBeg(Mtx)
#define AtomicEnd(Mtx)
const int SYS_LOG_02
Definition: XrdSysError.hh:101
const kXR_char XROOTD_MON_BOUNDP
const kXR_char XROOTD_MON_FORCED
XrdVERSIONINFO(XrdgetProtocol, xrootd)
XrdProtocol * XrdgetProtocol(const char *pname, char *parms, XrdProtocol_Config *pi)
XrdSysTrace XrdXrootdTrace("Xrootd")
int XrdgetProtocolPort(const char *pname, char *parms, XrdProtocol_Config *pi)
#define ROOTD_PQ
#define XRD_BOUNDPATH
#define XRD_NEED_AUTH
#define TRACEP(act, x)
static const char * reqName(kXR_unt16 reqCode)
Definition: XProtocol.cc:153
void Release(XrdBuffer *bp)
Definition: XrdBuffer.cc:221
XrdBuffer * Obtain(int bsz)
Definition: XrdBuffer.cc:140
int bsize
Definition: XrdBuffer.hh:46
char * buff
Definition: XrdBuffer.hh:45
static bool InDomain(XrdNetAddrInfo *epaddr)
Definition: XrdNetIF.cc:622
void Push(XrdObject< T > *Node)
Definition: XrdObject.hh:101
T * Pop()
Definition: XrdObject.hh:93
void Put(const char *varname, const char *value)
Definition: XrdOucEnv.hh:85
XrdSysMutex statsMutex
Definition: XrdOucStats.hh:55
void Bump(int &val)
Definition: XrdOucStats.hh:47
bool endswith(char c)
static int GidName(gid_t gID, char *gName, int gNsz, time_t keepT=0)
Definition: XrdOucUtils.cc:635
static int UidName(uid_t uID, char *uName, int uNsz, time_t keepT=0)
XrdSysError * eDest
Definition: XrdProtocol.hh:61
XrdNetAddrInfo * addrInfo
Entity's connection details.
Definition: XrdSecEntity.hh:80
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
Definition: XrdSecEntity.hh:67
gid_t gid
Unix gid or 0 if none.
Definition: XrdSecEntity.hh:87
void Reset(const char *spV=0)
uid_t uid
Unix uid or 0 if none.
Definition: XrdSecEntity.hh:86
char * moninfo
Information for monitoring.
Definition: XrdSecEntity.hh:76
char * host
Entity's host name dnr dependent.
Definition: XrdSecEntity.hh:70
virtual const char * Verify(SecurityRequest &secreq, ClientRequest &thereq, const char *thedata)
virtual void Delete()
Delete this object. Use this method as opposed to operator delete.
virtual void Delete()=0
Delete the protocol object. DO NOT use C++ delete() on this object.
virtual void Disc(const XrdSecEntity *client=0)
virtual int chksum(csFunc Func, const char *csName, const char *path, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0, const char *opaque=0)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:116
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:162
void Log(int mask, const char *esfx, const char *text1, const char *text2=0, const char *text3=0)
Definition: XrdSysError.hh:167
static char * s2hms(int sec, char *buff, int blen)
Definition: XrdSysTimer.cc:192
T fetch_or(T v) noexcept
T fetch_and(T v) noexcept
static void ClearErrorQueue()
Clear the SSL error queue for the calling thread.
Definition: XrdTls.cc:265
void Recycle(XrdXrootdMonitor *monP)
void Ref(int num)
static void Disc(unsigned int usrID)
XrdXrootdMonitor * Agent
void Disc(kXR_unt32 dictid, int csec, char Flags=0)
XrdXrootdPio * Next
Definition: XrdXrootdPio.hh:43
XrdXrootd::IOParms IO
Definition: XrdXrootdPio.hh:45
void Recycle()
Definition: XrdXrootdPio.cc:73
static XrdXrootdStats * SI
static const char * myInst
XrdXrootdProtocol * VerifyStream(int &rc, int pID, bool lok=true)
static XrdSfsFileSystem * digFS
XrdSecProtect * Protect
XrdNetPMark::Handle * pmHandle
static XrdNetPMark * PMark
XrdXrootdProtocol * Stream[maxStreams]
XrdXrootd::IOParms IO
static short as_okstutter
static XrdXrootdXPath RPList
static XrdNetSocket * AdminSock
XrdSecEntity * Client
XrdProtocol * Match(XrdLink *lp) override
struct XrdXrootdProtocol::GetDataCtl gdCtl
ClientRequest sigReq2Ver
static bool CloseRequestCb(void *cbarg)
XrdXrootdWVInfo * wvInfo
XrdXrootdPgwCtl * pgwCtl
static void Reclaim(XrdSfsXioHandle h)
XrdSysSemaphore * reTry
XrdXrootdFileTable * FTab
static XrdXrootdJob * JobCKS
static XrdSysError & eDest
static unsigned int getSID()
XrdSecProtocol * AuthProt
int getData(gdCallBack *gdcbP, const char *dtype, char *buff, int blen)
XrdSfsXioHandle Claim(const char *buff, int datasz, int minasz=0) override
static char * usxParms
XrdXrootdMonitor::User Monitor
static XrdXrootdRedirPI * RedirPI
static const char * myCName
XrdXrootdPio * pioFree
XrdSfsXioHandle Swap(const char *buff, XrdSfsXioHandle h=0) override
static XrdXrootdFileLock * Locker
SecurityRequest sigReq
int(XrdXrootdProtocol::* Resume)()
static XrdTlsContext * tlsCtx
XrdXrootdPio * pioLast
static XrdXrootdXPath XPList
static XrdScheduler * Sched
static struct XrdXrootdProtocol::RC_Table RouteClient
int Process(XrdLink *lp) override
void Recycle(XrdLink *lp, int consec, const char *reason) override
static char * Buffer(XrdSfsXioHandle h, int *bsz)
static const char * myUName
XrdXrootdResponse Response
int(XrdXrootdProtocol::* ResumePio)()
static const char * TraceID
static int Configure(char *parms, XrdProtocol_Config *pi)
int Stats(char *buff, int blen, int do_sync=0) override
static const int maxStreams
int getDump(const char *dtype, int dlen)
static XrdOucTList * JobCKTLST
static XrdXrootdXPath RQList
static XrdSecProtector * DHS
static XrdBuffManager * BPool
XrdSysSemaphore * boundRecycle
static XrdSecService * CIA
static RAtomic_int srvrAioOps
static const char * myGName
static uint64_t fsFeatures
XrdXrootdReqID ReqID
static XrdOucReqID * PrepID
XrdXrootdPio * pioFirst
XrdSysCondVar2 * endNote
static struct XrdXrootdProtocol::RD_Table Route[RD_Num]
static XrdSfsFileSystem * osFS
void setID(unsigned long long id)
void Set(XrdLink *lp)
long long rsegCnt
long long wsegCnt
long long readCnt
long long prerCnt
long long rvecCnt
long long writeCnt
long long wvecCnt
int Stats(char *buff, int blen, int do_sync=0)
virtual int gdDone()=0
static const uint64_t hasCACH
Feature: Implements a data cache.
Definition: XrdSfsFlags.hh:74
XrdXrootdStats * SI
XrdScheduler * Sched
XrdBuffManager * BPool
XrdSysError eLog
XrdXrootd::gdCallBack * CallBack
XrdXrootdFile * File