XRootD
Loading...
Searching...
No Matches
XrdSutBuffer.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d S u t B u f f e r . c c */
4/* */
5/* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Gerri Ganis for CERN */
7/* */
8/* This file is part of the XRootD software suite. */
9/* */
10/* XRootD is free software: you can redistribute it and/or modify it under */
11/* the terms of the GNU Lesser General Public License as published by the */
12/* Free Software Foundation, either version 3 of the License, or (at your */
13/* option) any later version. */
14/* */
15/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
16/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
17/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
18/* License for more details. */
19/* */
20/* You should have received a copy of the GNU Lesser General Public License */
21/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
22/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
23/* */
24/* The copyright holder's institutional names and contributor's names may not */
25/* be used to endorse or promote products derived from this software without */
26/* specific prior written permission of the institution or contributor. */
27/******************************************************************************/
28
29#include <cinttypes>
30#include <cstdio>
31#include <cstring>
32#include <cerrno>
33#include <netinet/in.h>
34#include <sys/types.h>
35
39#include "XrdSut/XrdSutTrace.hh"
40
41/******************************************************************************/
42/* */
43/* Buffer structure for managing exchanged buckets */
44/* */
45/******************************************************************************/
46
47//_____________________________________________________________________________
49{
50 // Constructor from compact form (used for exchange over the network)
51 // If the buffer begins with "&P=", then only the protocol name and
52 // options are extracted, assuming the format "&P=<protocol>,<options>".
53 // Otherwise the format "<protocol><step><bucket_1>...<bucket_n>" is
54 // assumed
55 EPNAME("Buffer::XrdSutBuffer");
56
57 bool ok = 1;
58
59 // Default initialization
60 fOptions = "";
61 fProtocol = "";
62 fStep = 0;
63
64 //
65 // Check type of buffer
66 if (!strncmp(buf,"&P=",3)) {
67 //
68 // Initial buffer format
69 // Extract protocol name and options
70 int cur = 3;
71 int k = 0;
72 while (buf[cur+k] && buf[cur+k] != ',' &&
73 k < XrdSecPROTOIDSIZE && (cur+k) < len) k++;
74 if (!k) {
75 PRINT("no protocol name - do nothing");
76 } else {
77 //
78 // Extract protocol name
79 char proto[XrdSecPROTOIDSIZE];
80 strncpy(proto,buf+cur,k);
81 proto[(k >= XrdSecPROTOIDSIZE ? XrdSecPROTOIDSIZE-1:k)]=0; // null-terminated
82 fProtocol = proto;
83 cur += (k+1);
84 //
85 // Extract options, if any
86 if (cur < len) {
87 k = 0;
88 while ((cur+k) < len && buf[cur+k])
89 k++;
90 if (k) {
91 char *opts = new char[k+1];
92 if (opts) {
93 strncpy(opts,buf+cur,k);
94 opts[k] = 0; // null-terminated
95 fOptions = opts;
96 delete[] opts;
97 }
98 }
99 cur += (k+1);
100 }
101 }
102
103 } else {
104 //
105 // Assume exchange info format
106 // Check integrity
107 int k = 0;
108 while ( k < XrdSecPROTOIDSIZE && k < len && buf[k]) { k++; }
109 if (!k || k == XrdSecPROTOIDSIZE) {
110 PRINT("no protocol name: do nothing");
111 ok = 0;
112 }
113 int cur = k+1;
114 if (ok) {
115 //
116 // Extract protocol name
117 char proto[XrdSecPROTOIDSIZE];
118 strcpy(proto,buf);
119 fProtocol = proto;
120
121 //
122 // Step/Iteration number
123 kXR_int32 step;
124 memcpy(&step,&buf[cur],sizeof(kXR_int32));
125 fStep = ntohl(step);
126 cur += sizeof(kXR_int32);
127 }
128
129 //
130 // Total length of buckets (sizes+buffers) (excluded trailing 0)
131 int ltot = len - sizeof(kXR_int32);
132 TRACE(Dump,"ltot: " <<ltot);
133
134 //
135 // Now the buckets
136 kXR_int32 type;
137 kXR_int32 blen;
138 XrdSutBucket *tmp = 0;
139 char *buck = 0;
140 while (ok) {
141
142 //
143 // Get type
144 memcpy(&type,&buf[cur],sizeof(kXR_int32));
145 type = ntohl(type);
146 TRACE(Dump,"type: " <<XrdSutBuckStr(type));
147
148 if (type == kXRS_none) {
149 //
150 // We are over
151 ok = 0;
152 } else {
153 //
154 cur += sizeof(kXR_int32);
155 //
156 // Get length and test consistency
157 memcpy(&blen,&buf[cur],sizeof(kXR_int32));
158 blen = ntohl(blen);
159 TRACE(Dump,"blen: " <<blen);
160 //
161 cur += sizeof(kXR_int32);
162 TRACE(Dump,"cur: " <<cur);
163 if ((cur-1+blen) > ltot)
164 ok = 0;
165 else {
166 //
167 // Store only active buckets
168 if (type != kXRS_inactive){
169 //
170 // Normal active bucket: save it in the vector
171 if ((buck = new char[blen])) {
172 memcpy(buck,&buf[cur],blen);
173 if ((tmp = new XrdSutBucket(buck,blen,type))) {
174 fBuckets.PushBack(tmp);
175 } else {
176 PRINT("error creating bucket: "<<XrdSutBuckStr(type)
177 <<" (size: "<<blen<<", !buck:"<<(!buck)<<")");
178 }
179 } else {
180 PRINT("error allocating buffer for bucket: "
181 <<XrdSutBuckStr(type)<<" (size:"<<blen<<")");
182 }
183 }
184 cur += blen;
185 }
186 }
187 }
188 }
189}
190
191//_____________________________________________________________________________
193{
194 // Destructor
195 // XrdSutBuffer is responsible of the buckets in the list
196 EPNAME("Buffer::~XrdSutBuffer");
197
198 XrdSutBucket *bp = fBuckets.Begin();
199 while (bp) {
200 TRACE(Dump,"type: " << bp->type);
201 delete bp;
202 // Get next bucket
203 bp = fBuckets.Next();
204 }
205}
206
207//_____________________________________________________________________________
208int XrdSutBuffer::UpdateBucket(const char *b, int sz, int ty)
209{
210 // Update existing bucket (or add a new bucket to the list)
211 // with sz bytes at 'b'.
212 // Returns 0 or -1 if error allocating bucket
213 EPNAME("Buffer::UpdateBucket");
214
215 XrdSutBucket *bp = GetBucket(ty);
216 if (!bp) {
217 bp = new XrdSutBucket(0,0,ty);
218 if (!bp) {
219 DEBUG("Out-Of-Memory allocating bucket");
220 return -1;
221 }
222 AddBucket(bp);
223 }
224 bp->SetBuf(b,sz);
225 // Done
226 return 0;
227}
228
229//_____________________________________________________________________________
231{
232 // Update existing bucket (or add a new bucket to the list)
233 // with string s.
234 // Returns 0 or -1 if error allocating bucket
235
236 return UpdateBucket(s.c_str(),s.length(),ty);
237}
238
239//_____________________________________________________________________________
240void XrdSutBuffer::Dump(const char *stepstr, bool all)
241{
242 // Dump content of buffer. If all is false, only active buckets are dumped;
243 // this is the default behaviour.
244 EPNAME("Buffer::Dump");
245
246 PRINT("//-----------------------------------------------------//");
247 PRINT("// //")
248 PRINT("// XrdSutBuffer DUMP //")
249 PRINT("// //")
250
251 int nbuck = fBuckets.Size();
252
253 PRINT("// Buffer : " <<this);
254 PRINT("// ");
255 PRINT("// Proto : " <<fProtocol.c_str());
256 if (fOptions.length()) {
257 PRINT("// Options : " <<fOptions.c_str());
258 } else {
259 PRINT("// Options : none");
260 }
261 if (stepstr) {
262 PRINT("// Step : " <<stepstr);
263 } else {
264 PRINT("// Step : " <<fStep);
265 }
266 if (!all) {
267 PRINT("// Dumping active buckets only ");
268 } else {
269 PRINT("// # of buckets : " <<nbuck);
270 }
271 PRINT("// ");
272
273 int kb = 0;
274 XrdSutBucket *bp = fBuckets.Begin();
275 while (bp) {
276 PRINT("// ");
277 if (all || bp->type != kXRS_inactive) {
278 PRINT("// buck: " <<kb++);
279 bp->Dump(0);
280 }
281 // Get next
282 bp = fBuckets.Next();
283 }
284 if (!all) PRINT("// # active buckets found: " << kb);
285 PRINT("// //")
286 PRINT("//-----------------------------------------------------//");
287}
288
289//_____________________________________________________________________________
290void XrdSutBuffer::Message(const char *prepose)
291{
292 // Print content of any bucket of type kXRS_message
293 // Prepose 'prepose', if defined
294
295 bool pripre = 0;
296 if (prepose)
297 pripre = 1;
298
299 XrdSutBucket *bp = fBuckets.Begin();
300 while (bp) {
301 if (bp->type == kXRS_message) {
302 if (bp->size > 0 && bp->buffer) {
303 if (pripre) {
304 XrdOucString premsg(prepose);
305 std::cerr << premsg << std::endl;
306 pripre = 0;
307 }
308 XrdOucString msg(bp->buffer,bp->size);
309 std::cerr << msg << std::endl;
310 }
311 }
312 // Get next
313 bp = fBuckets.Next();
314 }
315}
316
317//_____________________________________________________________________________
319{
320 // Search the vector of buckets for the first bucket of
321 // type 'type'. Reset its content and fill it with 'code'
322 // in network byte order. If no bucket 'type' exists, add
323 // a new one.
324 // Returns -1 if new bucket could be allocated; 0 otherwise .
325 EPNAME("Buffer::MarshalBucket");
326
327 // Convert to network byte order
328 kXR_int32 mcod = htonl(code);
329
330 // Get the bucket
331 XrdSutBucket *bck = GetBucket(type);
332 if (!bck) {
333 // Allocate a new one
334 bck = new XrdSutBucket(0,0,type);
335 if (!bck) {
336 DEBUG("could not allocate new bucket of type:"<<XrdSutBuckStr(type));
337 errno = ENOMEM;
338 return -1;
339 }
340 // Add it to the list
341 AddBucket(bck);
342 }
343
344 // Set content
345 bck->SetBuf((char *)(&mcod),sizeof(kXR_int32));
346
347 // We are done
348 return 0;
349}
350
351//_____________________________________________________________________________
353{
354 // Search the vector of buckets for the first bucket of
355 // type 'type'. Unmarshalled its content to host byte order
356 // and fill it in code.
357 // Returns 0 if ok.
358 // Returns -1 if no bucket of requested 'type' could be
359 // found; -2 if the bucket size is inconsistent.
360 EPNAME("Buffer::UnmarshalBucket");
361
362 code = 0;
363 // Get the bucket
364 XrdSutBucket *bck = GetBucket(type);
365 if (!bck) {
366 DEBUG("could not find a bucket of type:"<<XrdSutBuckStr(type));
367 errno = ENOENT;
368 return -1;
369 }
370 if (bck->size != sizeof(kXR_int32)) {
371 DEBUG("Wrong size: type:"<<XrdSutBuckStr(type)
372 <<", size:"<<bck->size<<", expected:"<<sizeof(kXR_int32));
373 errno = EINVAL;
374 return -2;
375 }
376 //
377 // Get the content
378 memcpy(&code,bck->buffer,sizeof(kXR_int32));
379 //
380 // Unmarshal
381 code = ntohl(code);
382
383 // We are done
384 return 0;
385}
386
387//_____________________________________________________________________________
389{
390 // Search the vector of buckets for the first bucket of
391 // type 'type'.
392 // If tag is defined, search buckets whose buffer contains tag
393 // in the form <tag>'\0'<rest_of_buffer>.
394 // Returns the pointer to the buffer; 0 if the no bucket
395 // is found
396
397 //
398 // Check tag, if any
399 int ltag = (tag) ? strlen(tag) : 0;
400 //
401 // Loop over buckets
402 XrdSutBucket *bp = fBuckets.Begin();
403 while (bp) {
404 if (type == bp->type && (!tag || (ltag < bp->size &&
405 !strncmp(bp->buffer,tag,ltag) &&
406 (bp->buffer)[ltag] == '\0')))
407 return bp;
408 // Get next
409 bp = fBuckets.Next();
410 }
411
412 // Nothing found
413 return 0;
414}
415
416//_____________________________________________________________________________
418{
419 // Deactivate first bucket of type 'type', if any
420 // If type == -1, deactivate all buckets (cleanup)
421
422 //
423 // Loop over buckets
424 XrdSutBucket *bp = fBuckets.Begin();
425 while (bp) {
426 if (type == bp->type) {
427 bp->type = kXRS_inactive;
428 break;
429 } else if (type == -1) {
430 bp->type = kXRS_inactive;
431 }
432 // Get next
433 bp = fBuckets.Next();
434 }
435}
436
437//_____________________________________________________________________________
438int XrdSutBuffer::Serialized(char **buffer, char opt)
439{
440 // Serialize the content in a form suited for exchange
441 // over the net; the result is saved in '*buffer', which
442 // must be deleted (opt = 'n', default) or freed (opt == 'm') by the caller.
443 // Returns the length of the buffer in case of success.
444 // Returns -1 in case of problems allocating the buffer.
445 EPNAME("Buffer::Serialized");
446
447 //
448 // Check that we got a valid argument
449 if (!buffer) {
450 DEBUG("invalid input argument");
451 errno = EINVAL;
452 return -1;
453 }
454
455 //
456 // Calculate the length of the buffer
457 int blen = fProtocol.length() + 1 + 2*sizeof(kXR_int32);
458 // buckets
459 XrdSutBucket *bp = fBuckets.Begin();
460 while (bp) {
461 if (bp->type != kXRS_inactive) {
462 blen += 2*sizeof(kXR_int32);
463 blen += bp->size;
464 }
465 // Get next
466 bp = fBuckets.Next();
467 }
468
469 //
470 // Allocate the buffer
471 *buffer = (opt == 'n') ? (new char[blen]) : (char *)malloc(blen);
472 if (!(*buffer))
473 return -1;
474 char *tbuf = *buffer;
475 int cur = 0;
476
477 //
478 // Add protocol
479 memcpy(tbuf,fProtocol.c_str(),fProtocol.length());
480 tbuf[fProtocol.length()] = 0;
481 cur += fProtocol.length() + 1;
482
483 //
484 // Add step number
485 kXR_int32 step = htonl(fStep);
486 memcpy(tbuf+cur,&step,sizeof(kXR_int32));
487 cur += sizeof(kXR_int32);
488
489 //
490 // Add buckets
491 bp = fBuckets.Begin();
492 while (bp) {
493 if (bp->type != kXRS_inactive) {
494 kXR_int32 type = htonl(bp->type);
495 memcpy(tbuf+cur,&type,sizeof(kXR_int32));
496 cur += sizeof(kXR_int32);
497 kXR_int32 size = htonl(bp->size);
498 memcpy(tbuf+cur,&size,sizeof(kXR_int32));
499 cur += sizeof(kXR_int32);
500 memcpy(tbuf+cur,bp->buffer,bp->size);
501 cur += bp->size;
502 }
503 // Get next bucket
504 bp = fBuckets.Next();
505 }
506
507 //
508 // Add 0 termination
509 kXR_int32 ltmp = htonl(kXRS_none);
510 memcpy(tbuf+cur,&ltmp,sizeof(kXR_int32));
511
512 // Return total length
513 return blen;
514}
int kXR_int32
Definition XPtypes.hh:89
#define DEBUG(x)
#define EPNAME(x)
#define PRINT(y)
#define XrdSecPROTOIDSIZE
struct myOpts opts
const char * XrdSutBuckStr(int kbck)
Definition XrdSutAux.cc:121
@ kXRS_message
Definition XrdSutAux.hh:68
@ kXRS_inactive
Definition XrdSutAux.hh:56
@ kXRS_none
Definition XrdSutAux.hh:55
#define TRACE(act, x)
Definition XrdTrace.hh:63
int length() const
const char * c_str() const
void PushBack(XrdSutBucket *b)
int Size() const
XrdSutBucket * Next()
XrdSutBucket * Begin()
kXR_int32 type
kXR_int32 size
int SetBuf(const char *nb=0, int ns=0)
void Dump(int opt=1)
int AddBucket(char *bp=0, int sz=0, int ty=0)
int UpdateBucket(const char *bp, int sz, int ty)
void Message(const char *prepose=0)
int Serialized(char **buffer, char opt='n')
XrdSutBuffer(const char *prot, const char *opts=0)
void Dump(const char *stepstr=0, bool all=false)
virtual ~XrdSutBuffer()
XrdSutBucket * GetBucket(kXR_int32 type, const char *tag=0)
kXR_int32 MarshalBucket(kXR_int32 type, kXR_int32 code)
void Deactivate(kXR_int32 type)
kXR_int32 UnmarshalBucket(kXR_int32 type, kXR_int32 &code)