XRootD
Loading...
Searching...
No Matches
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"
40#include "XrdSys/XrdSysError.hh"
42
43/******************************************************************************/
44/* C o n s t r u c t o r */
45/******************************************************************************/
46
47XrdNetMsg::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
127int 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
168int 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
190int 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
241int 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
260int 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
271int XrdNetMsg::retErr(int ecode, XrdNetAddr& theDest)
272{
273 return retErr(ecode, theDest.Name("unknown"));
274}
#define XRDNET_SENDONLY
Definition XrdNetOpts.hh:43
struct sockaddr_in6 v6
struct sockaddr Addr
struct sockaddr_in v4
#define close(a)
Definition XrdPosix.hh:48
#define writev(a, b, c)
Definition XrdPosix.hh:117
#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)
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)
int Relay(XrdNetPeer &Peer, const char *dest, int opts=0)
Definition XrdNet.cc:313