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/ExtensionBlockFactory.h"
00009 #include "ibrcommon/refcnt_ptr.h"
00010 #include <list>
00011 #include <cassert>
00012
00013 namespace dtn
00014 {
00015 namespace data
00016 {
00017 DefaultSerializer::DefaultSerializer(std::ostream& stream)
00018 : _stream(stream), _compressable(false)
00019 {
00020 }
00021
00022 DefaultSerializer::DefaultSerializer(std::ostream& stream, const Dictionary &d)
00023 : _stream(stream), _dictionary(d), _compressable(false)
00024 {
00025 }
00026
00027 void DefaultSerializer::rebuildDictionary(const dtn::data::Bundle &obj)
00028 {
00029
00030 _dictionary.clear();
00031
00032
00033 _dictionary.add(obj._destination);
00034 _dictionary.add(obj._source);
00035 _dictionary.add(obj._reportto);
00036 _dictionary.add(obj._custodian);
00037
00038
00039 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks;
00040
00041 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++)
00042 {
00043 const Block &b = (*(*iter));
00044 _dictionary.add( b.getEIDList() );
00045 }
00046 }
00047
00048 Serializer& DefaultSerializer::operator <<(const dtn::data::Bundle& obj)
00049 {
00050
00051 rebuildDictionary(obj);
00052
00053
00054 _compressable = isCompressable(obj);
00055
00056
00057 (*this) << (PrimaryBlock&)obj;
00058
00059
00060 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks;
00061
00062 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++)
00063 {
00064 const Block &b = (*(*iter));
00065 (*this) << b;
00066 }
00067
00068 return (*this);
00069 }
00070
00071 bool DefaultSerializer::isCompressable(const dtn::data::Bundle &obj) const
00072 {
00073
00074 bool compressable = ( obj._source.isCompressable() &&
00075 obj._destination.isCompressable() &&
00076 obj._reportto.isCompressable() &&
00077 obj._custodian.isCompressable() );
00078
00079 if (compressable)
00080 {
00081
00082 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks;
00083
00084 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++)
00085 {
00086 const Block &b = (*(*iter));
00087 const std::list<dtn::data::EID> eids = b.getEIDList();
00088
00089 for (std::list<dtn::data::EID>::const_iterator eit = eids.begin(); eit != eids.end(); eit++)
00090 {
00091 const dtn::data::EID &eid = (*eit);
00092 if (!eid.isCompressable())
00093 {
00094 return false;
00095 }
00096 }
00097 }
00098 }
00099
00100 return compressable;
00101 }
00102
00103 Serializer& DefaultSerializer::operator <<(const dtn::data::PrimaryBlock& obj)
00104 {
00105 _stream << dtn::data::BUNDLE_VERSION;
00106 _stream << dtn::data::SDNV(obj._procflags);
00107
00108
00109 size_t len = 0;
00110 dtn::data::SDNV primaryheader[14];
00111
00112 primaryheader[8] = SDNV(obj._timestamp);
00113 primaryheader[9] = SDNV(obj._sequencenumber);
00114 primaryheader[10] = SDNV(obj._lifetime);
00115
00116 pair<size_t, size_t> ref;
00117
00118 if (_compressable)
00119 {
00120
00121 ref = obj._destination.getCompressed();
00122 primaryheader[0] = SDNV(ref.first);
00123 primaryheader[1] = SDNV(ref.second);
00124
00125
00126 ref = obj._source.getCompressed();
00127 primaryheader[2] = SDNV(ref.first);
00128 primaryheader[3] = SDNV(ref.second);
00129
00130
00131 ref = obj._reportto.getCompressed();
00132 primaryheader[4] = SDNV(ref.first);
00133 primaryheader[5] = SDNV(ref.second);
00134
00135
00136 ref = obj._custodian.getCompressed();
00137 primaryheader[6] = SDNV(ref.first);
00138 primaryheader[7] = SDNV(ref.second);
00139
00140
00141 primaryheader[11] = SDNV(0);
00142 }
00143 else
00144 {
00145
00146 ref = _dictionary.getRef(obj._destination);
00147 primaryheader[0] = SDNV(ref.first);
00148 primaryheader[1] = SDNV(ref.second);
00149
00150
00151 ref = _dictionary.getRef(obj._source);
00152 primaryheader[2] = SDNV(ref.first);
00153 primaryheader[3] = SDNV(ref.second);
00154
00155
00156 ref = _dictionary.getRef(obj._reportto);
00157 primaryheader[4] = SDNV(ref.first);
00158 primaryheader[5] = SDNV(ref.second);
00159
00160
00161 ref = _dictionary.getRef(obj._custodian);
00162 primaryheader[6] = SDNV(ref.first);
00163 primaryheader[7] = SDNV(ref.second);
00164
00165
00166 primaryheader[11] = SDNV(_dictionary.getSize());
00167 len += _dictionary.getSize();
00168 }
00169
00170 for (int i = 0; i < 12; i++)
00171 {
00172 len += primaryheader[i].getLength();
00173 }
00174
00175 if (obj._procflags & dtn::data::Bundle::FRAGMENT)
00176 {
00177 primaryheader[12] = SDNV(obj._fragmentoffset);
00178 primaryheader[13] = SDNV(obj._appdatalength);
00179
00180 len += primaryheader[12].getLength();
00181 len += primaryheader[13].getLength();
00182 }
00183
00184
00185 _stream << SDNV(len);
00186
00187
00188
00189
00190
00191 for (int i = 0; i < 11; i++)
00192 {
00193 _stream << primaryheader[i];
00194 }
00195
00196 if (_compressable)
00197 {
00198
00199 _stream << primaryheader[11];
00200 }
00201 else
00202 {
00203
00204 _stream << _dictionary;
00205 }
00206
00207 if (obj._procflags & dtn::data::Bundle::FRAGMENT)
00208 {
00209 _stream << primaryheader[12];
00210 _stream << primaryheader[13];
00211 }
00212
00213 return (*this);
00214 }
00215
00216 Serializer& DefaultSerializer::operator <<(const dtn::data::Block& obj)
00217 {
00218 _stream << obj._blocktype;
00219 _stream << dtn::data::SDNV(obj._procflags);
00220
00221
00222 assert(!(obj._procflags & Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0));
00223
00224 if (obj._procflags & Block::BLOCK_CONTAINS_EIDS)
00225 {
00226 _stream << SDNV(obj._eids.size());
00227 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++)
00228 {
00229 pair<size_t, size_t> offsets;
00230
00231 if (_compressable)
00232 {
00233 offsets = _dictionary.getRef(*it);
00234 }
00235 else
00236 {
00237 offsets = (*it).getCompressed();
00238 }
00239
00240 _stream << SDNV(offsets.first);
00241 _stream << SDNV(offsets.second);
00242 }
00243 }
00244
00245
00246 _stream << SDNV(obj.getLength());
00247
00248
00249 obj.serialize(_stream);
00250
00251 return (*this);
00252 }
00253
00254 size_t DefaultSerializer::getLength(const dtn::data::Bundle &obj) const
00255 {
00256 size_t len = 0;
00257 len += getLength( (PrimaryBlock&)obj );
00258
00259
00260 std::list<refcnt_ptr<Block> > list = obj._blocks._blocks;
00261
00262 for (std::list<refcnt_ptr<Block> >::const_iterator iter = list.begin(); iter != list.end(); iter++)
00263 {
00264 const Block &b = (*(*iter));
00265 len += getLength( b );
00266 }
00267
00268 return len;
00269 }
00270
00271 size_t DefaultSerializer::getLength(const dtn::data::PrimaryBlock& obj) const
00272 {
00273 size_t len = 0;
00274
00275 len += sizeof(dtn::data::BUNDLE_VERSION);
00276 len += dtn::data::SDNV(obj._procflags).getLength();
00277
00278
00279 dtn::data::SDNV primaryheader[14];
00280 pair<size_t, size_t> ref;
00281
00282
00283 ref = _dictionary.getRef(obj._destination);
00284 primaryheader[0] = SDNV(ref.first);
00285 primaryheader[1] = SDNV(ref.second);
00286
00287
00288 ref = _dictionary.getRef(obj._source);
00289 primaryheader[2] = SDNV(ref.first);
00290 primaryheader[3] = SDNV(ref.second);
00291
00292
00293 ref = _dictionary.getRef(obj._reportto);
00294 primaryheader[4] = SDNV(ref.first);
00295 primaryheader[5] = SDNV(ref.second);
00296
00297
00298 ref = _dictionary.getRef(obj._custodian);
00299 primaryheader[6] = SDNV(ref.first);
00300 primaryheader[7] = SDNV(ref.second);
00301
00302
00303 primaryheader[8] = SDNV(obj._timestamp);
00304
00305
00306 primaryheader[9] = SDNV(obj._sequencenumber);
00307
00308
00309 primaryheader[10] = SDNV(obj._lifetime);
00310
00311
00312 primaryheader[11] = SDNV(_dictionary.getSize());
00313
00314 for (int i = 0; i < 12; i++)
00315 {
00316 len += primaryheader[i].getLength();
00317 }
00318
00319 len += _dictionary.getSize();
00320
00321 if (obj._procflags & dtn::data::Bundle::FRAGMENT)
00322 {
00323 primaryheader[12] = SDNV(obj._fragmentoffset);
00324 primaryheader[13] = SDNV(obj._appdatalength);
00325
00326 len += primaryheader[12].getLength();
00327 len += primaryheader[13].getLength();
00328 }
00329
00330 return len;
00331 }
00332
00333 size_t DefaultSerializer::getLength(const dtn::data::Block &obj) const
00334 {
00335 size_t len = 0;
00336
00337 len += sizeof(obj._blocktype);
00338 len += dtn::data::SDNV(obj._procflags).getLength();
00339
00340
00341 assert(!(obj._procflags & Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0));
00342
00343 if (obj._procflags & Block::BLOCK_CONTAINS_EIDS)
00344 {
00345 len += dtn::data::SDNV(obj._eids.size()).getLength();
00346 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++)
00347 {
00348 pair<size_t, size_t> offsets = _dictionary.getRef(*it);
00349 len += SDNV(offsets.first).getLength();
00350 len += SDNV(offsets.second).getLength();
00351 }
00352 }
00353
00354
00355 len += obj.getLength();
00356
00357 return len;
00358 }
00359
00360 DefaultDeserializer::DefaultDeserializer(std::istream& stream)
00361 : _stream(stream), _validator(_default_validator), _compressed(false)
00362 {
00363 }
00364
00365 DefaultDeserializer::DefaultDeserializer(std::istream &stream, Validator &v)
00366 : _stream(stream), _validator(v), _compressed(false)
00367 {
00368 }
00369
00370 DefaultDeserializer::DefaultDeserializer(std::istream &stream, const Dictionary &d)
00371 : _stream(stream), _validator(_default_validator), _dictionary(d), _compressed(false)
00372 {
00373 }
00374
00375 Deserializer& DefaultDeserializer::operator >>(dtn::data::Bundle& obj)
00376 {
00377 (*this) >> (PrimaryBlock&)obj;
00378
00379
00380 bool lastblock = false;
00381
00382
00383 while (!_stream.eof() && !lastblock)
00384 {
00385 char block_type;
00386
00387
00388 block_type = _stream.peek();
00389
00390 switch (block_type)
00391 {
00392 case 0:
00393 {
00394 throw dtn::InvalidDataException("block type is zero");
00395 break;
00396 }
00397
00398 case dtn::data::PayloadBlock::BLOCK_TYPE:
00399 {
00400 if (obj._procflags & dtn::data::Bundle::APPDATA_IS_ADMRECORD)
00401 {
00402
00403 dtn::data::ExtensionBlock &block = obj.push_back<dtn::data::ExtensionBlock>();
00404
00405
00406 (*this) >> block;
00407
00408
00409 ibrcommon::BLOB::Reference ref = block.getBLOB();
00410 char admfield; (*ref).get(admfield);
00411
00412
00413 stringstream ss;
00414 DefaultSerializer serializer(ss, _dictionary);
00415 DefaultDeserializer deserializer(ss, _dictionary);
00416
00417 serializer << block;
00418
00419
00420 obj.remove(block);
00421
00422 switch (admfield >> 4)
00423 {
00424 case 1:
00425 {
00426 dtn::data::StatusReportBlock &block = obj.push_back<dtn::data::StatusReportBlock>();
00427 deserializer >> block;
00428 lastblock = block.get(Block::LAST_BLOCK);
00429 break;
00430 }
00431
00432 case 2:
00433 {
00434 dtn::data::CustodySignalBlock &block = obj.push_back<dtn::data::CustodySignalBlock>();
00435 deserializer >> block;
00436 lastblock = block.get(Block::LAST_BLOCK);
00437 break;
00438 }
00439
00440 default:
00441 {
00442
00443 break;
00444 }
00445 }
00446
00447 }
00448 else
00449 {
00450 dtn::data::PayloadBlock &block = obj.push_back<dtn::data::PayloadBlock>();
00451 (*this) >> block;
00452
00453 lastblock = block.get(Block::LAST_BLOCK);
00454 }
00455 break;
00456 }
00457
00458 default:
00459 {
00460
00461 std::map<char, ExtensionBlockFactory*> &factories = dtn::data::Bundle::getExtensionBlockFactories();
00462 std::map<char, ExtensionBlockFactory*>::iterator iter = factories.find(block_type);
00463
00464 if (iter != factories.end())
00465 {
00466 ExtensionBlockFactory &f = (*iter->second);
00467 dtn::data::Block &block = obj.push_back(f);
00468 (*this) >> block;
00469 lastblock = block.get(Block::LAST_BLOCK);
00470 }
00471 else
00472 {
00473 dtn::data::ExtensionBlock &block = obj.push_back<dtn::data::ExtensionBlock>();
00474 (*this) >> block;
00475 lastblock = block.get(Block::LAST_BLOCK);
00476 }
00477 break;
00478 }
00479 }
00480 }
00481
00482
00483 _validator.validate(obj);
00484
00485 return (*this);
00486 }
00487
00488 Deserializer& DefaultDeserializer::operator >>(dtn::data::PrimaryBlock& obj)
00489 {
00490 char version = 0;
00491 SDNV tmpsdnv;
00492 SDNV blocklength;
00493
00494
00495 _stream.get(version);
00496 if (version != dtn::data::BUNDLE_VERSION) throw dtn::InvalidProtocolException("Bundle version differ from ours.");
00497
00498
00499 _stream >> tmpsdnv;
00500 obj._procflags = tmpsdnv.getValue();
00501
00502
00503 _stream >> blocklength;
00504
00505
00506 pair<SDNV, SDNV> ref[4];
00507 for (int i = 0; i < 4; i++)
00508 {
00509 _stream >> ref[i].first;
00510 _stream >> ref[i].second;
00511 }
00512
00513
00514 _stream >> tmpsdnv;
00515 obj._timestamp = tmpsdnv.getValue();
00516
00517
00518 _stream >> tmpsdnv;
00519 obj._sequencenumber = tmpsdnv.getValue();
00520
00521
00522 _stream >> tmpsdnv;
00523 obj._lifetime = tmpsdnv.getValue();
00524
00525 try {
00526
00527 _stream >> _dictionary;
00528
00529
00530 obj._destination = _dictionary.get(ref[0].first.getValue(), ref[0].second.getValue());
00531 obj._source = _dictionary.get(ref[1].first.getValue(), ref[1].second.getValue());
00532 obj._reportto = _dictionary.get(ref[2].first.getValue(), ref[2].second.getValue());
00533 obj._custodian = _dictionary.get(ref[3].first.getValue(), ref[3].second.getValue());
00534 _compressed = false;
00535 } catch (dtn::InvalidDataException ex) {
00536
00537 obj._destination = dtn::data::EID(ref[0].first.getValue(), ref[0].second.getValue());
00538 obj._source = dtn::data::EID(ref[1].first.getValue(), ref[1].second.getValue());
00539 obj._reportto = dtn::data::EID(ref[2].first.getValue(), ref[2].second.getValue());
00540 obj._custodian = dtn::data::EID(ref[3].first.getValue(), ref[3].second.getValue());
00541 _compressed = true;
00542 }
00543
00544
00545 if (obj._procflags & dtn::data::Bundle::FRAGMENT)
00546 {
00547 _stream >> tmpsdnv;
00548 obj._fragmentoffset = tmpsdnv.getValue();
00549
00550 _stream >> tmpsdnv;
00551 obj._appdatalength = tmpsdnv.getValue();
00552 }
00553
00554
00555 _validator.validate(obj);
00556
00557 return (*this);
00558 }
00559
00560 Deserializer& DefaultDeserializer::operator >>(dtn::data::Block& obj)
00561 {
00562 dtn::data::SDNV procflags_sdnv;
00563 _stream.get(obj._blocktype);
00564 _stream >> procflags_sdnv;
00565 obj._procflags = procflags_sdnv.getValue();
00566
00567
00568 if ( obj._procflags & dtn::data::Block::BLOCK_CONTAINS_EIDS)
00569 {
00570 SDNV eidcount;
00571 _stream >> eidcount;
00572
00573 for (unsigned int i = 0; i < eidcount.getValue(); i++)
00574 {
00575 SDNV scheme, ssp;
00576 _stream >> scheme;
00577 _stream >> ssp;
00578
00579 if (_compressed)
00580 {
00581 obj.addEID( dtn::data::EID(scheme.getValue(), ssp.getValue()) );
00582 }
00583 else
00584 {
00585 obj.addEID( _dictionary.get(scheme.getValue(), ssp.getValue()) );
00586 }
00587 }
00588 }
00589
00590
00591 SDNV block_size;
00592 _stream >> block_size;
00593 obj._blocksize = block_size.getValue();
00594
00595
00596 _validator.validate(obj, block_size.getValue());
00597
00598
00599 obj.deserialize(_stream);
00600
00601 return (*this);
00602 }
00603
00604 AcceptValidator::AcceptValidator()
00605 {
00606 }
00607
00608 AcceptValidator::~AcceptValidator()
00609 {
00610 }
00611
00612 void AcceptValidator::validate(const dtn::data::PrimaryBlock&) const throw (RejectedException)
00613 {
00614 }
00615
00616 void AcceptValidator::validate(const dtn::data::Block&, const size_t) const throw (RejectedException)
00617 {
00618
00619 }
00620
00621 void AcceptValidator::validate(const dtn::data::Bundle&) const throw (RejectedException)
00622 {
00623
00624 }
00625
00626 SeparateSerializer::SeparateSerializer(std::ostream& stream)
00627 : DefaultSerializer(stream)
00628 {
00629 }
00630
00631 SeparateSerializer::~SeparateSerializer()
00632 {
00633 }
00634
00635 Serializer& SeparateSerializer::operator <<(const dtn::data::Block& obj)
00636 {
00637 _stream << obj._blocktype;
00638 _stream << dtn::data::SDNV(obj._procflags);
00639
00640
00641 assert(!(obj._procflags & Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0));
00642
00643 if (obj._procflags & Block::BLOCK_CONTAINS_EIDS)
00644 {
00645 _stream << SDNV(obj._eids.size());
00646 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++)
00647 {
00648 dtn::data::BundleString str((*it).getString());
00649 _stream << str;
00650 }
00651 }
00652
00653
00654 _stream << SDNV(obj.getLength());
00655
00656
00657 obj.serialize(_stream);
00658
00659 return (*this);
00660 }
00661
00662 size_t SeparateSerializer::getLength(const dtn::data::Block &obj) const
00663 {
00664 size_t len = 0;
00665
00666 len += sizeof(obj._blocktype);
00667 len += dtn::data::SDNV(obj._procflags).getLength();
00668
00669
00670 assert(!(obj._procflags & Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0));
00671
00672 if (obj._procflags & Block::BLOCK_CONTAINS_EIDS)
00673 {
00674 len += dtn::data::SDNV(obj._eids.size()).getLength();
00675 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++)
00676 {
00677 dtn::data::BundleString str((*it).getString());
00678 len += str.getLength();
00679 }
00680 }
00681
00682
00683 len += obj.getLength();
00684
00685 return len;
00686 }
00687
00688 SeparateDeserializer::SeparateDeserializer(std::istream& stream, Bundle &b)
00689 : DefaultDeserializer(stream), _bundle(b)
00690 {
00691 }
00692
00693 SeparateDeserializer::~SeparateDeserializer()
00694 {
00695 }
00696
00697 void SeparateDeserializer::readBlock()
00698 {
00699 char block_type;
00700
00701
00702 block_type = _stream.peek();
00703
00704 switch (block_type)
00705 {
00706 case 0:
00707 {
00708 throw dtn::InvalidDataException("block type is zero");
00709 break;
00710 }
00711
00712 case dtn::data::PayloadBlock::BLOCK_TYPE:
00713 {
00714 if (_bundle._procflags & dtn::data::Bundle::APPDATA_IS_ADMRECORD)
00715 {
00716
00717 dtn::data::ExtensionBlock &block = _bundle.push_back<dtn::data::ExtensionBlock>();
00718
00719
00720 int blockbegin = _stream.tellg();
00721
00722
00723 (*this) >> block;
00724
00725
00726 ibrcommon::BLOB::Reference ref = block.getBLOB();
00727 char admfield; (*ref).get(admfield);
00728
00729
00730 _bundle.remove(block);
00731
00732
00733
00734 _stream.seekg(blockbegin);
00735
00736 switch (admfield >> 4)
00737 {
00738 case 1:
00739 {
00740 dtn::data::StatusReportBlock &block = _bundle.push_back<dtn::data::StatusReportBlock>();
00741 (*this) >> block;
00742 break;
00743 }
00744
00745 case 2:
00746 {
00747 dtn::data::CustodySignalBlock &block = _bundle.push_back<dtn::data::CustodySignalBlock>();
00748 (*this) >> block;
00749 break;
00750 }
00751
00752 default:
00753 {
00754
00755 break;
00756 }
00757 }
00758
00759 }
00760 else
00761 {
00762 dtn::data::PayloadBlock &block = _bundle.push_back<dtn::data::PayloadBlock>();
00763 (*this) >> block;
00764 }
00765 break;
00766 }
00767
00768 default:
00769 {
00770
00771 std::map<char, ExtensionBlockFactory*> &factories = dtn::data::Bundle::getExtensionBlockFactories();
00772 std::map<char, ExtensionBlockFactory*>::iterator iter = factories.find(block_type);
00773
00774 if (iter != factories.end())
00775 {
00776 ExtensionBlockFactory &f = (*iter->second);
00777 dtn::data::Block &block = _bundle.push_back(f);
00778 (*this) >> block;
00779 }
00780 else
00781 {
00782 dtn::data::ExtensionBlock &block = _bundle.push_back<dtn::data::ExtensionBlock>();
00783 (*this) >> block;
00784 }
00785 break;
00786 }
00787 }
00788 }
00789
00790 Deserializer& SeparateDeserializer::operator >>(dtn::data::Block& obj)
00791 {
00792 dtn::data::SDNV procflags_sdnv;
00793 _stream.get(obj._blocktype);
00794 _stream >> procflags_sdnv;
00795 obj._procflags = procflags_sdnv.getValue();
00796
00797
00798 if ( obj._procflags & dtn::data::Block::BLOCK_CONTAINS_EIDS)
00799 {
00800 SDNV eidcount;
00801 _stream >> eidcount;
00802
00803 for (unsigned int i = 0; i < eidcount.getValue(); i++)
00804 {
00805 dtn::data::BundleString str;
00806 _stream >> str;
00807 obj.addEID(dtn::data::EID(str));
00808 }
00809 }
00810
00811
00812 SDNV block_size;
00813 _stream >> block_size;
00814 obj._blocksize = block_size.getValue();
00815
00816
00817 _validator.validate(obj, block_size.getValue());
00818
00819
00820 obj.deserialize(_stream);
00821
00822 return (*this);
00823 }
00824 }
00825 }