From: tho Date: Mon, 19 Oct 2009 09:04:23 +0000 (+0000) Subject: Packets/80221Bundle: integrated GenericTLVRegistry X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=482523171f06cf239fd7e8c991f81711c02cf0ba;p=senf.git Packets/80221Bundle: integrated GenericTLVRegistry git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1501 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/Packets/80211Bundle/WLANBeaconPacket.cc b/senf/Packets/80211Bundle/WLANBeaconPacket.cc index ad49dbc..ade514e 100644 --- a/senf/Packets/80211Bundle/WLANBeaconPacket.cc +++ b/senf/Packets/80211Bundle/WLANBeaconPacket.cc @@ -44,7 +44,7 @@ prefix_ void senf::WLANBeaconPacketType::dump(packet p, std::ostream &os) typedef parser::ieList_t::container ieListContainer_t; ieListContainer_t ieListContainer (p->ieList()); for (ieListContainer_t::iterator i = ieListContainer.begin(); i != ieListContainer.end(); ++i) - (*i).dump( os); + i->dump( os); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/senf/Packets/80221Bundle/MIHPacket.cc b/senf/Packets/80221Bundle/MIHPacket.cc index 409f9b8..619b58d 100644 --- a/senf/Packets/80221Bundle/MIHPacket.cc +++ b/senf/Packets/80221Bundle/MIHPacket.cc @@ -27,74 +27,13 @@ //#include "MIHPacket.ih" // Custom includes -#include #include #include #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -namespace { - SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x8917, senf::MIHPacket); -} - -/////////////////////////////////////////////////////////////////////////// -// MIHFId_TLVParser - -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 = resizeValueField( str_size); - std::copy( id.begin(), id.end(), si); -} - -prefix_ void senf::MIHFId_TLVParser::setMACAddress(senf::MACAddress const &mac) -{ - safe_data_iterator si = resizeValueField(12); - std::copy( mac.begin(), mac.end(), getNAIEncodedOutputIterator(si)); -} - -prefix_ void senf::MIHFId_TLVParser::setINet4Address(senf::INet4Address const &addr) -{ - safe_data_iterator si = resizeValueField(8); - std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); -} - -prefix_ void senf::MIHFId_TLVParser::setINet6Address(senf::INet6Address const &addr) -{ - safe_data_iterator si = resizeValueField(32); - std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); -} - -prefix_ void senf::MIHFId_TLVParser::setEUI64(senf::EUI64 const &addr) -{ - safe_data_iterator si = resizeValueField(16); - std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); -} - -prefix_ senf::MIHFId senf::MIHFId_TLVParser::valueAs(MIHFId::Type type) - const -{ - if (length() == 0) return MIHFId(); - switch (type) { - case MIHFId::Empty: - return MIHFId(); - case MIHFId::MACAddress: - return MIHFId( asMACAddress()); - case MIHFId::INet4Address: - return MIHFId( asINet4Address()); - case MIHFId::INet6Address: - return MIHFId( asINet6Address()); - case MIHFId::String: - return MIHFId( asINet6Address()); - case MIHFId::EUI64: - return MIHFId( asINet6Address()); - } - return MIHFId(); -} +SENF_PACKET_REGISTRY_REGISTER( senf::EtherTypes, 0x8917, senf::MIHPacket); /////////////////////////////////////////////////////////////////////////// @@ -105,30 +44,20 @@ prefix_ void senf::MIHPacketType::dump(packet p, std::ostream &os) boost::io::ios_all_saver ias(os); os << "MIH Packet:\n" << " protocol header:\n" - << senf::fieldName(" version") << unsigned( p->version()) << "\n" - << senf::fieldName(" ack request") << p->ackRequest() << "\n" - << senf::fieldName(" ack response") << p->ackResponse() << "\n" - << senf::fieldName(" UIR") << p->uir() << "\n" - << senf::fieldName(" more fragments") << p->moreFragment() << "\n" - << senf::fieldName(" fragment number") << p->fragmentNr() << "\n" - << senf::fieldName(" message ID (MID)") << unsigned( p->messageId()) << "\n" - << senf::fieldName(" sid") << unsigned( p->sid()) << "\n" - << senf::fieldName(" opcode") << unsigned( p->opcode()) << "\n" - << senf::fieldName(" aid") << unsigned( p->aid()) << "\n" - << senf::fieldName(" transaction id") << unsigned( p->transactionId()) << "\n" - << senf::fieldName(" payload length") << unsigned( p->payloadLength()) << "\n" - << " source MIHF_Id TLV:\n" - << senf::fieldName(" type") << unsigned (p->src_mihfId().type()) << "\n" - << senf::fieldName(" 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" - << senf::fieldName(" type") << unsigned (p->dst_mihfId().type()) << "\n" - << senf::fieldName(" 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); + << senf::fieldName(" version") << unsigned( p->version()) << "\n" + << senf::fieldName(" ack request") << p->ackRequest() << "\n" + << senf::fieldName(" ack response") << p->ackResponse() << "\n" + << senf::fieldName(" UIR") << p->uir() << "\n" + << senf::fieldName(" more fragments") << p->moreFragment() << "\n" + << senf::fieldName(" fragment number") << p->fragmentNr() << "\n" + << senf::fieldName(" message ID (MID)") << unsigned( p->messageId()) << "\n" + << senf::fieldName(" sid") << unsigned( p->sid()) << "\n" + << senf::fieldName(" opcode") << unsigned( p->opcode()) << "\n" + << senf::fieldName(" aid") << unsigned( p->aid()) << "\n" + << senf::fieldName(" transaction id") << unsigned( p->transactionId()) << "\n" + << senf::fieldName(" payload length") << unsigned( p->payloadLength()) << "\n"; + p->src_mihfId().dump( os); + p->dst_mihfId().dump( os); } prefix_ void senf::MIHPacketType::finalize(packet p) @@ -153,14 +82,17 @@ prefix_ senf::PacketInterpreterBase::factory_t senf::MIHPacketType::nextPacketTy prefix_ void senf::MIHGenericPayloadPacketType::dump(packet p, std::ostream &os) { boost::io::ios_all_saver ias(os); - os << "MIH Payload (service specific TLVs):\n" - << " ToDo!\n"; + os << "MIH Payload (service specific TLVs):\n"; + typedef parser::tlvList_t::container tlvListContainer_t; + tlvListContainer_t tlvListContainer (p->tlvList()); + for (tlvListContainer_t::iterator i = tlvListContainer.begin(); i != tlvListContainer.end(); ++i) + i->dump( os); } prefix_ void senf::MIHGenericPayloadPacketType::finalize(packet p) { - typedef parser::tlv_list_t::container tlvContainer_t; - tlvContainer_t tlvs (p->tlv_list() ); + typedef parser::tlvList_t::container tlvContainer_t; + tlvContainer_t tlvs (p->tlvList() ); for (tlvContainer_t::iterator i (tlvs.begin()); i != tlvs.end(); ++i) i->finalizeLength(); } diff --git a/senf/Packets/80221Bundle/MIHPacket.hh b/senf/Packets/80221Bundle/MIHPacket.hh index e9f6f3c..e051bfb 100644 --- a/senf/Packets/80221Bundle/MIHPacket.hh +++ b/senf/Packets/80221Bundle/MIHPacket.hh @@ -78,16 +78,15 @@ namespace senf { SENF_PARSER_GOTO_OFFSET( 8, 8); // just to limit the offset calculation // Source MIHF Id - SENF_PARSER_FIELD ( src_mihfId, MIHFId_TLVParser ); + SENF_PARSER_FIELD ( src_mihfId, MIHFSrcIdTLVParser ); // Destination MIHF Id - SENF_PARSER_FIELD ( dst_mihfId, MIHFId_TLVParser ); + SENF_PARSER_FIELD ( dst_mihfId, MIHFDstIdTLVParser ); SENF_PARSER_FINALIZE ( MIHPacketParser ); SENF_PARSER_INIT() { + defaultInit(); version_() = 1; - src_mihfId().type() = 1; - dst_mihfId().type() = 2; } friend class MIHPacketType; @@ -132,7 +131,7 @@ namespace senf { struct MIHGenericPayloadPacketParser : public PacketParserBase { # include SENF_PARSER() - SENF_PARSER_LIST ( tlv_list, packetSize(), MIHGenericTLVParser ); + SENF_PARSER_LIST ( tlvList, packetSize(), MIHGenericTLVParser ); SENF_PARSER_FINALIZE ( MIHGenericPayloadPacketParser ); }; diff --git a/senf/Packets/80221Bundle/MIHPacket.test.cc b/senf/Packets/80221Bundle/MIHPacket.test.cc index 1a84a82..1ba5e0e 100644 --- a/senf/Packets/80221Bundle/MIHPacket.test.cc +++ b/senf/Packets/80221Bundle/MIHPacket.test.cc @@ -129,7 +129,8 @@ BOOST_AUTO_UNIT_TEST(MIHPacket_create_mac) 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 )); + SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data), + mihPacket.data().begin(), mihPacket.data().end() ); BOOST_CHECK_EQUAL( mihPacket->src_mihfId().asMACAddress(), MACAddress::from_string("01:02:03:04:05:06")); @@ -159,7 +160,8 @@ BOOST_AUTO_UNIT_TEST(MIHPacket_create_inet4) 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 )); + SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data), + mihPacket.data().begin(), mihPacket.data().end() ); BOOST_CHECK_EQUAL( mihPacket->src_mihfId().asINet4Address(), INet4Address::from_string("128.129.130.131")); @@ -197,7 +199,8 @@ BOOST_AUTO_UNIT_TEST(MIHPacket_create_inet6) 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 )); + SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data), + mihPacket.data().begin(), mihPacket.data().end() ); BOOST_CHECK_EQUAL( mihPacket->src_mihfId().asINet6Address(), INet6Address::from_string("::ffff:1.2.3.4")); @@ -237,19 +240,22 @@ BOOST_AUTO_UNIT_TEST(MIHPayload_parse) BOOST_REQUIRE( mihPacket.next().is() ); MIHGenericPayloadPacket mihPayload (mihPacket.next().as()); - BOOST_CHECK_EQUAL( mihPayload->tlv_list().size(), 2u); - MIHGenericPayloadPacket::Parser::tlv_list_t::container tlv_list_container ( - mihPayload->tlv_list()); + BOOST_CHECK_EQUAL( mihPayload->tlvList().size(), 2u); + MIHGenericPayloadPacket::Parser::tlvList_t::container tlvListContainer ( + mihPayload->tlvList()); - MIHGenericTLVParser tlv1 = *tlv_list_container.begin(); + MIHGenericTLVParser tlv1 = *tlvListContainer.begin(); BOOST_CHECK_EQUAL( tlv1.type(), 0x42); BOOST_CHECK_EQUAL( tlv1.length(), 0x0au); BOOST_CHECK_EQUAL( tlv1.value().size(), 0x0a); - MIHGenericTLVParser tlv2 = *boost::next(tlv_list_container.begin()); + MIHGenericTLVParser tlv2 = *boost::next(tlvListContainer.begin()); BOOST_CHECK_EQUAL( tlv2.type(), 0x43); BOOST_CHECK_EQUAL( tlv2.length(), 0x05u); BOOST_CHECK_EQUAL( tlv2.value().size(), 0x05); + + std::ostringstream oss (std::ostringstream::out); + SENF_CHECK_NO_THROW( mihPayload.dump( oss)); } @@ -262,18 +268,18 @@ BOOST_AUTO_UNIT_TEST(MIHPayload_create) mihPacket->dst_mihfId().setString( "test"); MIHGenericPayloadPacket mihPayload (MIHGenericPayloadPacket::createAfter(mihPacket)); - MIHGenericPayloadPacket::Parser::tlv_list_t::container tlvContainer ( - mihPayload->tlv_list() ); + MIHGenericPayloadPacket::Parser::tlvList_t::container tlvListContainer ( + mihPayload->tlvList() ); unsigned char tlv1_value[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; - MIHGenericTLVParser tlv1 ( tlvContainer.push_back_space()); + MIHGenericTLVParser tlv1 ( tlvListContainer.push_back_space()); tlv1.type() = 0x42; tlv1.value( tlv1_value); unsigned char tlv2_value[] = { 0x1a, 0x2b, 0x3c, 0x4d, 0x5e }; - MIHGenericTLVParser tlv2 ( tlvContainer.push_back_space()); + MIHGenericTLVParser tlv2 ( tlvListContainer.push_back_space()); tlv2.type() = 0x43; tlv2.value( tlv2_value); @@ -300,7 +306,6 @@ BOOST_AUTO_UNIT_TEST(MIHPayload_create) 0x05, // first bit not set, length=5 0x1a, 0x2b, 0x3c, 0x4d, 0x5e // value }; - SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data), mihPacket.data().begin(), mihPacket.data().end() ); } diff --git a/senf/Packets/80221Bundle/TLVParser.cc b/senf/Packets/80221Bundle/TLVParser.cc index 43ba4c2..8f9d942 100644 --- a/senf/Packets/80221Bundle/TLVParser.cc +++ b/senf/Packets/80221Bundle/TLVParser.cc @@ -33,6 +33,98 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// +SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHFSrcIdTLVParser ); +SENF_PACKET_TLV_REGISTRY_REGISTER( senf::MIHFDstIdTLVParser ); + +/////////////////////////////////////////////////////////////////////////// +// senf::MIHFIdTLVParser + +prefix_ void senf::MIHFIdTLVParser::dump(std::ostream & os) + const +{ + os << senf::fieldName(" type") << unsigned (type()) << "\n" + << senf::fieldName(" length") << unsigned (length()) << "\n" + << " value:\n"; + std::string src_mihfId (asString()); + hexdump(src_mihfId.begin(), src_mihfId.end(), os); +} + +prefix_ void senf::MIHFIdTLVParser::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 = resizeValueField( str_size); + std::copy( id.begin(), id.end(), si); +} + +prefix_ void senf::MIHFIdTLVParser::setMACAddress(senf::MACAddress const &mac) +{ + safe_data_iterator si = resizeValueField(12); + std::copy( mac.begin(), mac.end(), getNAIEncodedOutputIterator(si)); +} + +prefix_ void senf::MIHFIdTLVParser::setINet4Address(senf::INet4Address const &addr) +{ + safe_data_iterator si = resizeValueField(8); + std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); +} + +prefix_ void senf::MIHFIdTLVParser::setINet6Address(senf::INet6Address const &addr) +{ + safe_data_iterator si = resizeValueField(32); + std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); +} + +prefix_ void senf::MIHFIdTLVParser::setEUI64(senf::EUI64 const &addr) +{ + safe_data_iterator si = resizeValueField(16); + std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si)); +} + +prefix_ senf::MIHFId senf::MIHFIdTLVParser::valueAs(MIHFId::Type type) + const +{ + if (length() == 0) return MIHFId(); + switch (type) { + case MIHFId::Empty: + return MIHFId(); + case MIHFId::MACAddress: + return MIHFId( asMACAddress()); + case MIHFId::INet4Address: + return MIHFId( asINet4Address()); + case MIHFId::INet6Address: + return MIHFId( asINet6Address()); + case MIHFId::String: + return MIHFId( asINet6Address()); + case MIHFId::EUI64: + return MIHFId( asINet6Address()); + } + return MIHFId(); +} + + +/////////////////////////////////////////////////////////////////////////// +// senf::MIHFSrcIdTLVParser + +prefix_ void senf::MIHFSrcIdTLVParser::dump(std::ostream & os) + const +{ + os << " source MIHF_Id TLV:\n"; + MIHFIdTLVParser::dump(os); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::MIHFDstIdTLVParser + +prefix_ void senf::MIHFDstIdTLVParser::dump(std::ostream & os) + const +{ + os << " destination MIHF_Id TLV:\n"; + MIHFIdTLVParser::dump(os); +} + /////////////////////////////////////////////////////////////////////////// // MIHBaseTLVParser @@ -52,7 +144,7 @@ prefix_ senf::safe_data_iterator senf::MIHBaseTLVParser::resizeValueField( /////////////////////////////////////////////////////////////////////////// -// MIHTLVLengthParser +// senf::MIHTLVLengthParser prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::value() const { @@ -72,7 +164,6 @@ prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::value() c }; } - prefix_ void senf::MIHTLVLengthParser::value(value_type const & v) { switch (bytes() ) { @@ -101,7 +192,6 @@ prefix_ void senf::MIHTLVLengthParser::value(value_type const & v) underflow_flag() = (v <= 128); } - prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::maxValue() const { @@ -121,21 +211,18 @@ prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::maxValue( }; } - prefix_ senf::MIHTLVLengthParser const & senf::MIHTLVLengthParser::operator= (value_type other) { value(other); return *this; } - prefix_ void senf::MIHTLVLengthParser::init() const { defaultInit(); extended_length_flag() = false; } - prefix_ void senf::MIHTLVLengthParser::finalize() { value_type v = value(); @@ -159,7 +246,6 @@ prefix_ void senf::MIHTLVLengthParser::finalize() if (b != 5) resize_(5); } - prefix_ void senf::MIHTLVLengthParser:: maxValue(MIHTLVLengthParser::value_type v) { if (v <= 128) @@ -180,7 +266,6 @@ prefix_ void senf::MIHTLVLengthParser:: maxValue(MIHTLVLengthParser::value_type if (b < 5) resize_(5); } - prefix_ void senf::MIHTLVLengthParser::resize_(size_type size) { value_type v = value(); diff --git a/senf/Packets/80221Bundle/TLVParser.cci b/senf/Packets/80221Bundle/TLVParser.cci index 467a732..be724df 100644 --- a/senf/Packets/80221Bundle/TLVParser.cci +++ b/senf/Packets/80221Bundle/TLVParser.cci @@ -39,36 +39,36 @@ prefix_ senf::MIHTLVLengthParser::size_type senf::MIHTLVLengthParser::bytes() co } /////////////////////////////////////////////////////////////////////////// -// MIHFId_TLVParser +// MIHFIdTLVParser -prefix_ std::string senf::MIHFId_TLVParser::asString() +prefix_ std::string senf::MIHFIdTLVParser::asString() const { return std::string( i(1+length_().bytes()), i(1+length_().bytes()+length()) ); } -prefix_ senf::MACAddress senf::MIHFId_TLVParser::asMACAddress() +prefix_ senf::MACAddress senf::MIHFIdTLVParser::asMACAddress() const { return MACAddress::from_data( getNAIDecodedIterator( i(1+length_().bytes()), i(1+length_().bytes()+12) )); } -prefix_ senf::INet4Address senf::MIHFId_TLVParser::asINet4Address() +prefix_ senf::INet4Address senf::MIHFIdTLVParser::asINet4Address() const { return INet4Address::from_data( getNAIDecodedIterator( i(1+length_().bytes()), i(1+length_().bytes()+8) )); } -prefix_ senf::INet6Address senf::MIHFId_TLVParser::asINet6Address() +prefix_ senf::INet6Address senf::MIHFIdTLVParser::asINet6Address() const { return INet6Address::from_data( getNAIDecodedIterator( i(1+length_().bytes()), i(1+length_().bytes()+32) )); } -prefix_ senf::EUI64 senf::MIHFId_TLVParser::asEUI64() +prefix_ senf::EUI64 senf::MIHFIdTLVParser::asEUI64() const { return EUI64::from_data( diff --git a/senf/Packets/80221Bundle/TLVParser.hh b/senf/Packets/80221Bundle/TLVParser.hh index 1ee9bfa..e6caf9c 100644 --- a/senf/Packets/80221Bundle/TLVParser.hh +++ b/senf/Packets/80221Bundle/TLVParser.hh @@ -127,8 +127,10 @@ namespace senf { the current length value. */ void finalizeLength() { - protect(), length_().finalize(); + protect(), length_().finalize(); }; + + typedef GenericTLVParserRegistry Registry; protected: /// resize the packet after the length field to given size @@ -161,12 +163,12 @@ namespace senf { \note you must call mihfIdPacket.maxLengthValue( 253) *before* setting longer MIHF_IDs values. */ - class MIHFId_TLVParser : public MIHBaseTLVParser + class MIHFIdTLVParser : public MIHBaseTLVParser { # include SENF_PARSER() SENF_PARSER_INHERIT ( MIHBaseTLVParser ); SENF_PARSER_SKIP ( length(), 0 ); - SENF_PARSER_FINALIZE ( MIHFId_TLVParser ); + SENF_PARSER_FINALIZE ( MIHFIdTLVParser ); public: std::string asString() const; @@ -186,6 +188,8 @@ namespace senf { MIHFId valueAs(MIHFId::Type type) const; + void dump(std::ostream & os) const; + private: template struct binaryNAIEncoder { @@ -215,7 +219,31 @@ namespace senf { } }; - + struct MIHFSrcIdTLVParser : public MIHFIdTLVParser + { + MIHFSrcIdTLVParser(data_iterator i, state_type s) : MIHFIdTLVParser(i,s) {} + + void init() const { + defaultInit(); + type() << typeId+0; + } + static type_t::value_type const typeId = 1; + + void dump(std::ostream & os) const; + }; + + struct MIHFDstIdTLVParser : public MIHFIdTLVParser + { + MIHFDstIdTLVParser(data_iterator i, state_type s) : MIHFIdTLVParser(i,s) {} + + void init() const { + defaultInit(); + type() << typeId+0; + } + static type_t::value_type const typeId = 2; + + void dump(std::ostream & os) const; + }; }