XRootD
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 
45 XrdProtocol *XrdProtLoad::Protocol[ProtoMax] = {0};
46 char *XrdProtLoad::ProtName[ProtoMax] = {0};
47 
48 int XrdProtLoad::ProtoCnt = 0;
49 
50 namespace
51 {
52 struct 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 
62 std::vector<portMap> portVec;
63 
64 char *liblist[XrdProtLoad::ProtoMax];
66 const char *TraceID = "ProtLoad";
67 int libcnt = 0;
68 }
69 
70 namespace XrdGlobal
71 {
72 extern XrdSysError Log;
73 }
74 using 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 
116 int 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 
156 int 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 
178 void 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 
243 void 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 
256 int 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 
275 extern "C" XrdProtocol *XrdgetProtocol(const char *pname, char *parms,
276  XrdProtocol_Config *pi);
277 
278 XrdProtocol *XrdProtLoad::getProtocol(const char *lname,
279  const char *pname,
280  char *parms,
281  XrdProtocol_Config *pi)
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,
312  XrdProtocol_Config *pi);
313 
314 int XrdProtLoad::getProtocolPort(const char *lname,
315  const char *pname,
316  char *parms,
317  XrdProtocol_Config *pi)
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)
Definition: XrdBwmTrace.hh:54
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)
Definition: XrdProtLoad.cc:243
XrdProtocol * Match(XrdLink *)
Definition: XrdProtLoad.hh:50
XrdProtLoad(int port=-1)
Definition: XrdProtLoad.cc:80
static int Statistics(char *buff, int blen, int do_sync=0)
Definition: XrdProtLoad.cc:256
int Process(XrdLink *lp)
Definition: XrdProtLoad.cc:196
static int Port(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi)
Definition: XrdProtLoad.cc:156
static int Load(const char *lname, const char *pname, char *parms, XrdProtocol_Config *pi, bool istls)
Definition: XrdProtLoad.cc:116
static const int ProtoMax
Definition: XrdProtLoad.hh:63
virtual int Stats(char *buff, int blen, int do_sync=0)=0
virtual int Process(XrdLink *lp)=0
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
XrdSysError Log
Definition: XrdConfig.cc:112