XRootD
Loading...
Searching...
No Matches
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
59#include "XrdSys/XrdSysError.hh"
60#include "XrdSys/XrdSysFD.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
81namespace XrdGlobal
82{
83extern XrdSysError Log;
84};
85
86using 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
98namespace
99{
100const char KillMax = 60;
101const char KillMsk = 0x7f;
102const char KillXwt = 0x80;
103
104const char *TraceID = "Link";
105}
106
107/******************************************************************************/
108/* C o n s t r u c t o r */
109/******************************************************************************/
110
111XrdLink::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
156
157/******************************************************************************/
158/* C l i e n t */
159/******************************************************************************/
160
161int XrdLink::Client(char *nbuf, int nbsz) {return linkXQ.Client(nbuf, nbsz);}
162
163/******************************************************************************/
164/* C l o s e */
165/******************************************************************************/
166
167int XrdLink::Close(bool defer) {return linkXQ.Close(defer);}
168
169/******************************************************************************/
170/* Protected: D o I t */
171/******************************************************************************/
172
173void 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
204int 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//
218int 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
240void XrdLink::Hold(bool lk)
241{
243}
244
245/******************************************************************************/
246/* i s F l a w e d */
247/******************************************************************************/
248
249bool XrdLink::isFlawed() const {return linkXQ.LinkInfo.Etext != 0;}
250
251/******************************************************************************/
252/* i s I n s t a n c e */
253/******************************************************************************/
254
255bool XrdLink::isInstance(unsigned int inst) const
256 {return Instance == inst && linkXQ.PollInfo.FD >= 0;}
257
258/******************************************************************************/
259/* N a m e */
260/******************************************************************************/
261
262const char *XrdLink::Name() const {return linkXQ.Name();}
263
264/******************************************************************************/
265/* N e t A d d r */
266/******************************************************************************/
267const
269
270/******************************************************************************/
271/* P e e k */
272/******************************************************************************/
273
274int 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
284int 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
292int 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
300int 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
312int 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
322bool XrdLink::Register(const char *hName)
323{
324 return linkXQ.Register(hName);
325}
326
327/******************************************************************************/
328/* S e n d */
329/******************************************************************************/
330
331int 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
339int 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
353int 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="
386 }
387}
388
389/******************************************************************************/
390/* s e t E t e x t */
391/******************************************************************************/
392
393int 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
406void XrdLink::setID(const char *userid, int procid)
407 {linkXQ.setID(userid, procid);}
408
409/******************************************************************************/
410/* s e t N B */
411/******************************************************************************/
412
413bool 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
426XrdProtocol *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
443void 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
455void 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 }
481}
482
483/******************************************************************************/
484/* s e t T L S */
485/******************************************************************************/
486
487bool 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
500void XrdLink::Shutdown(bool getLock) {linkXQ.Shutdown(getLock);}
501
502/******************************************************************************/
503/* S t a t s */
504/******************************************************************************/
505
506int 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
513void XrdLink::syncStats(int *ctime) {linkXQ.syncStats(ctime);}
514
515/******************************************************************************/
516/* T e r m i n a t e */
517/******************************************************************************/
518
519int 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//
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
607time_t XrdLink::timeCon() const {return linkXQ.LinkInfo.conTime;}
608
609/******************************************************************************/
610/* U s e C n t */
611/******************************************************************************/
612
614
615/******************************************************************************/
616/* v e r T L S */
617/******************************************************************************/
618
619const char *XrdLink::verTLS()
620{
621 return (isTLS ? linkXQ.verTLS() : "");
622}
623
624/******************************************************************************/
625/* W a i t 4 D a t a */
626/******************************************************************************/
627
628int 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)
#define TRACEI(act, x)
Definition XrdTrace.hh:66
static short waitKill
static XrdLink * fd2link(int fd)
Definition XrdLinkCtl.hh:72
static XrdLink * Find(int &curr, XrdLinkMatch *who=0)
static short killWait
Link destruction control constants.
static int getName(int &curr, char *bname, int blen, XrdLinkMatch *who=0)
time_t conTime
XrdSysSemaphore IOSemaphore
XrdSysRecMutex opMutex
XrdSysCondVar * KillcvP
int TLS_Send(const char *Buff, int Blen)
int TLS_Peek(char *Buff, int Blen, int timeout)
int Client(char *buff, int blen)
XrdTlsPeerCerts * getPeerCerts()
XrdNetAddrInfo * AddrInfo()
Definition XrdLinkXeq.hh:57
XrdLinkInfo LinkInfo
const char * Name() const
Definition XrdLinkXeq.hh:85
int Close(bool defer=false)
int TLS_Recv(char *Buff, int Blen)
XrdProtocol * setProtocol(XrdProtocol *pp, bool push)
void Shutdown(bool getLock)
int Peek(char *buff, int blen, int timeout=-1)
int Backlog()
static int Stats(char *buff, int blen, bool do_sync=false)
XrdPollInfo PollInfo
void setID(const char *userid, int procid)
int Recv(char *buff, int blen)
int TLS_RecvAll(char *Buff, int Blen, int timeout)
int Send(const char *buff, int blen)
const char * verTLS()
bool setNB()
void setLocation(XrdNetAddrInfo::LocInfo &loc)
XrdProtocol * getProtocol()
Definition XrdLinkXeq.hh:82
int RecvAll(char *buff, int blen, int timeout=-1)
bool Register(const char *hName)
void setProtName(const char *name)
const XrdNetAddr * NetAddr() const
Definition XrdLinkXeq.hh:88
void syncStats(int *ctime=0)
bool setTLS(bool enable, XrdTlsContext *ctx=0)
int getIOStats(long long &inbytes, long long &outbytes, int &numstall, int &numtardy)
Definition XrdLinkXeq.hh:68
XrdPoll * Poller
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)
XrdSysError Log
Definition XrdConfig.cc:111