XRootD
Loading...
Searching...
No Matches
XrdProtLoad.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d P r o t L o a d . c c */
4/* */
5/* (c) 2006 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <vector>
31
33#include "XrdSys/XrdSysError.hh"
34
35#include "Xrd/XrdLink.hh"
36#include "Xrd/XrdProtLoad.hh"
37#include "Xrd/XrdTrace.hh"
38
39#include "XrdVersion.hh"
40
41/******************************************************************************/
42/* G l o b a l O b j e c t s */
43/******************************************************************************/
44
45XrdProtocol *XrdProtLoad::Protocol[ProtoMax] = {0};
46char *XrdProtLoad::ProtName[ProtoMax] = {0};
47
48int XrdProtLoad::ProtoCnt = 0;
49
50namespace
51{
52struct portMap
53 {int port;
54 short protIdx;
55 bool protTLS;
56
57 portMap(int pnum, int pidx, bool istls)
58 : port(pnum), protIdx(pidx), protTLS(istls) {}
59 ~portMap() {}
60 };
61
62std::vector<portMap> portVec;
63
64char *liblist[XrdProtLoad::ProtoMax];
66const char *TraceID = "ProtLoad";
67int libcnt = 0;
68}
69
70namespace XrdGlobal
71{
72extern XrdSysError Log;
73}
74using namespace XrdGlobal;
75
76/******************************************************************************/
77/* C o n s t r u c t o r a n d D e s t r u c t o r */
78/******************************************************************************/
79
81 XrdProtocol("protocol loader"), myPort(port)
82{
83 int j = 0;
84 bool hastls = false;
85
86// Extract out the protocols associated with this port
87//
88 for (int i = 0; i < (int)portVec.size(); i++)
89 {if (myPort == portVec[i].port)
90 {if (portVec[i].protTLS) hastls = true;
91 else myProt[j++] = portVec[i].protIdx;
92 }
93 }
94
95// Setup to handle tls protocols
96//
97 if (hastls)
98 {myProt[j++] = -1;
99 for (int i = 0; i < (int)portVec.size(); i++)
100 {if (myPort == portVec[i].port && portVec[i].protTLS)
101 myProt[j++] = portVec[i].protIdx;
102 }
103 }
104
105// Put in an end marker
106//
107 myProt[j] = -2;
108}
109
111
112/******************************************************************************/
113/* L o a d */
114/******************************************************************************/
115
116int XrdProtLoad::Load(const char *lname, const char *pname,
117 char *parms, XrdProtocol_Config *pi, bool istls)
118{
119 XrdProtocol *xp;
120 int port = pi->Port;
121
122// Trace this load if so wanted
123//
124 TRACE(DEBUG, "getting protocol object " <<pname);
125
126// First check to see that we haven't exceeded our protocol count
127//
128 if (ProtoCnt >= ProtoMax)
129 {Log.Emsg("Protocol", "Too many protocols have been defined.");
130 return 0;
131 }
132
133// Obtain an instance of this protocol
134//
135 xp = getProtocol(lname, pname, parms, pi);
136 if (!xp) {Log.Emsg("Protocol","Protocol", pname, "could not be loaded");
137 return 0;
138 }
139
140// Add protocol to our table of protocols.
141//
142 ProtName[ProtoCnt] = strdup(pname);
143 Protocol[ProtoCnt] = xp;
144 ProtoCnt++;
145
146// Map the port to this protocol
147//
148 Port(ProtoCnt, port, istls);
149 return ProtoCnt;
150}
151
152/******************************************************************************/
153/* P o r t */
154/******************************************************************************/
155
156int XrdProtLoad::Port(const char *lname, const char *pname,
157 char *parms, XrdProtocol_Config *pi)
158{
159 int port;
160
161// Obtain the port number to be used by this protocol
162//
163 port = getProtocolPort(lname, pname, parms, pi);
164
165// Trace this call if so wanted
166//
167 TRACE(DEBUG, "protocol " <<pname <<" wants to use port " <<port);
168
169// Make sure we can use the port
170//
171 if (port < 0) Log.Emsg("Protocol","Protocol", pname,
172 "port number could not be determined");
173 return port;
174}
175
176/******************************************************************************/
177
178void XrdProtLoad::Port(int protIdx, int port, bool isTLS)
179{
180 if (protIdx > 0 && protIdx <= ProtoCnt && port > 0)
181 {portMap pMap(port, protIdx-1, isTLS);
182 portVec.push_back(pMap);
183 TRACE(DEBUG, "enabling " <<(isTLS ? "tls port " : "port ") <<port
184 <<" for protocol " <<ProtName[protIdx-1]);
185 } else {
186 char buff[256];
187 snprintf(buff, sizeof(buff), "prot=%d port=%d;", protIdx, port);
188 Log.Emsg("Protocol", "Invalid Port() parms:", buff, "port not mapped!");
189 }
190}
191
192/******************************************************************************/
193/* P r o c e s s */
194/******************************************************************************/
195
197{
198 XrdProtocol *pp = 0;
199 signed char *pVec = myProt;
200 int i = 0;
201
202// Try to find a protocol match for this connection
203//
204 while(*pVec != -2)
205 {if (*pVec == -1)
206 {if (!(lp->setTLS(true)))
207 {lp->setEtext("TLS negotiation failed.");
208 return -1;
209 }
210 } else {i = *pVec;
211 if ((pp = Protocol[i]->Match(lp))) break;
212 else if (lp->isFlawed()) return -1;
213 }
214 pVec++;
215 }
216
217// Verify that we have an actual protocol
218//
219 if (!pp) {lp->setEtext("matching protocol not found"); return -1;}
220
221// Now attach the new protocol object to the link
222//
223 lp->setProtocol(pp);
224 lp->setProtName(ProtName[i]);
225
226// Trace this load if so wanted
227//
228 TRACE(DEBUG, "matched port " <<myPort <<" protocol " <<ProtName[i]);
229
230// Activate this link
231//
232 if (!lp->Activate()) {lp->setEtext("activation failed"); return -1;}
233
234// Take a short-cut and process the initial request as a sticky request
235//
236 return pp->Process(lp);
237}
238
239/******************************************************************************/
240/* R e c y c l e */
241/******************************************************************************/
242
243void XrdProtLoad::Recycle(XrdLink *lp, int ctime, const char *reason)
244{
245
246// Document non-protocol errors
247//
248 if (lp && reason)
249 Log.Emsg("Protocol", lp->ID, "terminated", reason);
250}
251
252/******************************************************************************/
253/* S t a t i s t i c s */
254/******************************************************************************/
255
256int XrdProtLoad::Statistics(char *buff, int blen, int do_sync)
257{
258 int i, k, totlen = 0;
259
260 for (i = 0; i < ProtoCnt && (blen > 0 || !buff); i++)
261 {k = Protocol[i]->Stats(buff, blen, do_sync);
262 totlen += k; buff += k; blen -= k;
263 }
264
265 return totlen;
266}
267
268/******************************************************************************/
269/* P r i v a t e M e t h o d s */
270/******************************************************************************/
271/******************************************************************************/
272/* g e t P r o t o c o l */
273/******************************************************************************/
274
275extern "C" XrdProtocol *XrdgetProtocol(const char *pname, char *parms,
277
278XrdProtocol *XrdProtLoad::getProtocol(const char *lname,
279 const char *pname,
280 char *parms,
282{
283 XrdProtocol *(*ep)(const char *, char *, XrdProtocol_Config *);
284 const char *xname = (lname ? lname : "");
285 void *epvoid;
286 int i;
287
288// If this is a builtin protocol getthe protocol object directly
289//
290 if (!lname) return XrdgetProtocol(pname, parms, pi);
291
292// Find the matching library. It must be here because getPort was already called
293//
294 for (i = 0; i < libcnt; i++) if (!strcmp(xname, liblist[i])) break;
295 if (i >= libcnt)
296 {Log.Emsg("Protocol", pname, "was lost during loading", lname);
297 return 0;
298 }
299
300// Obtain an instance of the protocol object and return it
301//
302 if (!(epvoid = libhndl[i]->Resolve("XrdgetProtocol"))) return 0;
303 ep = (XrdProtocol *(*)(const char*,char*,XrdProtocol_Config*))epvoid;
304 return ep(pname, parms, pi);
305}
306
307/******************************************************************************/
308/* g e t P r o t o c o l P o r t */
309/******************************************************************************/
310
311 extern "C" int XrdgetProtocolPort(const char *pname, char *parms,
313
314int XrdProtLoad::getProtocolPort(const char *lname,
315 const char *pname,
316 char *parms,
318{
319 static XrdVERSIONINFODEF(myVer, xrd, XrdVNUMBER, XrdVERSION);
320 const char *xname = (lname ? lname : "");
321 int (*ep)(const char *, char *, XrdProtocol_Config *);
322 void *epvoid;
323 int i;
324
325// If this is for the builtin protocol then get the port directly
326//
327 if (!lname) return XrdgetProtocolPort(pname, parms, pi);
328
329// See if the library is already opened, if not open it
330//
331 for (i = 0; i < libcnt; i++) if (!strcmp(xname, liblist[i])) break;
332 if (i >= libcnt)
333 {if (libcnt >= ProtoMax)
334 {Log.Emsg("Protocol", "Too many protocols have been defined.");
335 return -1;
336 }
337 if (!(libhndl[i] = new XrdOucPinLoader(&Log,&myVer,"protocol",lname)))
338 return -1;
339 liblist[i] = strdup(xname);
340 libcnt++;
341 }
342
343// Get the port number to be used
344//
345 if (!(epvoid = libhndl[i]->Resolve("XrdgetProtocolPort", 2)))
346 return (pi->Port < 0 ? 0 : pi->Port);
347 ep = (int (*)(const char*,char*,XrdProtocol_Config*))epvoid;
348 return ep(pname, parms, pi);
349}
#define DEBUG(x)
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
XrdProtocol * XrdgetProtocol(const char *pname, char *parms, XrdProtocol_Config *pi)
int XrdgetProtocolPort(const char *pname, char *parms, XrdProtocol_Config *pi)
#define TRACE(act, x)
Definition XrdTrace.hh:63
void Recycle(XrdLink *lp, int ctime, const char *txt)
XrdProtLoad(int port=-1)
static int Statistics(char *buff, int blen, int do_sync=0)
XrdProtocol * Match(XrdLink *)
int Process(XrdLink *lp)
static int Port(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi)
static int Load(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi, bool istls)
static const int ProtoMax
XrdProtocol(const char *jname)
virtual int Process(XrdLink *lp)=0
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
XrdSysError Log
Definition XrdConfig.cc:113