|
IBR-DTNSuite 0.6
|
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 }