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

Generated on Wed Mar 30 2011 11:11:49 for IBR-DTNSuite by  doxygen 1.7.1