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