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 #include <sys/uio.h>
34 
35 #include "XrdNet/XrdNet.hh"
36 #include "XrdNet/XrdNetMsg.hh"
37 #include "XrdNet/XrdNetOpts.hh"
38 #include "XrdNet/XrdNetPeer.hh"
39 #include "XrdNet/XrdNetRefresh.hh"
40 #include "XrdSys/XrdSysError.hh"
41 #include "XrdSys/XrdSysPlatform.hh"
42 
43 /******************************************************************************/
44 /* C o n s t r u c t o r */
45 /******************************************************************************/
46 
47 XrdNetMsg::XrdNetMsg(XrdSysError *erp, const char *dest, bool *aOK, bool refr)
48  : eDest(erp)
49 {
50  XrdNet myNet(erp);
51  bool aok = true;
52 
53 // Handle the case where no dest was specified. In this case we will always
54 // need the caller to specify a destination.
55 //
56  if (!dest)
57  {if ((FD = myNet.Relay(dest)) < 0)
58  {eDest->Emsg("NetMsg", "Unable to create UDP msg socket.");
59  aok = false;
60  }
61  if (aOK) *aOK = aok;
62  return;
63  }
64 
65 // Hande the common case where a dest is specified. We first make
66 // sure the dest is valid, eventhough that will occur again, so we van
67 // generate a resonable error message.
68 //
69  XrdNetAddr specDest;
70  const char *eText = specDest.Set(dest);
71  if (eText)
72  {eDest->Emsg("NetMsg", "Default", dest, "is unreachable");
73  if (aOK) *aOK = false;
74  return;
75  }
76 
77 // Obtain a file description for this socket and set the endpoint address
78 //
79  XrdNetPeer myPeer;
80 
81  if (!myNet.Relay(myPeer, dest, XRDNET_SENDONLY))
82  {eDest->Emsg("NetMsg", "Unable to create UDP msg socket.");
83  if (aOK) *aOK = false;
84  return;
85  }
86 
87 // Save the relevant information
88 //
89  dfltDest = strdup(myPeer.InetName ? myPeer.InetName : "Unknown!");
90  FD = myPeer.fd;
91  destOK = true;
92 
93 // If address refresh wanted, register this socket for refresh. This should
94 // never fail and if it does we return non-success.
95 //
96  if (refr && !XrdNetRefresh::Register(myPeer)) aok = false;
97 
98 // All done
99 //
100  if (aOK) *aOK = aok;
101 }
102 
103 /******************************************************************************/
104 /* D e s t r u c t o r */
105 /******************************************************************************/
106 
108 {
109 // If we are registered,deregister
110 //
112 
113 // Close the socket
114 //
115  if (close(FD) < 0)
116  eDest->Emsg("NetMsg", errno, "close socket for", dfltDest);
117 
118 // Free the poiinter to the default dest
119 //
120  free(dfltDest);
121 }
122 
123 /******************************************************************************/
124 /* S e n d */
125 /******************************************************************************/
126 
127 int XrdNetMsg::Send(const char *Buff, int Blen, const char *dest, int tmo)
128 {
129  int retc;
130 
131 // Get the buffer length of not specified
132 //
133  if (!Blen && !(Blen = strlen(Buff))) return 0;
134 
135 // Handle the case where we are sendingto he dest setup at construction. This
136 // is the most common case.
137 //
138  if (!dest)
139  {if (!destOK)
140  {eDest->Emsg("NetMsg", "Destination not specified."); return -1;}
141 
142  if (tmo >= 0 && !OK2Send(tmo, dfltDest)) return 1;
143 
144  do {retc = send(FD, (Sokdata_t)Buff, Blen, 0);
145  } while (retc < 0 && errno == EINTR);
146 
147  return (retc < 0 ? retErr(errno, dfltDest) : 0);
148  }
149 
150 // Caller want to send to a specific destination other than the default
151 //
152  XrdNetAddr specDest;
153 
154  if (specDest.Set(dest))
155  {eDest->Emsg("NetMsg", dest, "is unreachable"); return -1;}
156 
157  if (tmo >= 0 && !OK2Send(tmo, dest)) return 1;
158 
159  do {retc = sendto(FD, (Sokdata_t)Buff, Blen, 0,
160  specDest.SockAddr(), specDest.SockSize());}
161  while (retc < 0 && errno == EINTR);
162 
163  return (retc < 0 ? retErr(errno, specDest) : 0);
164 }
165 
166 /******************************************************************************/
167 
168 int XrdNetMsg::Send(const char *dest, const XrdNetSockAddr &netSA,
169  const char *Buff, int Blen, int tmo)
170 {
171  int aSize, retc;
172 
173  if (!Blen && !(Blen = strlen(Buff))) return 0;
174 
175  if (netSA.Addr.sa_family == AF_INET) aSize = sizeof(netSA.v4);
176  else if (netSA.Addr.sa_family == AF_INET6) aSize = sizeof(netSA.v6);
177  else return retErr(EAFNOSUPPORT, (dest ? dest : "Unknown!"));
178 
179  if (tmo >= 0 && !OK2Send(tmo, dest)) return 1;
180 
181  do {retc = sendto(FD, (Sokdata_t)Buff, Blen, 0, &netSA.Addr, aSize);}
182  while (retc < 0 && errno == EINTR);
183 
184  if (retc >= 0) return 0;
185  return retErr(errno, (dest ? dest : "Unknown!"));
186 }
187 
188 /******************************************************************************/
189 
190 int XrdNetMsg::Send(const struct iovec iov[], int iovcnt,
191  const char *dest, int tmo)
192 {
193 
194 // Handle the common case of sendingto the cobbected address
195 //
196  if (!dest)
197  {if (!destOK)
198  {eDest->Emsg("NetMsg", "Destination not specified."); return -1;}
199  if (tmo >= 0 && !OK2Send(tmo, dfltDest)) return 1;
200  if (writev(FD, iov, iovcnt) >= 0) return 0;
201  return retErr(errno, dfltDest);
202  }
203 
204 // Caller want to send to a specific destination other than the default
205 //
206  XrdNetAddr specDest;
207  int retc;
208 
209  if (specDest.Set(dest))
210  {eDest->Emsg("NetMsg", dest, "is unreachable"); return -1;}
211 
212 // Create the message via the msghdr
213 //
214  struct msghdr mHdr{};
215 
216  mHdr.msg_name = (void*)specDest.SockAddr();
217  mHdr.msg_namelen = specDest.SockSize();
218  mHdr.msg_iov = const_cast<struct iovec*>(iov);
219  mHdr.msg_iovlen = iovcnt;
220 
221 // Handle timeout if need be
222 //
223  if (tmo >= 0 && !OK2Send(tmo, dest)) return 1;
224 
225 // Send the message
226 //
227  do {retc = sendmsg(FD, &mHdr, 0);} while (retc < 0 && errno == EINTR);
228 
229 // All done
230 //
231  return (retc < 0 ? retErr(errno, specDest) : 0);
232 }
233 
234 /******************************************************************************/
235 /* P r i v a t e M e t h o d s */
236 /******************************************************************************/
237 /******************************************************************************/
238 /* O K 2 S e n d */
239 /******************************************************************************/
240 
241 int XrdNetMsg::OK2Send(int timeout, const char *dest)
242 {
243  struct pollfd polltab = {FD, POLLOUT|POLLWRNORM, 0};
244  int retc;
245 
246  do {retc = poll(&polltab, 1, timeout);} while(retc < 0 && errno == EINTR);
247 
248  if (retc == 0 || !(polltab.revents & (POLLOUT | POLLWRNORM)))
249  eDest->Emsg("NetMsg", "UDP link to", dest, "is blocked.");
250  else if (retc < 0)
251  eDest->Emsg("NetMsg",errno,"poll", dest);
252  else return 1;
253  return 0;
254 }
255 
256 /******************************************************************************/
257 /* r e t E r r */
258 /******************************************************************************/
259 
260 int XrdNetMsg::retErr(int ecode, const char *theDest)
261 {
262  if (!theDest)
263  {if (!destOK)
264  {eDest->Emsg("NetMsg", "Destination not specified."); return -1;}
265  theDest = dfltDest;
266  }
267  eDest->Emsg("NetMsg", ecode, "send to", theDest);
268  return (EWOULDBLOCK == ecode || EAGAIN == ecode ? 1 : -1);
269 }
270 
271 int XrdNetMsg::retErr(int ecode, XrdNetAddr& theDest)
272 {
273  return retErr(ecode, theDest.Name("unknown"));
274 }
static XrdSysError eDest(0,"crypto_")
#define XRDNET_SENDONLY
Definition: XrdNetOpts.hh:43
struct sockaddr_in6 v6
struct sockaddr Addr
struct sockaddr_in v4
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
#define close(a)
Definition: XrdPosix.hh:48
#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:260
int Send(const char *buff, int blen=0, const char *dest=0, int tmo=-1)
Definition: XrdNetMsg.cc:127
XrdNetMsg(XrdSysError *erp, const char *dest=0, bool *aOK=0, bool refr=false)
Definition: XrdNetMsg.cc:47
XrdSysError * eDest
Definition: XrdNetMsg.hh:145
int OK2Send(int timeout, const char *dest)
Definition: XrdNetMsg.cc:241
~XrdNetMsg()
Destructor.
Definition: XrdNetMsg.cc:107
bool destOK
Definition: XrdNetMsg.hh:148
bool isRefr
Definition: XrdNetMsg.hh:149
char * dfltDest
Definition: XrdNetMsg.hh:146
char * InetName
Definition: XrdNetPeer.hh:44
static bool Register(XrdNetPeer &Peer)
static void UnRegister(int fd)
Definition: XrdNet.hh:52
int Relay(XrdNetPeer &Peer, const char *dest, int opts=0)
Definition: XrdNet.cc:313
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95