libdap++  Updated for version 3.12.0
XDRStreamMarshaller.cc
Go to the documentation of this file.
1 // XDRStreamMarshaller.cc
2 
3 // -*- mode: c++; c-basic-offset:4 -*-
4 
5 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
6 // Access Protocol.
7 
8 // Copyright (c) 2002,2003 OPeNDAP, Inc.
9 // Author: Patrick West <pwest@ucar.edu>
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26 
27 // (c) COPYRIGHT URI/MIT 1994-1999
28 // Please read the full copyright statement in the file COPYRIGHT_URI.
29 //
30 // Authors:
31 // pwest Patrick West <pwest@ucar.edu>
32 
33 #include "XDRStreamMarshaller.h"
34 
35 #include <iostream>
36 #include <sstream>
37 #include <iomanip>
38 
39 using namespace std;
40 
41 //#define DODS_DEBUG 1
42 
43 #include "Vector.h"
44 #include "util.h"
45 #include "debug.h"
46 
47 namespace libdap {
48 
49 char *XDRStreamMarshaller::d_buf = 0;
50 
51 #define XDR_DAP_BUFF_SIZE 256
52 
61 XDRStreamMarshaller::XDRStreamMarshaller(ostream &out) : // , bool checksum, bool write_data) :
62  /*&d_sink(0),*/ d_out(out)//, _MD_CTX(0), _write_data(write_data), _checksum_ctx_valid(false)
63 {
64  if (!d_buf)
65  d_buf = (char *) malloc(XDR_DAP_BUFF_SIZE);
66  if (!d_buf)
67  throw Error("Failed to allocate memory for data serialization.");
68 
69  //&d_sink = new XDR;
70  xdrmem_create( &d_sink, d_buf, XDR_DAP_BUFF_SIZE, XDR_ENCODE);
71 
72 #if CHECKSUMS
73  if (checksum) {
74  _MD_CTX = EVP_MD_CTX_create();
75  }
76 #endif
77 }
78 
79 XDRStreamMarshaller::XDRStreamMarshaller() :
80  Marshaller(), /*&d_sink(0),*/ d_out(cout)
81 {
82  throw InternalErr(__FILE__, __LINE__, "Default constructor not implemented.");
83 }
84 
85 XDRStreamMarshaller::XDRStreamMarshaller(const XDRStreamMarshaller &m) :
86  Marshaller(m), /*&d_sink(0),*/ d_out(cout)
87 {
88  throw InternalErr(__FILE__, __LINE__, "Copy constructor not implemented.");
89 }
90 
91 XDRStreamMarshaller &
92 XDRStreamMarshaller::operator=(const XDRStreamMarshaller &)
93 {
94  throw InternalErr(__FILE__, __LINE__, "Copy operator not implemented.");
95 
96  return *this;
97 }
98 
100 {
101  xdr_destroy(&d_sink); //delete_xdrstdio(&d_sink);
102  //delete(&d_sink);
103  //&d_sink = 0;
104 
105 #if CHECKSUMS
106  if (_MD_CTX)
107  EVP_MD_CTX_destroy(_MD_CTX);
108 #endif
109 }
110 
111 #if 0
112 
116 void XDRStreamMarshaller::reset_checksum()
117 {
118 #if CHECKSUMS
119  if (_MD_CTX == 0)
120  throw InternalErr( __FILE__, __LINE__, "reset_checksum() called by checksum is not enabled.");
121 
122  if (EVP_DigestInit_ex(_MD_CTX, EVP_sha1(), 0) == 0)
123  throw Error("Failed to initialize checksum object.");
124 
125  _checksum_ctx_valid = true;
126 #endif
127 }
128 
134 string XDRStreamMarshaller::get_checksum()
135 {
136 #if CHECKSUMS
137  if (_MD_CTX == 0)
138  throw InternalErr(__FILE__, __LINE__, "checksum_init() called by checksum is not enabled.");
139 
140  if (_checksum_ctx_valid) {
141  // '...Final()' 'erases' the context so the next call without a reset
142  // returns a bogus value.
143  _checksum_ctx_valid = false;
144 
145  vector<unsigned char> md(EVP_MAX_MD_SIZE);
146  unsigned int md_len;
147  if (EVP_DigestFinal_ex(_MD_CTX, &md[0], &md_len) == 0)
148  throw Error("Error computing the checksum (checksum computation).");
149 
150  ostringstream oss;
151  oss.setf(ios::hex, ios::basefield);
152  for (unsigned int i = 0; i < md_len; ++i) {
153  oss << setfill('0') << setw(2) << (unsigned int) md[i];
154  }
155 
156  _checksum = oss.str();
157  }
158 
159  return _checksum;
160 #else
161  return "";
162 #endif
163 }
164 
165 void XDRStreamMarshaller::checksum_update(const void *data, unsigned long len)
166 {
167 #if CHECKSUMS
168  if (_MD_CTX == 0)
169  throw InternalErr( __FILE__, __LINE__, "checksum_init() called by checksum is not enabled.");
170 
171  if (!_checksum_ctx_valid)
172  throw InternalErr( __FILE__, __LINE__, "Invalid checksum context (checksum update).");
173 
174  if (EVP_DigestUpdate(_MD_CTX, data, len) == 0) {
175  _checksum_ctx_valid = false;
176  throw Error("Error computing the checksum (checksum update).");
177  }
178 #endif
179 }
180 #endif
181 
183 {
184 #if CHECKSUM
185  if (_MD_CTX)
186  checksum_update(&val, sizeof(dods_byte));
187 #endif
188 // if (_write_data) {
189  DBG( std::cerr << "put_byte: " << val << std::endl );
190 
191  if (!xdr_setpos( &d_sink, 0 ))
192  throw Error("Network I/O Error. Could not send byte data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
193 
194  if (!xdr_char(&d_sink, (char *) &val))
195  throw Error("Network I/O Error. Could not send byte data.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
196 
197  unsigned int bytes_written = xdr_getpos( &d_sink );
198  if (!bytes_written)
199  throw Error("Network I/O Error. Could not send byte data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
200 
201  d_out.write(d_buf, bytes_written);
202 // }
203 }
204 
206 {
207 #if 0
208  if (_MD_CTX)
209  checksum_update(&val, sizeof(dods_int16));
210 #endif
211 // if (_write_data) {
212  if (!xdr_setpos( &d_sink, 0 ))
213  throw Error("Network I/O Error. Could not send int 16 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
214 
215  if (!XDR_INT16(&d_sink, &val))
216  throw Error("Network I/O Error. Could not send int 16 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
217 
218  unsigned int bytes_written = xdr_getpos( &d_sink );
219  if (!bytes_written)
220  throw Error("Network I/O Error. Could not send int 16 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
221 
222  d_out.write(d_buf, bytes_written);
223 // }
224 }
225 
227 {
228 #if 0
229  if (_MD_CTX)
230  checksum_update(&val, sizeof(dods_int32));
231 #endif
232 // if (_write_data) {
233  if (!xdr_setpos( &d_sink, 0 ))
234  throw Error("Network I/O Error. Could not send int 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
235 
236  if (!XDR_INT32(&d_sink, &val))
237  throw Error("Network I/O Error. Culd not read int 32 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
238 
239  unsigned int bytes_written = xdr_getpos( &d_sink );
240  if (!bytes_written)
241  throw Error("Network I/O Error. Could not send int 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
242 
243  d_out.write(d_buf, bytes_written);
244 // }
245 }
246 
248 {
249 #if 0
250  if (_MD_CTX)
251  checksum_update(&val, sizeof(dods_float32));
252 #endif
253 // if (_write_data) {
254  if (!xdr_setpos( &d_sink, 0 ))
255  throw Error("Network I/O Error. Could not send float 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
256 
257  if (!xdr_float(&d_sink, &val))
258  throw Error("Network I/O Error. Could not send float 32 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
259 
260  unsigned int bytes_written = xdr_getpos( &d_sink );
261  if (!bytes_written)
262  throw Error("Network I/O Error. Could not send float 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
263 
264  d_out.write(d_buf, bytes_written);
265 // }
266 }
267 
269 {
270 #if 0
271  if (_MD_CTX)
272  checksum_update(&val, sizeof(dods_float64));
273 #endif
274 // if (_write_data) {
275  if (!xdr_setpos( &d_sink, 0 ))
276  throw Error("Network I/O Error. Could not send float 64 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
277 
278  if (!xdr_double(&d_sink, &val))
279  throw Error("Network I/O Error. Could not send float 64 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
280 
281  unsigned int bytes_written = xdr_getpos( &d_sink );
282  if (!bytes_written)
283  throw Error("Network I/O Error. Could not send float 64 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
284 
285  d_out.write(d_buf, bytes_written);
286 // }
287 }
288 
290 {
291 #if 0
292  if (_MD_CTX)
293  checksum_update(&val, sizeof(dods_uint16));
294 #endif
295 // if (_write_data) {
296  if (!xdr_setpos( &d_sink, 0 ))
297  throw Error("Network I/O Error. Could not send uint 16 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
298 
299  if (!XDR_UINT16(&d_sink, &val))
300  throw Error("Network I/O Error. Could not send uint 16 data. This may be due to a\nbug in libdap or a problem with the network connection.");
301 
302  unsigned int bytes_written = xdr_getpos( &d_sink );
303  if (!bytes_written)
304  throw Error("Network I/O Error. Could not send uint 16 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
305 
306  d_out.write(d_buf, bytes_written);
307 // }
308 }
309 
311 {
312 #if 0
313  if (_MD_CTX)
314  checksum_update(&val, sizeof(dods_uint32));
315 #endif
316 // if (_write_data) {
317  if (!xdr_setpos( &d_sink, 0 ))
318  throw Error("Network I/O Error. Could not send uint 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
319 
320  if (!XDR_UINT32(&d_sink, &val))
321  throw Error("Network I/O Error. Could not send uint 32 data. This may be due to a\nbug in libdap or a problem with the network connection.");
322 
323  unsigned int bytes_written = xdr_getpos( &d_sink );
324  if (!bytes_written)
325  throw Error("Network I/O Error. Could not send uint 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
326 
327  d_out.write(d_buf, bytes_written);
328 // }
329 }
330 
331 void XDRStreamMarshaller::put_str(const string &val)
332 {
333 #if 0
334  if (_MD_CTX)
335  checksum_update(val.c_str(), val.length());
336 #endif
337  int size = val.length() + 8;
338 #if 0
339  char *str_buf = (char *) malloc(size);
340 
341  if (!str_buf) {
342  throw Error("Failed to allocate memory for string data serialization.");
343  }
344 #endif
345 
346  XDR str_sink;
347  vector<char> str_buf(size);
348  //XDR *str_sink = new XDR;
349  try {
350  xdrmem_create(&str_sink, &str_buf[0], size, XDR_ENCODE);
351 
352  if (!xdr_setpos( &str_sink, 0 ))
353  throw Error(
354  "Network I/O Error. Could not send string data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
355 
356  const char *out_tmp = val.c_str();
357  if (!xdr_string(&str_sink, (char **) &out_tmp, size))
358  throw Error(
359  "Network I/O Error. Could not send string data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
360 
361  unsigned int bytes_written = xdr_getpos( &str_sink );
362  if (!bytes_written)
363  throw Error(
364  "Network I/O Error. Could not send string data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
365 
366  d_out.write(&str_buf[0], bytes_written);
367 
368  xdr_destroy(&str_sink);
369  }
370  catch (...) {
371  xdr_destroy(&str_sink);
372  throw;
373  }
374 }
375 
376 void XDRStreamMarshaller::put_url(const string &val)
377 {
378  put_str(val);
379 }
380 
381 void XDRStreamMarshaller::put_opaque(char *val, unsigned int len)
382 {
383 #if 0
384  if (_MD_CTX)
385  checksum_update(&val, len);
386 #endif
387 // if (_write_data) {
388  if (len > XDR_DAP_BUFF_SIZE)
389  throw Error("Network I/O Error. Could not send opaque data - length of opaque data larger than allowed");
390 
391  if (!xdr_setpos( &d_sink, 0 ))
392  throw Error("Network I/O Error. Could not send opaque data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
393 
394  if (!xdr_opaque(&d_sink, val, len))
395  throw Error("Network I/O Error. Could not send opaque data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
396 
397  unsigned int bytes_written = xdr_getpos( &d_sink );
398  if (!bytes_written)
399  throw Error("Network I/O Error. Could not send opaque data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
400 
401  d_out.write(d_buf, bytes_written);
402 // }
403 }
404 
406 {
407 #if 0
408  if (_MD_CTX)
409  checksum_update(&val, sizeof(int));
410 #endif
411 // if (_write_data) {
412  if (!xdr_setpos( &d_sink, 0 ))
413  throw Error("Network I/O Error. Could not send int data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
414 
415  if (!xdr_int(&d_sink, &val))
416  throw Error("Network I/O Error(1). Could not send int data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
417 
418  unsigned int bytes_written = xdr_getpos( &d_sink );
419  if (!bytes_written)
420  throw Error("Network I/O Error. Could not send int data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
421 
422  d_out.write(d_buf, bytes_written);
423 // }
424 }
425 
426 void XDRStreamMarshaller::put_vector(char *val, int num, Vector &)
427 {
428  if (!val) throw InternalErr(__FILE__, __LINE__, "Could not send byte vector data. Buffer pointer is not set.");
429 #if 0
430  if (_MD_CTX)
431  checksum_update(val, num);
432 #endif
433  put_int(num);
434 
435  // this is the word boundary for writing xdr bytes in a vector.
436  const unsigned int add_to = 8;
437 #if 0
438  char *byte_buf = (char *) malloc(num + add_to);
439  if (!byte_buf) throw Error("Failed to allocate memory for byte vector data serialization.");
440 #endif
441  vector<char> byte_buf(num + add_to);
442  XDR byte_sink;
443  try {
444  xdrmem_create(&byte_sink, &byte_buf[0], num + add_to, XDR_ENCODE);
445  if (!xdr_setpos( &byte_sink, 0 ))
446  throw Error(
447  "Network I/O Error. Could not send byte vector data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
448 
449  if (!xdr_bytes(&byte_sink, (char **) &val, (unsigned int *) &num, num + add_to))
450  throw Error(
451  "Network I/O Error(2). Could not send byte vector data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
452 
453  unsigned int bytes_written = xdr_getpos( &byte_sink );
454  if (!bytes_written)
455  throw Error(
456  "Network I/O Error. Could not send byte vector data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
457 
458  d_out.write(&byte_buf[0], bytes_written);
459 
460  xdr_destroy(&byte_sink);
461  }
462  catch (...) {
463  xdr_destroy(&byte_sink);
464  throw;
465  }
466 }
467 
468 void
469 XDRStreamMarshaller::put_vector( char *val, int num, int width, Vector &vec )
470 {
471  put_vector(val, num, width, vec.var()->type());
472 }
473 
474 
475 void XDRStreamMarshaller::put_vector(char *val, unsigned int num, int width, Type type)
476 {
477  if (!val) throw InternalErr(__FILE__, __LINE__, "Buffer pointer is not set.");
478 #if CHECKSUM
479  if (_MD_CTX)
480  checksum_update(val, num * width);
481 #endif
482  put_int(num);
483 
484  int use_width = width;
485  if (use_width < 4) use_width = 4;
486 
487  // the size is the number of elements num times the width of each
488  // element, then add 4 bytes for the number of elements
489  int size = (num * use_width) + 4;
490 
491  // allocate enough memory for the elements
492 #if 0
493  char *vec_buf = (char *) malloc(size);
494  if (!vec_buf)
495  throw Error("Failed to allocate memory for vector data serialization.");
496 #endif
497  vector<char> vec_buf(size);
498  XDR vec_sink;
499  try {
500  xdrmem_create(&vec_sink, &vec_buf[0], size, XDR_ENCODE);
501 
502  // set the position of the sink to 0, we're starting at the beginning
503  if (!xdr_setpos( &vec_sink, 0 ))
504  throw Error(
505  "Network I/O Error. Could not send vector data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
506 
507  // write the array to the buffer
508  if (!xdr_array(&vec_sink, (char **) &val, (unsigned int *) &num, size, width, XDRUtils::xdr_coder(type)))
509  throw Error(
510  "Network I/O Error(2). Could not send vector data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
511 
512  // how much was written to the buffer
513  unsigned int bytes_written = xdr_getpos( &vec_sink );
514  if (!bytes_written)
515  throw Error(
516  "Network I/O Error. Could not send vector data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
517 
518  // write that much out to the output stream
519  d_out.write(&vec_buf[0], bytes_written);
520 
521  xdr_destroy(&vec_sink);
522  }
523  catch (...) {
524  xdr_destroy(&vec_sink);
525  throw;
526  }
527 }
528 
529 void XDRStreamMarshaller::dump(ostream &strm) const
530 {
531  strm << DapIndent::LMarg << "XDRStreamMarshaller::dump - (" << (void *) this << ")" << endl;
532 }
533 
534 } // namespace libdap
535 
#define XDR_UINT32
Definition: config.h:909
uint8_t dods_byte
virtual void dump(ostream &strm) const
dump the contents of this object to the specified ostream
Holds a one-dimensional collection of DAP2 data types.
Definition: Vector.h:78
#define XDR_UINT16
Definition: config.h:906
virtual void put_int16(dods_int16 val)
Type
Identifies the data type.
Definition: BaseType.h:137
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:282
virtual void put_uint16(dods_uint16 val)
#define XDR_INT32
Definition: config.h:903
virtual void put_float64(dods_float64 val)
uint16_t dods_uint16
const int XDR_DAP_BUFF_SIZE
A class for software fault reporting.
Definition: InternalErr.h:64
virtual void put_byte(dods_byte val)
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:380
#define DBG(x)
Definition: debug.h:58
double dods_float64
virtual void put_float32(dods_float32 val)
virtual void put_opaque(char *val, unsigned int len)
uint32_t dods_uint32
virtual void put_str(const string &val)
#define XDR_INT16
Definition: config.h:900
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:78
int16_t dods_int16
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:53
virtual void put_vector(char *val, int num, Vector &vec)
static xdrproc_t xdr_coder(const Type &t)
Returns a function used to encode elements of an array.
Definition: XDRUtils.cc:143
A class for error processing.
Definition: Error.h:90
virtual void put_int32(dods_int32 val)
virtual void put_uint32(dods_uint32 val)
virtual void put_url(const string &val)
int32_t dods_int32