From: tho Date: Thu, 15 Jan 2009 16:19:03 +0000 (+0000) Subject: 80221Bundle: implemented standard compliant parser for MIHF_Id X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=ffd0e5bf26f993bab27c777f71d58285867345d7;p=senf.git 80221Bundle: implemented standard compliant parser for MIHF_Id git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1062 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/80221Bundle/MIHPacket.cc b/Packets/80221Bundle/MIHPacket.cc index 97407c2..6c167f8 100644 --- a/Packets/80221Bundle/MIHPacket.cc +++ b/Packets/80221Bundle/MIHPacket.cc @@ -28,11 +28,70 @@ // Custom includes #include "../../Packets/Packets.hh" +#include "../../Utils/hexdump.hh" #include #define prefix_ +prefix_ std::string senf::MIHFId_TLVParser::asString() + const +{ + return std::string( i(1+length_bytes()), i(1+length_bytes()+length()) ); +} + +prefix_ void senf::MIHFId_TLVParser::setString(std::string const &id) +{ + size_type str_size (id.size()); + // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21) + if (str_size > 253) + throw std::length_error("maximum length of a MIHF_ID is 253 octets"); + safe_data_iterator si = resizeValue( str_size); + std::copy( id.begin(), id.end(), si); +} + + +prefix_ senf::MACAddress senf::MIHFId_TLVParser::asMACAddress() + const +{ + return MACAddress::from_data( + getNAIDecodedIterator( i(1+length_bytes()), i(1+length_bytes()+12) )); +} + +prefix_ void senf::MIHFId_TLVParser::setMACAddress(senf::MACAddress const &mac) +{ + safe_data_iterator si = resizeValue(12); + std::copy( mac.begin(), mac.end(), getNAIEncodedOutputIterator(si)); +} + + +prefix_ senf::INet4Address senf::MIHFId_TLVParser::asINet4Address() + const +{ + return INet4Address::from_data( + getNAIDecodedIterator( i(1+length_bytes()), i(1+length_bytes()+8) )); +} + +prefix_ void senf::MIHFId_TLVParser::setINet4Address(senf::INet4Address const &addr) +{ + safe_data_iterator si = resizeValue(8); + std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); +} + +prefix_ senf::INet6Address senf::MIHFId_TLVParser::asINet6Address() + const +{ + return INet6Address::from_data( + getNAIDecodedIterator( i(1+length_bytes()), i(1+length_bytes()+32) )); +} + +prefix_ void senf::MIHFId_TLVParser::setINet6Address(senf::INet6Address const &addr) +{ + safe_data_iterator si = resizeValue(32); + std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); +} + + prefix_ void senf::MIHPacketType::dump(packet p, std::ostream &os) { boost::io::ios_all_saver ias(os); @@ -49,14 +108,24 @@ prefix_ void senf::MIHPacketType::dump(packet p, std::ostream &os) << " Opcode: " << unsigned( p->opcode()) << "\n" << " AID: " << unsigned( p->aid()) << "\n" << " Transaction ID: " << unsigned( p->transactionId()) << "\n" - << " payload length: " << unsigned( p->payloadLength()) << "\n"; + << " payload length: " << unsigned( p->payloadLength()) << "\n" + << " source MIHF_Id TLV:\n" + << " length: " << unsigned (p->src_mihfId().length()) << "\n" + << " value:\n"; + std::string src_mihfId (p->src_mihfId().asString()); + hexdump(src_mihfId.begin(), src_mihfId.end(), os); + os << " destination MIHF_Id TLV:\n" + << " length: " << unsigned (p->dst_mihfId().length()) << "\n" + << " value:\n"; + std::string dst_mihfId (p->dst_mihfId().asString()); + hexdump(dst_mihfId.begin(), dst_mihfId.end(), os); } prefix_ void senf::MIHPacketType::finalize(packet p) { - p->source_length() << senf::bytes( p->source_mihf_id()); - p->destination_length() << senf::bytes( p->destination_mihf_id()); + p->src_mihfId().shrinkLength(); + p->dst_mihfId().shrinkLength(); p->payloadLength_() << p.size() - 8; } diff --git a/Packets/80221Bundle/MIHPacket.hh b/Packets/80221Bundle/MIHPacket.hh index a67f0a6..7128135 100644 --- a/Packets/80221Bundle/MIHPacket.hh +++ b/Packets/80221Bundle/MIHPacket.hh @@ -28,18 +28,70 @@ // Custom includes #include "../../Packets/Packets.hh" +#include "../../Socket/Protocols/Raw/MACAddress.hh" +#include "../../Socket/Protocols/INet/INet4Address.hh" +#include "../../Socket/Protocols/INet/INet6Address.hh" #include "TLVPacket.hh" +#include +#include + //#include "MIHPacket.mpp" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { - struct MIHF_IdParser : public PacketParserBase + // the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21) + // we could set maxLengthValue in INIT, but for the most MIHF_IDs the default + // maximum length of 127 should be enough. + // The user must call mihPacket->src_mihfId().maxLengthValue( 127) before + // setting longer MIHF_IDs + class MIHFId_TLVParser : public BaseTLVPacketParser { # include SENF_PARSER() + SENF_PARSER_INHERIT ( BaseTLVPacketParser ); + SENF_PARSER_SKIP ( length(), 0 ); + SENF_PARSER_FINALIZE ( MIHFId_TLVParser ); - SENF_PARSER_FINALIZE ( MIHF_IdParser ); + std::string asString() const; + void setString(std::string const &id); + + senf::MACAddress asMACAddress() const; + void setMACAddress(senf::MACAddress const &mac); + + senf::INet4Address asINet4Address() const; + void setINet4Address(senf::INet4Address const &addr); + + senf::INet6Address asINet6Address() const; + void setINet6Address(senf::INet6Address const &addr); + + private: + template + struct binaryNAIEncoder { + binaryNAIEncoder(OutputIterator &i) : i_(i) {} + void operator()(const boost::uint8_t &v) const { + *i_++ = '\\'; + *i_++ = v; + } + OutputIterator &i_; + }; + template + static boost::function_output_iterator > getNAIEncodedOutputIterator(OutputIterator i) { + return boost::make_function_output_iterator(binaryNAIEncoder(i)); + } + + struct binaryNAIDecoder { + binaryNAIDecoder() : readNextByte_(true) {} + bool operator()(const boost::uint8_t &v) { + readNextByte_ = readNextByte_ ? false : true; + return readNextByte_; + } + bool readNextByte_; + }; + template + static boost::filter_iterator getNAIDecodedIterator(Iterator begin, Iterator end) { + return boost::make_filter_iterator(begin, end); + } }; struct MIHPacketParser : public PacketParserBase @@ -64,21 +116,16 @@ namespace senf { SENF_PARSER_FIELD_RO ( payloadLength, UInt16Parser ); // Source MIHF Id - SENF_PARSER_PRIVATE_FIELD ( source_type, UInt8Parser ); - SENF_PARSER_PRIVATE_FIELD ( source_length, DynamicTLVLengthParser ); - SENF_PARSER_FIELD ( source_mihf_id, MIHF_IdParser ); - + SENF_PARSER_FIELD ( src_mihfId, MIHFId_TLVParser ); // Destination MIHF Id - SENF_PARSER_PRIVATE_FIELD ( destination_type, UInt8Parser ); - SENF_PARSER_PRIVATE_FIELD ( destination_length, DynamicTLVLengthParser ); - SENF_PARSER_FIELD ( destination_mihf_id, MIHF_IdParser ); + SENF_PARSER_FIELD ( dst_mihfId, MIHFId_TLVParser ); SENF_PARSER_FINALIZE ( MIHPacketParser ); SENF_PARSER_INIT() { version_() = 1; - source_type() = 1; - destination_type() = 2; + src_mihfId().type() = 1; + dst_mihfId().type() = 2; } friend class MIHPacketType; diff --git a/Packets/80221Bundle/MIHPacket.test.cc b/Packets/80221Bundle/MIHPacket.test.cc index e0c9583..d4f4df0 100644 --- a/Packets/80221Bundle/MIHPacket.test.cc +++ b/Packets/80221Bundle/MIHPacket.test.cc @@ -30,30 +30,144 @@ #include #include "MIHPacket.hh" -#include "senf/Utils/hexdump.hh" + using namespace senf; #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -BOOST_AUTO_UNIT_TEST(MIHPacket_create) +BOOST_AUTO_UNIT_TEST(MIHPacket_create_string) +{ + MIHPacket mihPacket (MIHPacket::create()); + // set some fields + mihPacket->fragmentNr() = 42; + mihPacket->transactionId() = 21; + mihPacket->src_mihfId().setString( "senf@berlios.de"); + mihPacket->dst_mihfId().setString( "test"); + mihPacket.finalizeThis(); + + unsigned char data[] = { + // MIH header + 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x17, + // source MIHF_ID TLV: + 0x01, 0x0f, // type, length + 0x73, 0x65, 0x6e, 0x66, 0x40, 0x62, 0x65, 0x72, 0x6c, + 0x69, 0x6f, 0x73, 0x2e, 0x64, 0x65, // value + // destination MIHF_ID TLV: + 0x02, 0x04, 0x74, 0x65, 0x73, 0x74 + }; + BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data )); + BOOST_CHECK_EQUAL( mihPacket->src_mihfId().asString(), "senf@berlios.de"); + BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().asString(), "test"); + + // now expand a MIHF_ID + mihPacket->dst_mihfId().maxLengthValue(253); + mihPacket->dst_mihfId().setString( std::string(200, 'x')); + mihPacket.finalizeThis(); + + BOOST_CHECK_EQUAL( mihPacket.size(), 8 + 17 + 203); + BOOST_CHECK_EQUAL( mihPacket->payloadLength(), 17 + 203); + BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().length(), 200); + BOOST_CHECK_EQUAL( senf::bytes(mihPacket->dst_mihfId()), 203); +} + + +BOOST_AUTO_UNIT_TEST(MIHPacket_create_mac) { MIHPacket mihPacket (MIHPacket::create()); // set some fields mihPacket->fragmentNr() = 42; mihPacket->transactionId() = 21; + mihPacket->src_mihfId().setMACAddress( MACAddress::from_string("01:02:03:04:05:06")); + mihPacket->dst_mihfId().setMACAddress( MACAddress::from_string("07:08:09:0a:0b:0c")); mihPacket.finalizeThis(); -// mihPacket.dump(std::cout); -// senf::hexdump(mihPacket.data().begin(), mihPacket.data().end(), std::cout); + unsigned char data[] = { + // MIH header + 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x1c, + // source MIHF_ID TLV: + 0x01, 0x0c, // type, length + 0x5c, 0x01, 0x5c, 0x02, 0x5c, 0x03, 0x5c, 0x04, 0x5c, 0x05, 0x5c, 0x06, // value (nai-encoded) + // destination MIHF_ID TLV: + 0x02, 0x0c, // type, length + 0x5c, 0x07, 0x5c, 0x08, 0x5c, 0x09, 0x5c, 0x0a, 0x5c, 0x0b, 0x5c, 0x0c // value (nai-encoded) + }; + BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data )); + BOOST_CHECK_EQUAL( + mihPacket->src_mihfId().asMACAddress(), + MACAddress::from_string("01:02:03:04:05:06")); + BOOST_CHECK_EQUAL( + mihPacket->dst_mihfId().asMACAddress(), + MACAddress::from_string("07:08:09:0a:0b:0c")); +} + + +BOOST_AUTO_UNIT_TEST(MIHPacket_create_inet4) +{ + MIHPacket mihPacket (MIHPacket::create()); + // set some fields + mihPacket->fragmentNr() = 42; + mihPacket->transactionId() = 21; + mihPacket->src_mihfId().setINet4Address( INet4Address::from_string("128.129.130.131")); + mihPacket->dst_mihfId().setINet4Address( INet4Address::from_string("132.133.134.135")); + mihPacket.finalizeThis(); + + unsigned char data[] = { + // MIH header + 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x14, + // source MIHF_ID TLV: + 0x01, 0x08, // type, length + 0x5c, 0x80, 0x5c, 0x81, 0x5c, 0x82, 0x5c, 0x83, // value (nai-encoded) + // destination MIHF_ID TLV: + 0x02, 0x08, // type, length + 0x5c, 0x84, 0x5c, 0x85, 0x5c, 0x86, 0x5c, 0x87 // value (nai-encoded) + }; + BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data )); + BOOST_CHECK_EQUAL( + mihPacket->src_mihfId().asINet4Address(), + INet4Address::from_string("128.129.130.131")); + BOOST_CHECK_EQUAL( + mihPacket->dst_mihfId().asINet4Address(), + INet4Address::from_string("132.133.134.135")); +} + + +BOOST_AUTO_UNIT_TEST(MIHPacket_create_inet6) +{ + MIHPacket mihPacket (MIHPacket::create()); + // set some fields + mihPacket->fragmentNr() = 42; + mihPacket->transactionId() = 21; + mihPacket->src_mihfId().setINet6Address( INet6Address::from_string("::ffff:1.2.3.4")); + mihPacket->dst_mihfId().setINet6Address( INet6Address::from_string("::ffff:5.6.7.8")); + mihPacket.finalizeThis(); unsigned char data[] = { - 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, - 0x01, 0x00, - 0x02, 0x00 + // MIH header + 0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x44, + // source MIHF_ID TLV: + 0x01, 0x20, // type, length + // value (nai-encoded): + 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, + 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, + 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0xff, 0x5c, 0xff, + 0x5c, 0x01, 0x5c, 0x02, 0x5c, 0x03, 0x5c, 0x04, + // destination MIHF_ID TLV: + 0x02, 0x20, // type, length + // value (nai-encoded): + 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, + 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0x00, + 0x5c, 0x00, 0x5c, 0x00, 0x5c, 0xff, 0x5c, 0xff, + 0x5c, 0x05, 0x5c, 0x06, 0x5c, 0x07, 0x5c, 0x08 }; - BOOST_CHECK( equal( mihPacket.data().begin(), mihPacket.data().end(), data )); + BOOST_CHECK(equal( mihPacket.data().begin(), mihPacket.data().end(), data )); + BOOST_CHECK_EQUAL( + mihPacket->src_mihfId().asINet6Address(), + INet6Address::from_string("::ffff:1.2.3.4")); + BOOST_CHECK_EQUAL( + mihPacket->dst_mihfId().asINet6Address(), + INet6Address::from_string("::ffff:5.6.7.8") ); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Packets/80221Bundle/TLVPacket.cc b/Packets/80221Bundle/TLVPacket.cc index 3bf2039..12d9bfd 100644 --- a/Packets/80221Bundle/TLVPacket.cc +++ b/Packets/80221Bundle/TLVPacket.cc @@ -28,11 +28,26 @@ // Custom includes #include -#include +#include "../../Utils/hexdump.hh" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// +prefix_ senf::safe_data_iterator senf::BaseTLVPacketParser::resizeValue( + DynamicTLVLengthParser::value_type size) +{ + DynamicTLVLengthParser::value_type current_length ( length()); + length( size); + + safe_data_iterator si (data(), boost::next(i(), 1 + length_bytes() )); + if (current_length > size) + data().erase( si, boost::next(si, current_length-size)); + else + data().insert( si, size-current_length, 0); + return si; +} + + prefix_ senf::DynamicTLVLengthParser::value_type senf::DynamicTLVLengthParser::value() const { switch (bytes() ) { @@ -148,15 +163,6 @@ prefix_ void senf::DynamicTLVLengthParser:: maxValue(DynamicTLVLengthParser::val } -prefix_ senf::PacketInterpreterBase::range senf::GenericTLVPacketParser::value() - const -{ - senf::PacketData::iterator begin (boost::next(data().begin(), 1 + length_bytes() )); - return PacketInterpreterBase::range( - begin, boost::next( begin, length()) ); -} - - prefix_ void senf::DynamicTLVLengthParser::resize(size_type size) { value_type v = value(); @@ -178,6 +184,15 @@ prefix_ void senf::DynamicTLVLengthParser::resize(size_type size) } +prefix_ senf::PacketInterpreterBase::range senf::GenericTLVPacketParser::value() + const +{ + senf::PacketData::iterator begin (boost::next(data().begin(), 1 + length_bytes() )); + return PacketInterpreterBase::range( + begin, boost::next( begin, length()) ); +} + + prefix_ void senf::GenericTLVPacketType::dump(packet p, std::ostream & os) { boost::io::ios_all_saver ias(os); diff --git a/Packets/80221Bundle/TLVPacket.ct b/Packets/80221Bundle/TLVPacket.ct index 5800158..efae0f6 100644 --- a/Packets/80221Bundle/TLVPacket.ct +++ b/Packets/80221Bundle/TLVPacket.ct @@ -33,16 +33,7 @@ template prefix_ void senf::GenericTLVPacketParser::value(ForwardReadableRange const &range) { - DynamicTLVLengthParser::value_type range_size ( boost::size(range)); - DynamicTLVLengthParser::value_type current_length ( length()); - length( range_size); - - safe_data_iterator si (data(), boost::next(i(), 1 + length_bytes() )); - if (current_length > range_size) - data().erase( si, boost::next(si, current_length-range_size)); - else - data().insert( si, range_size-current_length, 0); - + safe_data_iterator si = resizeValue( boost::size(range) ); std::copy( boost::begin(range), boost::end(range), si); } diff --git a/Packets/80221Bundle/TLVPacket.hh b/Packets/80221Bundle/TLVPacket.hh index 057f06f..c337aec 100644 --- a/Packets/80221Bundle/TLVPacket.hh +++ b/Packets/80221Bundle/TLVPacket.hh @@ -88,14 +88,16 @@ namespace senf { protected: size_type length_bytes() const { return length_().bytes(); }; void length(DynamicTLVLengthParser::value_type &v) { length_() = v; }; + senf::safe_data_iterator resizeValue(DynamicTLVLengthParser::value_type size); }; struct GenericTLVPacketParser : public BaseTLVPacketParser { # include SENF_PARSER() - SENF_PARSER_INHERIT( BaseTLVPacketParser ) - SENF_PARSER_FINALIZE( GenericTLVPacketParser ); + SENF_PARSER_INHERIT ( BaseTLVPacketParser ); + SENF_PARSER_SKIP ( length(), 0 ); + SENF_PARSER_FINALIZE ( GenericTLVPacketParser ); SENF_PARSER_INIT() { maxLengthValue( DynamicTLVLengthParser::max_value);