libdap++  Updated for version 3.13.1
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 "config.h"
34 
35 #include "XDRStreamMarshaller.h"
36 
37 #include <iostream>
38 #include <sstream>
39 #include <iomanip>
40 
41 using namespace std;
42 
43 //#define DODS_DEBUG 1
44 
45 #include "Vector.h"
46 #include "util.h"
47 #include "debug.h"
48 
49 namespace libdap {
50 
51 char *XDRStreamMarshaller::d_buf = 0;
52 
53 #define XDR_DAP_BUFF_SIZE 256
54 
63 XDRStreamMarshaller::XDRStreamMarshaller(ostream &out) : // , bool checksum, bool write_data) :
64  /*&d_sink(0),*/ d_out(out)//, _MD_CTX(0), _write_data(write_data), _checksum_ctx_valid(false)
65 {
66  if (!d_buf)
67  d_buf = (char *) malloc(XDR_DAP_BUFF_SIZE);
68  if (!d_buf)
69  throw Error("Failed to allocate memory for data serialization.");
70 
71  //&d_sink = new XDR;
72  xdrmem_create( &d_sink, d_buf, XDR_DAP_BUFF_SIZE, XDR_ENCODE);
73 
74 #if CHECKSUMS
75  if (checksum) {
76  _MD_CTX = EVP_MD_CTX_create();
77  }
78 #endif
79 }
80 
81 XDRStreamMarshaller::XDRStreamMarshaller() :
82  Marshaller(), /*&d_sink(0),*/ d_out(cout)
83 {
84  throw InternalErr(__FILE__, __LINE__, "Default constructor not implemented.");
85 }
86 
87 XDRStreamMarshaller::XDRStreamMarshaller(const XDRStreamMarshaller &m) :
88  Marshaller(m), /*&d_sink(0),*/ d_out(cout)
89 {
90  throw InternalErr(__FILE__, __LINE__, "Copy constructor not implemented.");
91 }
92 
93 XDRStreamMarshaller &
94 XDRStreamMarshaller::operator=(const XDRStreamMarshaller &)
95 {
96  throw InternalErr(__FILE__, __LINE__, "Copy operator not implemented.");
97 
98  return *this;
99 }
100 
102 {
103  xdr_destroy(&d_sink); //delete_xdrstdio(&d_sink);
104  //delete(&d_sink);
105  //&d_sink = 0;
106 
107 #if CHECKSUMS
108  if (_MD_CTX)
109  EVP_MD_CTX_destroy(_MD_CTX);
110 #endif
111 }
112 
113 #if 0
114 
118 void XDRStreamMarshaller::reset_checksum()
119 {
120 #if CHECKSUMS
121  if (_MD_CTX == 0)
122  throw InternalErr( __FILE__, __LINE__, "reset_checksum() called by checksum is not enabled.");
123 
124  if (EVP_DigestInit_ex(_MD_CTX, EVP_sha1(), 0) == 0)
125  throw Error("Failed to initialize checksum object.");
126 
127  _checksum_ctx_valid = true;
128 #endif
129 }
130 
136 string XDRStreamMarshaller::get_checksum()
137 {
138 #if CHECKSUMS
139  if (_MD_CTX == 0)
140  throw InternalErr(__FILE__, __LINE__, "checksum_init() called by checksum is not enabled.");
141 
142  if (_checksum_ctx_valid) {
143  // '...Final()' 'erases' the context so the next call without a reset
144  // returns a bogus value.
145  _checksum_ctx_valid = false;
146 
147  vector<unsigned char> md(EVP_MAX_MD_SIZE);
148  unsigned int md_len;
149  if (EVP_DigestFinal_ex(_MD_CTX, &md[0], &md_len) == 0)
150  throw Error("Error computing the checksum (checksum computation).");
151 
152  ostringstream oss;
153  oss.setf(ios::hex, ios::basefield);
154  for (unsigned int i = 0; i < md_len; ++i) {
155  oss << setfill('0') << setw(2) << (unsigned int) md[i];
156  }
157 
158  _checksum = oss.str();
159  }
160 
161  return _checksum;
162 #else
163  return "";
164 #endif
165 }
166 
167 void XDRStreamMarshaller::checksum_update(const void *data, unsigned long len)
168 {
169 #if CHECKSUMS
170  if (_MD_CTX == 0)
171  throw InternalErr( __FILE__, __LINE__, "checksum_init() called by checksum is not enabled.");
172 
173  if (!_checksum_ctx_valid)
174  throw InternalErr( __FILE__, __LINE__, "Invalid checksum context (checksum update).");
175 
176  if (EVP_DigestUpdate(_MD_CTX, data, len) == 0) {
177  _checksum_ctx_valid = false;
178  throw Error("Error computing the checksum (checksum update).");
179  }
180 #endif
181 }
182 #endif
183 
185 {
186 #if CHECKSUM
187  if (_MD_CTX)
188  checksum_update(&val, sizeof(dods_byte));
189 #endif
190 // if (_write_data) {
191  DBG( std::cerr << "put_byte: " << val << std::endl );
192 
193  if (!xdr_setpos( &d_sink, 0 ))
194  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.");
195 
196  if (!xdr_char(&d_sink, (char *) &val))
197  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.");
198 
199  unsigned int bytes_written = xdr_getpos( &d_sink );
200  if (!bytes_written)
201  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.");
202 
203  d_out.write(d_buf, bytes_written);
204 // }
205 }
206 
208 {
209 #if 0
210  if (_MD_CTX)
211  checksum_update(&val, sizeof(dods_int16));
212 #endif
213 // if (_write_data) {
214  if (!xdr_setpos( &d_sink, 0 ))
215  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.");
216 
217  if (!XDR_INT16(&d_sink, &val))
218  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.");
219 
220  unsigned int bytes_written = xdr_getpos( &d_sink );
221  if (!bytes_written)
222  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.");
223 
224  d_out.write(d_buf, bytes_written);
225 // }
226 }
227 
229 {
230 #if 0
231  if (_MD_CTX)
232  checksum_update(&val, sizeof(dods_int32));
233 #endif
234 // if (_write_data) {
235  if (!xdr_setpos( &d_sink, 0 ))
236  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.");
237 
238  if (!XDR_INT32(&d_sink, &val))
239  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.");
240 
241  unsigned int bytes_written = xdr_getpos( &d_sink );
242  if (!bytes_written)
243  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.");
244 
245  d_out.write(d_buf, bytes_written);
246 // }
247 }
248 
250 {
251 #if 0
252  if (_MD_CTX)
253  checksum_update(&val, sizeof(dods_float32));
254 #endif
255 // if (_write_data) {
256  if (!xdr_setpos( &d_sink, 0 ))
257  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.");
258 
259  if (!xdr_float(&d_sink, &val))
260  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.");
261 
262  unsigned int bytes_written = xdr_getpos( &d_sink );
263  if (!bytes_written)
264  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.");
265 
266  d_out.write(d_buf, bytes_written);
267 // }
268 }
269 
271 {
272 #if 0
273  if (_MD_CTX)
274  checksum_update(&val, sizeof(dods_float64));
275 #endif
276 // if (_write_data) {
277  if (!xdr_setpos( &d_sink, 0 ))
278  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.");
279 
280  if (!xdr_double(&d_sink, &val))
281  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.");
282 
283  unsigned int bytes_written = xdr_getpos( &d_sink );
284  if (!bytes_written)
285  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.");
286 
287  d_out.write(d_buf, bytes_written);
288 // }
289 }
290 
292 {
293 #if 0
294  if (_MD_CTX)
295  checksum_update(&val, sizeof(dods_uint16));
296 #endif
297 // if (_write_data) {
298  if (!xdr_setpos( &d_sink, 0 ))
299  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.");
300 
301  if (!XDR_UINT16(&d_sink, &val))
302  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.");
303 
304  unsigned int bytes_written = xdr_getpos( &d_sink );
305  if (!bytes_written)
306  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.");
307 
308  d_out.write(d_buf, bytes_written);
309 // }
310 }
311 
313 {
314 #if 0
315  if (_MD_CTX)
316  checksum_update(&val, sizeof(dods_uint32));
317 #endif
318 // if (_write_data) {
319  if (!xdr_setpos( &d_sink, 0 ))
320  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.");
321 
322  if (!XDR_UINT32(&d_sink, &val))
323  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.");
324 
325  unsigned int bytes_written = xdr_getpos( &d_sink );
326  if (!bytes_written)
327  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.");
328 
329  d_out.write(d_buf, bytes_written);
330 // }
331 }
332 
333 void XDRStreamMarshaller::put_str(const string &val)
334 {
335 #if 0
336  if (_MD_CTX)
337  checksum_update(val.c_str(), val.length());
338 #endif
339  int size = val.length() + 8;
340 #if 0
341  char *str_buf = (char *) malloc(size);
342 
343  if (!str_buf) {
344  throw Error("Failed to allocate memory for string data serialization.");
345  }
346 #endif
347 
348  XDR str_sink;
349  vector<char> str_buf(size);
350  //XDR *str_sink = new XDR;
351  try {
352  xdrmem_create(&str_sink, &str_buf[0], size, XDR_ENCODE);
353 
354  if (!xdr_setpos( &str_sink, 0 ))
355  throw Error(
356  "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.");
357 
358  const char *out_tmp = val.c_str();
359  if (!xdr_string(&str_sink, (char **) &out_tmp, size))
360  throw Error(
361  "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.");
362 
363  unsigned int bytes_written = xdr_getpos( &str_sink );
364  if (!bytes_written)
365  throw Error(
366  "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.");
367 
368  d_out.write(&str_buf[0], bytes_written);
369 
370  xdr_destroy(&str_sink);
371  }
372  catch (...) {
373  xdr_destroy(&str_sink);
374  throw;
375  }
376 }
377 
378 void XDRStreamMarshaller::put_url(const string &val)
379 {
380  put_str(val);
381 }
382 
383 void XDRStreamMarshaller::put_opaque(char *val, unsigned int len)
384 {
385 #if 0
386  if (_MD_CTX)
387  checksum_update(&val, len);
388 #endif
389 // if (_write_data) {
390  if (len > XDR_DAP_BUFF_SIZE)
391  throw Error("Network I/O Error. Could not send opaque data - length of opaque data larger than allowed");
392 
393  if (!xdr_setpos( &d_sink, 0 ))
394  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.");
395 
396  if (!xdr_opaque(&d_sink, val, len))
397  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.");
398 
399  unsigned int bytes_written = xdr_getpos( &d_sink );
400  if (!bytes_written)
401  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.");
402 
403  d_out.write(d_buf, bytes_written);
404 // }
405 }
406 
408 {
409 #if 0
410  if (_MD_CTX)
411  checksum_update(&val, sizeof(int));
412 #endif
413 // if (_write_data) {
414  if (!xdr_setpos( &d_sink, 0 ))
415  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.");
416 
417  if (!xdr_int(&d_sink, &val))
418  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.");
419 
420  unsigned int bytes_written = xdr_getpos( &d_sink );
421  if (!bytes_written)
422  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.");
423 
424  d_out.write(d_buf, bytes_written);
425 // }
426 }
427 
428 void XDRStreamMarshaller::put_vector(char *val, int num, Vector &)
429 {
430  if (!val) throw InternalErr(__FILE__, __LINE__, "Could not send byte vector data. Buffer pointer is not set.");
431 #if 0
432  if (_MD_CTX)
433  checksum_update(val, num);
434 #endif
435  put_int(num);
436 
437  // this is the word boundary for writing xdr bytes in a vector.
438  const unsigned int add_to = 8;
439 #if 0
440  char *byte_buf = (char *) malloc(num + add_to);
441  if (!byte_buf) throw Error("Failed to allocate memory for byte vector data serialization.");
442 #endif
443  vector<char> byte_buf(num + add_to);
444  XDR byte_sink;
445  try {
446  xdrmem_create(&byte_sink, &byte_buf[0], num + add_to, XDR_ENCODE);
447  if (!xdr_setpos( &byte_sink, 0 ))
448  throw Error(
449  "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.");
450 
451  if (!xdr_bytes(&byte_sink, (char **) &val, (unsigned int *) &num, num + add_to))
452  throw Error(
453  "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.");
454 
455  unsigned int bytes_written = xdr_getpos( &byte_sink );
456  if (!bytes_written)
457  throw Error(
458  "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.");
459 
460  d_out.write(&byte_buf[0], bytes_written);
461 
462  xdr_destroy(&byte_sink);
463  }
464  catch (...) {
465  xdr_destroy(&byte_sink);
466  throw;
467  }
468 }
469 
470 void
471 XDRStreamMarshaller::put_vector( char *val, int num, int width, Vector &vec )
472 {
473  put_vector(val, num, width, vec.var()->type());
474 }
475 
476 
477 void XDRStreamMarshaller::put_vector(char *val, unsigned int num, int width, Type type)
478 {
479  if (!val) throw InternalErr(__FILE__, __LINE__, "Buffer pointer is not set.");
480 #if CHECKSUM
481  if (_MD_CTX)
482  checksum_update(val, num * width);
483 #endif
484  put_int(num);
485 
486  int use_width = width;
487  if (use_width < 4) use_width = 4;
488 
489  // the size is the number of elements num times the width of each
490  // element, then add 4 bytes for the number of elements
491  int size = (num * use_width) + 4;
492 
493  // allocate enough memory for the elements
494 #if 0
495  char *vec_buf = (char *) malloc(size);
496  if (!vec_buf)
497  throw Error("Failed to allocate memory for vector data serialization.");
498 #endif
499  vector<char> vec_buf(size);
500  XDR vec_sink;
501  try {
502  xdrmem_create(&vec_sink, &vec_buf[0], size, XDR_ENCODE);
503 
504  // set the position of the sink to 0, we're starting at the beginning
505  if (!xdr_setpos( &vec_sink, 0 ))
506  throw Error(
507  "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.");
508 
509  // write the array to the buffer
510  if (!xdr_array(&vec_sink, (char **) &val, (unsigned int *) &num, size, width, XDRUtils::xdr_coder(type)))
511  throw Error(
512  "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.");
513 
514  // how much was written to the buffer
515  unsigned int bytes_written = xdr_getpos( &vec_sink );
516  if (!bytes_written)
517  throw Error(
518  "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.");
519 
520  // write that much out to the output stream
521  d_out.write(&vec_buf[0], bytes_written);
522 
523  xdr_destroy(&vec_sink);
524  }
525  catch (...) {
526  xdr_destroy(&vec_sink);
527  throw;
528  }
529 }
530 
531 void XDRStreamMarshaller::dump(ostream &strm) const
532 {
533  strm << DapIndent::LMarg << "XDRStreamMarshaller::dump - (" << (void *) this << ")" << endl;
534 }
535 
536 } // namespace libdap
537 
#define XDR_UINT32
Definition: config.h:969
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:966
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:963
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:960
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:80
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:145
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