XrdSutBuffer.cc

Go to the documentation of this file.
00001 // $Id: XrdSutBuffer.cc 30949 2009-11-02 16:37:58Z ganis $
00002 
00003 const char *XrdSutBufferCVSID = "$Id: XrdSutBuffer.cc 30949 2009-11-02 16:37:58Z ganis $";
00004 /******************************************************************************/
00005 /*                                                                            */
00006 /*                      X r d S u t B u f f e r . c c                         */
00007 /*                                                                            */
00008 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00009 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00010 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00011 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00012 /******************************************************************************/
00013 
00014 #include <stdio.h>
00015 #include <string.h>
00016 #include <errno.h>
00017 
00018 #include <XrdSec/XrdSecInterface.hh>
00019 #include <XrdOuc/XrdOucString.hh>
00020 #include <XrdSut/XrdSutBuffer.hh>
00021 #include <XrdSut/XrdSutTrace.hh>
00022 
00023 /******************************************************************************/
00024 /*                                                                            */
00025 /*  Buffer structure for managing exchanged buckets                           */
00026 /*                                                                            */
00027 /******************************************************************************/
00028 
00029 //_____________________________________________________________________________
00030 XrdSutBuffer::XrdSutBuffer(const char *buf, kXR_int32 len)
00031 {
00032    // Constructor from compact form (used for exchange over the network)
00033    // If the buffer begins with "&P=", then only the protocol name and
00034    // options are extracted, assuming the format "&P=<protocol>,<options>".
00035    // Otherwise the format "<protocol><step><bucket_1>...<bucket_n>" is
00036    // assumed 
00037    EPNAME("Buffer::XrdSutBuffer");
00038 
00039    bool ok = 1;
00040 
00041    // Default initialization
00042    fOptions = "";
00043    fProtocol = "";
00044    fStep = 0;
00045 
00046    //
00047    // Check type of buffer
00048    if (!strncmp(buf,"&P=",3)) {
00049       //
00050       // Initial buffer format
00051       // Extract protocol name and options
00052       int cur = 3;
00053       int k = 0;
00054       while (buf[cur+k] && buf[cur+k] != ',' &&
00055              k < XrdSecPROTOIDSIZE && (cur+k) < len) k++;
00056       if (!k) {
00057          PRINT("no protocol name - do nothing");
00058       } else {
00059          //
00060          // Extract protocol name
00061          char proto[XrdSecPROTOIDSIZE];
00062          strncpy(proto,buf+cur,k);
00063          proto[k] = 0;  // null-terminated
00064          fProtocol = proto;
00065          cur += (k+1);
00066          //
00067          // Extract options, if any
00068          if (cur < len) {
00069             k = 0;
00070             while ((cur+k) < len && buf[cur+k])
00071                k++;
00072             if (k) {
00073                char *opts = new char[k+1];
00074                if (opts) {
00075                   strncpy(opts,buf+cur,k);
00076                   opts[k] = 0;  // null-terminated
00077                   fOptions = opts;
00078                   delete[] opts;
00079                }
00080             }
00081             cur += (k+1);
00082          }
00083       }
00084 
00085    } else {
00086       //
00087       // Assume exchange info format
00088       // Check integrity
00089       int k = 0;
00090       while (buf[k] && k < XrdSecPROTOIDSIZE && k < len) { k++; } 
00091       if (!k || k == XrdSecPROTOIDSIZE) {
00092          PRINT("no protocol name: do nothing");
00093          ok = 0;
00094       }
00095       int cur = k+1;
00096       if (ok) {
00097          //
00098          // Extract protocol name
00099          char proto[XrdSecPROTOIDSIZE];
00100          strcpy(proto,buf);
00101          fProtocol = proto;
00102       
00103          //
00104          // Step/Iteration number
00105          kXR_int32 step;
00106          memcpy(&step,&buf[cur],sizeof(kXR_int32));
00107          fStep = ntohl(step);
00108          cur += sizeof(kXR_int32);
00109       }
00110 
00111       //
00112       // Total length of buckets (sizes+buffers) (excluded trailing 0)
00113       int ltot = len - sizeof(kXR_int32);
00114       TRACE(Dump,"ltot: " <<ltot);
00115       
00116       //
00117       // Now the buckets
00118       kXR_int32 type;
00119       kXR_int32 blen;
00120       XrdSutBucket *tmp = 0;
00121       char *buck = 0;
00122       while (ok) {
00123       
00124          //
00125          // Get type 
00126          memcpy(&type,&buf[cur],sizeof(kXR_int32));
00127          type = ntohl(type);
00128          TRACE(Dump,"type: " <<XrdSutBuckStr(type));
00129       
00130          if (type == kXRS_none) {
00131             //
00132             // We are over
00133             ok = 0;
00134          } else {
00135             //
00136             cur += sizeof(kXR_int32);
00137             //
00138             // Get length and test consistency
00139             memcpy(&blen,&buf[cur],sizeof(kXR_int32));
00140             blen = ntohl(blen);
00141             TRACE(Dump,"blen: " <<blen);
00142             //
00143             cur += sizeof(kXR_int32);
00144             TRACE(Dump,"cur: " <<cur);
00145             if ((cur-1+blen) > ltot)
00146                ok = 0;
00147             else {
00148                //
00149                // Store only active buckets
00150                if (type != kXRS_inactive){
00151                   //
00152                   // Normal active bucket: save it in the vector
00153                   if ((buck = new char[blen])) {
00154                      memcpy(buck,&buf[cur],blen);
00155                      if ((tmp = new XrdSutBucket(buck,blen,type))) {
00156                         fBuckets.PushBack(tmp);
00157                      } else {
00158                         PRINT("error creating bucket: "<<XrdSutBuckStr(type)
00159                               <<" (size: "<<blen<<", !buck:"<<(!buck)<<")");
00160                      }
00161                   } else {
00162                      PRINT("error allocating buffer for bucket: "
00163                            <<XrdSutBuckStr(type)<<" (size:"<<blen<<")");
00164                   }
00165                }
00166                cur += blen;
00167             }
00168          }
00169       }
00170    }
00171 }
00172 
00173 //_____________________________________________________________________________
00174 XrdSutBuffer::~XrdSutBuffer()
00175 {
00176    // Destructor
00177    // XrdSutBuffer is responsible of the buckets in the list
00178    EPNAME("Buffer::~XrdSutBuffer");
00179 
00180    XrdSutBucket *bp = fBuckets.Begin();
00181    while (bp) {
00182       TRACE(Dump,"type: " << bp->type);
00183       delete bp;
00184       // Get next bucket
00185       bp = fBuckets.Next();
00186    }
00187 }
00188 
00189 //_____________________________________________________________________________
00190 int XrdSutBuffer::UpdateBucket(const char *b, int sz, int ty)
00191 {
00192    // Update existing bucket (or add a new bucket to the list)
00193    // with sz bytes at 'b'.
00194    // Returns 0 or -1 if error allocating bucket
00195    EPNAME("Buffer::UpdateBucket");
00196 
00197    XrdSutBucket *bp = GetBucket(ty);
00198    if (!bp) {
00199       bp = new XrdSutBucket(0,0,ty);
00200       if (!bp) {
00201          DEBUG("Out-Of-Memory allocating bucket");
00202          return -1;
00203       }
00204       AddBucket(bp);
00205    }
00206    bp->SetBuf(b,sz);
00207    // Done
00208    return 0;
00209 }
00210 
00211 //_____________________________________________________________________________
00212 int XrdSutBuffer::UpdateBucket(XrdOucString s, int ty)
00213 {
00214    // Update existing bucket (or add a new bucket to the list)
00215    // with string s.
00216    // Returns 0 or -1 if error allocating bucket
00217 
00218    return UpdateBucket(s.c_str(),s.length(),ty);
00219 }
00220 
00221 //_____________________________________________________________________________
00222 void XrdSutBuffer::Dump(const char *stepstr)
00223 {
00224    // Dump content of buffer
00225    EPNAME("Buffer::Dump");
00226 
00227    PRINT("//-----------------------------------------------------//");
00228    PRINT("//                                                     //")
00229    PRINT("//            XrdSutBuffer DUMP                        //")
00230    PRINT("//                                                     //")
00231 
00232    int nbuck = fBuckets.Size();
00233 
00234    PRINT("//  Buffer        : " <<this);
00235    PRINT("// ");
00236    PRINT("//  Proto         : " <<fProtocol.c_str());
00237    if (fOptions.length()) {
00238       PRINT("//  Options       : " <<fOptions.c_str());
00239    } else {
00240       PRINT("//  Options       : none");
00241    }
00242    if (stepstr) {
00243       PRINT("//  Step          : " <<stepstr);
00244    } else {
00245       PRINT("//  Step          : " <<fStep);
00246    }
00247    PRINT("//  # of buckets  : " <<nbuck);
00248    PRINT("// ");
00249  
00250    int kb = 0;
00251    XrdSutBucket *bp = fBuckets.Begin();
00252    while (bp) {
00253       PRINT("// ");
00254       PRINT("//  buck: " <<kb++);
00255       bp->Dump(0);
00256       // Get next
00257       bp = fBuckets.Next();
00258    }
00259    PRINT("//                                                     //")
00260    PRINT("//-----------------------------------------------------//");
00261 }
00262 
00263 //_____________________________________________________________________________
00264 void XrdSutBuffer::Message(const char *prepose)
00265 {
00266    // Print content of any bucket of type kXRS_message
00267    // Prepose 'prepose', if defined 
00268 
00269    bool pripre = 0;
00270    if (prepose)
00271       pripre = 1;
00272  
00273    XrdSutBucket *bp = fBuckets.Begin();
00274    while (bp) {
00275       if (bp->type == kXRS_message) {
00276          if (bp->size > 0 && bp->buffer) {
00277             if (pripre) {
00278                XrdOucString premsg(prepose);
00279                cerr << premsg << endl;
00280                pripre = 0;
00281             }
00282             XrdOucString msg(bp->buffer,bp->size);
00283             cerr << msg << endl;
00284          }
00285       }
00286       // Get next
00287       bp = fBuckets.Next();
00288    }
00289 }
00290 
00291 //_____________________________________________________________________________
00292 kXR_int32 XrdSutBuffer::MarshalBucket(kXR_int32 type, kXR_int32 code)
00293 {
00294    // Search the vector of buckets for the first bucket of
00295    // type 'type'. Reset its content and fill it with 'code'
00296    // in network byte order. If no bucket 'type' exists, add
00297    // a new one.
00298    // Returns -1 if new bucket could be allocated; 0 otherwise .
00299    EPNAME("Buffer::MarshalBucket");
00300 
00301    // Convert to network byte order
00302    kXR_int32 mcod = htonl(code);
00303 
00304    // Get the bucket
00305    XrdSutBucket *bck = GetBucket(type);
00306    if (!bck) {
00307       // Allocate a new one
00308       bck = new XrdSutBucket(0,0,type);
00309       if (!bck) {
00310          DEBUG("could not allocate new bucket of type:"<<XrdSutBuckStr(type));
00311          errno = ENOMEM;
00312          return -1;
00313       }
00314       // Add it to the list
00315       AddBucket(bck);
00316    }
00317 
00318    // Set content
00319    bck->SetBuf((char *)(&mcod),sizeof(kXR_int32));
00320 
00321    // We are done
00322    return 0;
00323 }
00324 
00325 //_____________________________________________________________________________
00326 kXR_int32 XrdSutBuffer::UnmarshalBucket(kXR_int32 type, kXR_int32 &code)
00327 {
00328    // Search the vector of buckets for the first bucket of
00329    // type 'type'. Unmarshalled its content to host byte order
00330    // and fill it in code.
00331    // Returns 0 if ok.
00332    // Returns -1 if no bucket of requested 'type' could be
00333    // found; -2 if the bucket size is inconsistent.
00334    EPNAME("Buffer::UnmarshalBucket");
00335 
00336    code = 0;
00337    // Get the bucket
00338    XrdSutBucket *bck = GetBucket(type);
00339    if (!bck) {
00340       DEBUG("could not find a bucket of type:"<<XrdSutBuckStr(type));
00341       errno = ENOENT;
00342       return -1;
00343    }
00344    if (bck->size != sizeof(kXR_int32)) {
00345       DEBUG("Wrong size: type:"<<XrdSutBuckStr(type)
00346             <<", size:"<<bck->size<<", expected:"<<sizeof(kXR_int32));
00347       errno = EINVAL;
00348       return -2;
00349    }
00350    //
00351    // Get the content
00352    memcpy(&code,bck->buffer,sizeof(kXR_int32));
00353    //
00354    // Unmarshal
00355    code = ntohl(code);
00356 
00357    // We are done
00358    return 0;
00359 }
00360 
00361 //_____________________________________________________________________________
00362 XrdSutBucket *XrdSutBuffer::GetBucket(kXR_int32 type, const char *tag)
00363 {
00364    // Search the vector of buckets for the first bucket of
00365    // type 'type'.
00366    // If tag is defined, search buckets whose buffer contains tag
00367    // in the form <tag>'\0'<rest_of_buffer>.
00368    // Returns the pointer to the buffer; 0 if the no bucket
00369    // is found
00370 
00371    //
00372    // Check tag, if any
00373    int ltag = (tag) ? strlen(tag) : 0;
00374    //
00375    // Loop over buckets
00376    XrdSutBucket *bp = fBuckets.Begin();
00377    while (bp) {
00378       if (type == bp->type && (!tag || (ltag < bp->size && 
00379                                         !strncmp(bp->buffer,tag,ltag) && 
00380                                         (bp->buffer)[ltag] == '\0')))
00381          return bp;
00382       // Get next
00383       bp = fBuckets.Next();
00384    }
00385 
00386    // Nothing found
00387    return 0;
00388 }
00389 
00390 //_____________________________________________________________________________
00391 void XrdSutBuffer::Deactivate(kXR_int32 type)
00392 {
00393    // Deactivate first bucket of type 'type', if any
00394    // If type == -1, deactivate all buckets (cleanup)
00395 
00396    //
00397    // Loop over buckets
00398    XrdSutBucket *bp = fBuckets.Begin();
00399    while (bp) {
00400       if (type == bp->type) {
00401          bp->type = kXRS_inactive;
00402          break;
00403       } else if (type == -1) {
00404          bp->type = kXRS_inactive;
00405       }
00406       // Get next
00407       bp = fBuckets.Next();
00408    }
00409 }
00410 
00411 //_____________________________________________________________________________
00412 int XrdSutBuffer::Serialized(char **buffer, char opt)
00413 {
00414    // Serialize the content in a form suited for exchange
00415    // over the net; the result is saved in '*buffer', which
00416    // must be deleted (opt = 'n', default) or freed (opt == 'm') by the caller.
00417    // Returns the length of the buffer in case of success.
00418    // Returns -1 in case of problems allocating the buffer.
00419    EPNAME("Buffer::Serialized");
00420 
00421    //
00422    // Check that we got a valid argument
00423    if (!buffer) {
00424       DEBUG("invalid input argument");
00425       errno = EINVAL;
00426       return -1;
00427    }
00428 
00429    //
00430    // Calculate the length of the buffer
00431    int blen = fProtocol.length() + 1 + 2*sizeof(kXR_int32);
00432    // buckets
00433    XrdSutBucket *bp = fBuckets.Begin();
00434    while (bp) {
00435       if (bp->type != kXRS_inactive) {
00436          blen += 2*sizeof(kXR_int32);
00437          blen += bp->size;
00438       }
00439       // Get next
00440       bp = fBuckets.Next();
00441    }
00442 
00443    //
00444    // Allocate the buffer
00445    *buffer = (opt == 'n') ? (new char[blen]) : (char *)malloc(blen);
00446    if (!(*buffer))
00447       return -1;
00448    char *tbuf = *buffer;
00449    int cur = 0;
00450 
00451    //
00452    // Add protocol
00453    memcpy(tbuf,fProtocol.c_str(),fProtocol.length());
00454    tbuf[fProtocol.length()] = 0;
00455    cur += fProtocol.length() + 1;
00456 
00457    //
00458    // Add step number
00459    kXR_int32 step = htonl(fStep);
00460    memcpy(tbuf+cur,&step,sizeof(kXR_int32));
00461    cur += sizeof(kXR_int32);
00462 
00463    //
00464    // Add buckets
00465    bp = fBuckets.Begin();
00466    while (bp) {
00467       if (bp->type != kXRS_inactive) {
00468          kXR_int32 type = htonl(bp->type);
00469          memcpy(tbuf+cur,&type,sizeof(kXR_int32));
00470          cur += sizeof(kXR_int32);
00471          kXR_int32 size = htonl(bp->size);
00472          memcpy(tbuf+cur,&size,sizeof(kXR_int32));
00473          cur += sizeof(kXR_int32);
00474          memcpy(tbuf+cur,bp->buffer,bp->size);
00475          cur += bp->size;
00476       }
00477       // Get next bucket
00478       bp = fBuckets.Next();
00479    }
00480 
00481    //
00482    // Add 0 termination
00483    kXR_int32 ltmp = htonl(kXRS_none);
00484    memcpy(tbuf+cur,&ltmp,sizeof(kXR_int32));
00485 
00486    // Return total length
00487    return blen;
00488 }

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