39#if defined(__linux__) || defined(__GNU__)
40#include <netinet/tcp.h>
48#if defined(__solaris__) || defined(__linux__) || defined(__GNU__)
49#include <sys/sendfile.h>
116 strcpy(
Lname,
"somewhere");
159 if (nbsz <= 0)
return 0;
161 if ((ulen +
HNlen) >= nbsz) ulen = 0;
162 else {strncpy(nbuf,
ID, ulen);
175 int csec, fd, rc = 0;
197 sendQ->Terminate(
this);
295 if (fd >= 2) {
if (
KeepFD) rc = 0;
296 else rc = (
close(fd) < 0 ? errno : 0);
298 if (rc)
Log.Emsg(
"Link", rc,
"close",
ID);
333 do {rc =
Protocol->Process(
this);}
while (!rc &&
Sched.canStick());
334 else {
Log.Emsg(
"Link",
"Dispatch on closed link",
ID);
344 else if (rc != -EINPROGRESS) doCl =
true;
381 struct pollfd polltab = {
PollInfo.FD, POLLIN|POLLRDNORM, 0};
392 do {retc = poll(&polltab, 1, timeout);}
while(retc < 0 && errno == EINTR);
394 {
if (retc == 0)
return 0;
395 return Log.Emsg(
"Link", -errno,
"poll",
ID);
400 if (!(polltab.revents & (POLLIN|POLLRDNORM)))
407 do {mlen = recv(
LinkInfo.FD, Buff, Blen, MSG_PEEK);}
408 while(mlen < 0 && errno == EINTR);
412 if (mlen >= 0)
return int(mlen);
413 Log.Emsg(
"Link", errno,
"peek on",
ID);
430 do {rlen =
read(
LinkInfo.FD, Buff, Blen);}
while(rlen < 0 && errno == EINTR);
434 if (rlen >= 0)
return int(rlen);
435 if (
LinkInfo.FD >= 0)
Log.Emsg(
"Link", errno,
"receive from",
ID);
444 struct pollfd polltab = {
PollInfo.FD, POLLIN|POLLRDNORM, 0};
445 ssize_t rlen, totlen = 0;
456 {
do {retc = poll(&polltab,1,timeout);}
while(retc < 0 && errno == EINTR);
466 return (
LinkInfo.FD >= 0 ?
Log.Emsg(
"Link",-errno,
"poll",
ID) : -1);
471 if (!(polltab.revents & (POLLIN|POLLRDNORM)))
480 do {rlen = recv(
LinkInfo.FD, Buff, Blen, 0);}
481 while(rlen < 0 && errno == EINTR);
483 {
if (!rlen)
return -ENOMSG;
484 if (
LinkInfo.FD > 0)
Log.Emsg(
"Link", -errno,
"receive from",
ID);
487 totlen += rlen; Blen -= rlen; Buff += rlen;
499 struct pollfd polltab = {
PollInfo.FD, POLLIN|POLLRDNORM, 0};
509 do {retc = poll(&polltab,1,timeout);}
while(retc < 0 && errno == EINTR);
515 return (
LinkInfo.FD >= 0 ?
Log.Emsg(
"Link",-errno,
"poll",
ID) : -1);
520 if (!(polltab.revents & (POLLIN|POLLRDNORM)))
536 int seglen, segcnt =
maxIOV, totlen = 0;
538 for (
int i = 0; i < segcnt; i++) seglen +=
iov[i].iov_len;
539 if ((rlen =
RecvIOV(
iov, segcnt)) < 0)
return rlen;
541 if (rlen < seglen)
break;
544 if (iocnt <=
maxIOV) segcnt = iocnt;
559 struct pollfd polltab = {
PollInfo.FD, POLLIN|POLLRDNORM, 0};
567 {
do {retc = poll(&polltab,1,timeout);}
while(retc < 0 && errno == EINTR);
569 {
if (!retc)
return -ETIMEDOUT;
570 Log.Emsg(
"Link",errno,
"poll",
ID);
573 if (!(polltab.revents & (POLLIN|POLLRDNORM)))
583 do {rlen = recv(
LinkInfo.FD, Buff, Blen, MSG_WAITALL);}
584 while(rlen < 0 && errno == EINTR);
588 if (
int(rlen) == Blen)
return Blen;
589 if (!rlen) {
TRACEI(
DEBUG,
"No RecvAll() data; errno=" <<errno);}
590 else if (rlen > 0)
Log.Emsg(
"RecvAll",
"Premature end from",
ID);
591 else if (
LinkInfo.FD >= 0)
Log.Emsg(
"Link", errno,
"receive from",
ID);
609 while(retc < 0 && errno == EINTR);
613 if (retc < 0)
Log.Emsg(
"Link", errno,
"receive from",
ID);
638 ssize_t retc = 0, bytesleft = Blen;
649 {retc =
sendQ->Send(Buff, Blen);
658 {
if (errno == EINTR)
continue;
661 bytesleft -= retc; Buff += retc;
667 if (retc >= 0)
return Blen;
668 Log.Emsg(
"Link", errno,
"send to",
ID);
687 {retc =
sendQ->Send(
iov, iocnt, bytes);
702 int seglen, segcnt =
maxIOV, iolen = 0;
704 for (
int i = 0; i < segcnt; i++) seglen +=
iov[i].iov_len;
705 if ((retc =
SendIOV(
iov, segcnt, seglen)) < 0)
712 if (iocnt <=
maxIOV) segcnt = iocnt;
725#if !defined(HAVE_SENDFILE)
729#elif defined(__solaris__)
732 size_t xframt, totamt, bytes = 0;
738 for (i = 0; i < sfN; sfP++, i++)
740 {vecSF[i].sfv_fd = SFV_FD_SELF;
741 vecSF[i].sfv_off = (off_t)sfP->buffer;
743 vecSF[i].sfv_fd = sfP->
fdnum;
744 vecSF[i].sfv_off = sfP->offset;
746 vecSF[i].sfv_flag = 0;
747 vecSF[i].sfv_len = sfP->
sendsz;
758do{retc = sendfilev(
LinkInfo.FD, vecSFP, sfN, &xframt);
770 if (retc < 0 && errno != EINTR)
break;
776 while(xframt > 0 && sfN)
777 {
if ((ssize_t)xframt < (ssize_t)vecSFP->sfv_len)
778 {vecSFP->sfv_off += xframt; vecSFP->sfv_len -= xframt;
break;}
779 xframt -= vecSFP->sfv_len; vecSFP++; sfN--;
786 retc = (retc < 0 ? errno : ECANCELED);
788 Log.Emsg(
"Link", retc,
"send file to",
ID);
791#elif defined(__linux__) || defined(__GNU__)
793 static const int setON = 1, setOFF = 0;
794 ssize_t retc = 0, bytesleft;
796 int i, xfrbytes = 0, uncork = 1, xIntr = 0;
806 if (setsockopt(
PollInfo.FD, SOL_TCP, TCP_CORK, &setON,
sizeof(setON)) < 0)
807 {
Log.Emsg(
"Link", errno,
"cork socket for",
ID);
808 uncork = 0;
sfOK = 0;
813 for (i = 0; i < sfN; sfP++, i++)
815 else {myOffset = sfP->offset; bytesleft = sfP->
sendsz;
817 && (retc=sendfile(
LinkInfo.FD,sfP->
fdnum,&myOffset,bytesleft)) > 0)
818 {bytesleft -= retc; xIntr++;}
820 if (retc < 0 && errno == EINTR)
continue;
821 if (retc <= 0)
break;
828 {
if (retc == 0) errno = ECANCELED;
830 Log.Emsg(
"Link", errno,
"send file to",
ID);
837 && setsockopt(
PollInfo.FD, SOL_TCP, TCP_CORK, &setOFF,
sizeof(setOFF)) < 0)
838 Log.Emsg(
"Link", errno,
"uncork socket for",
ID);
842 if (xIntr > sfN)
SfIntr += (xIntr - sfN);
860 ssize_t retc = 0, bytesleft = Blen;
866 {
if (errno == EINTR)
continue;
869 bytesleft -= retc; Buff += retc;
883 ssize_t bytesleft, n, retc = 0;
893 bytesleft =
static_cast<ssize_t
>(bytes);
896 while(retc < 0 && errno == EINTR);
897 if (retc >= bytesleft || retc < 0)
break;
899 while(retc >= (n =
static_cast<ssize_t
>(
iov->iov_len)))
900 {retc -= n;
iov++; iocnt--;}
901 Buff = (
const char *)
iov->iov_base + retc; n -= retc;
iov++; iocnt--;
903 {
if (errno == EINTR)
continue;
906 n -= retc; Buff += retc; bytesleft -= retc;
908 if (retc < 0 || iocnt < 1)
break;
913 if (retc >= 0)
return bytes;
914 Log.Emsg(
"Link", errno,
"send to",
ID);
924 char buff[
sizeof(
Uname)], *bp, *sp;
927 snprintf(buff,
sizeof(buff),
"%s.%d:%d", userid, procid,
PollInfo.FD);
929 sp = buff + ulen - 1;
931 if (ulen > (
int)
sizeof(
Uname)) ulen =
sizeof(
Uname);
933 while(ulen--) {*bp = *sp; bp--; sp--;}
950#if !defined(__linux__)
998 Addr.SetDialect(name);
1017 if (
isTLS == enable)
return true;
1024 Addr.SetTLS(enable);
1030 eNote =
tlsIO.Init(*ctx,
PollInfo.FD, rwMode, hsMode,
false,
false,
ID);
1036 snprintf(buff,
sizeof(buff),
"Unable to enable tls for %s;",
ID);
1037 Log.Emsg(
"LinkXeq", buff, eNote);
1049 else {
isTLS = enable;
1050 Addr.SetTLS(enable);
1051 Log.Emsg(
"LinkXeq",
ID,
"connection upgraded to",
verTLS());
1062 Log.Emsg(
"TLS", rc,
"send file to",
ID);
1076 TRACEI(
DEBUG, (getLock ?
"Async" :
"Sync") <<
" link shutdown in progress");
1080 if (getLock)
LinkInfo.opMutex.Lock();
1089 Log.Emsg(
"Link", errno,
"shutdown FD for",
ID);
1095 if (getLock)
LinkInfo.opMutex.UnLock();
1104 static const char statfmt[] =
"<stats id=\"link\"><num>%d</num>"
1105 "<maxn>%d</maxn><tot>%lld</tot><in>%lld</in><out>%lld</out>"
1106 "<ctime>%lld</ctime><tmo>%d</tmo><stall>%d</stall>"
1107 "<sfps>%d</sfps></stats>";
1112 if (!buff)
return sizeof(statfmt)+17*6;
1145 if (!ctime)
LinkInfo.opMutex.Lock();
1158 {*ctime = time(0) -
LinkInfo.conTime;
1188 if (!ctime)
LinkInfo.opMutex.UnLock();
1200 snprintf(msg,
sizeof(msg),
"Unable to %s %s;", act,
ID);
1201 Log.Emsg(
"TLS", msg, reason.c_str());
1224 if (rc < 1)
return rc;
1229 retc =
tlsIO.Peek(Buff, Blen, rlen);
1255 retc =
tlsIO.Read(Buff, Blen, rlen);
1267 int pend, rlen, totlen = 0;
1277 {pend =
tlsIO.Pending(
true);
1280 {
if (pend < 0)
return -1;
1294 retc =
tlsIO.Read(Buff, Blen, rlen);
1296 {
if (!totlen)
return -ENOMSG;
1300 if (rlen <= 0)
break;
1301 totlen += rlen; Blen -= rlen; Buff += rlen;
1314 int Blen, rlen, totlen = 0;
1323 for (
int i = 0; i < iocnt; i++)
1324 {Buff = (
char *)
iov[i].iov_base;
1325 Blen =
iov[i].iov_len;
1326 rlen =
TLS_Recv(Buff, Blen, timeout,
true);
1327 if (rlen <= 0)
break;
1329 if (rlen < Blen)
break;
1348 {retc =
tlsIO.Pending(
true);
1350 if (retc < 1)
return (retc ? -1 : -ETIMEDOUT);
1365 ssize_t bytesleft = Blen;
1381 {retc =
tlsIO.Write(Buff, bytesleft, byteswritten);
1383 bytesleft -= byteswritten; Buff += byteswritten;
1411 for (
int i = 0; i < iocnt; i++)
1412 {ssize_t bytesleft =
iov[i].iov_len;
1413 char *Buff = (
char *)
iov[i].iov_base;
1415 {retc =
tlsIO.Write(Buff, bytesleft, byteswritten);
1417 bytesleft -= byteswritten; Buff += byteswritten;
1431 int bytes, buffsz, fileFD, retc;
1440 for (
int i = 0; i < sfN; sfP++, i++)
1441 {
if (!(bytes = sfP->
sendsz))
continue;
1444 {
if (!
TLS_Write(sfP->buffer, bytes))
return -1;
1447 offset = sfP->offset;
1448 fileFD = sfP->
fdnum;
1449 buffsz = (bytes < (int)
sizeof(myBuff) ? bytes :
sizeof(myBuff));
1450 do {
do {retc =
pread(fileFD, myBuff, buffsz, offset);}
1451 while(retc < 0 && errno == EINTR);
1452 if (retc < 0)
return SFError(errno);
1454 if (!
TLS_Write(myBuff, buffsz))
return -1;
1455 offset += buffsz; bytes -= buffsz; totamt += retc;
1477 {retc =
tlsIO.Write(Buff, Blen, byteswritten);
1482 Blen -= byteswritten; Buff += byteswritten;
1496 return tlsIO.Version();
#define pread(a, b, c, d)
static void SyncAll()
Synchronize statustics for ll links.
static void Unhook(int fd)
Unhook a link from the active table of links.
static const char * TraceID
bool(* CloseRequestCb)(void *)
int TLS_Send(const char *Buff, int Blen)
int TLS_Error(const char *act, XrdTls::RC rc)
int TLS_Peek(char *Buff, int Blen, int timeout)
int Client(char *buff, int blen)
XrdTlsPeerCerts * getPeerCerts()
int Close(bool defer=false)
int TLS_Recv(char *Buff, int Blen)
int sendData(const char *Buff, int Blen)
bool TLS_Write(const char *Buff, int Blen)
int SendIOV(const struct iovec *iov, int iocnt, int bytes)
XrdProtocol * setProtocol(XrdProtocol *pp, bool push)
static long long LinkCountTot
void Shutdown(bool getLock)
int Peek(char *buff, int blen, int timeout=-1)
static int Stats(char *buff, int blen, bool do_sync=false)
void setID(const char *userid, int procid)
int Recv(char *buff, int blen)
static long long LinkBytesIn
int TLS_RecvAll(char *Buff, int Blen, int timeout)
int Send(const char *buff, int blen)
int RecvIOV(const struct iovec *iov, int iocnt)
static long long LinkConTime
int RecvAll(char *buff, int blen, int timeout=-1)
bool Register(const char *hName)
static XrdSysMutex statsMutex
void setProtName(const char *name)
static long long LinkBytesOut
void syncStats(int *ctime=0)
bool setTLS(bool enable, XrdTlsContext *ctx=0)
bool RegisterCloseRequestCb(XrdProtocol *pp, bool(*cb)(void *), void *cbarg)
void Serialize()
Wait for all outstanding requests to be completed on the link.
int Wait4Data(int timeout)
char * ID
Pointer to the client's link identity.
static char * Poll2Text(short events)
static void Detach(XrdPollInfo &pInfo)
void Lock(XrdSysMutex *Mutex)
int fd
Socket file descriptor.
long long bytesOut
Bytes written to the socket.
int consec
Seconds connected.
long long bytesIn
Bytes read from the socket.
const char * tident
Pointer to the client's trace identifier.
@ TLS_HS_BLOCK
Always block during handshake.
@ TLS_RBL_WBL
blocking read blocking write
static std::string RC2Text(XrdTls::RC rc, bool dbg=false)
@ TLS_AOK
All went well, will always be zero.
int fdnum
File descriptor for data.
int sendsz
Length of data at offset.