IBR-DTNSuite  0.8
ibrdtn/ibrdtn/security/MutualSerializer.cpp
Go to the documentation of this file.
00001 #include "ibrdtn/config.h"
00002 #include "ibrdtn/security/MutualSerializer.h"
00003 #include "ibrdtn/data/Bundle.h"
00004 #include "ibrdtn/data/Block.h"
00005 #include "ibrdtn/data/EID.h"
00006 #include "ibrdtn/security/SecurityBlock.h"
00007 #include <ibrcommon/Logger.h>
00008 
00009 #include <arpa/inet.h>
00010 
00011 #ifdef __DEVELOPMENT_ASSERTIONS__
00012 #include <cassert>
00013 #endif
00014 
00015 #ifdef HAVE_GLIB
00016 #include <glib.h>
00017 #else
00018 // needed for Debian Lenny whichs older clibrary does not provide htobe64(x)
00019 #include <endian.h>
00020 #if __BYTE_ORDER == __LITTLE_ENDIAN
00021 #include <bits/byteswap.h>
00022 #define GUINT64_TO_BE(x)  __bswap_64(x)
00023 #else
00024 #define GUINT64_TO_BE(x) (x)
00025 #endif
00026 #endif
00027 
00028 namespace dtn
00029 {
00030         namespace security
00031         {
00032                 MutualSerializer::MutualSerializer(std::ostream& stream, const dtn::data::Block *ignore)
00033                  : dtn::data::DefaultSerializer(stream), _ignore(ignore), _ignore_previous_bundles(ignore != NULL)
00034                  {
00035                  }
00036 
00037                 MutualSerializer::~MutualSerializer()
00038                 {
00039                 }
00040 
00041                 dtn::data::Serializer& MutualSerializer::operator<<(const dtn::data::PrimaryBlock &obj)
00042                 {
00043                         // we want to ignore all block before "ignore"
00044                         if (_ignore != NULL) _ignore_previous_bundles = true;
00045 
00046                         // write unpacked primary block
00047                         // bundle version
00048                         _stream << dtn::data::BUNDLE_VERSION;
00049 
00050                         // processing flags
00051                         (*this) << dtn::data::SDNV(obj._procflags & 0x0000000007C1BE);
00052 
00053                         // length of header
00054                         (*this) << (u_int32_t)getLength(obj);
00055 
00056                         // dest, source, report to id
00057                         (*this) << obj._destination;
00058                         (*this) << obj._source;
00059                         (*this) << obj._reportto;
00060 
00061                         // timestamp
00062                         (*this) << dtn::data::SDNV(obj._timestamp);
00063                         (*this) << dtn::data::SDNV(obj._sequencenumber);
00064 
00065                         // lifetime
00066                         (*this) << dtn::data::SDNV(obj._lifetime);
00067 
00068                         return *this;
00069                 }
00070 
00071                 dtn::data::Serializer& MutualSerializer::operator<<(const dtn::data::Block &obj)
00072                 {
00073                         // do we ignore the current block?
00074                         if (_ignore_previous_bundles && (&obj != _ignore))
00075                         {
00076                                 return *this;
00077                         }
00078                         else
00079                         {
00080                                 // process all following bundles
00081                                 _ignore_previous_bundles = false;
00082                         }
00083 
00084                         // only take payload related blocks
00085                         if (obj.getType() != dtn::data::PayloadBlock::BLOCK_TYPE
00086                                 && obj.getType() != SecurityBlock::PAYLOAD_INTEGRITY_BLOCK
00087                                 && obj.getType() != SecurityBlock::PAYLOAD_CONFIDENTIAL_BLOCK)
00088                         {
00089                                 return *this;
00090                         }
00091 
00092                         _stream << obj._blocktype;
00093                         (*this) << dtn::data::SDNV(obj._procflags & 0x0000000000000077);
00094 
00095 #ifdef __DEVELOPMENT_ASSERTIONS__
00096                         // test: BLOCK_CONTAINS_EIDS => (_eids.size() > 0)
00097                         assert(!obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0));
00098 #endif
00099 
00100                         if (obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS))
00101                                 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++)
00102                                         (*this) << (*it);
00103 
00104                         try {
00105                                 const dtn::security::SecurityBlock &sb = dynamic_cast<const dtn::security::SecurityBlock&>(obj);
00106                                 
00107                                 if ( (sb.getType() == SecurityBlock::PAYLOAD_INTEGRITY_BLOCK) || (sb.getType() == SecurityBlock::PAYLOAD_CONFIDENTIAL_BLOCK) )
00108                                 {
00109                                         // write size of the payload in the block
00110                                         (*this) << dtn::data::SDNV(sb.getLength_mutable());
00111 
00112                                         sb.serialize_mutable_without_security_result(*this);
00113                                 }
00114                         } catch (const std::bad_cast&) {
00115                                 // write size of the payload in the block
00116                                 (*this) << dtn::data::SDNV(obj.getLength());
00117 
00118                                 // write the payload of the block
00119                                 size_t slength = 0;
00120                                 obj.serialize(_stream, slength);
00121                         };
00122 
00123                         return (*this);
00124                 }
00125 
00126                 size_t MutualSerializer::getLength(const dtn::data::Bundle&)
00127                 {
00128 #ifdef __DEVELOPMENT_ASSERTIONS__
00129                         assert(false);
00130 #endif
00131                         return 0;
00132                 }
00133 
00134                 size_t MutualSerializer::getLength(const dtn::data::PrimaryBlock &obj) const
00135                 {
00136                         // predict the block length
00137                         // length in bytes
00138                         // starting with the fields after the length field
00139 
00140                         // dest id length
00141                         u_int32_t length = 4;
00142                         // dest id
00143                         length += obj._destination.getString().size();
00144                         // source id length
00145                         length += 4;
00146                         // source id
00147                         length += obj._source.getString().size();
00148                         // report to id length
00149                         length += 4;
00150                         // report to id
00151                         length += obj._reportto.getString().size();
00152                         // creation time: 2*SDNV
00153                         length += 2*sdnv_size;
00154                         // lifetime: SDNV
00155                         length += sdnv_size;
00156 
00157                         IBRCOMMON_LOGGER_DEBUG_ex(ibrcommon::Logger::LOGGER_DEBUG) << "length: " << length << IBRCOMMON_LOGGER_ENDL;
00158 
00159                         return length;
00160                 }
00161 
00162                 size_t MutualSerializer::getLength(const dtn::data::Block &obj) const
00163                 {
00164                         size_t len = 0;
00165 
00166                         len += sizeof(obj._blocktype);
00167                         // proc flags
00168                         len += sdnv_size;
00169 
00170 #ifdef __DEVELOPMENT_ASSERTIONS__
00171                         // test: BLOCK_CONTAINS_EIDS => (_eids.size() > 0)
00172                         assert(!obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS) || (obj._eids.size() > 0));
00173 #endif
00174 
00175                         if (obj.get(dtn::data::Block::BLOCK_CONTAINS_EIDS))
00176                                 for (std::list<dtn::data::EID>::const_iterator it = obj._eids.begin(); it != obj._eids.end(); it++)
00177                                         len += it->getString().size();
00178 
00179                         // size-field of the size of the payload in the block
00180                         len += sdnv_size;
00181 
00182                         try {
00183                                 const dtn::security::SecurityBlock &sb = dynamic_cast<const dtn::security::SecurityBlock&>(obj);
00184 
00185                                 // add size of the payload in the block
00186                                 len += sb.getLength_mutable();
00187                         } catch (const std::bad_cast&) {
00188                                 // add size of the payload in the block
00189                                 len += obj.getLength();
00190                         };
00191 
00192                         return len;
00193                 }
00194 
00195 
00196                 dtn::data::Serializer& MutualSerializer::operator<<(const u_int32_t value)
00197                 {
00198                         u_int32_t be = htonl(value);
00199                         _stream.write(reinterpret_cast<char*>(&be), sizeof(u_int32_t));
00200                         return *this;
00201                 }
00202 
00203                 dtn::data::Serializer& MutualSerializer::operator<<(const dtn::data::EID& value)
00204                 {
00205                         u_int32_t length = value.getString().length();
00206                         (*this) << length;
00207                         _stream << value.getString();
00208 
00209                         return *this;
00210                 }
00211 
00212                 dtn::data::Serializer& MutualSerializer::operator<<(const dtn::data::SDNV& value)
00213                 {
00214                         // endianess muahahaha ...
00215                         // and now we are gcc centric, even older versions work
00216                         u_int64_t be = GUINT64_TO_BE(value.getValue());
00217                         _stream.write(reinterpret_cast<char*>(&be), sizeof(u_int64_t));
00218                         return *this;
00219                 }
00220 
00221                 dtn::data::Serializer& MutualSerializer::operator<<(const dtn::security::SecurityBlock::TLVList& list)
00222                 {
00223                         (*this) << dtn::data::SDNV(list.getLength());
00224                         _stream << list.toString();
00225                         return *this;
00226                 }
00227         }
00228 }