IBR-DTNSuite  0.10
PlainSerializer.cpp
Go to the documentation of this file.
1 /*
2  * PlainSerializer.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
24 #include "ibrdtn/data/Bundle.h"
25 #include "ibrdtn/utils/Utils.h"
26 #include <ibrcommon/refcnt_ptr.h>
29 #include <ibrcommon/Logger.h>
30 #include <list>
31 
32 namespace dtn
33 {
34  namespace api
35  {
37  {
38  if (data == "raw") return PlainSerializer::RAW;
39  if (data == "base64") return PlainSerializer::BASE64;
40  if (data == "skip") return PlainSerializer::SKIP_PAYLOAD;
42  }
43 
45  {
46  switch (enc) {
48  return "raw";
50  return "base64";
52  return "skip";
53  default:
54  return "invalid";
55  }
56  }
57 
58  PlainSerializer::PlainSerializer(std::ostream &stream, Encoding enc)
59  : _stream(stream), _encoding(enc)
60  {
61  }
62 
64  {
65  }
66 
68  {
69  // serialize the primary block
70  (*this) << (dtn::data::PrimaryBlock&)obj;
71 
72  // block count
73  _stream << "Blocks: " << obj.size() << std::endl;
74 
75  // serialize all secondary blocks
76  for (dtn::data::Bundle::const_iterator iter = obj.begin(); iter != obj.end(); ++iter)
77  {
78  const dtn::data::Block &b = (**iter);
79  _stream << std::endl;
80  (*this) << b;
81  }
82 
83  _stream << std::endl;
84 
85  return (*this);
86  }
87 
89  {
90  _stream << "Processing flags: " << obj.procflags.toString() << std::endl;
91  _stream << "Timestamp: " << obj.timestamp.toString() << std::endl;
92  _stream << "Sequencenumber: " << obj.sequencenumber.toString() << std::endl;
93  _stream << "Source: " << obj.source.getString() << std::endl;
94  _stream << "Destination: " << obj.destination.getString() << std::endl;
95  _stream << "Reportto: " << obj.reportto.getString() << std::endl;
96  _stream << "Custodian: " << obj.custodian.getString() << std::endl;
97  _stream << "Lifetime: " << obj.lifetime.toString() << std::endl;
98 
100  {
101  _stream << "Fragment offset: " << obj.fragmentoffset.toString() << std::endl;
102  _stream << "Application data length: " << obj.appdatalength.toString() << std::endl;
103  }
104 
105  return (*this);
106  }
107 
109  {
110  _stream << "Block: " << (int)((unsigned char)obj.getType()) << std::endl;
111 
112  std::stringstream flags;
113 
115  {
116  flags << " LAST_BLOCK";
117  }
118 
120  {
121  flags << " REPLICATE_IN_EVERY_FRAGMENT";
122  }
123 
125  {
126  flags << " TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED";
127  }
128 
130  {
131  flags << " DELETE_BUNDLE_IF_NOT_PROCESSED";
132  }
133 
135  {
136  flags << " DISCARD_IF_NOT_PROCESSED";
137  }
138 
140  {
141  flags << " FORWARDED_WITHOUT_PROCESSED";
142  }
143 
144  if (flags.str().length() > 0)
145  {
146  _stream << "Flags:" << flags.str() << std::endl;
147  }
148 
150  {
151  std::list<dtn::data::EID> eid_list = obj.getEIDList();
152 
153  for (std::list<dtn::data::EID>::const_iterator iter = eid_list.begin(); iter != eid_list.end(); ++iter)
154  {
155  _stream << "EID: " << (*iter).getString() << std::endl;
156  }
157  }
158 
159  _stream << "Length: " << obj.getLength() << std::endl;
160  _stream << "Encoding: " << PlainSerializer::printEncoding(_encoding) << std::endl;
161 
162  if (_encoding != SKIP_PAYLOAD)
163  {
164  try {
165  _stream << std::endl;
166 
167  // put data here
168  dtn::data::Length slength = 0;
169  switch(_encoding)
170  {
171  case BASE64:
172  {
173  ibrcommon::Base64Stream b64(_stream, false, 80);
174  obj.serialize(b64, slength);
175  b64 << std::flush;
176  break;
177  }
178 
179  case RAW:
180  obj.serialize(_stream, slength);
181  _stream << std::flush;
182  break;
183 
184  default:
185  break;
186  }
187 
188  } catch (const std::exception &ex) {
189  std::cerr << ex.what() << std::endl;
190  }
191 
192  _stream << std::endl;
193  }
194 
195  return (*this);
196  }
197 
199  {
200  return 0;
201  }
202 
204  {
205  return 0;
206  }
207 
209  {
210  return 0;
211  }
212 
214  : _stream(stream), _lastblock(false)
215  {
216  }
217 
219  {
220  }
221 
223  {
224  dtn::data::BundleBuilder builder(obj);
225 
226  // clear all blocks
227  obj.clear();
228 
229  // read the primary block
230  (*this) >> (dtn::data::PrimaryBlock&)obj;
231 
232  // read until the last block
233  _lastblock = false;
234 
235  // read all BLOCKs
236  while (!_stream.eof() && !_lastblock)
237  {
238  try {
239  readBlock(builder);
241  IBRCOMMON_LOGGER_DEBUG_TAG("PlainDeserializer", 5) << "unknown block has been discarded " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL;
242  } catch (const UnknownBlockException &ex) {
243  IBRCOMMON_LOGGER_DEBUG_TAG("PlainDeserializer", 5) << "unknown administrative block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL;
244  } catch (const BlockNotProcessableException &ex) {
245  IBRCOMMON_LOGGER_DEBUG_TAG("PlainDeserializer", 5) << "unprocessable block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL;
246  }
247  }
248 
249  return (*this);
250  }
251 
253  {
254  std::string data;
255 
256  // read until the first empty line appears
257  while (_stream.good())
258  {
259  getline(_stream, data);
260 
261  std::string::reverse_iterator iter = data.rbegin();
262  if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1);
263 
264 // // strip off the last char
265 // data.erase(data.size() - 1);
266 
267  // abort after the first empty line
268  if (data.size() == 0) break;
269 
270  // split header value
271  std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1);
272 
273  // if there are not enough parameter abort with an error
274  if (values.size() < 1) throw ibrcommon::Exception("parsing error");
275 
276  // assign header value
277  if (values[0] == "Processing flags")
278  {
279  obj.procflags.fromString(values[1]);
280  }
281  else if (values[0] == "Timestamp")
282  {
283  obj.timestamp.fromString(values[1]);
284  }
285  else if (values[0] == "Sequencenumber")
286  {
287  obj.sequencenumber.fromString(values[1]);
288  }
289  else if (values[0] == "Source")
290  {
291  obj.source = values[1];
292  }
293  else if (values[0] == "Destination")
294  {
295  obj.destination = values[1];
296  }
297  else if (values[0] == "Reportto")
298  {
299  obj.reportto = values[1];
300  }
301  else if (values[0] == "Custodian")
302  {
303  obj.custodian = values[1];
304  }
305  else if (values[0] == "Lifetime")
306  {
307  obj.lifetime.fromString(values[1]);
308  }
309  else if (values[0] == "Fragment offset")
310  {
311  obj.fragmentoffset.fromString(values[1]);
312  }
313  else if (values[0] == "Application data length")
314  {
315  obj.appdatalength.fromString(values[1]);
316  }
317  }
318 
319  return (*this);
320  }
321 
323  {
324  std::string data;
325  dtn::data::Length blocksize = 0;
327 
328  // read until the first empty line appears
329  while (_stream.good())
330  {
331  getline(_stream, data);
332 
333  std::string::reverse_iterator iter = data.rbegin();
334  if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1);
335 
336 // // strip off the last char
337 // data.erase(data.size() - 1);
338 
339  // abort after the first empty line
340  if (data.size() == 0) break;
341 
342  // split header value
343  std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1);
344 
345  // skip invalid lines
346  if(values.size() < 2)
347  continue;
348 
349  // assign header value
350  if (values[0] == "Flags")
351  {
352  std::vector<std::string> flags = dtn::utils::Utils::tokenize(" ", values[1]);
353 
354  for (std::vector<std::string>::const_iterator iter = flags.begin(); iter != flags.end(); ++iter)
355  {
356  const std::string &value = (*iter);
357  if (value == "LAST_BLOCK")
358  {
360  _lastblock = true;
361  }
362  else if (value == "FORWARDED_WITHOUT_PROCESSED")
363  {
365  }
366  else if (value == "DISCARD_IF_NOT_PROCESSED")
367  {
369  }
370  else if (value == "DELETE_BUNDLE_IF_NOT_PROCESSED")
371  {
373  }
374  else if (value == "TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED")
375  {
377  }
378  else if (value == "REPLICATE_IN_EVERY_FRAGMENT")
379  {
381  }
382  }
383  }
384  else if (values[0] == "EID")
385  {
386  obj.addEID(values[1]);
388  }
389  else if (values[0] == "Length")
390  {
391  std::stringstream ss; ss.str(values[1]);
392  ss >> blocksize;
393  }
394  else if (values[0] == "Encoding")
395  {
396  std::stringstream ss; ss << values[1]; ss.clear(); ss >> values[1];
397  enc = PlainSerializer::parseEncoding(values[1]);
398  }
399  }
400 
401  // then read the payload
402  IBRCOMMON_LOGGER_DEBUG_TAG("PlainDeserializer", 20) << "API expecting payload size of " << blocksize << IBRCOMMON_LOGGER_ENDL;
403 
404  switch(enc)
405  {
407  {
408  ibrcommon::Base64Reader base64_decoder(_stream, blocksize);
409  obj.deserialize(base64_decoder, blocksize);
410  break;
411  }
413  obj.deserialize(_stream, blocksize);
414  break;
415 
416  default:
417  break;
418  }
419 
420  std::string buffer;
421 
422  // read the appended newline character
423  getline(_stream, buffer);
424  std::string::reverse_iterator iter = buffer.rbegin();
425  if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1);
426  if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty");
427 
428  // read the final empty line
429  getline(_stream, buffer);
430  iter = buffer.rbegin();
431  if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1);
432  if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty");
433 
434  return (*this);
435  }
436 
438  {
439  std::string data;
440  dtn::data::Length blocksize = 0;
442 
443  // read until the first empty line appears
444  while (_stream.good())
445  {
446  getline(_stream, data);
447 
448  std::string::reverse_iterator iter = data.rbegin();
449  if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1);
450 
451  // abort after the first empty line
452  if (data.size() == 0) break;
453 
454  // split header value
455  std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1);
456 
457  // skip invalid lines
458  if(values.size() < 1)
459  continue;
460 
461  // assign header value
462  if (values[0] == "Length")
463  {
464  std::stringstream ss; ss.str(values[1]);
465  ss >> blocksize;
466  }
467  else if (values[0] == "Encoding")
468  {
469  std::stringstream ss; ss << values[1]; ss.clear(); ss >> values[1];
470  enc = PlainSerializer::parseEncoding(values[1]);
471  }
472  }
473 
474  // then read the payload
475  switch (enc)
476  {
478  {
479  ibrcommon::Base64Reader base64_decoder(_stream, blocksize);
480  ibrcommon::BLOB::copy(*obj, base64_decoder, blocksize);
481  break;
482  }
484  ibrcommon::BLOB::copy(*obj, _stream, blocksize);
485  break;
486 
487  default:
488  break;
489  }
490 
491  std::string buffer;
492 
493  // read the appended newline character
494  getline(_stream, buffer);
495  std::string::reverse_iterator iter = buffer.rbegin();
496  if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1);
497  if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty");
498 
499  // read the final empty line
500  getline(_stream, buffer);
501  iter = buffer.rbegin();
502  if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1);
503  if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty");
504 
505  return (*this);
506  }
507 
509  {
510  _stream << "Length: " << block.getLength() << std::endl;
511  _stream << "Encoding: " << PlainSerializer::printEncoding(_encoding) << std::endl;
512  _stream << std::endl;
513 
514  size_t slength = 0;
515 
516  switch(_encoding)
517  {
518  case BASE64:
519  {
520  // put data here
521  ibrcommon::Base64Stream b64(_stream, false, 80);
522  block.serialize(b64, slength);
523  b64 << std::flush;
524  break;
525  }
526 
527  case RAW:
528  block.serialize(_stream, slength);
529  break;
530 
531  default:
532  break;
533  }
534  _stream << std::endl;
535  }
536 
537  void PlainSerializer::writeData(std::istream &stream, const dtn::data::Length &len)
538  {
539  _stream << "Length: " << len << std::endl;
540  _stream << "Encoding: " << PlainSerializer::printEncoding(_encoding) << std::endl;
541  _stream << std::endl;
542 
543  switch(_encoding)
544  {
545  case BASE64:
546  {
547  ibrcommon::Base64Stream b64(_stream, false, 80);
548  ibrcommon::BLOB::copy(b64, stream, len);
549  b64 << std::flush;
550  break;
551  }
552 
553  case RAW:
554  ibrcommon::BLOB::copy(_stream, stream, len);
555  _stream << std::flush;
556  break;
557 
558  default:
559  break;
560  }
561  _stream << std::endl;
562  }
563 
564  void PlainDeserializer::readData(std::ostream &stream)
565  {
566  std::string data;
567  dtn::data::Length len = 0;
569 
570  // read headers until an empty line
571  while (true)
572  {
573  // read the block type (first line)
574  getline(_stream, data);
575 
576  std::string::reverse_iterator iter = data.rbegin();
577  if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1);
578 
579  // abort if the line data is empty
580  if (data.size() == 0) break;
581 
582  // split header value
583  std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1);
584 
585  if (values[0] == "Length")
586  {
587  std::stringstream ss; ss.str(values[1]);
588  ss >> len;
589  }
590  else if (values[0] == "Encoding")
591  {
592  std::stringstream ss; ss << values[1]; ss.clear(); ss >> values[1];
593  enc = PlainSerializer::parseEncoding(values[1]);
594  }
595  else
596  {
597  throw dtn::InvalidDataException("unknown block header");
598  }
599  }
600 
601  if (enc == PlainSerializer::BASE64)
602  {
603  ibrcommon::Base64Stream b64(stream, true);
604 
605  while (b64.good())
606  {
607  getline(_stream, data);
608 
609  std::string::reverse_iterator iter = data.rbegin();
610  if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1);
611 
612  // abort after the first empty line
613  if (data.size() == 0) break;
614 
615  // put the line into the stream decoder
616  b64 << data;
617  }
618 
619  b64 << std::flush;
620  } else if (enc == PlainSerializer::RAW) {
621  ibrcommon::BLOB::copy(stream, _stream, len);
622  }
623  }
624 
626  {
627  std::string buffer;
628  dtn::data::block_t block_type;
629 
630  // read the block type (first line)
631  getline(_stream, buffer);
632 
633  std::string::reverse_iterator iter = buffer.rbegin();
634  if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1);
635 
636  // abort if the line data is empty
637  if (buffer.size() == 0) throw dtn::InvalidDataException("block header is missing");
638 
639  // split header value
640  std::vector<std::string> values = dtn::utils::Utils::tokenize(":", buffer, 1);
641 
642  if (values[0] == "Block")
643  {
644  std::stringstream ss; ss.str(values[1]);
645  int type;
646  ss >> type;
647  block_type = static_cast<dtn::data::block_t>(type);
648  }
649  else
650  {
651  throw dtn::InvalidDataException("need block type as first header");
652  }
653 
654  try {
656  dtn::data::Block &block = builder.insert(block_type, procflags);
657  (*this) >> block;
658  return block;
660  // TODO: skip block
661  throw;
662  }
663  }
664  }
665 }