XRootD
Loading...
Searching...
No Matches
XrdCmsParser.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d C m s P a r s e r . 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 <cstdio>
32#include <cerrno>
33#include <cinttypes>
34#include <cstdarg>
35#include <stddef.h>
36#include <cstdlib>
37#include <cstring>
38#include <netinet/in.h>
39#include <sys/types.h>
40
43#include "XrdCms/XrdCmsTrace.hh"
44
47
49
50#include "XrdSys/XrdSysError.hh"
51
52using namespace XrdCms;
53
54/******************************************************************************/
55/* L o c a l C l a s s e s */
56/******************************************************************************/
57
59{
60public:
61
62const char **nameVec() {return (const char **)PupNVec;}
63
64 XrdCmsParseInit(int mVal, ...)
65 {va_list ap;
66 int vp = mVal;
67// const char *Dummy;
68 memset(PupNVec, 0, sizeof(PupNVec));
69 va_start(ap, mVal);
70 do { if (vp < XrdCmsRRData::Arg_Count)
71 PupNVec[vp] = va_arg(ap, char *);
72 else va_arg(ap, char *);
73 } while((vp = va_arg(ap, int)));
74 va_end(ap);
75 }
77
78private:
79
80static char *PupNVec[XrdCmsRRData::Arg_Count];
81
82};
83
84/******************************************************************************/
85/* S t a t i c O b j e c t s */
86/******************************************************************************/
87
88char *XrdCmsParseInit::PupNVec[XrdCmsRRData::Arg_Count];
89
91 XrdCmsRRData::Arg_AToken, "authtoken",
92 XrdCmsRRData::Arg_Avoid, "bad_host",
94 XrdCmsRRData::Arg_Datlen, "datalen",
96 XrdCmsRRData::Arg_Ilist, "interfaces",
100 XrdCmsRRData::Arg_Opaque2, "opaque2",
106 XrdCmsRRData::Arg_dskFree, "diskfree",
107 XrdCmsRRData::Arg_dskTot, "disktotal",
108 XrdCmsRRData::Arg_dskMinf, "diskminf",
109 XrdCmsRRData::Arg_dskUtil, "diskutil",
114 0, (const char *)0
115 );
116
117// The structure that defines the item names to the packer/unpacker
118//
119XrdOucPupNames XrdCmsParser::PupName(XrdCmsParseArgN.nameVec(),
121
122// Common protocol data unpacker
123//
124XrdOucPup XrdCmsParser::Pup(&Say, &XrdCmsParser::PupName);
125
126// Reference array
127//
128XrdOucPupArgs *XrdCmsParser::vecArgs[kYR_MaxReq] = {0};
129
130// The actual parser object
131//
132XrdCmsParser XrdCms::Parser;
133
134/******************************************************************************/
135/* S t a t i c P a r s i n g D e s i f i n i t i o n s */
136/******************************************************************************/
137
138// {chmod, mkdir, mkpath, trunc} <id> <mode> <path> [<opq>]
139//
140XrdOucPupArgs XrdCmsParser::fwdArgA[] =
141/*0*/ {setPUP1(XrdCmsRRData::Arg_Ident, char, XrdCmsRRData, Ident),
144/*3*/ setPUP0(Fence),
145/*4*/ setPUP1(XrdCmsRRData::Arg_Opaque, char, XrdCmsRRData, Opaque),
146/*5*/ setPUP1(XrdCmsRRData::Arg_Datlen,EndFill,XrdCmsRRData, Request.datalen)
147 };
148
149// mv <id> <path1> <path2> [<opq1> [<opq2>]]
150//
151XrdOucPupArgs XrdCmsParser::fwdArgB[] =
152/*0*/ {setPUP1(XrdCmsRRData::Arg_Ident, char, XrdCmsRRData, Ident),
154/*2*/ setPUP1(XrdCmsRRData::Arg_Path2, char, XrdCmsRRData, Path2),
155/*3*/ setPUP0(Fence),
156/*4*/ setPUP1(XrdCmsRRData::Arg_Opaque, char, XrdCmsRRData, Opaque),
157/*5*/ setPUP1(XrdCmsRRData::Arg_Opaque2, char, XrdCmsRRData, Opaque2),
158/*6*/ setPUP1(XrdCmsRRData::Arg_Datlen,EndFill,XrdCmsRRData, Request.datalen)
159 };
160
161// {rm, rmdir, statfs} <id> <path> <opq>
162//
163XrdOucPupArgs XrdCmsParser::fwdArgC[] =
164/*0*/ {setPUP1(XrdCmsRRData::Arg_Ident, char, XrdCmsRRData, Ident),
166/*2*/ setPUP0(Fence),
167/*3*/ setPUP1(XrdCmsRRData::Arg_Opaque, char, XrdCmsRRData, Opaque),
168/*4*/ setPUP1(XrdCmsRRData::Arg_Datlen,EndFill,XrdCmsRRData, Request.datalen)
169 };
170
171// {locate, select} <id> <opts> <path> [<opq> [<avoid>]]
172//
173XrdOucPupArgs XrdCmsParser::locArgs[] =
174/*0*/ {setPUP1(XrdCmsRRData::Arg_Ident, char, XrdCmsRRData, Ident),
177/*3*/ setPUP1(XrdCmsRRData::Arg_Datlen,Datlen, XrdCmsRRData, PathLen),
178/*4*/ setPUP0(Fence),
179/*5*/ setPUP1(XrdCmsRRData::Arg_Opaque, char, XrdCmsRRData, Opaque),
180/*6*/ setPUP1(XrdCmsRRData::Arg_Avoid, char, XrdCmsRRData, Avoid),
181/*7*/ setPUP1(XrdCmsRRData::Arg_Datlen,EndFill,XrdCmsRRData, Request.datalen)
182 };
183
184// prepadd <id> <reqid> <notify> <prty> <mode> <path> [<opaque>]
185//
186XrdOucPupArgs XrdCmsParser::padArgs[] =
187/*0*/ {setPUP1(XrdCmsRRData::Arg_Ident, char, XrdCmsRRData, Ident),
188/*1*/ setPUP1(XrdCmsRRData::Arg_Reqid, char, XrdCmsRRData, Reqid),
189/*2*/ setPUP1(XrdCmsRRData::Arg_Notify, char, XrdCmsRRData, Notify),
193/*6*/ setPUP1(XrdCmsRRData::Arg_Datlen,Datlen, XrdCmsRRData, PathLen),
194/*7*/ setPUP0(Fence),
195/*8*/ setPUP1(XrdCmsRRData::Arg_Opaque, char, XrdCmsRRData, Opaque),
196/*9*/ setPUP1(XrdCmsRRData::Arg_Datlen,EndFill,XrdCmsRRData, Request.datalen)
197 };
198
199// prepdel <id> <reqid>
200//
201XrdOucPupArgs XrdCmsParser::pdlArgs[] =
202/*0*/ {setPUP1(XrdCmsRRData::Arg_Ident, char, XrdCmsRRData, Ident),
203/*1*/ setPUP1(XrdCmsRRData::Arg_Reqid, char, XrdCmsRRData, Reqid),
204/*2*/ setPUP1(XrdCmsRRData::Arg_Datlen,EndFill,XrdCmsRRData, Request.datalen)
205 };
206
207// avail <dskFree> <dskUtil>
208//
209XrdOucPupArgs XrdCmsParser::avlArgs[] =
210/*0*/ {setPUP1(XrdCmsRRData::Arg_dskFree, int, XrdCmsRRData, dskFree),
212/*2*/ setPUP0(End)
213 };
214
215// try <path>
216//
217XrdOucPupArgs XrdCmsParser::pthArgs[] =
219/*1*/ setPUP1(XrdCmsRRData::Arg_Datlen,Datlen, XrdCmsRRData, PathLen),
220/*2*/ setPUP1(XrdCmsRRData::Arg_Datlen,EndFill,XrdCmsRRData, Request.datalen)
221 };
222
223// load <cpu> <io> <load> <mem> <pag> <dut> <dsk>
224// 0 1 2 3 5 5
225XrdOucPupArgs XrdCmsParser::lodArgs[] =
226/*0*/ {setPUP1(XrdCmsRRData::Arg_theLoad, char, XrdCmsRRData, Opaque),
228/*2*/ setPUP0(End)
229 };
230
231XrdOucPupArgs XrdCmsParser::logArgs[] =
234/*2*/ setPUP1(XrdCmsRRData::Arg_Info, int, CmsLoginData, HoldTime),
238/*6*/ setPUP1(XrdCmsRRData::Arg_Info, short, CmsLoginData, fsNum),
239/*7*/ setPUP1(XrdCmsRRData::Arg_dskUtil, short, CmsLoginData, fsUtil),
240/*8*/ setPUP1(XrdCmsRRData::Arg_Port, short, CmsLoginData, dPort),
241/*9*/ setPUP1(XrdCmsRRData::Arg_Port, short, CmsLoginData, sPort),
242/*0*/ setPUP0(Fence),
244/*2*/ setPUP1(XrdCmsRRData::Arg_Path, char, CmsLoginData, Paths),
245/*3*/ setPUP1(XrdCmsRRData::Arg_Ilist, char, CmsLoginData, ifList),
246/*4*/ setPUP1(XrdCmsRRData::Arg_CGI, char, CmsLoginData, envCGI),
248 };
249
250/******************************************************************************/
251/* C o n s t r u c t o r */
252/******************************************************************************/
253
255{
256 static int Done = 0;
257
258// Setup the Parse vector
259//
260 if (!Done)
261 {vecArgs[kYR_login] = logArgs;
262 vecArgs[kYR_chmod] = fwdArgA;
263 vecArgs[kYR_locate] = locArgs;
264 vecArgs[kYR_mkdir] = fwdArgA;
265 vecArgs[kYR_mkpath] = fwdArgA;
266 vecArgs[kYR_mv] = fwdArgB;
267 vecArgs[kYR_prepadd] = padArgs;
268 vecArgs[kYR_prepdel] = pdlArgs;
269 vecArgs[kYR_rm] = fwdArgC;
270 vecArgs[kYR_rmdir] = fwdArgC;
271 vecArgs[kYR_select] = locArgs;
272 vecArgs[kYR_rm] = fwdArgC;
273 vecArgs[kYR_statfs] = pthArgs;
274 vecArgs[kYR_avail] = avlArgs;
275 vecArgs[kYR_gone] = pthArgs;
276 vecArgs[kYR_trunc] = fwdArgA;
277 vecArgs[kYR_try] = pthArgs;
278 vecArgs[kYR_have] = pthArgs;
279 vecArgs[kYR_load] = lodArgs;
280 vecArgs[kYR_state] = pthArgs;
281 Done = 1;
282 }
283}
284
285/******************************************************************************/
286/* D e c o d e */
287/******************************************************************************/
288
289// Decode responses to the redirector. Very simple lean protocol.
290
291int XrdCmsParser::Decode(const char *Man, CmsRRHdr &hdr, XrdOucBuffer *dBuff,
292 XrdOucErrInfo *eInfo)
293{
294 EPNAME("Decode");
295 static const int mvsz = static_cast<int>(sizeof(kXR_unt32));
296 kXR_unt32 uval;
297 int Result, msgval, msglen, dlen = dBuff->DataLen();
298 const char *Path = eInfo->getErrData(), *User = eInfo->getErrUser();
299 const char *Mgr = (Man ? Man : "?");
300 char *msg, *data = dBuff->Buffer();
301
302// Path may be null here, fix it
303//
304 if (!Path) Path = "";
305
306// Responses are always in the form of <int><string>
307//
308 if (dlen < mvsz) {msgval = 0; msg = (char *)""; msglen = 0;}
309 else {memcpy(&uval, data, mvsz);
310 msgval = static_cast<int>(ntohl(uval));
311 if (dlen == mvsz) {msg = (char *)""; msglen = 0;}
312 else {msg = data+mvsz; msglen = dlen - mvsz;}
313 }
314
315// Now decode the response code
316//
317 switch(hdr.rrCode)
318
319 {case kYR_redirect: Result = SFS_REDIRECT;
320 TRACE(Redirect, Mgr <<" redirects " <<User <<" to "
321 <<msg <<':' <<msgval <<' ' <<Path);
322 break;
323 case kYR_wait: Result = SFS_STALL;
324 TRACE(Redirect, Mgr <<" delays " <<User <<' ' <<msgval <<' ' <<Path);
325 break;
326 case kYR_waitresp: Result = SFS_STARTED;
327 TRACE(Redirect, Mgr <<" idles " <<User <<' ' <<msgval <<' ' <<Path);
328 break;
329 case kYR_data: Result = SFS_DATA; msgval = msglen;
330 TRACE(Redirect, Mgr <<" sent " <<User <<" '" <<msg <<"' " <<Path);
331 if (msglen > (int)XrdOucEI::Max_Error_Len)
333 if (myBuff)
334 {myBuff->SetLen(msglen, (msglen ? mvsz : 0));
335 eInfo->setErrInfo(msglen, myBuff);
336 return Result;
337 }
338 }
339 break;
340 case kYR_error: Result = SFS_ERROR;
341 if (msgval) msgval = -mapError(msgval);
342 TRACE(Redirect, Mgr <<" gave " <<User <<" err " <<msgval
343 <<" '" <<msg <<"' " <<Path);
344 break;
345 default: msgval=0; Result = SFS_ERROR;
346 msg = (char *)"Redirector protocol error";
347 TRACE(Redirect, User <<" given error msg '"
348 <<msg <<"' due to " << Mgr <<' ' <<Path);
349 }
350
351// Insert the information into the error object
352//
353 eInfo->setErrInfo(msgval, msg);
354 return Result;
355}
356
357/******************************************************************************/
358/* m a p E r r o r */
359/******************************************************************************/
360
361int XrdCmsParser::mapError(const char *ecode)
362{
363 if (!strcmp("ENOENT", ecode)) return ENOENT;
364 if (!strcmp("EEXIST", ecode)) return EEXIST;
365 if (!strcmp("EPERM", ecode)) return EPERM;
366 if (!strcmp("EACCES", ecode)) return EACCES;
367 if (!strcmp("EIO", ecode)) return EIO;
368 if (!strcmp("ENOMEM", ecode)) return ENOMEM;
369 if (!strcmp("ENOSPC", ecode)) return ENOSPC;
370 if (!strcmp("ENAMETOOLONG", ecode)) return ENAMETOOLONG;
371 if (!strcmp("ENETUNREACH", ecode)) return ENETUNREACH;
372 if (!strcmp("ENOTBLK", ecode)) return ENOTBLK;
373 if (!strcmp("EISDIR", ecode)) return EISDIR;
374 return EINVAL;
375}
376
378{
379 switch(ecode)
380 {case kYR_ENOENT: return ENOENT;
381 case kYR_EPERM: return EPERM;
382 case kYR_EACCES: return EACCES;
383 case kYR_EIO: return EIO;
384 case kYR_ENOMEM: return ENOMEM;
385 case kYR_ENOSPC: return ENOSPC;
386 case kYR_ENAMETOOLONG: return ENAMETOOLONG;
387 case kYR_ENETUNREACH: return ENETUNREACH;
388 case kYR_ENOTBLK: return ENOTBLK;
389 case kYR_EISDIR: return EISDIR;
390 case kYR_FSError: return ENODEV;
391 case kYR_SrvError: return EFAULT;
392 case kYR_RWConflict: return EEXIST;
393 case kYR_noReplicas: return EADDRNOTAVAIL;
394 default: return EINVAL;
395 }
396}
397
398/******************************************************************************/
399/* P a c k */
400/******************************************************************************/
401
402int XrdCmsParser::Pack(int rnum, struct iovec *iovP, struct iovec *iovE,
403 char *Base, char *Work)
404{
405 XrdOucPupArgs *PArgs;
406 const char *reason;
407 char buff[16];
408 int iovcnt;
409
410// Pack the request
411//
412 if ((PArgs = PupArgs(rnum)))
413 if ((iovcnt = Pup.Pack(iovP, iovE, PArgs, Base, Work))) return iovcnt;
414 else reason = "too much data for code";
415 else reason = "invalid request code -";
416
417// Indicate failure (we don't translate the request code as it drags in too
418// many dependent object files, sigh.
419//
420 sprintf(buff, "%d", rnum);
421 Say.Emsg("Pack", "Unable to pack request;", reason, buff);
422 return 0;
423}
unsigned int kXR_unt32
Definition XPtypes.hh:90
#define EPNAME(x)
XrdCmsParseInit XrdCmsParseArgN(XrdCmsRRData::Arg_Null, "", XrdCmsRRData::Arg_AToken, "authtoken", XrdCmsRRData::Arg_Avoid, "bad_host", XrdCmsRRData::Arg_CGI, "CGI", XrdCmsRRData::Arg_Datlen, "datalen", XrdCmsRRData::Arg_Ident, "ident", XrdCmsRRData::Arg_Ilist, "interfaces", XrdCmsRRData::Arg_Mode, "mode", XrdCmsRRData::Arg_Notify, "notify", XrdCmsRRData::Arg_Opaque, "opaque", XrdCmsRRData::Arg_Opaque2, "opaque2", XrdCmsRRData::Arg_Opts, "opts", XrdCmsRRData::Arg_Path, "path", XrdCmsRRData::Arg_Path2, "path2", XrdCmsRRData::Arg_Prty, "prty", XrdCmsRRData::Arg_Reqid, "reqid", XrdCmsRRData::Arg_dskFree, "diskfree", XrdCmsRRData::Arg_dskTot, "disktotal", XrdCmsRRData::Arg_dskMinf, "diskminf", XrdCmsRRData::Arg_dskUtil, "diskutil", XrdCmsRRData::Arg_theLoad, "load", XrdCmsRRData::Arg_Info, "info", XrdCmsRRData::Arg_Port, "port", XrdCmsRRData::Arg_SID, "SID", 0,(const char *) 0)
#define setPUP1(Name, Type, Base, Var)
Definition XrdOucPup.hh:88
#define setPUP0(Type)
Definition XrdOucPup.hh:86
static const kXR_int32 Version
int Mode
XrdOucString Path
#define SFS_DATA
#define SFS_ERROR
#define SFS_REDIRECT
#define SFS_STALL
#define SFS_STARTED
#define TRACE(act, x)
Definition XrdTrace.hh:63
const char ** nameVec()
XrdCmsParseInit(int mVal,...)
static int mapError(const char *ecode)
static XrdOucPupArgs * PupArgs(int rnum)
static int Pack(int rnum, struct iovec *iovP, struct iovec *iovE, char *Base, char *Work)
static int Decode(const char *Man, XrdCms::CmsRRHdr &hdr, XrdOucBuffer *dBuff, XrdOucErrInfo *eInfo)
static XrdOucPup Pup
char * Buffer() const
XrdOucBuffer * Highjack(int bPsz=0)
void SetLen(int dataL, int dataO=0)
const char * getErrUser()
const char * getErrData()
int setErrInfo(int code, const char *emsg)
static int Pack(struct iovec **, const char *, unsigned short &buff)
Definition XrdOucPup.cc:52
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
@ kYR_ENAMETOOLONG
Definition YProtocol.hh:157
@ kYR_FSError
Definition YProtocol.hh:161
@ kYR_ENOSPC
Definition YProtocol.hh:156
@ kYR_ENETUNREACH
Definition YProtocol.hh:158
@ kYR_EACCES
Definition YProtocol.hh:152
@ kYR_noReplicas
Definition YProtocol.hh:164
@ kYR_ENOMEM
Definition YProtocol.hh:155
@ kYR_ENOENT
Definition YProtocol.hh:150
@ kYR_SrvError
Definition YProtocol.hh:162
@ kYR_EISDIR
Definition YProtocol.hh:160
@ kYR_EPERM
Definition YProtocol.hh:151
@ kYR_ENOTBLK
Definition YProtocol.hh:159
@ kYR_RWConflict
Definition YProtocol.hh:163
@ kYR_redirect
Definition YProtocol.hh:143
@ kYR_waitresp
Definition YProtocol.hh:145
@ kYR_error
Definition YProtocol.hh:142
XrdSysError Say
kXR_char rrCode
Definition YProtocol.hh:84
@ kYR_select
Definition YProtocol.hh:100
@ kYR_mkpath
Definition YProtocol.hh:94
@ kYR_prepdel
Definition YProtocol.hh:97
@ kYR_statfs
Definition YProtocol.hh:111
@ kYR_login
Definition YProtocol.hh:90
@ kYR_prepadd
Definition YProtocol.hh:96
@ kYR_chmod
Definition YProtocol.hh:91
@ kYR_rmdir
Definition YProtocol.hh:99
@ kYR_mkdir
Definition YProtocol.hh:93
@ kYR_state
Definition YProtocol.hh:110
@ kYR_locate
Definition YProtocol.hh:92
@ kYR_trunc
Definition YProtocol.hh:113
@ kYR_MaxReq
Definition YProtocol.hh:118
@ kYR_avail
Definition YProtocol.hh:102
static const size_t Max_Error_Len