IBR-DTNSuite
0.8
|
00001 /* 00002 * PlainSerializer.cpp 00003 * 00004 * Created on: 16.06.2011 00005 * Author: morgenro 00006 */ 00007 00008 #include "config.h" 00009 #include "ibrdtn/api/PlainSerializer.h" 00010 #include "ibrdtn/utils/Utils.h" 00011 #include <ibrcommon/refcnt_ptr.h> 00012 #include <ibrcommon/data/Base64Stream.h> 00013 #include <ibrcommon/data/Base64Reader.h> 00014 #include <ibrcommon/Logger.h> 00015 #include <list> 00016 00017 namespace dtn 00018 { 00019 namespace api 00020 { 00021 PlainSerializer::PlainSerializer(std::ostream &stream, bool skip_payload) 00022 : _stream(stream), _skip_payload(skip_payload) 00023 { 00024 } 00025 00026 PlainSerializer::~PlainSerializer() 00027 { 00028 } 00029 00030 dtn::data::Serializer& PlainSerializer::operator<<(const dtn::data::Bundle &obj) 00031 { 00032 // serialize the primary block 00033 (*this) << (dtn::data::PrimaryBlock&)obj; 00034 00035 // serialize all secondary blocks 00036 const std::list<const dtn::data::Block*> list = obj.getBlocks(); 00037 00038 // block count 00039 _stream << "Blocks: " << list.size() << std::endl; 00040 00041 for (std::list<const dtn::data::Block*>::const_iterator iter = list.begin(); iter != list.end(); iter++) 00042 { 00043 const dtn::data::Block &b = (*(*iter)); 00044 _stream << std::endl; 00045 (*this) << b; 00046 } 00047 00048 _stream << std::endl; 00049 00050 return (*this); 00051 } 00052 00053 dtn::data::Serializer& PlainSerializer::operator<<(const dtn::data::PrimaryBlock &obj) 00054 { 00055 _stream << "Processing flags: " << obj._procflags << std::endl; 00056 _stream << "Timestamp: " << obj._timestamp << std::endl; 00057 _stream << "Sequencenumber: " << obj._sequencenumber << std::endl; 00058 _stream << "Source: " << obj._source.getString() << std::endl; 00059 _stream << "Destination: " << obj._destination.getString() << std::endl; 00060 _stream << "Reportto: " << obj._reportto.getString() << std::endl; 00061 _stream << "Custodian: " << obj._custodian.getString() << std::endl; 00062 _stream << "Lifetime: " << obj._lifetime << std::endl; 00063 00064 if (obj._procflags & dtn::data::PrimaryBlock::FRAGMENT) 00065 { 00066 _stream << "Fragment offset: " << obj._fragmentoffset << std::endl; 00067 _stream << "Application data length: " << obj._appdatalength << std::endl; 00068 } 00069 00070 return (*this); 00071 } 00072 00073 dtn::data::Serializer& PlainSerializer::operator<<(const dtn::data::Block &obj) 00074 { 00075 _stream << "Block: " << (int)((unsigned char)obj.getType()) << std::endl; 00076 00077 std::stringstream flags; 00078 00079 if (obj.get(dtn::data::Block::LAST_BLOCK)) 00080 { 00081 flags << " LAST_BLOCK"; 00082 } 00083 00084 if (obj.get(dtn::data::Block::REPLICATE_IN_EVERY_FRAGMENT)) 00085 { 00086 flags << " REPLICATE_IN_EVERY_FRAGMENT"; 00087 } 00088 00089 if (obj.get(dtn::data::Block::TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED)) 00090 { 00091 flags << " TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED"; 00092 } 00093 00094 if (obj.get(dtn::data::Block::DELETE_BUNDLE_IF_NOT_PROCESSED)) 00095 { 00096 flags << " DELETE_BUNDLE_IF_NOT_PROCESSED"; 00097 } 00098 00099 if (obj.get(dtn::data::Block::DISCARD_IF_NOT_PROCESSED)) 00100 { 00101 flags << " DISCARD_IF_NOT_PROCESSED"; 00102 } 00103 00104 if (obj.get(dtn::data::Block::FORWARDED_WITHOUT_PROCESSED)) 00105 { 00106 flags << " FORWARDED_WITHOUT_PROCESSED"; 00107 } 00108 00109 if (flags.str().length() > 0) 00110 { 00111 _stream << "Flags:" << flags.str() << std::endl; 00112 } 00113 00114 if (obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS)) 00115 { 00116 std::list<dtn::data::EID> eid_list = obj.getEIDList(); 00117 00118 for (std::list<dtn::data::EID>::const_iterator iter = eid_list.begin(); iter != eid_list.end(); iter++) 00119 { 00120 _stream << "EID: " << (*iter).getString() << std::endl; 00121 } 00122 } 00123 00124 _stream << "Length: " << obj.getLength() << std::endl; 00125 00126 00127 if(!_skip_payload){ 00128 try { 00129 00130 _stream << std::endl; 00131 00132 // put data here 00133 ibrcommon::Base64Stream b64(_stream, false, 80); 00134 size_t slength = 0; 00135 obj.serialize(b64, slength); 00136 b64 << std::flush; 00137 } catch (const std::exception &ex) { 00138 std::cerr << ex.what() << std::endl; 00139 } 00140 00141 _stream << std::endl; 00142 } 00143 00144 return (*this); 00145 } 00146 00147 dtn::data::Serializer &PlainSerializer::serialize(ibrcommon::BLOB::iostream &obj, size_t limit){ 00148 size_t len = obj.size(); 00149 if(limit < len && limit > 0) 00150 { 00151 len = limit; 00152 } 00153 00154 _stream << "Length: " << len << std::endl; 00155 _stream << std::endl; 00156 00157 ibrcommon::Base64Stream b64(_stream, false, 80); 00158 ibrcommon::BLOB::copy(b64, *obj, len); 00159 b64 << std::flush; 00160 00161 _stream << std::endl; 00162 00163 return *this; 00164 } 00165 00166 size_t PlainSerializer::getLength(const dtn::data::Bundle &obj) 00167 { 00168 return 0; 00169 } 00170 00171 size_t PlainSerializer::getLength(const dtn::data::PrimaryBlock &obj) const 00172 { 00173 return 0; 00174 } 00175 00176 size_t PlainSerializer::getLength(const dtn::data::Block &obj) const 00177 { 00178 return 0; 00179 } 00180 00181 PlainDeserializer::PlainDeserializer(std::istream &stream) 00182 : _stream(stream) 00183 { 00184 } 00185 00186 PlainDeserializer::~PlainDeserializer() 00187 { 00188 } 00189 00190 dtn::data::Deserializer& PlainDeserializer::operator>>(dtn::data::Bundle &obj) 00191 { 00192 // clear all blocks 00193 obj.clearBlocks(); 00194 00195 // read the primary block 00196 (*this) >> (dtn::data::PrimaryBlock&)obj; 00197 00198 // read until the last block 00199 bool lastblock = false; 00200 00201 // read all BLOCKs 00202 while (!_stream.eof() && !lastblock) 00203 { 00204 try 00205 { 00206 dtn::data::Block& block = readBlock(BlockInserter(obj, BlockInserter::END), obj.get(dtn::data::Bundle::APPDATA_IS_ADMRECORD)); 00207 lastblock = block.get(dtn::data::Block::LAST_BLOCK); 00208 } 00209 catch (const UnknownBlockException &ex) 00210 { 00211 IBRCOMMON_LOGGER_DEBUG(5) << "unknown administrative block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL; 00212 } 00213 catch (const BlockNotProcessableException &ex) 00214 { 00215 IBRCOMMON_LOGGER_DEBUG(5) << "unprocessable block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL; 00216 } 00217 } 00218 00219 return (*this); 00220 } 00221 00222 dtn::data::Deserializer& PlainDeserializer::operator>>(dtn::data::PrimaryBlock &obj) 00223 { 00224 std::string data; 00225 00226 // read until the first empty line appears 00227 while (_stream.good()) 00228 { 00229 std::stringstream ss; 00230 getline(_stream, data); 00231 00232 std::string::reverse_iterator iter = data.rbegin(); 00233 if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1); 00234 00235 // // strip off the last char 00236 // data.erase(data.size() - 1); 00237 00238 // abort after the first empty line 00239 if (data.size() == 0) break; 00240 00241 // split header value 00242 std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1); 00243 00244 // if there are not enough parameter abort with an error 00245 if (values.size() < 1) throw ibrcommon::Exception("parsing error"); 00246 00247 // assign header value 00248 if (values[0] == "Processing flags") 00249 { 00250 ss.clear(); ss.str(values[1]); 00251 ss >> obj._procflags; 00252 } 00253 else if (values[0] == "Timestamp") 00254 { 00255 ss.clear(); ss.str(values[1]); 00256 ss >> obj._timestamp; 00257 } 00258 else if (values[0] == "Sequencenumber") 00259 { 00260 ss.clear(); ss.str(values[1]); 00261 ss >> obj._sequencenumber; 00262 } 00263 else if (values[0] == "Source") 00264 { 00265 obj._source = values[1]; 00266 } 00267 else if (values[0] == "Destination") 00268 { 00269 obj._destination = values[1]; 00270 } 00271 else if (values[0] == "Reportto") 00272 { 00273 obj._reportto = values[1]; 00274 } 00275 else if (values[0] == "Custodian") 00276 { 00277 obj._custodian = values[1]; 00278 } 00279 else if (values[0] == "Lifetime") 00280 { 00281 ss.clear(); ss.str(values[1]); 00282 ss >> obj._lifetime; 00283 } 00284 else if (values[0] == "Fragment offset") 00285 { 00286 ss.clear(); ss.str(values[1]); 00287 ss >> obj._fragmentoffset; 00288 } 00289 else if (values[0] == "Application data length") 00290 { 00291 ss.clear(); ss.str(values[1]); 00292 ss >> obj._appdatalength; 00293 } 00294 } 00295 00296 return (*this); 00297 } 00298 00299 dtn::data::Deserializer& PlainDeserializer::operator>>(dtn::data::Block &obj) 00300 { 00301 std::string data; 00302 size_t blocksize = 0; 00303 00304 // read until the first empty line appears 00305 while (_stream.good()) 00306 { 00307 getline(_stream, data); 00308 00309 std::string::reverse_iterator iter = data.rbegin(); 00310 if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1); 00311 00312 // // strip off the last char 00313 // data.erase(data.size() - 1); 00314 00315 // abort after the first empty line 00316 if (data.size() == 0) break; 00317 00318 // split header value 00319 std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1); 00320 00321 // skip invalid lines 00322 if(values.size() < 2) 00323 continue; 00324 00325 // assign header value 00326 if (values[0] == "Flags") 00327 { 00328 std::vector<std::string> flags = dtn::utils::Utils::tokenize(" ", values[1]); 00329 00330 for (std::vector<std::string>::const_iterator iter = flags.begin(); iter != flags.end(); iter++) 00331 { 00332 const std::string &value = (*iter); 00333 if (value == "LAST_BLOCK") 00334 { 00335 obj.set(dtn::data::Block::LAST_BLOCK, true); 00336 } 00337 else if (value == "FORWARDED_WITHOUT_PROCESSED") 00338 { 00339 obj.set(dtn::data::Block::FORWARDED_WITHOUT_PROCESSED, true); 00340 } 00341 else if (value == "DISCARD_IF_NOT_PROCESSED") 00342 { 00343 obj.set(dtn::data::Block::DISCARD_IF_NOT_PROCESSED, true); 00344 } 00345 else if (value == "DELETE_BUNDLE_IF_NOT_PROCESSED") 00346 { 00347 obj.set(dtn::data::Block::DELETE_BUNDLE_IF_NOT_PROCESSED, true); 00348 } 00349 else if (value == "TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED") 00350 { 00351 obj.set(dtn::data::Block::TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED, true); 00352 } 00353 else if (value == "REPLICATE_IN_EVERY_FRAGMENT") 00354 { 00355 obj.set(dtn::data::Block::REPLICATE_IN_EVERY_FRAGMENT, true); 00356 } 00357 } 00358 } 00359 else if (values[0] == "EID") 00360 { 00361 obj.addEID(values[1]); 00362 obj.set(dtn::data::Block::BLOCK_CONTAINS_EIDS, true); 00363 } 00364 else if (values[0] == "Length") 00365 { 00366 std::stringstream ss; ss.str(values[1]); 00367 ss >> blocksize; 00368 } 00369 } 00370 00371 // then read the payload 00372 IBRCOMMON_LOGGER_DEBUG(20) << "API expecting payload size of " << blocksize << IBRCOMMON_LOGGER_ENDL; 00373 ibrcommon::Base64Reader base64_decoder(_stream, blocksize); 00374 obj.deserialize(base64_decoder, blocksize); 00375 00376 std::string buffer; 00377 00378 // read the appended newline character 00379 getline(_stream, buffer); 00380 std::string::reverse_iterator iter = buffer.rbegin(); 00381 if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1); 00382 if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty"); 00383 00384 // read the final empty line 00385 getline(_stream, buffer); 00386 iter = buffer.rbegin(); 00387 if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1); 00388 if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty"); 00389 00390 return (*this); 00391 } 00392 00393 dtn::data::Deserializer& PlainDeserializer::operator>>(ibrcommon::BLOB::iostream &obj) 00394 { 00395 std::string data; 00396 size_t blocksize = 0; 00397 00398 // read until the first empty line appears 00399 while (_stream.good()) 00400 { 00401 getline(_stream, data); 00402 00403 std::string::reverse_iterator iter = data.rbegin(); 00404 if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1); 00405 00406 // abort after the first empty line 00407 if (data.size() == 0) break; 00408 00409 // split header value 00410 std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1); 00411 00412 // skip invalid lines 00413 if(values.size() < 1) 00414 continue; 00415 00416 // assign header value 00417 if (values[0] == "Length") 00418 { 00419 std::stringstream ss; ss.str(values[1]); 00420 ss >> blocksize; 00421 } 00422 } 00423 00424 // then read the payload 00425 ibrcommon::Base64Reader base64_decoder(_stream, blocksize); 00426 ibrcommon::BLOB::copy(*obj, base64_decoder, blocksize); 00427 //*obj.iostream() << base64_decoder.rdbuf() << std::flush; 00428 00429 std::string buffer; 00430 00431 // read the appended newline character 00432 getline(_stream, buffer); 00433 std::string::reverse_iterator iter = buffer.rbegin(); 00434 if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1); 00435 if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty"); 00436 00437 // read the final empty line 00438 getline(_stream, buffer); 00439 iter = buffer.rbegin(); 00440 if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1); 00441 if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty"); 00442 00443 return (*this); 00444 } 00445 00446 dtn::data::Deserializer& PlainDeserializer::operator>>(std::ostream &stream) 00447 { 00448 ibrcommon::Base64Stream b64(stream, true); 00449 std::string data; 00450 00451 while (b64.good()) 00452 { 00453 getline(_stream, data); 00454 00455 std::string::reverse_iterator iter = data.rbegin(); 00456 if ( (*iter) == '\r' ) data = data.substr(0, data.length() - 1); 00457 00458 // // strip off the last char 00459 // data.erase(data.size() - 1); 00460 00461 // abort after the first empty line 00462 if (data.size() == 0) break; 00463 00464 // put the line into the stream decoder 00465 b64 << data; 00466 } 00467 00468 b64 << std::flush; 00469 00470 return (*this); 00471 } 00472 00473 dtn::data::Block& PlainDeserializer::readBlock(BlockInserter inserter, bool payload_is_adm) 00474 { 00475 std::string buffer; 00476 int block_type; 00477 00478 // read the block type (first line) 00479 getline(_stream, buffer); 00480 00481 std::string::reverse_iterator iter = buffer.rbegin(); 00482 if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1); 00483 00484 // abort if the line data is empty 00485 if (buffer.size() == 0) throw dtn::InvalidDataException("block header is missing"); 00486 00487 // split header value 00488 std::vector<std::string> values = dtn::utils::Utils::tokenize(":", buffer, 1); 00489 00490 if (values[0] == "Block") 00491 { 00492 std::stringstream ss; ss.str(values[1]); 00493 ss >> block_type; 00494 } 00495 else 00496 { 00497 throw dtn::InvalidDataException("need block type as first header"); 00498 } 00499 00500 switch (block_type) 00501 { 00502 case 0: 00503 { 00504 throw dtn::InvalidDataException("block type is zero"); 00505 break; 00506 } 00507 00508 case dtn::data::PayloadBlock::BLOCK_TYPE: 00509 { 00510 //if (payload_is_adm) 00511 if (payload_is_adm) 00512 { 00513 // create a temporary block 00514 dtn::data::ExtensionBlock block; 00515 block.set(dtn::data::Block::LAST_BLOCK, false); 00516 00517 // read the block data 00518 (*this) >> block; 00519 00520 // access the payload to get the first byte 00521 char admfield; 00522 ibrcommon::BLOB::Reference ref = block.getBLOB(); 00523 ref.iostream()->get(admfield); 00524 00525 // write the block into a temporary stream 00526 stringstream ss; 00527 PlainSerializer serializer(ss); 00528 PlainDeserializer deserializer(ss); 00529 00530 serializer << block; 00531 00532 switch (admfield >> 4) 00533 { 00534 case 1: 00535 { 00536 dtn::data::StatusReportBlock &block = inserter.insert<dtn::data::StatusReportBlock>(); 00537 block.set(dtn::data::Block::LAST_BLOCK, false); 00538 deserializer >> block; 00539 //lastblock = block.get(dtn::data::Block::LAST_BLOCK); 00540 return block; 00541 } 00542 00543 case 2: 00544 { 00545 dtn::data::CustodySignalBlock &block = inserter.insert<dtn::data::CustodySignalBlock>(); 00546 block.set(dtn::data::Block::LAST_BLOCK, false); 00547 deserializer >> block; 00548 //lastblock = block.get(dtn::data::Block::LAST_BLOCK); 00549 //break; 00550 return block; 00551 } 00552 00553 default: 00554 { 00555 // drop unknown administrative block 00556 throw UnknownBlockException("unknown administrative record"); 00557 break; 00558 } 00559 } 00560 00561 } 00562 else 00563 { 00564 dtn::data::PayloadBlock &block = inserter.insert<dtn::data::PayloadBlock>(); 00565 block.set(dtn::data::Block::LAST_BLOCK, false); 00566 (*this) >> block; 00567 00568 return block; 00569 } 00570 } 00571 00572 default: 00573 { 00574 // get a extension block factory 00575 try { 00576 dtn::data::ExtensionBlock::Factory &f = dtn::data::ExtensionBlock::Factory::get((char) block_type); 00577 00578 dtn::data::Block &block = inserter.insert(f); 00579 block.set(dtn::data::Block::LAST_BLOCK, false); 00580 (*this) >> block; 00581 00582 if (block.get(dtn::data::Block::DISCARD_IF_NOT_PROCESSED)) 00583 { 00584 //IBRCOMMON_LOGGER_DEBUG(5) << "unprocessable block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL; 00585 00586 throw BlockNotProcessableException(); 00587 } 00588 return block; 00589 } 00590 catch (const BlockNotProcessableException &ex){ 00591 throw ex; 00592 } 00593 catch (const ibrcommon::Exception &ex) 00594 { 00595 dtn::data::ExtensionBlock &block = inserter.insert<dtn::data::ExtensionBlock>(); 00596 block.set(dtn::data::Block::LAST_BLOCK, false); 00597 (*this) >> block; 00598 00599 if (block.get(dtn::data::Block::DISCARD_IF_NOT_PROCESSED)) 00600 { 00601 //IBRCOMMON_LOGGER_DEBUG(5) << "unprocessable block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL; 00602 00603 throw BlockNotProcessableException(); 00604 } 00605 return block; 00606 } 00607 } 00608 } 00609 } 00610 00611 PlainDeserializer::BlockInserter::BlockInserter(dtn::data::Bundle &bundle, POSITION alignment, int pos) 00612 : _bundle(&bundle), _alignment(alignment), _pos(pos) 00613 { 00614 } 00615 00616 dtn::data::Block &PlainDeserializer::BlockInserter::insert(dtn::data::ExtensionBlock::Factory &f) 00617 { 00618 switch (_alignment) 00619 { 00620 case FRONT: 00621 return _bundle->push_front(f); 00622 case END: 00623 return _bundle->push_back(f); 00624 default: 00625 if(_pos <= 0) 00626 return _bundle->push_front(f); 00627 00628 try 00629 { 00630 dtn::data::Block &prev_block = _bundle->getBlock(_pos-1); 00631 return _bundle->insert(f, prev_block); 00632 } 00633 catch (const std::exception &ex) 00634 { 00635 return _bundle->push_back(f); 00636 } 00637 } 00638 } 00639 00640 PlainDeserializer::BlockInserter::POSITION PlainDeserializer::BlockInserter::getAlignment() const 00641 { 00642 return _alignment; 00643 } 00644 } 00645 }