00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdOucPupCVSID = "$Id: XrdOucPup.cc 30949 2009-11-02 16:37:58Z ganis $";
00014
00015 #include <errno.h>
00016 #include <sys/uio.h>
00017 #include <netinet/in.h>
00018 #include <inttypes.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021
00022 #ifdef WIN32
00023 #include <direct.h>
00024 #include "XrdSys/XrdWin32.hh"
00025 #endif
00026
00027 #include "XrdOuc/XrdOucPup.hh"
00028 #include "XrdSys/XrdSysError.hh"
00029 #include "XrdSys/XrdSysHeaders.hh"
00030 #include "XrdSys/XrdSysPlatform.hh"
00031
00032
00033
00034
00035
00036 int XrdOucPup::Pack(struct iovec **iovP,
00037 const char *data,
00038 unsigned short &buff)
00039 {
00040 unsigned short dlen;
00041 struct iovec *vP = *iovP;
00042
00043
00044
00045
00046 vP->iov_base = (char *)&buff; vP->iov_len = sizeof(buff); vP++;
00047
00048 if (data)
00049 {dlen = static_cast<unsigned short>(strlen(data)+1);
00050 buff = htons(dlen);
00051 vP->iov_base = (char *)data; vP->iov_len = dlen; vP++;
00052 } else {buff = 0; dlen = 0;}
00053
00054 *iovP = vP;
00055 return dlen+sizeof(buff);
00056 }
00057
00058
00059
00060 int XrdOucPup::Pack(struct iovec **iovP,
00061 const char *data,
00062 unsigned short &buff,
00063 int dlen)
00064 {
00065 struct iovec *vP = *iovP;
00066
00067 vP->iov_base = (char *)&buff; vP->iov_len = sizeof(buff); vP++;
00068
00069 if (data)
00070 {buff = htons(static_cast<unsigned short>(dlen));
00071 vP->iov_base = (char *)data; vP->iov_len = dlen; vP++;
00072 } else {buff = 0; dlen = 0;}
00073
00074 *iovP = vP;
00075 return dlen+sizeof(buff);
00076 }
00077
00078
00079
00080 int XrdOucPup::Pack(char **buff,
00081 const char *data,
00082 int dlen)
00083 {
00084 char *bp = *buff;
00085 unsigned short xlen;
00086
00087 if (data)
00088 {if (dlen < 0) dlen = strlen(data)+1;
00089 xlen = htons(static_cast<unsigned short>(dlen));
00090 memcpy(bp, &xlen, sizeof(xlen)); bp += sizeof(xlen);
00091 memcpy(bp, data, dlen);
00092 bp += dlen;
00093 } else {*bp++ = '\0'; *bp++ = '\0'; dlen = 0;}
00094
00095 *buff = bp;
00096 return dlen+sizeof(xlen);
00097 }
00098
00099
00100
00101 int XrdOucPup::Pack(char **buff,
00102 unsigned int data)
00103 {
00104 unsigned int netData = htonl(data);
00105 char *bp = *buff;
00106
00107 if (netData & PT_Mask)
00108 {*bp = static_cast<char>(PT_int);
00109 memcpy(bp+1, &netData, sizeof(netData));
00110 *buff = bp + sizeof(netData)+1;
00111 return sizeof(netData)+1;
00112 }
00113 (*(char *)&netData) |= PT_int | PT_Inline;
00114 memcpy(bp, &netData, sizeof(netData));
00115 *buff = bp + sizeof(netData);
00116 return sizeof(netData);
00117 }
00118
00119
00120
00121 int XrdOucPup::Pack(struct iovec *iovP, struct iovec *iovE, XrdOucPupArgs *pup,
00122 char *base, char *Work)
00123 {
00124 static char Nil[] = {PT_char, '\0'};
00125 static const int Sz16 = sizeof(short) + 1;
00126 static const int Sz32 = sizeof(int) + 1;
00127 static const int Sz64 = sizeof(long long) + 1;
00128 struct iovec *vP = iovP;
00129 XrdOucPupArgs *pP = pup;
00130 char *wP = Work;
00131 int Dtype, dlen = 0, TotLen = 0;
00132
00133 unsigned long long n64;
00134 unsigned int n32;
00135 unsigned short n16;
00136
00137 union {unsigned long long *B64;
00138 unsigned int *B32;
00139 unsigned short *B16;
00140 char **B08;} Base;
00141
00142 do {Base.B08 = (char **)(base + pP->Doffs);
00143 Dtype = pP->Dtype;
00144
00145
00146 switch(Dtype)
00147 {case PT_char:
00148 if (!*Base.B08) {vP->iov_base = Nil; vP->iov_len = 2;
00149 vP++; TotLen += 2; break;
00150 }
00151 dlen = (pP->Dlen < 0 ? strlen(*Base.B08)+1 : pP->Dlen);
00152 if (dlen > MaxLen)
00153 return eMsg("string too long packing", int(pP-pup), pP);
00154 if (vP >= iovE)
00155 return eMsg("too many args packing", int(pP-pup), pP);
00156 n16 = htons(static_cast<unsigned short>(dlen));
00157 vP->iov_base = wP; vP->iov_len = sizeof(n16); vP++;
00158 memcpy(wP, &n16, sizeof(n16)); wP += sizeof(n16);
00159 vP->iov_base = *Base.B08; vP->iov_len = dlen; vP++;
00160 TotLen += dlen + sizeof(n16);
00161 break;
00162
00163 case PT_short:
00164 n16 = htons(*Base.B16);
00165 *wP = static_cast<char>(PT_short);
00166 memcpy(wP+1, &n16, sizeof(n16));
00167 vP->iov_base = wP; vP->iov_len = Sz16; vP++;
00168 wP += Sz16; TotLen += Sz16; dlen = sizeof(n16);
00169 break;
00170
00171 case PT_int:
00172 n32 = htonl(*Base.B32);
00173 *wP = static_cast<char>(PT_int);
00174 memcpy(wP+1, &n32, sizeof(n32));
00175 vP->iov_base = wP; vP->iov_len = Sz32; vP++;
00176 wP += Sz32; TotLen += Sz32; dlen = sizeof(n32);
00177 break;
00178
00179 case PT_longlong:
00180 h2nll(*Base.B64, n64);
00181 *wP = static_cast<char>(PT_longlong);
00182 memcpy(wP+1, &n64, sizeof(n64));
00183 vP->iov_base = wP; vP->iov_len = Sz64; vP++;
00184 wP += Sz64; TotLen += Sz64; dlen = sizeof(n64);
00185 break;
00186
00187 case PT_special: break;
00188
00189 case PT_Fence: break;
00190 case PT_Ignore: break;
00191
00192 case PT_MandS:
00193 case PT_Mark:
00194 *Base.B08 = (char *)vP;
00195 if (pP->Dtype == PT_Mark) break;
00196
00197 case PT_Skip:
00198 vP++;
00199 break;
00200
00201 case PT_Datlen:
00202 *Base.B32 = dlen;
00203 break;
00204
00205 case PT_Totlen:
00206 *Base.B32 = TotLen;
00207 break;
00208
00209 case PT_EndFill:
00210 *Base.B16 = htons(static_cast<unsigned short>(TotLen));
00211 case PT_End:
00212 return static_cast<int>(vP-iovP);
00213
00214 default: {}
00215 }
00216 pP++;
00217 } while(vP < iovE);
00218
00219
00220
00221 return eMsg("arg list too long packing", int(pP-pup), pup);
00222 }
00223
00224
00225
00226
00227
00228
00229 int XrdOucPup::Unpack( char **buff,
00230 const char *bend,
00231 char **data,
00232 int &dlen)
00233 {
00234 unsigned short temp;
00235 char *bnxt = *buff;
00236
00237
00238
00239 if ((bnxt = bnxt+sizeof(temp)) > bend) return 0;
00240 memcpy(&temp, *buff, sizeof(temp));
00241 dlen = static_cast<int>(ntohs(temp));
00242
00243
00244
00245 if (dlen) {*data = (char *)bnxt; bnxt += dlen;}
00246 else *data = 0;
00247 *buff = bnxt;
00248 return (bnxt <= bend);
00249 }
00250
00251
00252
00253 int XrdOucPup::Unpack(const char *buff, const char *bend,
00254 XrdOucPupArgs *pup, char *base)
00255 {
00256 const char *bp = buff, *dp;
00257 XrdOucPupArgs *uP = pup;
00258 int dlen = 0, Dtype, Aok = 0, Done = 0;
00259 union {unsigned long long b64;
00260 unsigned int b32;
00261 unsigned short b16;
00262 unsigned char b08;} Temp;
00263
00264 union {unsigned long long *B64;
00265 unsigned int *B32;
00266 unsigned short *B16;
00267 char **B08;} Base;
00268
00269
00270 while(!Done)
00271 {Base.B08 = (char **)(base+uP->Doffs);
00272 if (uP->Dtype & PT_MaskD)
00273 {switch(uP->Dtype)
00274 {case PT_Fence: Aok = 1; break;
00275 case PT_Datlen: *Base.B32 = dlen; break;
00276 case PT_End:
00277 case PT_EndFill: Done = 1; uP--; break;
00278 default: {}
00279 }
00280 uP++; continue;
00281 }
00282 if (bp+2 > bend)
00283 return eMsg("buffer overrun unpacking", int(uP-pup), uP);
00284 if (uP->Dtype == PT_char && !(*bp & PT_short))
00285 {memcpy(&Temp.b16, bp, sizeof(unsigned short));
00286 dlen = static_cast<int>(ntohs(Temp.b16));
00287 bp += sizeof(unsigned short);
00288 if (dlen)
00289 if (bp+dlen > bend)
00290 return eMsg("buffer overrun unpacking", int(uP-pup), uP);
00291 else *Base.B08 = (char *)bp;
00292 else if (!Aok) break;
00293 else *Base.B08 = 0;
00294 } else {
00295 Dtype = static_cast<int>(*bp & PT_MaskT);
00296 if ((unsigned char)Dtype != uP->Dtype)
00297 return eMsg("arg/data mismatch unpacking", int(uP-pup), uP);
00298 if (!(dlen = (*bp & PT_MaskB)>>3)) dlen = sizeof(unsigned short);
00299 dp = (*bp & PT_Inline ? bp : bp+1);
00300 if (dp+dlen > bend)
00301 return eMsg("buffer overrun unpacking", int(uP-pup), uP);
00302 memcpy(&Temp.b64, dp, dlen);
00303 if (bp == dp) Temp.b08 &= PT_MaskD;
00304 else bp++;
00305 switch(Dtype)
00306 {case PT_short: *Base.B16 = ntohs(Temp.b16); break;
00307
00308 case PT_int: *Base.B32 = ntohl(Temp.b32); break;
00309
00310 case PT_longlong: *Base.B64 = ntohll(Temp.b64); break;
00311
00312 default: {}
00313 }
00314 }
00315 uP++; bp += dlen;
00316 };
00317
00318
00319
00320 if (Aok || uP->Dtype == PT_End || uP->Dtype == PT_EndFill)
00321 return static_cast<int>(uP-pup);
00322 return eMsg("missing arg unpacking", int(uP-pup), uP);
00323 }
00324
00325
00326
00327
00328
00329 int XrdOucPup::eMsg(const char *etxt, int ino, XrdOucPupArgs *pup)
00330 {
00331 const char *dtn;
00332 char buff[1024];
00333
00334
00335
00336 if (!eDest) return 0;
00337
00338
00339
00340 switch(pup->Dtype)
00341 {case PT_char: dtn = "char"; break;
00342 case PT_short: dtn = "short"; break;
00343 case PT_int: dtn = "int"; break;
00344 case PT_longlong: dtn = "long long"; break;
00345 case PT_special: dtn = "special"; break;
00346 default: dtn = ""; break;
00347 };
00348
00349
00350
00351 sprintf(buff, "%s arg %d: %s.", dtn, ino,
00352 (!Names||pup->Name >= Names->NLnum ? "?" : Names->NList[pup->Name]));
00353
00354 eDest->Emsg("Pup", etxt, buff);
00355 return 0;
00356 }