XrdOucPup.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d O u c P u p . c c                           */
00004 /*                                                                            */
00005 /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdOucPup.cc 30949 2009-11-02 16:37:58Z ganis $
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 /*                                  P a c k                                   */
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 // Pack the data as "<short len><char>" if data is present or "<short 0>" o/w.
00044 // When data is present, the null byte is always included.
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        //cerr <<"arg " <<pP-pup <<" type " <<Dtype <<' '
00145        //     <<(Names->NList[pP->Name] ? Names->NList[pP->Name] : "?") <<endl;
00146        switch(Dtype)
00147              {case PT_char:
00148 /* Null Pointer */ 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 /* Full String */  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 // We over-ran the iovec array
00220 //
00221    return eMsg("arg list too long packing", int(pP-pup), pup);
00222 }
00223 
00224 /******************************************************************************/
00225 /*                                U n p a c k                                 */
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 // Grab the length but make sure it's within bounds
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 // Now grab the data
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 // Make sure we are not missing any items
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 /*                                  e M s g                                   */
00327 /******************************************************************************/
00328   
00329 int XrdOucPup::eMsg(const char *etxt, int ino, XrdOucPupArgs *pup)
00330 {
00331    const char *dtn;
00332    char buff[1024];
00333 
00334 // Check if we can print an error message
00335 //
00336    if (!eDest) return 0;
00337 
00338 // Get type name
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 // Format the message
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 }

Generated on Tue Jul 5 14:46:50 2011 for ROOT_528-00b_version by  doxygen 1.5.1