XRootD
XrdNetMsg.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d N e t M s g . c c */
4 /* */
5 /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <cerrno>
32 #include <poll.h>
33 
34 #include "XrdNet/XrdNet.hh"
35 #include "XrdNet/XrdNetMsg.hh"
36 #include "XrdNet/XrdNetOpts.hh"
37 #include "XrdSys/XrdSysError.hh"
38 #include "XrdSys/XrdSysPlatform.hh"
39 
40 /******************************************************************************/
41 /* C o n s t r u c t o r */
42 /******************************************************************************/
43 
44 XrdNetMsg::XrdNetMsg(XrdSysError *erp, const char *dest, bool *aOK)
45 {
46  XrdNet myNet(erp);
47  bool aok = true;
48 
49  eDest = erp; FD = -1; destOK = 0;
50  if (dest)
51  {const char *eText = dfltDest.Set(dest);
52  if (!eText) destOK = 1;
53  else {eDest->Emsg("Msg", "Default", dest, "is unreachable");
54  aok = false;
55  }
56  }
57 
58  if ((FD = myNet.Relay(dest)) < 0)
59  {eDest->Emsg("Msg", "Unable to create UDP msg socket.");
60  aok = false;
61  }
62 
63  if (aOK) *aOK = aok;
64 }
65 
66 /******************************************************************************/
67 /* S e n d */
68 /******************************************************************************/
69 
70 int XrdNetMsg::Send(const char *Buff, int Blen, const char *dest, int tmo)
71 {
72  XrdNetAddr *theDest;
73  int retc;
74 
75  if (!Blen && !(Blen = strlen(Buff))) return 0;
76 
77  if (!dest)
78  {if (!destOK)
79  {eDest->Emsg("Msg", "Destination not specified."); return -1;}
80  theDest = &dfltDest;
81  }
82  else if (specDest.Set(dest))
83  {eDest->Emsg("Msg", dest, "is unreachable"); return -1;}
84  else theDest = &specDest;
85 
86  if (tmo >= 0 && !OK2Send(tmo, dest)) return 1;
87 
88  do {retc = sendto(FD, (Sokdata_t)Buff, Blen, 0,
89  theDest->SockAddr(), theDest->SockSize());}
90  while (retc < 0 && errno == EINTR);
91 
92  return (retc < 0 ? retErr(errno, theDest) : 0);
93 }
94 
95 /******************************************************************************/
96 
97 int XrdNetMsg::Send(const char *dest, const XrdNetSockAddr &netSA,
98  const char *Buff, int Blen, int tmo)
99 {
100  int aSize, retc;
101 
102  if (!Blen && !(Blen = strlen(Buff))) return 0;
103 
104  if (netSA.Addr.sa_family == AF_INET) aSize = sizeof(netSA.v4);
105  else if (netSA.Addr.sa_family == AF_INET6) aSize = sizeof(netSA.v6);
106  else return -1;
107 
108  if (tmo >= 0 && !OK2Send(tmo, dest)) return 1;
109 
110  do {retc = sendto(FD, (Sokdata_t)Buff, Blen, 0, &netSA.Addr, aSize);}
111  while (retc < 0 && errno == EINTR);
112 
113  if (retc >= 0) return 1;
114  return (EWOULDBLOCK == errno || EAGAIN == errno ? 1 : -1);
115 }
116 
117 /******************************************************************************/
118 
119 int XrdNetMsg::Send(const struct iovec iov[], int iovcnt,
120  const char *dest, int tmo)
121 {
122  char buff[4096], *bp = buff;
123  int i, dsz = sizeof(buff);
124 
125  if (tmo >= 0 && !OK2Send(tmo, dest)) return 1;
126 
127  for (i = 0; i < iovcnt; i++)
128  {dsz -= iov[i].iov_len;
129  if (dsz < 0) return retErr(EMSGSIZE, dest);
130  memcpy((void *)bp,(const void *)iov[i].iov_base,iov[i].iov_len);
131  bp += iov[i].iov_len;
132  }
133 
134  return Send(buff, (int)(bp-buff), dest, -1);
135 }
136 
137 /******************************************************************************/
138 /* P r i v a t e M e t h o d s */
139 /******************************************************************************/
140 /******************************************************************************/
141 /* O K 2 S e n d */
142 /******************************************************************************/
143 
144 int XrdNetMsg::OK2Send(int timeout, const char *dest)
145 {
146  struct pollfd polltab = {FD, POLLOUT|POLLWRNORM, 0};
147  int retc;
148 
149  do {retc = poll(&polltab, 1, timeout);} while(retc < 0 && errno == EINTR);
150 
151  if (retc == 0 || !(polltab.revents & (POLLOUT | POLLWRNORM)))
152  eDest->Emsg("Msg", "UDP link to", dest, "is blocked.");
153  else if (retc < 0)
154  eDest->Emsg("Msg",errno,"poll", dest);
155  else return 1;
156  return 0;
157 }
158 
159 /******************************************************************************/
160 /* r e t E r r */
161 /******************************************************************************/
162 
163 int XrdNetMsg::retErr(int ecode, const char *theDest)
164 {
165  if (!theDest)
166  {if (!destOK)
167  {eDest->Emsg("Msg", "Destination not specified."); return -1;}
168  theDest = dfltDest.Name("unknown");
169  }
170  eDest->Emsg("Msg", ecode, "send to", theDest);
171  return (EWOULDBLOCK == ecode || EAGAIN == ecode ? 1 : -1);
172 }
173 
174 int XrdNetMsg::retErr(int ecode, XrdNetAddr *theDest)
175 {
176  return retErr(ecode, theDest->Name("unknown"));
177 }
struct sockaddr_in6 v6
struct sockaddr Addr
struct sockaddr_in v4
#define Sokdata_t
const sockaddr * SockAddr()
SOCKLEN_t SockSize()
const char * Name(const char *eName=0, const char **eText=0)
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
int retErr(int ecode, const char *theDest)
Definition: XrdNetMsg.cc:163
XrdNetAddr specDest
Definition: XrdNetMsg.hh:139
int Send(const char *buff, int blen=0, const char *dest=0, int tmo=-1)
Definition: XrdNetMsg.cc:70
XrdNetAddr dfltDest
Definition: XrdNetMsg.hh:138
XrdSysError * eDest
Definition: XrdNetMsg.hh:137
int OK2Send(int timeout, const char *dest)
Definition: XrdNetMsg.cc:144
int destOK
Definition: XrdNetMsg.hh:140
XrdNetMsg(XrdSysError *erp, const char *dest=0, bool *aOK=0)
Definition: XrdNetMsg.cc:44
Definition: XrdNet.hh:52
int Relay(XrdNetPeer &Peer, const char *dest, int opts=0)
Definition: XrdNet.cc:310
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95