00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdNetMsgCVSID = "$Id: XrdNetMsg.cc 35287 2010-09-14 21:19:35Z ganis $";
00014
00015 #include <sys/poll.h>
00016
00017 #include "XrdNet/XrdNet.hh"
00018 #include "XrdNet/XrdNetDNS.hh"
00019 #include "XrdNet/XrdNetMsg.hh"
00020 #include "XrdNet/XrdNetOpts.hh"
00021 #include "XrdNet/XrdNetPeer.hh"
00022 #include "XrdNet/XrdNetSocket.hh"
00023 #include "XrdSys/XrdSysError.hh"
00024 #include "XrdSys/XrdSysPlatform.hh"
00025
00026
00027
00028
00029
00030 XrdNetMsg::XrdNetMsg(XrdSysError *erp, const char *dest)
00031 {
00032 XrdNet myNet(erp);
00033 XrdNetPeer Peer;
00034
00035 eDest = erp; DestHN = 0; DestIP = 0; DestSZ = 0; FD = -1;
00036 if (dest)
00037 {if (XrdNetSocket::socketAddr(erp, dest, &DestIP, DestSZ))
00038 eDest->Emsg("Msg", "Default", dest, "is unreachable");
00039 else DestHN = strdup(dest);
00040 }
00041
00042 if (!myNet.Relay(Peer, dest, XRDNET_SENDONLY))
00043 eDest->Emsg("Msg", "Unable top create UDP msg socket.");
00044 else FD = Peer.fd;
00045 }
00046
00047
00048
00049
00050
00051 int XrdNetMsg::Send(const char *Buff, int Blen, const char *dest, int tmo)
00052 {
00053 int retc, eCode, dL, doFree = 0;
00054 struct sockaddr *dP;
00055
00056 if (!Blen && !(Blen = strlen(Buff))) return 0;
00057
00058 if (!dest)
00059 {if (!DestHN)
00060 {eDest->Emsg("Msg", "Destination not specified."); return -1;}
00061 dP = DestIP; dL = DestSZ; dest = DestHN;
00062 }
00063 else if (XrdNetSocket::socketAddr(eDest, dest, &dP, dL))
00064 {eDest->Emsg("Msg", dest, "is unreachable"); return -1;}
00065 else doFree = 1;
00066
00067 if (tmo >= 0 && !OK2Send(tmo, dest)) {if (doFree) free(dP); return 1;}
00068
00069 do {retc = sendto(FD, (Sokdata_t)Buff, Blen, 0, dP, dL);}
00070 while (retc < 0 && errno == EINTR);
00071
00072 if (retc < 0) eCode = errno;
00073 if (doFree) free(dP);
00074 if (retc < 0) return retErr(errno, dest);
00075 return 0;
00076 }
00077
00078
00079
00080 int XrdNetMsg::Send(const struct iovec iov[], int iovcnt,
00081 const char *dest, int tmo)
00082 {
00083 char buff[4096], *bp = buff;
00084 int i, dsz = sizeof(buff);
00085
00086 if (tmo >= 0 && !OK2Send(tmo, dest)) return 1;
00087
00088 for (i = 0; i < iovcnt; i++)
00089 {dsz -= iov[i].iov_len;
00090 if (dsz < 0) return retErr(EMSGSIZE, dest);
00091 memcpy((void *)bp,(const void *)iov[i].iov_base,iov[i].iov_len);
00092 bp += iov[i].iov_len;
00093 }
00094
00095 return Send(buff, (int)(bp-buff), dest, -1);
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105 int XrdNetMsg::OK2Send(int timeout, const char *dest)
00106 {
00107 struct pollfd polltab = {FD, POLLOUT|POLLWRNORM, 0};
00108 int retc;
00109
00110 do {retc = poll(&polltab, 1, timeout);} while(retc < 0 && errno == EINTR);
00111
00112 if (retc == 0 || !(polltab.revents & (POLLOUT | POLLWRNORM)))
00113 eDest->Emsg("Msg", "UDP link to", dest, "is blocked.");
00114 else if (retc < 0)
00115 eDest->Emsg("Msg",errno,"poll", dest);
00116 else return 1;
00117 return 0;
00118 }
00119
00120
00121
00122
00123
00124 int XrdNetMsg::retErr(int ecode, const char *dest)
00125 {
00126 eDest->Emsg("Msg", ecode, "send to", dest);
00127 return (EWOULDBLOCK == ecode || EAGAIN == ecode ? 1 : -1);
00128 }