• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1