00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdProtLoadCVSID = "$Id: XrdProtLoad.cc 29874 2009-08-21 16:56:04Z ganis $";
00014
00015 #include "XrdSys/XrdSysError.hh"
00016 #include "XrdSys/XrdSysPlugin.hh"
00017
00018 #include "Xrd/XrdLink.hh"
00019 #include "Xrd/XrdPoll.hh"
00020 #include "Xrd/XrdProtLoad.hh"
00021 #include "Xrd/XrdTrace.hh"
00022
00023
00024
00025
00026
00027 extern XrdSysError XrdLog;
00028
00029 extern XrdOucTrace XrdTrace;
00030
00031 XrdProtocol *XrdProtLoad::ProtoWAN[ProtoMax] = {0};
00032 XrdProtocol *XrdProtLoad::Protocol[ProtoMax] = {0};
00033 char *XrdProtLoad::ProtName[ProtoMax] = {0};
00034 int XrdProtLoad::ProtPort[ProtoMax] = {0};
00035
00036 int XrdProtLoad::ProtoCnt = 0;
00037 int XrdProtLoad::ProtWCnt = 0;
00038
00039 char *XrdProtLoad::liblist[ProtoMax];
00040 XrdSysPlugin *XrdProtLoad::libhndl[ProtoMax];
00041
00042 int XrdProtLoad::libcnt = 0;
00043
00044
00045
00046
00047
00048 XrdProtLoad::XrdProtLoad(int port) :
00049 XrdProtocol("protocol loader") {myPort = port;}
00050
00051 XrdProtLoad::~XrdProtLoad() {}
00052
00053
00054
00055
00056
00057 int XrdProtLoad::Load(const char *lname, const char *pname,
00058 char *parms, XrdProtocol_Config *pi)
00059 {
00060 XrdProtocol *xp;
00061 int i, j, port = pi->Port;
00062 int wanopt = pi->WANPort;
00063
00064
00065
00066 if (TRACING(TRACE_DEBUG))
00067 {XrdTrace.Beg("Protocol");
00068 cerr <<"getting protocol object " <<pname;
00069 XrdTrace.End();
00070 }
00071
00072
00073
00074 if (ProtoCnt >= ProtoMax)
00075 {XrdLog.Emsg("Protocol", "Too many protocols have been defined.");
00076 return 0;
00077 }
00078
00079
00080
00081 if (lname) xp = getProtocol(lname, pname, parms, pi);
00082 else xp = XrdgetProtocol(pname, parms, pi);
00083 if (!xp) {XrdLog.Emsg("Protocol","Protocol", pname, "could not be loaded");
00084 return 0;
00085 }
00086
00087
00088
00089 if (wanopt) ProtoWAN[ProtWCnt++] = xp;
00090
00091
00092
00093 for (i = ProtoCnt-1; i >= 0; i--) if (port == ProtPort[i]) break;
00094 for (j = ProtoCnt-1; j > i; j--)
00095 {ProtName[j+1] = ProtName[j];
00096 ProtPort[j+1] = ProtPort[j];
00097 Protocol[j+1] = Protocol[j];
00098 }
00099
00100
00101
00102 ProtName[j+1] = strdup(pname);
00103 ProtPort[j+1] = port;
00104 Protocol[j+1] = xp;
00105 ProtoCnt++;
00106 return 1;
00107 }
00108
00109
00110
00111
00112
00113 int XrdProtLoad::Port(const char *lname, const char *pname,
00114 char *parms, XrdProtocol_Config *pi)
00115 {
00116 int port;
00117
00118
00119
00120 if (TRACING(TRACE_DEBUG))
00121 {XrdTrace.Beg("Protocol");
00122 cerr <<"getting port from protocol " <<pname;
00123 XrdTrace.End();
00124 }
00125
00126
00127
00128 if (lname) port = getProtocolPort(lname, pname, parms, pi);
00129 else port = XrdgetProtocolPort(pname, parms, pi);
00130 if (port < 0) XrdLog.Emsg("Protocol","Protocol", pname,
00131 "port number could not be determined");
00132 return port;
00133 }
00134
00135
00136
00137
00138
00139 int XrdProtLoad::Process(XrdLink *lp)
00140 {
00141 XrdProtocol *pp = 0;
00142 int i;
00143
00144
00145
00146 if (myPort < 0)
00147 {for (i = 0; i < ProtWCnt; i++)
00148 if ((pp = ProtoWAN[i]->Match(lp))) break;
00149 else if (lp->isFlawed()) return -1;
00150 } else {
00151 for (i = 0; i < ProtoCnt; i++)
00152 if (myPort == ProtPort[i] && (pp = Protocol[i]->Match(lp))) break;
00153 else if (lp->isFlawed()) return -1;
00154 }
00155 if (!pp) {lp->setEtext("matching protocol not found"); return -1;}
00156
00157
00158
00159 lp->setProtocol(pp);
00160
00161
00162
00163 if (TRACING(TRACE_DEBUG))
00164 {XrdTrace.Beg("Protocol");
00165 cerr <<"matched protocol " <<ProtName[i];
00166 XrdTrace.End();
00167 }
00168
00169
00170
00171 if (!XrdPoll::Attach(lp)) {lp->setEtext("attach failed"); return -1;}
00172
00173
00174
00175 return pp->Process(lp);
00176 }
00177
00178
00179
00180
00181
00182 void XrdProtLoad::Recycle(XrdLink *lp, int ctime, const char *reason)
00183 {
00184
00185
00186
00187 if (lp && reason)
00188 XrdLog.Emsg("Protocol", lp->ID, "terminated", reason);
00189 }
00190
00191
00192
00193
00194
00195 int XrdProtLoad::Stats(char *buff, int blen, int do_sync)
00196 {
00197 int i, k, totlen = 0;
00198
00199 for (i = 0; i < ProtoCnt && (blen > 0 || !buff); i++)
00200 {k = Protocol[i]->Stats(buff, blen, do_sync);
00201 totlen += k; buff += k; blen -= k;
00202 }
00203
00204 return totlen;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214 XrdProtocol *XrdProtLoad::getProtocol(const char *lname,
00215 const char *pname,
00216 char *parms,
00217 XrdProtocol_Config *pi)
00218 {
00219 XrdProtocol *(*ep)(const char *, char *, XrdProtocol_Config *);
00220 void *epvoid;
00221 int i;
00222
00223
00224
00225 for (i = 0; i < libcnt; i++) if (!strcmp(lname, liblist[i])) break;
00226 if (i >= libcnt)
00227 {XrdLog.Emsg("Protocol", pname, "was lost during loading", lname);
00228 return 0;
00229 }
00230
00231
00232
00233 if (!(epvoid = libhndl[i]->getPlugin("XrdgetProtocol"))) return 0;
00234 ep = (XrdProtocol *(*)(const char*,char*,XrdProtocol_Config*))epvoid;
00235 return ep(pname, parms, pi);
00236 }
00237
00238
00239
00240
00241
00242 int XrdProtLoad::getProtocolPort(const char *lname,
00243 const char *pname,
00244 char *parms,
00245 XrdProtocol_Config *pi)
00246 {
00247 int (*ep)(const char *, char *, XrdProtocol_Config *);
00248 void *epvoid;
00249 int i;
00250
00251
00252
00253 for (i = 0; i < libcnt; i++) if (!strcmp(lname, liblist[i])) break;
00254 if (i >= libcnt)
00255 {if (libcnt >= ProtoMax)
00256 {XrdLog.Emsg("Protocol", "Too many protocols have been defined.");
00257 return -1;
00258 }
00259 if (!(libhndl[i] = new XrdSysPlugin(&XrdLog, lname))) return -1;
00260 liblist[i] = strdup(lname);
00261 libcnt++;
00262 }
00263
00264
00265
00266 if (!(epvoid = libhndl[i]->getPlugin("XrdgetProtocolPort", 1)))
00267 return (pi->Port < 0 ? 0 : pi->Port);
00268 ep = (int (*)(const char*,char*,XrdProtocol_Config*))epvoid;
00269 return ep(pname, parms, pi);
00270 }