IBR-DTNSuite
0.8
|
00001 #include "ibrdtn/data/Serializer.h" 00002 #include "ibrdtn/data/Bundle.h" 00003 #include "ibrdtn/data/Block.h" 00004 #include "ibrdtn/data/BundleString.h" 00005 #include "ibrdtn/data/StatusReportBlock.h" 00006 #include "ibrdtn/data/CustodySignalBlock.h" 00007 #include "ibrdtn/data/ExtensionBlock.h" 00008 #include "ibrdtn/data/PayloadBlock.h" 00009 #include "ibrdtn/data/MetaBundle.h" 00010 #include "ibrdtn/utils/Clock.h" 00011 #include <ibrcommon/refcnt_ptr.h> 00012 #include <ibrcommon/Logger.h> 00013 #include <list> 00014 00015 #ifdef __DEVELOPMENT_ASSERTIONS__ 00016 #include <cassert> 00017 #endif 00018 00019 namespace dtn 00020 { 00021 namespace data 00022 { 00023 DefaultSerializer::DefaultSerializer(std::ostream& stream) 00024 : _stream(stream), _compressable(false) 00025 { 00026 } 00027 00028 DefaultSerializer::DefaultSerializer(std::ostream& stream, const Dictionary &d) 00029 : _stream(stream), _dictionary(d), _compressable(false) 00030 { 00031 } 00032 00033 void DefaultSerializer::rebuildDictionary(const dtn::data::Bundle &obj) 00034 { 00035 // clear the dictionary 00036 _dictionary.clear(); 00037 00038 // rebuild the dictionary 00039 _dictionary.add(obj._destination); 00040 _dictionary.add(obj._source); 00041 _dictionary.add(obj._reportto); 00042 _dictionary.add(obj._custodian); 00043 00044 // add EID of all secondary blocks 00045 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks; 00046 00047 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++) 00048 { 00049 const Block &b = (*(*iter)); 00050 _dictionary.add( b.getEIDList() ); 00051 } 00052 } 00053 00054 Serializer& DefaultSerializer::operator <<(const dtn::data::Bundle& obj) 00055 { 00056 // rebuild the dictionary 00057 rebuildDictionary(obj); 00058 00059 // check if the bundle header could be compressed 00060 _compressable = isCompressable(obj); 00061 00062 // serialize the primary block 00063 (*this) << (PrimaryBlock&)obj; 00064 00065 // serialize all secondary blocks 00066 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks; 00067 00068 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++) 00069 { 00070 const Block &b = (*(*iter)); 00071 (*this) << b; 00072 } 00073 00074 return (*this); 00075 } 00076 00077 Serializer& DefaultSerializer::operator<<(const dtn::data::BundleFragment &obj) 00078 { 00079 // rebuild the dictionary 00080 rebuildDictionary(obj._bundle); 00081 00082 // check if the bundle header could be compressed 00083 _compressable = isCompressable(obj._bundle); 00084 00085 PrimaryBlock prim = obj._bundle; 00086 prim.set(dtn::data::PrimaryBlock::FRAGMENT, true); 00087 00088 // set the application length according to the payload block size 00089 try { 00090 const dtn::data::PayloadBlock &payload = obj._bundle.getBlock<dtn::data::PayloadBlock>(); 00091 prim._appdatalength = payload.getLength(); 00092 } catch (dtn::data::Bundle::NoSuchBlockFoundException&) { 00093 prim._appdatalength = 0; 00094 } 00095 00096 // set the fragmentation offset 00097 prim._fragmentoffset += obj._offset; 00098 00099 // serialize the primary block 00100 (*this) << prim; 00101 00102 // serialize all secondary blocks 00103 std::list<refcnt_ptr<Block> > list = obj._bundle._blocks._blocks; 00104 bool post_payload = false; 00105 00106 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++) 00107 { 00108 const Block &b = (*(*iter)); 00109 00110 try { 00111 // test if this is the payload block 00112 const dtn::data::PayloadBlock &payload = dynamic_cast<const dtn::data::PayloadBlock&>(b); 00113 00114 // serialize the clipped block 00115 serialize(payload, obj._offset, obj._length); 00116 00117 // we had serialized the payload block 00118 post_payload = true; 00119 } catch (const std::bad_cast&) { 00120 // serialize this block if 00121 // ... this block is before the payload block and marked as replicated in every fragment 00122 // ... this block is after the payload block and all remaining bytes of the payload block are included 00123 if (post_payload || b.get(dtn::data::Block::REPLICATE_IN_EVERY_FRAGMENT)) 00124 { 00125 (*this) << b; 00126 } 00127 } 00128 } 00129 00130 return (*this); 00131 } 00132 00133 bool DefaultSerializer::isCompressable(const dtn::data::Bundle &obj) const 00134 { 00135 // check if all EID are compressable 00136 bool compressable = ( obj._source.isCompressable() && 00137 obj._destination.isCompressable() && 00138 obj._reportto.isCompressable() && 00139 obj._custodian.isCompressable() ); 00140 00141 if (compressable) 00142 { 00143 // add EID of all secondary blocks 00144 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks; 00145 00146 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++) 00147 { 00148 const Block &b = (*(*iter)); 00149 const std::list<dtn::data::EID> eids = b.getEIDList(); 00150 00151 for (std::list<dtn::data::EID>::const_iterator eit = eids.begin(); eit != eids.end(); eit++) 00152 { 00153 const dtn::data::EID &eid = (*eit); 00154 if (!eid.isCompressable()) 00155 { 00156 return false; 00157 } 00158 } 00159 } 00160 } 00161 00162 return compressable; 00163 } 00164 00165 Serializer& DefaultSerializer::operator <<(const dtn::data::PrimaryBlock& obj) 00166 { 00167 _stream << dtn::data::BUNDLE_VERSION; // bundle version 00168 _stream << dtn::data::SDNV(obj._procflags); // processing flags 00169 00170 // predict the block length 00171 size_t len = 0; 00172 dtn::data::SDNV primaryheader[14]; 00173 00174 primaryheader[8] = SDNV(obj._timestamp); // timestamp 00175 primaryheader[9] = SDNV(obj._sequencenumber); // sequence number 00176 primaryheader[10] = SDNV(obj._lifetime); // lifetime 00177 00178 pair<size_t, size_t> ref; 00179 00180 if (_compressable) 00181 { 00182 // destination reference 00183 ref = obj._destination.getCompressed(); 00184 primaryheader[0] = SDNV(ref.first); 00185 primaryheader[1] = SDNV(ref.second); 00186 00187 // source reference 00188 ref = obj._source.getCompressed(); 00189 primaryheader[2] = SDNV(ref.first); 00190 primaryheader[3] = SDNV(ref.second); 00191 00192 // reportto reference 00193 ref = obj._reportto.getCompressed(); 00194 primaryheader[4] = SDNV(ref.first); 00195 primaryheader[5] = SDNV(ref.second); 00196 00197 // custodian reference 00198 ref = obj._custodian.getCompressed(); 00199 primaryheader[6] = SDNV(ref.first); 00200 primaryheader[7] = SDNV(ref.second); 00201 00202 // dictionary size is zero in a compressed bundle header 00203 primaryheader[11] = SDNV(0); 00204 } 00205 else 00206 { 00207 // destination reference 00208 ref = _dictionary.getRef(obj._destination); 00209 primaryheader[0] = SDNV(ref.first); 00210 primaryheader[1] = SDNV(ref.second); 00211 00212 // source reference 00213 ref = _dictionary.getRef(obj._source); 00214 primaryheader[2] = SDNV(ref.first); 00215 primaryheader[3] = SDNV(ref.second); 00216 00217 // reportto reference 00218 ref = _dictionary.getRef(obj._reportto); 00219 primaryheader[4] = SDNV(ref.first); 00220 primaryheader[5] = SDNV(ref.second); 00221 00222 // custodian reference 00223 ref = _dictionary.getRef(obj._custodian); 00224 primaryheader[6] = SDNV(ref.first); 00225 primaryheader[7] = SDNV(ref.second); 00226 00227 // dictionary size 00228 primaryheader[11] = SDNV(_dictionary.getSize()); 00229 len += _dictionary.getSize(); 00230 } 00231 00232 for (int i = 0; i < 12; i++) 00233 { 00234 len += primaryheader[i].getLength(); 00235 } 00236 00237 if (obj.get(dtn::data::Bundle::FRAGMENT)) 00238 { 00239 primaryheader[12] = SDNV(obj._fragmentoffset); 00240 primaryheader[13] = SDNV(obj._appdatalength); 00241 00242 len += primaryheader[12].getLength(); 00243 len += primaryheader[13].getLength(); 00244 } 00245 00246 // write the block length 00247 _stream << SDNV(len); 00248 00249 /* 00250 * write the ref block of the dictionary 00251 * this includes scheme and ssp for destination, source, reportto and custodian. 00252 */ 00253 for (int i = 0; i < 11; i++) 00254 { 00255 _stream << primaryheader[i]; 00256 } 00257 00258 if (_compressable) 00259 { 00260 // write the size of the dictionary (always zero here) 00261 _stream << primaryheader[11]; 00262 } 00263 else 00264 { 00265 // write size of dictionary + bytearray 00266 _stream << _dictionary; 00267 } 00268 00269 if (obj.get(dtn::data::Bundle::FRAGMENT)) 00270 { 00271 _stream << primaryheader[12]; // FRAGMENTATION_OFFSET 00272 _stream << primaryheader[13]; // APPLICATION_DATA_LENGTH 00273 } 00274 00275 return (*this); 00276 } 00277 00278 Serializer& DefaultSerializer::operator <<(const dtn::data::Block& obj) 00279 { 00280 _stream << obj._blocktype; 00281 _stream << dtn::data::SDNV(obj._procflags); 00282 00283 #ifdef __DEVELOPMENT_ASSERTIONS__ 00284 // test: BLOCK_CONTAINS_EIDS => (_eids.size() > 0) 00285 assert(!obj.get(Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0)); 00286 #endif 00287 00288 if (obj.get(Block::BLOCK_CONTAINS_EIDS)) 00289 { 00290 _stream << SDNV(obj._eids.size()); 00291 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++) 00292 { 00293 pair<size_t, size_t> offsets; 00294 00295 if (_compressable) 00296 { 00297 offsets = (*it).getCompressed(); 00298 } 00299 else 00300 { 00301 offsets = _dictionary.getRef(*it); 00302 } 00303 00304 _stream << SDNV(offsets.first); 00305 _stream << SDNV(offsets.second); 00306 } 00307 } 00308 00309 // write size of the payload in the block 00310 _stream << SDNV(obj.getLength()); 00311 00312 // write the payload of the block 00313 size_t slength = 0; 00314 obj.serialize(_stream, slength); 00315 00316 return (*this); 00317 } 00318 00319 Serializer& DefaultSerializer::serialize(const dtn::data::PayloadBlock& obj, size_t clip_offset, size_t clip_length) 00320 { 00321 _stream << obj._blocktype; 00322 _stream << dtn::data::SDNV(obj._procflags); 00323 00324 #ifdef __DEVELOPMENT_ASSERTIONS__ 00325 // test: BLOCK_CONTAINS_EIDS => (_eids.size() > 0) 00326 assert(!obj.get(Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0)); 00327 #endif 00328 00329 if (obj.get(Block::BLOCK_CONTAINS_EIDS)) 00330 { 00331 _stream << SDNV(obj._eids.size()); 00332 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++) 00333 { 00334 pair<size_t, size_t> offsets; 00335 00336 if (_compressable) 00337 { 00338 offsets = (*it).getCompressed(); 00339 } 00340 else 00341 { 00342 offsets = _dictionary.getRef(*it); 00343 } 00344 00345 _stream << SDNV(offsets.first); 00346 _stream << SDNV(offsets.second); 00347 } 00348 } 00349 00350 // get the remaining payload size 00351 size_t payload_size = obj.getLength(); 00352 size_t remain = payload_size - clip_offset; 00353 00354 // check if the remaining data length is >= clip_length 00355 if (payload_size < clip_offset) 00356 { 00357 // set the real predicted payload length 00358 // write size of the payload in the block 00359 _stream << SDNV(0); 00360 } 00361 else 00362 if (remain > clip_length) 00363 { 00364 // set the real predicted payload length 00365 // write size of the payload in the block 00366 _stream << SDNV(clip_length); 00367 00368 // now skip the <offset>-bytes and all bytes after <offset + length> 00369 obj.serialize( _stream, clip_offset, clip_length ); 00370 } 00371 else 00372 { 00373 // set the real predicted payload length 00374 // write size of the payload in the block 00375 _stream << SDNV(remain); 00376 00377 // now skip the <offset>-bytes and all bytes after <offset + length> 00378 obj.serialize( _stream, clip_offset, remain ); 00379 } 00380 00381 return (*this); 00382 } 00383 00384 size_t DefaultSerializer::getLength(const dtn::data::Bundle &obj) 00385 { 00386 // rebuild the dictionary 00387 rebuildDictionary(obj); 00388 00389 size_t len = 0; 00390 len += getLength( (PrimaryBlock&)obj ); 00391 00392 // add size of all blocks 00393 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks; 00394 00395 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++) 00396 { 00397 const Block &b = (*(*iter)); 00398 len += getLength( b ); 00399 } 00400 00401 return len; 00402 } 00403 00404 size_t DefaultSerializer::getLength(const dtn::data::PrimaryBlock& obj) const 00405 { 00406 size_t len = 0; 00407 00408 len += sizeof(dtn::data::BUNDLE_VERSION); // bundle version 00409 len += dtn::data::SDNV(obj._procflags).getLength(); // processing flags 00410 00411 // primary header 00412 dtn::data::SDNV primaryheader[14]; 00413 pair<size_t, size_t> ref; 00414 00415 if (_compressable) 00416 { 00417 // destination reference 00418 ref = obj._destination.getCompressed(); 00419 primaryheader[0] = SDNV(ref.first); 00420 primaryheader[1] = SDNV(ref.second); 00421 00422 // source reference 00423 ref = obj._source.getCompressed(); 00424 primaryheader[2] = SDNV(ref.first); 00425 primaryheader[3] = SDNV(ref.second); 00426 00427 // reportto reference 00428 ref = obj._reportto.getCompressed(); 00429 primaryheader[4] = SDNV(ref.first); 00430 primaryheader[5] = SDNV(ref.second); 00431 00432 // custodian reference 00433 ref = obj._custodian.getCompressed(); 00434 primaryheader[6] = SDNV(ref.first); 00435 primaryheader[7] = SDNV(ref.second); 00436 00437 // dictionary size 00438 primaryheader[11] = SDNV(0); 00439 } 00440 else 00441 { 00442 // destination reference 00443 ref = _dictionary.getRef(obj._destination); 00444 primaryheader[0] = SDNV(ref.first); 00445 primaryheader[1] = SDNV(ref.second); 00446 00447 // source reference 00448 ref = _dictionary.getRef(obj._source); 00449 primaryheader[2] = SDNV(ref.first); 00450 primaryheader[3] = SDNV(ref.second); 00451 00452 // reportto reference 00453 ref = _dictionary.getRef(obj._reportto); 00454 primaryheader[4] = SDNV(ref.first); 00455 primaryheader[5] = SDNV(ref.second); 00456 00457 // custodian reference 00458 ref = _dictionary.getRef(obj._custodian); 00459 primaryheader[6] = SDNV(ref.first); 00460 primaryheader[7] = SDNV(ref.second); 00461 00462 // dictionary size 00463 primaryheader[11] = SDNV(_dictionary.getSize()); 00464 } 00465 00466 // timestamp 00467 primaryheader[8] = SDNV(obj._timestamp); 00468 00469 // sequence number 00470 primaryheader[9] = SDNV(obj._sequencenumber); 00471 00472 // lifetime 00473 primaryheader[10] = SDNV(obj._lifetime); 00474 00475 for (int i = 0; i < 11; i++) 00476 { 00477 len += primaryheader[i].getLength(); 00478 } 00479 00480 if (_compressable) 00481 { 00482 // write the size of the dictionary (always zero here) 00483 len += primaryheader[11].getLength(); 00484 } 00485 else 00486 { 00487 // write size of dictionary + bytearray 00488 len += primaryheader[11].getLength(); 00489 len += _dictionary.getSize(); 00490 } 00491 00492 if (obj.get(dtn::data::Bundle::FRAGMENT)) 00493 { 00494 primaryheader[12] = SDNV(obj._fragmentoffset); 00495 primaryheader[13] = SDNV(obj._appdatalength); 00496 00497 len += primaryheader[12].getLength(); 00498 len += primaryheader[13].getLength(); 00499 } 00500 00501 len += SDNV(len).getLength(); 00502 00503 return len; 00504 } 00505 00506 size_t DefaultSerializer::getLength(const dtn::data::Block &obj) const 00507 { 00508 size_t len = 0; 00509 00510 len += sizeof(obj._blocktype); 00511 len += dtn::data::SDNV(obj._procflags).getLength(); 00512 00513 #ifdef __DEVELOPMENT_ASSERTIONS__ 00514 // test: BLOCK_CONTAINS_EIDS => (_eids.size() > 0) 00515 assert(!obj.get(Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0)); 00516 #endif 00517 00518 if (obj.get(Block::BLOCK_CONTAINS_EIDS)) 00519 { 00520 len += dtn::data::SDNV(obj._eids.size()).getLength(); 00521 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++) 00522 { 00523 pair<size_t, size_t> offsets = _dictionary.getRef(*it); 00524 len += SDNV(offsets.first).getLength(); 00525 len += SDNV(offsets.second).getLength(); 00526 } 00527 } 00528 00529 // size of the payload in the block 00530 len += obj.getLength(); 00531 00532 return len; 00533 } 00534 00535 DefaultDeserializer::DefaultDeserializer(std::istream& stream) 00536 : _stream(stream), _validator(_default_validator), _compressed(false), _fragmentation(false) 00537 { 00538 } 00539 00540 DefaultDeserializer::DefaultDeserializer(std::istream &stream, Validator &v) 00541 : _stream(stream), _validator(v), _compressed(false), _fragmentation(false) 00542 { 00543 } 00544 00545 DefaultDeserializer::DefaultDeserializer(std::istream &stream, const Dictionary &d) 00546 : _stream(stream), _validator(_default_validator), _dictionary(d), _compressed(false), _fragmentation(false) 00547 { 00548 } 00549 00550 void DefaultDeserializer::setFragmentationSupport(bool val) 00551 { 00552 _fragmentation = val; 00553 } 00554 00555 Deserializer& DefaultDeserializer::operator >>(dtn::data::Bundle& obj) 00556 { 00557 // clear all blocks 00558 obj.clearBlocks(); 00559 00560 // read the primary block 00561 (*this) >> (PrimaryBlock&)obj; 00562 00563 // read until the last block 00564 bool lastblock = false; 00565 00566 // read all BLOCKs 00567 while (!_stream.eof() && !lastblock) 00568 { 00569 char block_type; 00570 00571 // BLOCK_TYPE 00572 block_type = _stream.peek(); 00573 00574 switch (block_type) 00575 { 00576 case 0: 00577 { 00578 throw dtn::InvalidDataException("block type is zero"); 00579 break; 00580 } 00581 00582 case dtn::data::PayloadBlock::BLOCK_TYPE: 00583 { 00584 if (obj.get(dtn::data::Bundle::APPDATA_IS_ADMRECORD)) 00585 { 00586 // create a temporary block 00587 dtn::data::ExtensionBlock &block = obj.push_back<dtn::data::ExtensionBlock>(); 00588 00589 // read the block data 00590 (*this) >> block; 00591 00592 // access the payload to get the first byte 00593 char admfield; 00594 ibrcommon::BLOB::Reference ref = block.getBLOB(); 00595 ref.iostream()->get(admfield); 00596 00597 // write the block into a temporary stream 00598 stringstream ss; 00599 DefaultSerializer serializer(ss, _dictionary); 00600 DefaultDeserializer deserializer(ss, _dictionary); 00601 00602 serializer << block; 00603 00604 // remove the temporary block 00605 obj.remove(block); 00606 00607 switch (admfield >> 4) 00608 { 00609 case 1: 00610 { 00611 dtn::data::StatusReportBlock &block = obj.push_back<dtn::data::StatusReportBlock>(); 00612 deserializer >> block; 00613 lastblock = block.get(Block::LAST_BLOCK); 00614 break; 00615 } 00616 00617 case 2: 00618 { 00619 dtn::data::CustodySignalBlock &block = obj.push_back<dtn::data::CustodySignalBlock>(); 00620 deserializer >> block; 00621 lastblock = block.get(Block::LAST_BLOCK); 00622 break; 00623 } 00624 00625 default: 00626 { 00627 // drop unknown administrative block 00628 break; 00629 } 00630 } 00631 00632 } 00633 else 00634 { 00635 dtn::data::PayloadBlock &block = obj.push_back<dtn::data::PayloadBlock>(); 00636 00637 try { 00638 (*this) >> block; 00639 } catch (dtn::PayloadReceptionInterrupted &ex) { 00640 // some debugging 00641 IBRCOMMON_LOGGER_DEBUG(15) << "Reception of bundle payload failed." << IBRCOMMON_LOGGER_ENDL; 00642 00643 // interrupted transmission 00644 if (!obj.get(dtn::data::PrimaryBlock::DONT_FRAGMENT) && (block.getLength() > 0) && _fragmentation) 00645 { 00646 IBRCOMMON_LOGGER_DEBUG(25) << "Create a fragment." << IBRCOMMON_LOGGER_ENDL; 00647 00648 if ( !obj.get(dtn::data::PrimaryBlock::FRAGMENT) ) 00649 { 00650 obj.set(dtn::data::PrimaryBlock::FRAGMENT, true); 00651 obj._appdatalength = ex.length; 00652 obj._fragmentoffset = 0; 00653 } 00654 } 00655 else 00656 { 00657 throw ex; 00658 } 00659 } 00660 00661 lastblock = block.get(Block::LAST_BLOCK); 00662 } 00663 break; 00664 } 00665 00666 default: 00667 { 00668 // get a extension block factory 00669 try { 00670 ExtensionBlock::Factory &f = dtn::data::ExtensionBlock::Factory::get(block_type); 00671 00672 dtn::data::Block &block = obj.push_back(f); 00673 (*this) >> block; 00674 lastblock = block.get(Block::LAST_BLOCK); 00675 } 00676 catch (const ibrcommon::Exception &ex) 00677 { 00678 dtn::data::ExtensionBlock &block = obj.push_back<dtn::data::ExtensionBlock>(); 00679 (*this) >> block; 00680 lastblock = block.get(Block::LAST_BLOCK); 00681 00682 if (block.get(dtn::data::Block::DISCARD_IF_NOT_PROCESSED)) 00683 { 00684 IBRCOMMON_LOGGER_DEBUG(5) << "unprocessable block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL; 00685 00686 // remove the block 00687 obj.remove(block); 00688 } 00689 } 00690 break; 00691 } 00692 } 00693 } 00694 00695 // validate this bundle 00696 _validator.validate(obj); 00697 00698 return (*this); 00699 } 00700 00701 Deserializer& DefaultDeserializer::operator>>(dtn::data::MetaBundle &obj) 00702 { 00703 dtn::data::PrimaryBlock pb; 00704 (*this) >> pb; 00705 00706 obj.appdatalength = pb._appdatalength; 00707 obj.custodian = pb._custodian; 00708 obj.destination = pb._destination; 00709 obj.expiretime = dtn::utils::Clock::getExpireTime(pb._timestamp, pb._lifetime); 00710 obj.fragment = pb.get(dtn::data::PrimaryBlock::FRAGMENT); 00711 obj.hopcount = 0; 00712 obj.lifetime = pb._lifetime; 00713 obj.offset = pb._fragmentoffset; 00714 obj.procflags = pb._procflags; 00715 obj.received = 0; 00716 obj.reportto = pb._reportto; 00717 obj.sequencenumber = pb._sequencenumber; 00718 obj.source = pb._source; 00719 obj.timestamp = pb._timestamp; 00720 00721 return (*this); 00722 } 00723 00724 Deserializer& DefaultDeserializer::operator >>(dtn::data::PrimaryBlock& obj) 00725 { 00726 char version = 0; 00727 SDNV tmpsdnv; 00728 SDNV blocklength; 00729 00730 // check for the right version 00731 _stream.get(version); 00732 if (version != dtn::data::BUNDLE_VERSION) throw dtn::InvalidProtocolException("Bundle version differ from ours."); 00733 00734 // PROCFLAGS 00735 _stream >> tmpsdnv; // processing flags 00736 obj._procflags = tmpsdnv.getValue(); 00737 00738 // BLOCK LENGTH 00739 _stream >> blocklength; 00740 00741 // EID References 00742 pair<SDNV, SDNV> ref[4]; 00743 for (int i = 0; i < 4; i++) 00744 { 00745 _stream >> ref[i].first; 00746 _stream >> ref[i].second; 00747 } 00748 00749 // timestamp 00750 _stream >> tmpsdnv; 00751 obj._timestamp = tmpsdnv.getValue(); 00752 00753 // sequence number 00754 _stream >> tmpsdnv; 00755 obj._sequencenumber = tmpsdnv.getValue(); 00756 00757 // lifetime 00758 _stream >> tmpsdnv; 00759 obj._lifetime = tmpsdnv.getValue(); 00760 00761 try { 00762 // dictionary 00763 _stream >> _dictionary; 00764 00765 // decode EIDs 00766 obj._destination = _dictionary.get(ref[0].first.getValue(), ref[0].second.getValue()); 00767 obj._source = _dictionary.get(ref[1].first.getValue(), ref[1].second.getValue()); 00768 obj._reportto = _dictionary.get(ref[2].first.getValue(), ref[2].second.getValue()); 00769 obj._custodian = _dictionary.get(ref[3].first.getValue(), ref[3].second.getValue()); 00770 _compressed = false; 00771 } catch (const dtn::InvalidDataException&) { 00772 // error while reading the dictionary. We assume that this is a compressed bundle header. 00773 obj._destination = dtn::data::EID(ref[0].first.getValue(), ref[0].second.getValue()); 00774 obj._source = dtn::data::EID(ref[1].first.getValue(), ref[1].second.getValue()); 00775 obj._reportto = dtn::data::EID(ref[2].first.getValue(), ref[2].second.getValue()); 00776 obj._custodian = dtn::data::EID(ref[3].first.getValue(), ref[3].second.getValue()); 00777 _compressed = true; 00778 } 00779 00780 // fragmentation? 00781 if (obj.get(dtn::data::Bundle::FRAGMENT)) 00782 { 00783 _stream >> tmpsdnv; 00784 obj._fragmentoffset = tmpsdnv.getValue(); 00785 00786 _stream >> tmpsdnv; 00787 obj._appdatalength = tmpsdnv.getValue(); 00788 } 00789 00790 // validate this primary block 00791 _validator.validate(obj); 00792 00793 return (*this); 00794 } 00795 00796 Deserializer& DefaultDeserializer::operator >>(dtn::data::Block& obj) 00797 { 00798 dtn::data::SDNV procflags_sdnv; 00799 _stream.get(obj._blocktype); 00800 _stream >> procflags_sdnv; 00801 00802 // set the processing flags but do not overwrite the lastblock bit 00803 obj._procflags = procflags_sdnv.getValue() & (~(dtn::data::Block::LAST_BLOCK) | obj._procflags); 00804 00805 // read EIDs 00806 if ( obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS)) 00807 { 00808 SDNV eidcount; 00809 _stream >> eidcount; 00810 00811 for (unsigned int i = 0; i < eidcount.getValue(); i++) 00812 { 00813 SDNV scheme, ssp; 00814 _stream >> scheme; 00815 _stream >> ssp; 00816 00817 if (_compressed) 00818 { 00819 obj.addEID( dtn::data::EID(scheme.getValue(), ssp.getValue()) ); 00820 } 00821 else 00822 { 00823 obj.addEID( _dictionary.get(scheme.getValue(), ssp.getValue()) ); 00824 } 00825 } 00826 } 00827 00828 // read the size of the payload in the block 00829 SDNV block_size; 00830 _stream >> block_size; 00831 00832 // validate this block 00833 _validator.validate(obj, block_size.getValue()); 00834 00835 // read the payload of the block 00836 obj.deserialize(_stream, block_size.getValue()); 00837 00838 return (*this); 00839 } 00840 00841 AcceptValidator::AcceptValidator() 00842 { 00843 } 00844 00845 AcceptValidator::~AcceptValidator() 00846 { 00847 } 00848 00849 void AcceptValidator::validate(const dtn::data::PrimaryBlock&) const throw (RejectedException) 00850 { 00851 } 00852 00853 void AcceptValidator::validate(const dtn::data::Block&, const size_t) const throw (RejectedException) 00854 { 00855 00856 } 00857 00858 void AcceptValidator::validate(const dtn::data::Bundle&) const throw (RejectedException) 00859 { 00860 00861 } 00862 00863 SeparateSerializer::SeparateSerializer(std::ostream& stream) 00864 : DefaultSerializer(stream) 00865 { 00866 } 00867 00868 SeparateSerializer::~SeparateSerializer() 00869 { 00870 } 00871 00872 Serializer& SeparateSerializer::operator <<(const dtn::data::Block& obj) 00873 { 00874 _stream << obj._blocktype; 00875 _stream << dtn::data::SDNV(obj._procflags); 00876 00877 #ifdef __DEVELOPMENT_ASSERTIONS__ 00878 // test: BLOCK_CONTAINS_EIDS => (_eids.size() > 0) 00879 assert(!obj.get(Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0)); 00880 #endif 00881 00882 if (obj.get(Block::BLOCK_CONTAINS_EIDS)) 00883 { 00884 _stream << SDNV(obj._eids.size()); 00885 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++) 00886 { 00887 dtn::data::BundleString str((*it).getString()); 00888 _stream << str; 00889 } 00890 } 00891 00892 // write size of the payload in the block 00893 _stream << SDNV(obj.getLength()); 00894 00895 // write the payload of the block 00896 size_t slength = 0; 00897 obj.serialize(_stream, slength); 00898 00899 return (*this); 00900 } 00901 00902 size_t SeparateSerializer::getLength(const dtn::data::Block &obj) const 00903 { 00904 size_t len = 0; 00905 00906 len += sizeof(obj._blocktype); 00907 len += dtn::data::SDNV(obj._procflags).getLength(); 00908 00909 #ifdef __DEVELOPMENT_ASSERTIONS__ 00910 // test: BLOCK_CONTAINS_EIDS => (_eids.size() > 0) 00911 assert(!obj.get(Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0)); 00912 #endif 00913 00914 if (obj.get(Block::BLOCK_CONTAINS_EIDS)) 00915 { 00916 len += dtn::data::SDNV(obj._eids.size()).getLength(); 00917 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++) 00918 { 00919 dtn::data::BundleString str((*it).getString()); 00920 len += str.getLength(); 00921 } 00922 } 00923 00924 // size of the payload in the block 00925 len += obj.getLength(); 00926 00927 return len; 00928 } 00929 00930 SeparateDeserializer::SeparateDeserializer(std::istream& stream, Bundle &b) 00931 : DefaultDeserializer(stream), _bundle(b) 00932 { 00933 } 00934 00935 SeparateDeserializer::~SeparateDeserializer() 00936 { 00937 } 00938 00939 dtn::data::Block& SeparateDeserializer::readBlock() 00940 { 00941 char block_type; 00942 00943 // BLOCK_TYPE 00944 block_type = _stream.peek(); 00945 00946 switch (block_type) 00947 { 00948 case 0: 00949 { 00950 throw dtn::InvalidDataException("block type is zero"); 00951 break; 00952 } 00953 00954 case dtn::data::PayloadBlock::BLOCK_TYPE: 00955 { 00956 if (_bundle.get(dtn::data::Bundle::APPDATA_IS_ADMRECORD)) 00957 { 00958 // create a temporary block 00959 dtn::data::ExtensionBlock &block = _bundle.push_back<dtn::data::ExtensionBlock>(); 00960 00961 // remember the current read position 00962 int blockbegin = _stream.tellg(); 00963 00964 // read the block data 00965 (*this) >> block; 00966 00967 // access the payload to get the first byte 00968 char admfield; 00969 ibrcommon::BLOB::Reference ref = block.getBLOB(); 00970 ref.iostream()->get(admfield); 00971 00972 // remove the temporary block 00973 _bundle.remove(block); 00974 00975 // reset the read pointer 00976 // BEWARE: this will not work on non-buffered streams like TCP! 00977 _stream.seekg(blockbegin); 00978 00979 switch (admfield >> 4) 00980 { 00981 case 1: 00982 { 00983 dtn::data::StatusReportBlock &block = _bundle.push_back<dtn::data::StatusReportBlock>(); 00984 (*this) >> block; 00985 return block; 00986 } 00987 00988 case 2: 00989 { 00990 dtn::data::CustodySignalBlock &block = _bundle.push_back<dtn::data::CustodySignalBlock>(); 00991 (*this) >> block; 00992 return block; 00993 } 00994 00995 default: 00996 { 00997 // drop unknown administrative block 00998 return block; 00999 } 01000 } 01001 01002 } 01003 else 01004 { 01005 dtn::data::PayloadBlock &block = _bundle.push_back<dtn::data::PayloadBlock>(); 01006 (*this) >> block; 01007 return block; 01008 } 01009 break; 01010 } 01011 01012 default: 01013 { 01014 // get a extension block factory 01015 try { 01016 ExtensionBlock::Factory &f = dtn::data::ExtensionBlock::Factory::get(block_type); 01017 dtn::data::Block &block = _bundle.push_back(f); 01018 (*this) >> block; 01019 return block; 01020 } catch (const ibrcommon::Exception &ex) { 01021 dtn::data::ExtensionBlock &block = _bundle.push_back<dtn::data::ExtensionBlock>(); 01022 (*this) >> block; 01023 return block; 01024 } 01025 break; 01026 } 01027 } 01028 } 01029 01030 Deserializer& SeparateDeserializer::operator >>(dtn::data::Block& obj) 01031 { 01032 dtn::data::SDNV procflags_sdnv; 01033 _stream.get(obj._blocktype); 01034 _stream >> procflags_sdnv; 01035 obj._procflags = procflags_sdnv.getValue(); 01036 01037 // read EIDs 01038 if ( obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS)) 01039 { 01040 SDNV eidcount; 01041 _stream >> eidcount; 01042 01043 for (unsigned int i = 0; i < eidcount.getValue(); i++) 01044 { 01045 dtn::data::BundleString str; 01046 _stream >> str; 01047 obj.addEID(dtn::data::EID(str)); 01048 } 01049 } 01050 01051 // read the size of the payload in the block 01052 SDNV block_size; 01053 _stream >> block_size; 01054 // obj._blocksize = block_size.getValue(); 01055 01056 // validate this block 01057 _validator.validate(obj, block_size.getValue()); 01058 01059 // read the payload of the block 01060 obj.deserialize(_stream, block_size.getValue()); 01061 01062 return (*this); 01063 } 01064 } 01065 }