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