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