IBR-DTNSuite 0.6

ibrdtn/ibrdtn/api/PlainSerializer.cpp

Go to the documentation of this file.
00001 /*
00002  * PlainSerializer.cpp
00003  *
00004  *  Created on: 16.06.2011
00005  *      Author: morgenro
00006  */
00007 
00008 #include "config.h"
00009 #include "ibrdtn/api/PlainSerializer.h"
00010 #include "ibrdtn/utils/Utils.h"
00011 #include <ibrcommon/refcnt_ptr.h>
00012 #include <ibrcommon/data/Base64Stream.h>
00013 #include <ibrcommon/data/Base64Reader.h>
00014 #include <ibrcommon/Logger.h>
00015 #include <list>
00016 
00017 namespace dtn
00018 {
00019         namespace api
00020         {
00021                 PlainSerializer::PlainSerializer(std::ostream &stream)
00022                  : _stream(stream)
00023                 {
00024                 }
00025 
00026                 PlainSerializer::~PlainSerializer()
00027                 {
00028                 }
00029 
00030                 dtn::data::Serializer& PlainSerializer::operator<<(const dtn::data::Bundle &obj)
00031                 {
00032                         // serialize the primary block
00033                         (*this) << (dtn::data::PrimaryBlock&)obj;
00034 
00035                         // serialize all secondary blocks
00036                         const std::list<const dtn::data::Block*> list = obj.getBlocks();
00037 
00038                         // block count
00039                         _stream << "Blocks: " << list.size() << std::endl;
00040 
00041                         for (std::list<const dtn::data::Block*>::const_iterator iter = list.begin(); iter != list.end(); iter++)
00042                         {
00043                                 const dtn::data::Block &b = (*(*iter));
00044                                 _stream << std::endl;
00045                                 (*this) << b;
00046                         }
00047 
00048                         _stream << std::endl;
00049 
00050                         return (*this);
00051                 }
00052 
00053                 dtn::data::Serializer& PlainSerializer::operator<<(const dtn::data::PrimaryBlock &obj)
00054                 {
00055                         _stream << "Processing flags: " << obj._procflags << std::endl;
00056                         _stream << "Timestamp: " << obj._timestamp << std::endl;
00057                         _stream << "Sequencenumber: " << obj._sequencenumber << std::endl;
00058                         _stream << "Source: " << obj._source.getString() << std::endl;
00059                         _stream << "Destination: " << obj._destination.getString() << std::endl;
00060                         _stream << "Reportto: " << obj._reportto.getString() << std::endl;
00061                         _stream << "Custodian: " << obj._custodian.getString() << std::endl;
00062                         _stream << "Lifetime: " << obj._lifetime << std::endl;
00063 
00064                         if (obj._procflags & dtn::data::PrimaryBlock::FRAGMENT)
00065                         {
00066                                 _stream << "Fragment offset: " << obj._fragmentoffset << std::endl;
00067                                 _stream << "Application data length: " << obj._appdatalength << std::endl;
00068                         }
00069 
00070                         return (*this);
00071                 }
00072 
00073                 dtn::data::Serializer& PlainSerializer::operator<<(const dtn::data::Block &obj)
00074                 {
00075                         _stream << "Block: " << (int)obj.getType() << std::endl;
00076 
00077                         std::stringstream flags;
00078 
00079                         if (obj.get(dtn::data::Block::LAST_BLOCK))
00080                         {
00081                                 flags << " LAST_BLOCK";
00082                         }
00083 
00084                         if (obj.get(dtn::data::Block::REPLICATE_IN_EVERY_FRAGMENT))
00085                         {
00086                                 flags << " REPLICATE_IN_EVERY_FRAGMENT";
00087                         }
00088 
00089                         if (obj.get(dtn::data::Block::TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED))
00090                         {
00091                                 flags << " TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED";
00092                         }
00093 
00094                         if (obj.get(dtn::data::Block::DELETE_BUNDLE_IF_NOT_PROCESSED))
00095                         {
00096                                 flags << " DELETE_BUNDLE_IF_NOT_PROCESSED";
00097                         }
00098 
00099                         if (obj.get(dtn::data::Block::DISCARD_IF_NOT_PROCESSED))
00100                         {
00101                                 flags << " DISCARD_IF_NOT_PROCESSED";
00102                         }
00103 
00104                         if (obj.get(dtn::data::Block::FORWARDED_WITHOUT_PROCESSED))
00105                         {
00106                                 flags << " FORWARDED_WITHOUT_PROCESSED";
00107                         }
00108 
00109                         if (flags.str().length() > 0)
00110                         {
00111                                 _stream << "Flags:" << flags.str() << std::endl;
00112                         }
00113 
00114                         if (obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS))
00115                         {
00116                                 std::list<dtn::data::EID> eid_list = obj.getEIDList();
00117 
00118                                 for (std::list<dtn::data::EID>::const_iterator iter = eid_list.begin(); iter != eid_list.end(); iter++)
00119                                 {
00120                                         _stream << "EID: " << (*iter).getString() << std::endl;
00121                                 }
00122                         }
00123 
00124                         _stream << "Length: " << obj.getLength() << std::endl;
00125 
00126                         try {
00127                                 _stream << std::endl;
00128 
00129                                 // put data here
00130                                 ibrcommon::Base64Stream b64(_stream, false, 80);
00131                                 size_t slength = 0;
00132                                 obj.serialize(b64, slength);
00133                                 b64 << std::flush;
00134                         } catch (const std::exception &ex) {
00135                                 std::cerr << ex.what() << std::endl;
00136                         }
00137 
00138                         _stream << std::endl;
00139 
00140                         return (*this);
00141                 }
00142 
00143                 size_t PlainSerializer::getLength(const dtn::data::Bundle &obj)
00144                 {
00145                         return 0;
00146                 }
00147 
00148                 size_t PlainSerializer::getLength(const dtn::data::PrimaryBlock &obj) const
00149                 {
00150                         return 0;
00151                 }
00152 
00153                 size_t PlainSerializer::getLength(const dtn::data::Block &obj) const
00154                 {
00155                         return 0;
00156                 }
00157 
00158                 PlainDeserializer::PlainDeserializer(std::istream &stream)
00159                  : _stream(stream)
00160                 {
00161                 }
00162 
00163                 PlainDeserializer::~PlainDeserializer()
00164                 {
00165                 }
00166 
00167                 dtn::data::Deserializer& PlainDeserializer::operator>>(dtn::data::Bundle &obj)
00168                 {
00169                         // clear all blocks
00170                         obj.clearBlocks();
00171 
00172                         // read the primary block
00173                         (*this) >> (dtn::data::PrimaryBlock&)obj;
00174 
00175                         // read until the last block
00176                         bool lastblock = false;
00177 
00178                         // buffer for all read line calls
00179                         std::string buffer;
00180 
00181                         // read all BLOCKs
00182                         while (!_stream.eof() && !lastblock)
00183                         {
00184                                 char block_type;
00185 
00186                                 // read the block type (first line)
00187                                 getline(_stream, buffer);
00188 
00189 //                              // strip off the last char
00190 //                              buffer.erase(buffer.size() - 1);
00191 
00192                                 // abort if the line data is empty
00193                                 if (buffer.size() == 0) throw dtn::InvalidDataException("block header is missing");
00194 
00195                                 // split header value
00196                                 std::vector<std::string> values = dtn::utils::Utils::tokenize(":", buffer, 1);
00197 
00198                                 if (values[0] == "Block")
00199                                 {
00200                                         std::stringstream ss; ss.str(values[1]);
00201                                         ss >> (int&)block_type;
00202                                 }
00203                                 else
00204                                 {
00205                                         throw dtn::InvalidDataException("need block type as first header");
00206                                 }
00207 
00208                                 switch (block_type)
00209                                 {
00210                                         case 0:
00211                                         {
00212                                                 throw dtn::InvalidDataException("block type is zero");
00213                                                 break;
00214                                         }
00215 
00216                                         case dtn::data::PayloadBlock::BLOCK_TYPE:
00217                                         {
00218                                                 if (obj.get(dtn::data::Bundle::APPDATA_IS_ADMRECORD))
00219                                                 {
00220                                                         // create a temporary block
00221                                                         dtn::data::ExtensionBlock &block = obj.push_back<dtn::data::ExtensionBlock>();
00222 
00223                                                         // read the block data
00224                                                         (*this) >> block;
00225 
00226                                                         // access the payload to get the first byte
00227                                                         char admfield;
00228                                                         ibrcommon::BLOB::Reference ref = block.getBLOB();
00229                                                         ref.iostream()->get(admfield);
00230 
00231                                                         // write the block into a temporary stream
00232                                                         stringstream ss;
00233                                                         PlainSerializer serializer(ss);
00234                                                         PlainDeserializer deserializer(ss);
00235 
00236                                                         serializer << block;
00237 
00238                                                         // remove the temporary block
00239                                                         obj.remove(block);
00240 
00241                                                         switch (admfield >> 4)
00242                                                         {
00243                                                                 case 1:
00244                                                                 {
00245                                                                         dtn::data::StatusReportBlock &block = obj.push_back<dtn::data::StatusReportBlock>();
00246                                                                         deserializer >> block;
00247                                                                         lastblock = block.get(dtn::data::Block::LAST_BLOCK);
00248                                                                         break;
00249                                                                 }
00250 
00251                                                                 case 2:
00252                                                                 {
00253                                                                         dtn::data::CustodySignalBlock &block = obj.push_back<dtn::data::CustodySignalBlock>();
00254                                                                         deserializer >> block;
00255                                                                         lastblock = block.get(dtn::data::Block::LAST_BLOCK);
00256                                                                         break;
00257                                                                 }
00258 
00259                                                                 default:
00260                                                                 {
00261                                                                         // drop unknown administrative block
00262                                                                         break;
00263                                                                 }
00264                                                         }
00265 
00266                                                 }
00267                                                 else
00268                                                 {
00269                                                         dtn::data::PayloadBlock &block = obj.push_back<dtn::data::PayloadBlock>();
00270                                                         (*this) >> block;
00271 
00272                                                         lastblock = block.get(dtn::data::Block::LAST_BLOCK);
00273                                                 }
00274                                                 break;
00275                                         }
00276 
00277                                         default:
00278                                         {
00279                                                 // get a extension block factory
00280                                                 try {
00281                                                         dtn::data::ExtensionBlock::Factory &f = dtn::data::ExtensionBlock::Factory::get(block_type);
00282 
00283                                                         dtn::data::Block &block = obj.push_back(f);
00284                                                         (*this) >> block;
00285                                                         lastblock = block.get(dtn::data::Block::LAST_BLOCK);
00286 
00287                                                         if (block.get(dtn::data::Block::DISCARD_IF_NOT_PROCESSED))
00288                                                         {
00289                                                                 IBRCOMMON_LOGGER_DEBUG(5) << "unprocessable block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL;
00290 
00291                                                                 // remove the block
00292                                                                 obj.remove(block);
00293                                                         }
00294                                                 }
00295                                                 catch (const ibrcommon::Exception &ex)
00296                                                 {
00297                                                         dtn::data::ExtensionBlock &block = obj.push_back<dtn::data::ExtensionBlock>();
00298                                                         (*this) >> block;
00299                                                         lastblock = block.get(dtn::data::Block::LAST_BLOCK);
00300 
00301                                                         if (block.get(dtn::data::Block::DISCARD_IF_NOT_PROCESSED))
00302                                                         {
00303                                                                 IBRCOMMON_LOGGER_DEBUG(5) << "unprocessable block in bundle " << obj.toString() << " has been removed" << IBRCOMMON_LOGGER_ENDL;
00304 
00305                                                                 // remove the block
00306                                                                 obj.remove(block);
00307                                                         }
00308                                                 }
00309                                                 break;
00310                                         }
00311                                 }
00312                         }
00313 
00314                         return (*this);
00315                 }
00316 
00317                 dtn::data::Deserializer& PlainDeserializer::operator>>(dtn::data::PrimaryBlock &obj)
00318                 {
00319                         std::string data;
00320 
00321                         // read until the first empty line appears
00322                         while (_stream.good())
00323                         {
00324                                 std::stringstream ss;
00325                                 getline(_stream, data);
00326 
00327 //                              // strip off the last char
00328 //                              data.erase(data.size() - 1);
00329 
00330                                 // abort after the first empty line
00331                                 if (data.size() == 0) break;
00332 
00333                                 // split header value
00334                                 std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1);
00335 
00336                                 // if there are not enough parameter abort with an error
00337                                 if (values.size() < 1) throw ibrcommon::Exception("parsing error");
00338 
00339                                 // assign header value
00340                                 if (values[0] == "Processing flags")
00341                                 {
00342                                         ss.clear(); ss.str(values[1]);
00343                                         ss >> obj._procflags;
00344                                 }
00345                                 else if (values[0] == "Timestamp")
00346                                 {
00347                                         ss.clear(); ss.str(values[1]);
00348                                         ss >> obj._timestamp;
00349                                 }
00350                                 else if (values[0] == "Sequencenumber")
00351                                 {
00352                                         ss.clear(); ss.str(values[1]);
00353                                         ss >> obj._sequencenumber;
00354                                 }
00355                                 else if (values[0] == "Source")
00356                                 {
00357                                         obj._source = values[1];
00358                                 }
00359                                 else if (values[0] == "Destination")
00360                                 {
00361                                         obj._destination = values[1];
00362                                 }
00363                                 else if (values[0] == "Reportto")
00364                                 {
00365                                         obj._reportto = values[1];
00366                                 }
00367                                 else if (values[0] == "Custodian")
00368                                 {
00369                                         obj._custodian = values[1];
00370                                 }
00371                                 else if (values[0] == "Lifetime")
00372                                 {
00373                                         ss.clear(); ss.str(values[1]);
00374                                         ss >> obj._lifetime;
00375                                 }
00376                                 else if (values[0] == "Fragment offset")
00377                                 {
00378                                         ss.clear(); ss.str(values[1]);
00379                                         ss >> obj._fragmentoffset;
00380                                 }
00381                                 else if (values[0] == "Application data length")
00382                                 {
00383                                         ss.clear(); ss.str(values[1]);
00384                                         ss >> obj._appdatalength;
00385                                 }
00386                         }
00387 
00388                         return (*this);
00389                 }
00390 
00391                 dtn::data::Deserializer& PlainDeserializer::operator>>(dtn::data::Block &obj)
00392                 {
00393                         std::string data;
00394                         size_t blocksize = 0;
00395 
00396                         // read until the first empty line appears
00397                         while (_stream.good())
00398                         {
00399                                 getline(_stream, data);
00400 
00401 //                              // strip off the last char
00402 //                              data.erase(data.size() - 1);
00403 
00404                                 // abort after the first empty line
00405                                 if (data.size() == 0) break;
00406 
00407                                 // split header value
00408                                 std::vector<std::string> values = dtn::utils::Utils::tokenize(":", data, 1);
00409 
00410                                 // assign header value
00411                                 if (values[0] == "Flags")
00412                                 {
00413                                         std::vector<std::string> flags = dtn::utils::Utils::tokenize(" ", values[1]);
00414 
00415                                         for (std::vector<std::string>::const_iterator iter = flags.begin(); iter != flags.end(); iter++)
00416                                         {
00417                                                 const std::string &value = (*iter);
00418                                                 if (value == "LAST_BLOCK")
00419                                                 {
00420                                                         obj.set(dtn::data::Block::LAST_BLOCK, true);
00421                                                 }
00422                                                 else if (value == "FORWARDED_WITHOUT_PROCESSED")
00423                                                 {
00424                                                         obj.set(dtn::data::Block::FORWARDED_WITHOUT_PROCESSED, true);
00425                                                 }
00426                                                 else if (value == "DISCARD_IF_NOT_PROCESSED")
00427                                                 {
00428                                                         obj.set(dtn::data::Block::DISCARD_IF_NOT_PROCESSED, true);
00429                                                 }
00430                                                 else if (value == "DELETE_BUNDLE_IF_NOT_PROCESSED")
00431                                                 {
00432                                                         obj.set(dtn::data::Block::DELETE_BUNDLE_IF_NOT_PROCESSED, true);
00433                                                 }
00434                                                 else if (value == "TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED")
00435                                                 {
00436                                                         obj.set(dtn::data::Block::TRANSMIT_STATUSREPORT_IF_NOT_PROCESSED, true);
00437                                                 }
00438                                                 else if (value == "REPLICATE_IN_EVERY_FRAGMENT")
00439                                                 {
00440                                                         obj.set(dtn::data::Block::REPLICATE_IN_EVERY_FRAGMENT, true);
00441                                                 }
00442                                         }
00443                                 }
00444                                 else if (values[0] == "EID")
00445                                 {
00446                                         obj.addEID(values[1]);
00447                                 }
00448                                 else if (values[0] == "Length")
00449                                 {
00450                                         std::stringstream ss; ss.str(values[1]);
00451                                         ss >> blocksize;
00452                                 }
00453                         }
00454 
00455                         // then read the payload
00456                         ibrcommon::Base64Reader base64_decoder(_stream, blocksize);
00457                         obj.deserialize(base64_decoder, blocksize);
00458 
00459                         // read the final empty line
00460                         std::string buffer;
00461                         getline(_stream, buffer);
00462 
00463                         if (buffer.size() != 0) throw dtn::InvalidDataException("last line not empty");
00464 
00465                         return (*this);
00466                 }
00467 
00468                 dtn::data::Deserializer& PlainDeserializer::operator>>(std::ostream &stream)
00469                 {
00470                         ibrcommon::Base64Stream b64(stream, true);
00471                         std::string data;
00472 
00473                         while (b64.good())
00474                         {
00475                                 getline(_stream, data);
00476 
00477 //                              // strip off the last char
00478 //                              data.erase(data.size() - 1);
00479 
00480                                 // abort after the first empty line
00481                                 if (data.size() == 0) break;
00482 
00483                                 // put the line into the stream decoder
00484                                 b64 << data;
00485                         }
00486 
00487                         b64 << std::flush;
00488 
00489                         return (*this);
00490                 }
00491         }
00492 }