IBR-DTNSuite 0.6

ibrdtn/ibrdtn/data/Serializer.cpp

Go to the documentation of this file.
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 }