XRootD
XrdLink.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d L i n k . c c */
4 /* */
5 /* (c) 2018 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 #include <signal.h>
32 #include <cstdio>
33 #include <cstring>
34 #include <sys/types.h>
35 #include <sys/uio.h>
36 
37 #if defined(__linux__) || defined(__GNU__)
38 #include <netinet/tcp.h>
39 #if !defined(TCP_CORK)
40 #undef HAVE_SENDFILE
41 #endif
42 #endif
43 
44 #ifdef HAVE_SENDFILE
45 
46 #ifndef __APPLE__
47 #if !defined(__FreeBSD__)
48 #include <sys/sendfile.h>
49 #else
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <sys/uio.h>
53 #endif
54 #endif
55 
56 #endif
57 
58 #include "XrdSys/XrdSysAtomics.hh"
59 #include "XrdSys/XrdSysError.hh"
60 #include "XrdSys/XrdSysFD.hh"
61 #include "XrdSys/XrdSysPlatform.hh"
62 
63 #include "Xrd/XrdBuffer.hh"
64 
65 #include "Xrd/XrdLinkCtl.hh"
66 #include "Xrd/XrdPoll.hh"
67 
68 #define TRACE_IDENT ID
69 #include "Xrd/XrdTrace.hh"
70 
71 #include "XrdSys/XrdSysError.hh"
72 
73 #ifndef ETIME
74 #define ETIME ETIMEDOUT
75 #endif
76 
77 /******************************************************************************/
78 /* G l o b a l s */
79 /******************************************************************************/
80 
81 namespace XrdGlobal
82 {
83 extern XrdSysError Log;
84 };
85 
86 using namespace XrdGlobal;
87 
88 /******************************************************************************/
89 /* S t a t i c M e m b e r s */
90 /******************************************************************************/
91 
92 #if defined(HAVE_SENDFILE)
93  bool XrdLink::sfOK = true;
94 #else
95  bool XrdLink::sfOK = false;
96 #endif
97 
98 namespace
99 {
100 const unsigned char KillMax = 60;
101 const unsigned char KillMsk = 0x7f;
102 const unsigned char KillXwt = 0x80;
103 
104 const char *TraceID = "Link";
105 }
106 
107 /******************************************************************************/
108 /* C o n s t r u c t o r */
109 /******************************************************************************/
110 
111 XrdLink::XrdLink(XrdLinkXeq &lxq) : XrdJob("connection"), linkXQ(lxq),
112  HostName(0)
113 {
114  memset(rsvd1, 0, sizeof(rsvd1));
115  memset(rsvd2, 0, sizeof(rsvd2));
116  ResetLink();
117 }
118 
120 {
121  if (HostName) {free(HostName); HostName = 0;}
122  Instance = 0;
123  isBridged= false;
124  isTLS = false;
125 }
126 
127 /******************************************************************************/
128 /* A c t i v a t e */
129 /******************************************************************************/
130 
132 {
133 
134 // Attach this link to a poller
135 //
137 }
138 
139 /******************************************************************************/
140 /* A d d r I n f o */
141 /******************************************************************************/
142 
144 
145 /******************************************************************************/
146 /* a r m B r i d g e */
147 /******************************************************************************/
148 
150 
151 /******************************************************************************/
152 /* B a c k l o g */
153 /******************************************************************************/
154 
155 int XrdLink::Backlog() {return linkXQ.Backlog();}
156 
157 /******************************************************************************/
158 /* C l i e n t */
159 /******************************************************************************/
160 
161 int XrdLink::Client(char *nbuf, int nbsz) {return linkXQ.Client(nbuf, nbsz);}
162 
163 /******************************************************************************/
164 /* C l o s e */
165 /******************************************************************************/
166 
167 int XrdLink::Close(bool defer) {return linkXQ.Close(defer);}
168 
169 /******************************************************************************/
170 /* Protected: D o I t */
171 /******************************************************************************/
172 
173 void XrdLink::DoIt() {} // This is overridden by the implementation
174 
175 /******************************************************************************/
176 /* E n a b l e */
177 /******************************************************************************/
178 
180 {
182 }
183 
184 /******************************************************************************/
185 /* F D n u m */
186 /******************************************************************************/
187 
189 {
190  return linkXQ.PollInfo.FD;
191 }
192 
193 /******************************************************************************/
194 /* F i n d */
195 /******************************************************************************/
196 
198  {return XrdLinkCtl::Find(curr, who);}
199 
200 /******************************************************************************/
201 /* g e t I O S t a t s */
202 /******************************************************************************/
203 
204 int XrdLink::getIOStats(long long &inbytes, long long &outbytes,
205  int &numstall, int &numtardy)
206  {return linkXQ.getIOStats(inbytes, outbytes,
207  numstall, numtardy);
208  }
209 
210 /******************************************************************************/
211 /* g e t N a m e */
212 /******************************************************************************/
213 
214 // Warning: curr must be set to a value of 0 or less on the initial call and
215 // not touched therafter unless null is returned. Returns the length
216 // the name in nbuf.
217 //
218 int XrdLink::getName(int &curr, char *nbuf, int nbsz, XrdLinkMatch *who)
219  {return XrdLinkCtl::getName(curr, nbuf, nbsz, who);}
220 
221 /******************************************************************************/
222 /* g e t P e e r C e r t s */
223 /******************************************************************************/
224 
226 {
227  return linkXQ.getPeerCerts();
228 }
229 
230 /******************************************************************************/
231 /* g e t P r o t o c o l */
232 /******************************************************************************/
233 
235 
236 /******************************************************************************/
237 /* H o l d */
238 /******************************************************************************/
239 
240 void XrdLink::Hold(bool lk)
241 {
243 }
244 
245 /******************************************************************************/
246 /* i s F l a w e d */
247 /******************************************************************************/
248 
249 bool XrdLink::isFlawed() const {return linkXQ.LinkInfo.Etext != 0;}
250 
251 /******************************************************************************/
252 /* i s I n s t a n c e */
253 /******************************************************************************/
254 
255 bool XrdLink::isInstance(unsigned int inst) const
256  {return Instance == inst && linkXQ.PollInfo.FD >= 0;}
257 
258 /******************************************************************************/
259 /* N a m e */
260 /******************************************************************************/
261 
262 const char *XrdLink::Name() const {return linkXQ.Name();}
263 
264 /******************************************************************************/
265 /* N e t A d d r */
266 /******************************************************************************/
267 const
269 
270 /******************************************************************************/
271 /* P e e k */
272 /******************************************************************************/
273 
274 int XrdLink::Peek(char *Buff, int Blen, int timeout)
275 {
276  if (isTLS) return linkXQ.TLS_Peek(Buff, Blen, timeout);
277  else return linkXQ.Peek (Buff, Blen, timeout);
278 }
279 
280 /******************************************************************************/
281 /* R e c v */
282 /******************************************************************************/
283 
284 int XrdLink::Recv(char *Buff, int Blen)
285 {
286  if (isTLS) return linkXQ.TLS_Recv(Buff, Blen);
287  else return linkXQ.Recv (Buff, Blen);
288 }
289 
290 /******************************************************************************/
291 
292 int XrdLink::Recv(char *Buff, int Blen, int timeout)
293 {
294  if (isTLS) return linkXQ.TLS_Recv(Buff, Blen, timeout);
295  else return linkXQ.Recv (Buff, Blen, timeout);
296 }
297 
298 /******************************************************************************/
299 
300 int XrdLink::Recv(const struct iovec *iov, int iocnt, int timeout)
301 {
302 // Execute the send
303 //
304  if (isTLS) return linkXQ.TLS_Recv(iov, iocnt, timeout);
305  else return linkXQ.Recv (iov, iocnt, timeout);
306 }
307 
308 /******************************************************************************/
309 /* R e c v A l l */
310 /******************************************************************************/
311 
312 int XrdLink::RecvAll(char *Buff, int Blen, int timeout)
313 {
314  if (isTLS) return linkXQ.TLS_RecvAll(Buff, Blen, timeout);
315  else return linkXQ.RecvAll (Buff, Blen, timeout);
316 }
317 
318 /******************************************************************************/
319 /* R e g i s t e r */
320 /******************************************************************************/
321 
322 bool XrdLink::Register(const char *hName)
323 {
324  return linkXQ.Register(hName);
325 }
326 
327 /******************************************************************************/
328 /* S e n d */
329 /******************************************************************************/
330 
331 int XrdLink::Send(const char *Buff, int Blen)
332 {
333  if (isTLS) return linkXQ.TLS_Send(Buff, Blen);
334  else return linkXQ.Send (Buff, Blen);
335 }
336 
337 /******************************************************************************/
338 
339 int XrdLink::Send(const struct iovec *iov, int iocnt, int bytes)
340 {
341 // Allways make sure we have a total byte count
342 //
343  if (!bytes) for (int i = 0; i < iocnt; i++) bytes += iov[i].iov_len;
344 
345 // Execute the send
346 //
347  if (isTLS) return linkXQ.TLS_Send(iov, iocnt, bytes);
348  else return linkXQ.Send (iov, iocnt, bytes);
349 }
350 
351 /******************************************************************************/
352 
353 int XrdLink::Send(const sfVec *sfP, int sfN)
354 {
355 // Make sure we have valid vector count
356 //
357  if (sfN < 1 || sfN > XrdOucSFVec::sfMax)
358  {Log.Emsg("Link", E2BIG, "send file to", ID);
359  return -1;
360  }
361 
362 // Do the send
363 //
364  if (isTLS) return linkXQ.TLS_Send(sfP, sfN);
365  else return linkXQ.Send (sfP, sfN);
366 }
367 
368 /******************************************************************************/
369 /* S e r i a l i z e */
370 /******************************************************************************/
371 
373 {
374 
375 // This is meant to make sure that no protocol objects are refering to this
376 // link so that we can safely run in pseudo single thread mode for critical
377 // functions.
378 //
381  else {linkXQ.LinkInfo.doPost++;
383  TRACEI(DEBUG, "Waiting for link serialization; use="
384  <<linkXQ.LinkInfo.InUse);
386  }
387 }
388 
389 /******************************************************************************/
390 /* s e t E t e x t */
391 /******************************************************************************/
392 
393 int XrdLink::setEtext(const char *text)
394 {
397  linkXQ.LinkInfo.Etext = (text ? strdup(text) : 0);
399  return -1;
400 }
401 
402 /******************************************************************************/
403 /* s e t I D */
404 /******************************************************************************/
405 
406 void XrdLink::setID(const char *userid, int procid)
407  {linkXQ.setID(userid, procid);}
408 
409 /******************************************************************************/
410 /* s e t N B */
411 /******************************************************************************/
412 
413 bool XrdLink::setNB() {return linkXQ.setNB();}
414 
415 /******************************************************************************/
416 /* s e t L o c a t i o n */
417 /******************************************************************************/
418 
420  {linkXQ.setLocation(loc);}
421 
422 /******************************************************************************/
423 /* s e t P r o t o c o l */
424 /******************************************************************************/
425 
426 XrdProtocol *XrdLink::setProtocol(XrdProtocol *pp, bool runit, bool push)
427 {
428 
429 // Ask the mplementation to set or push the protocol
430 //
431  XrdProtocol *op = linkXQ.setProtocol(pp, push);
432 
433 // Run the protocol if so requested
434 //
435  if (runit) DoIt();
436  return op;
437 }
438 
439 /******************************************************************************/
440 /* s e t P r o t N a m e */
441 /******************************************************************************/
442 
443 void XrdLink::setProtName(const char *name)
444 {
445 
446 // Ask the mplementation to set the name.
447 //
448  linkXQ.setProtName(name);
449 }
450 
451 /******************************************************************************/
452 /* s e t R e f */
453 /******************************************************************************/
454 
455 void XrdLink::setRef(int use)
456 {
458  TRACEI(DEBUG,"Setting FD "<<linkXQ.LinkInfo.FD <<" ref to "
459  <<linkXQ.LinkInfo.InUse <<'+'
460  <<use <<" post=" <<linkXQ.LinkInfo.doPost);
461  linkXQ.LinkInfo.InUse += use;
462 
463  if (!linkXQ.LinkInfo.InUse)
465  Log.Emsg("Link", "Zero use count for", ID);
466  }
467  else if (linkXQ.LinkInfo.InUse == 1 && linkXQ.LinkInfo.doPost)
468  {while(linkXQ.LinkInfo.doPost)
470  TRACEI(CONN, "setRef posted link");
472  }
474  }
475  else if (linkXQ.LinkInfo.InUse < 0)
476  {linkXQ.LinkInfo.InUse = 1;
478  Log.Emsg("Link", "Negative use count for", ID);
479  }
480  else linkXQ.LinkInfo.opMutex.UnLock();
481 }
482 
483 /******************************************************************************/
484 /* s e t T L S */
485 /******************************************************************************/
486 
487 bool XrdLink::setTLS(bool enable, XrdTlsContext *ctx)
488 {
489 // If we are already in a compatible mode, we are done
490 //
491  if (isTLS == enable) return true;
492 
493  return linkXQ.setTLS(enable, ctx);
494 }
495 
496 /******************************************************************************/
497 /* S h u t d o w n */
498 /******************************************************************************/
499 
500 void XrdLink::Shutdown(bool getLock) {linkXQ.Shutdown(getLock);}
501 
502 /******************************************************************************/
503 /* S t a t s */
504 /******************************************************************************/
505 
506 int XrdLink::Stats(char *buff, int blen, bool do_sync)
507  {return XrdLinkXeq::Stats(buff, blen, do_sync);}
508 
509 /******************************************************************************/
510 /* s y n c S t a t s */
511 /******************************************************************************/
512 
513 void XrdLink::syncStats(int *ctime) {linkXQ.syncStats(ctime);}
514 
515 /******************************************************************************/
516 /* T e r m i n a t e */
517 /******************************************************************************/
518 
519 int XrdLink::Terminate(const char *owner, int fdnum, unsigned int inst)
520 {
521 
522 // Find the correspodning link and check for self-termination. Otherwise, if
523 // the target link is owned by the owner then ask the link to terminate itself.
524 //
525  if (!owner)
526  {XrdLink *lp;
527  char *cp;
528  if (!(lp = XrdLinkCtl::fd2link(fdnum, inst))) return -ESRCH;
529  if (lp == this) return 0;
530  lp->Hold(true);
531  if (!(cp = index(ID, ':')) || strncmp(lp->ID, ID, cp-ID)
532  || strcmp(HostName, lp->Host()))
533  {lp->Hold(false);
534  return -EACCES;
535  }
536  int rc = lp->Terminate(ID, fdnum, inst);
537  lp->Hold(false);
538  return rc;
539  }
540 
541 // At this pint, we are excuting in the context of the target link.
542 // If this link is now dead, simply ignore the request. Typically, this
543 // indicates a race condition that the server won.
544 //
545  if ( linkXQ.PollInfo.FD != fdnum || Instance != inst
546  || !linkXQ.PollInfo.Poller || !linkXQ.getProtocol()) return -EPIPE;
547 
548 // Check if we have too many tries here
549 //
550  int wTime, killTries;
551  killTries = linkXQ.LinkInfo.KillCnt & KillMsk;
552  if (killTries > KillMax) return -ETIME;
553 
554 // Wait time increases as we have more unsuccessful kills. Update numbers.
555 //
556  wTime = killTries++;
557  linkXQ.LinkInfo.KillCnt = killTries | KillXwt;
558 
559 // Make sure we can disable this link. If not, then force the caller to wait
560 // a tad more than the read timeout interval.
561 //
564  {wTime = wTime*2+XrdLinkCtl::waitKill;
565  return (wTime > 60 ? 60: wTime);
566  }
567 
568 // Set the pointer to our condvar. We are holding the opMutex to prevent a race.
569 //
570  XrdSysCondVar killDone(0);
571  linkXQ.LinkInfo.KillcvP = &killDone;
572  killDone.Lock();
573 
574 // We can now disable the link and schedule a close
575 //
576  char buff[1024];
577  snprintf(buff, sizeof(buff), "ended by %s", owner);
578  buff[sizeof(buff)-1] = '\0';
581 
582 // Now wait for the link to shutdown. This avoids lock problems.
583 //
584  if (killDone.Wait(int(XrdLinkCtl::killWait))) wTime += XrdLinkCtl::killWait;
585  else wTime = -EPIPE;
586  killDone.UnLock();
587 
588 // Reobtain the opmutex so that we can zero out the pointer the condvar pntr
589 // This is really stupid code but because we don't have a way of associating
590 // an arbitrary mutex with a condvar. But since this code is rarely executed
591 // the ugliness is sort of tolerable.
592 //
594  linkXQ.LinkInfo.KillcvP = 0;
596 
597 // Do some tracing
598 //
599  TRACEI(DEBUG,"Terminate " << (wTime <= 0 ? "complete ":"timeout ") <<wTime);
600  return wTime;
601 }
602 
603 /******************************************************************************/
604 /* t i m e C o n */
605 /******************************************************************************/
606 
607 time_t XrdLink::timeCon() const {return linkXQ.LinkInfo.conTime;}
608 
609 /******************************************************************************/
610 /* U s e C n t */
611 /******************************************************************************/
612 
613 int XrdLink::UseCnt() const {return linkXQ.LinkInfo.InUse;}
614 
615 /******************************************************************************/
616 /* v e r T L S */
617 /******************************************************************************/
618 
619 const char *XrdLink::verTLS()
620 {
621  return (isTLS ? linkXQ.verTLS() : "");
622 }
623 
624 /******************************************************************************/
625 /* W a i t 4 D a t a */
626 /******************************************************************************/
627 
628 int XrdLink::Wait4Data(int timeout)
629 {
630  struct pollfd polltab = {linkXQ.PollInfo.FD, POLLIN|POLLRDNORM, 0};
631  int retc;
632 
633 // Issue poll and do preliminary check
634 //
635  do {retc = poll(&polltab, 1, timeout);} while(retc < 0 && errno == EINTR);
636  if (retc != 1)
637  {if (retc == 0) return 0;
638  Log.Emsg("Link", -errno, "poll", ID);
639  return -1;
640  }
641 
642 // Verify it is safe to read now
643 //
644  if (!(polltab.revents & (POLLIN|POLLRDNORM)))
645  {Log.Emsg("Link", XrdPoll::Poll2Text(polltab.revents), "polling", ID);
646  return -1;
647  }
648  return 1;
649 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define TRACEI(act, x)
Definition: XrdTrace.hh:66
Definition: XrdJob.hh:43
static XrdLink * fd2link(int fd)
Definition: XrdLinkCtl.hh:72
static short waitKill
Definition: XrdLinkCtl.hh:191
static XrdLink * Find(int &curr, XrdLinkMatch *who=0)
Definition: XrdLinkCtl.cc:202
static short killWait
Link destruction control constants.
Definition: XrdLinkCtl.hh:190
static int getName(int &curr, char *bname, int blen, XrdLinkMatch *who=0)
Definition: XrdLinkCtl.cc:248
time_t conTime
Definition: XrdLinkInfo.hh:44
XrdSysSemaphore IOSemaphore
Definition: XrdLinkInfo.hh:43
char * Etext
Definition: XrdLinkInfo.hh:45
XrdSysRecMutex opMutex
Definition: XrdLinkInfo.hh:46
XrdSysCondVar * KillcvP
Definition: XrdLinkInfo.hh:42
int TLS_Send(const char *Buff, int Blen)
Definition: XrdLinkXeq.cc:1314
int TLS_Peek(char *Buff, int Blen, int timeout)
Definition: XrdLinkXeq.cc:1161
int Client(char *buff, int blen)
Definition: XrdLinkXeq.cc:152
XrdTlsPeerCerts * getPeerCerts()
Definition: XrdLinkXeq.cc:321
XrdLinkInfo LinkInfo
Definition: XrdLinkXeq.hh:144
const char * Name() const
Definition: XrdLinkXeq.hh:85
int Close(bool defer=false)
Definition: XrdLinkXeq.cc:172
int TLS_Recv(char *Buff, int Blen)
Definition: XrdLinkXeq.cc:1193
XrdProtocol * setProtocol(XrdProtocol *pp, bool push)
Definition: XrdLinkXeq.cc:927
void Shutdown(bool getLock)
Definition: XrdLinkXeq.cc:1022
int Peek(char *buff, int blen, int timeout=-1)
Definition: XrdLinkXeq.cc:330
int Backlog()
Definition: XrdLinkXeq.cc:139
static int Stats(char *buff, int blen, bool do_sync=false)
Definition: XrdLinkXeq.cc:1054
XrdPollInfo PollInfo
Definition: XrdLinkXeq.hh:145
void setID(const char *userid, int procid)
Definition: XrdLinkXeq.cc:874
XrdNetAddrInfo * AddrInfo()
Definition: XrdLinkXeq.hh:57
int Recv(char *buff, int blen)
Definition: XrdLinkXeq.cc:373
int TLS_RecvAll(char *Buff, int Blen, int timeout)
Definition: XrdLinkXeq.cc:1292
const XrdNetAddr * NetAddr() const
Definition: XrdLinkXeq.hh:88
int Send(const char *buff, int blen)
Definition: XrdLinkXeq.cc:588
const char * verTLS()
Definition: XrdLinkXeq.cc:1446
bool setNB()
Definition: XrdLinkXeq.cc:898
void setLocation(XrdNetAddrInfo::LocInfo &loc)
Definition: XrdLinkXeq.hh:107
int RecvAll(char *buff, int blen, int timeout=-1)
Definition: XrdLinkXeq.cc:509
bool Register(const char *hName)
Definition: XrdLinkXeq.cc:573
void setProtName(const char *name)
Definition: XrdLinkXeq.cc:944
void syncStats(int *ctime=0)
Definition: XrdLinkXeq.cc:1090
XrdProtocol * getProtocol()
Definition: XrdLinkXeq.hh:82
bool setTLS(bool enable, XrdTlsContext *ctx=0)
Definition: XrdLinkXeq.cc:958
int getIOStats(long long &inbytes, long long &outbytes, int &numstall, int &numtardy)
Definition: XrdLinkXeq.hh:68
bool isEnabled
Definition: XrdPollInfo.hh:46
XrdPoll * Poller
Definition: XrdPollInfo.hh:43
virtual int Enable(XrdPollInfo &pInfo)=0
static char * Poll2Text(short events)
Definition: XrdPoll.cc:272
virtual void Disable(XrdPollInfo &pInfo, const char *etxt=0)=0
static int Attach(XrdPollInfo &pInfo)
Definition: XrdPoll.cc:144
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdSysError Log
Definition: XrdConfig.cc:112