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