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