From: tho Date: Thu, 8 Jan 2009 17:11:04 +0000 (+0000) Subject: uff. nearly completely new TLVPacket implementation. X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=bd67664cb4ea1b36c9bb52a622e02341e4f0131f;p=senf.git uff. nearly completely new TLVPacket implementation. git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1047 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/80221Bundle/MIHPacket.hh b/Packets/80221Bundle/MIHPacket.hh index a7dcc78..b84bbe9 100644 --- a/Packets/80221Bundle/MIHPacket.hh +++ b/Packets/80221Bundle/MIHPacket.hh @@ -38,7 +38,7 @@ namespace senf { struct MIHF_IdParser : public senf::PacketParserBase { # include SENF_FIXED_PARSER() - + SENF_PARSER_FINALIZE ( MIHF_IdParser ); }; @@ -55,9 +55,9 @@ namespace senf { SENF_PARSER_SKIP_BITS ( 1 ); // MIH message ID (MID) - SENF_PARSER_BITFIELD ( sid, 4, unsigned ); - SENF_PARSER_BITFIELD ( opcode, 2, unsigned ); - SENF_PARSER_BITFIELD ( aid, 10, unsigned ); + SENF_PARSER_BITFIELD ( sid, 4, unsigned ); + SENF_PARSER_BITFIELD ( opcode, 2, unsigned ); + SENF_PARSER_BITFIELD ( aid, 10, unsigned ); SENF_PARSER_SKIP_BITS ( 4 ); SENF_PARSER_BITFIELD ( transactionId, 12, unsigned ); @@ -78,7 +78,7 @@ namespace senf { SENF_PARSER_INIT() { version_() = 1; source_type() = 1; - destination_type() = 1; + destination_type() = 2; } }; diff --git a/Packets/80221Bundle/TLVPacket.cc b/Packets/80221Bundle/TLVPacket.cc index 42ccd70..177a2e1 100644 --- a/Packets/80221Bundle/TLVPacket.cc +++ b/Packets/80221Bundle/TLVPacket.cc @@ -47,52 +47,46 @@ prefix_ senf::DynamicTLVLengthParser::value_type senf::DynamicTLVLengthParser::v case 5: return parse( 1 ).value(); default: - throw(UnsuportedTLVPacketException()); + throw(TLVLengthException()); }; } + prefix_ void senf::DynamicTLVLengthParser::value(value_type const & v) { - SafePacketParserWrapper safeThis (*this); - if (v < 128u) { - if (bytes() != 1) - resize(1, safeThis); - safeThis->fixed_length_field() = v; + switch (bytes() ) { + case 1: + if (v > 127) throw( TLVLengthException()); + fixed_length_field() = v; return; - } - if (v <= UInt8Parser::max_value) { - if (bytes() != 2) - resize(2, safeThis); - safeThis->parse(1) = v; + case 2: + if (v > UInt8Parser::max_value) throw( TLVLengthException()); + parse(1) = v; return; - } - if (v <= UInt16Parser::max_value) { - if (bytes() != 3) - resize(3, safeThis); - safeThis->parse(1) = v; + case 3: + if (v > UInt16Parser::max_value) throw( TLVLengthException()); + parse(1) = v; return; - } - if (v <= UInt24Parser::max_value) { - if (bytes() != 4) - resize(4, safeThis); - safeThis->parse(1) = v; + case 4: + if (v > UInt24Parser::max_value) throw( TLVLengthException()); + parse(1) = v; return; - } - if (v <= UInt32Parser::max_value) { - if (bytes() != 5) - resize(5, safeThis); - safeThis->parse(1) = v; + case 5: + parse(1) = v; return; - } - throw(UnsuportedTLVPacketException()); + default: + throw( TLVLengthException()); + }; } + prefix_ senf::DynamicTLVLengthParser const & senf::DynamicTLVLengthParser::operator= (value_type other) { value(other); return *this; } + prefix_ senf::DynamicTLVLengthParser::size_type senf::DynamicTLVLengthParser::bytes() const { if ( extended_length_flag() ) @@ -101,32 +95,91 @@ prefix_ senf::DynamicTLVLengthParser::size_type senf::DynamicTLVLengthParser::by return 1; } + prefix_ void senf::DynamicTLVLengthParser::init() const { defaultInit(); - extended_length_flag() = 0; + extended_length_flag() = false; } -prefix_ void senf::DynamicTLVLengthParser::resize( - size_type size, SafePacketParserWrapper &safeThis) + +prefix_ void senf::DynamicTLVLengthParser::shrink() { - std::cout << "DynamicTLVLengthParser::resize " << unsigned( size) << "\n"; - if (size > 1) { - safeThis->extended_length_flag() = true; - safeThis->fixed_length_field() = size - 1; - } else { - safeThis->extended_length_flag() = false; + value_type v = value(); + size_type b = bytes(); + if (v <= 127) { + if (b != 1) resize(1); + return; } - + if (v <= UInt8Parser::max_value) { + if (b != 2) resize(2); + return; + } + if (v <= UInt16Parser::max_value) { + if (b != 3) resize(3); + return; + } + if (v <= UInt24Parser::max_value) { + if (b != 4) resize(4); + return; + } + if (b != 5) resize(5); +} + + +prefix_ void senf::BaseTLVPacketParser:: maxLengthValue(DynamicTLVLengthParser::value_type v) + const +{ + if (v <= 127) + return; + size_type b = senf::bytes( length_()); + if (v <= UInt8Parser::max_value) { + if (b < 2) length_().resize(2); + return; + } + if (v <= UInt16Parser::max_value) { + if (b < 3) length_().resize(3); + return; + } + if (v <= UInt24Parser::max_value) { + if (b < 4) length_().resize(4); + return; + } + if (b < 5) length_().resize(5); +} + + +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(); size_type current_size (bytes()); - safe_data_iterator si (data(), i()); + SafePacketParserWrapper safeThis (*this); + safe_data_iterator si (data(), i()); if (current_size > size) data().erase( si, boost::next(si, current_size-size)); else data().insert( si, size-current_size, 0); + + if (size > 1) { + safeThis->extended_length_flag() = true; + safeThis->fixed_length_field() = size - 1; + } else { + safeThis->extended_length_flag() = false; + } + value(v); } + prefix_ void senf::GenericTLVPacketType::dump(packet p, std::ostream & os) { boost::io::ios_all_saver ias(os); @@ -136,30 +189,11 @@ prefix_ void senf::GenericTLVPacketType::dump(packet p, std::ostream & os) << " length: " << unsigned( p->length()) << "\n"; } -//prefix_ void senf::GenericTLVPacketType::finalize(packet p) -//{ -// try { -// PacketData::size_type size = p.next().data().size(); -// if ( size > DynamicTLVLengthParser::max_value ) -// throw(UnsuportedTLVPacketException()); -// p->length() = size; -// } -// catch (InvalidPacketChainException & ex) { -// ; -// } -//} - - -//template -//prefix_ senf::PacketInterpreterBase::optional_range -//senf::TLVPacketType::nextPacketRange(packet p) -//{ -// if (p.data().size() < 5) -// return no_range(); -// return range( -// boost::next(p.data().begin(), 4 + senf::bytes(p->length()) ), -// p.data().end() ); -//} + +prefix_ void senf::GenericTLVPacketType::finalize(packet p) +{ + p->shrinkLength(); +} ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Packets/80221Bundle/TLVPacket.ct b/Packets/80221Bundle/TLVPacket.ct new file mode 100644 index 0000000..26e53f3 --- /dev/null +++ b/Packets/80221Bundle/TLVPacket.ct @@ -0,0 +1,61 @@ +// $Id: TLVPacket.ct 1029 2008-12-19 13:08:19Z tho $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Thorsten Horstmann +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief TLVPacket non-inline template implementation */ + +//#include "TLVPacket.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ void senf::GenericTLVPacketParser::value(ForwardReadableRange const &range) +{ + size_type range_size ( boost::size(range)); + size_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); + + std::copy( boost::begin(range), boost::end(range), si); +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// comment-column: 40 +// End: diff --git a/Packets/80221Bundle/TLVPacket.hh b/Packets/80221Bundle/TLVPacket.hh index 1180839..f2fdc36 100644 --- a/Packets/80221Bundle/TLVPacket.hh +++ b/Packets/80221Bundle/TLVPacket.hh @@ -35,22 +35,12 @@ namespace senf { - /** \brief xxx - - \todo document me - \todo add usefull exceptions strings - - \ingroup protocolbundle_80221 - */ - struct UnsuportedTLVPacketException : public senf::Exception - { UnsuportedTLVPacketException() - : senf::Exception("length of length can be max. 4 bytes. Sorry."){} }; - - /** \brief xxx - \todo document me - - \ingroup protocolbundle_80221 - */ + + struct TLVLengthException : public senf::Exception + { TLVLengthException() + : senf::Exception("TLVLengthException"){} }; + + class DynamicTLVLengthParser : public detail::packet::IntParserOps, public PacketParserBase @@ -71,51 +61,46 @@ namespace senf { void init() const; # include SENF_PARSER() - SENF_PARSER_PRIVATE_BITFIELD ( extended_length_flag, 1, bool ); SENF_PARSER_PRIVATE_BITFIELD ( fixed_length_field, 7, unsigned ); - - private: -// typedef FlagParser < 0 > ExtendedLengthFlagParser; -// typedef UIntFieldParser < 1, 8 > FixedLengthParser; -// -// ExtendedLengthFlagParser extended_length_flag() const { -// return parse( 0 ); -// } -// -// FixedLengthParser fixed_length_field() const { -// return parse( 0 ); -// } - - void resize(size_type size, SafePacketParserWrapper &safeThis); + void resize(size_type size); + void shrink(); }; - /** \brief parse TLVPacket Packet - - \todo document me - - \see TLVPacketType - - \ingroup protocolbundle_80221 - */ - struct GenericTLVPacketParser : public PacketParserBase + + class BaseTLVPacketParser : public PacketParserBase { # include SENF_PARSER() + SENF_PARSER_FIELD ( type, UInt8Parser ); + SENF_PARSER_FIELD_RO ( length, DynamicTLVLengthParser ); + SENF_PARSER_FINALIZE ( BaseTLVPacketParser ); - SENF_PARSER_FIELD ( type, UInt8Parser ); - SENF_PARSER_FIELD_RO ( length, DynamicTLVLengthParser ); - SENF_PARSER_VECTOR ( value, bytes(length), UInt8Parser ); + void maxLengthValue(DynamicTLVLengthParser::value_type v) const; + void shrinkLength() { length_().shrink(); }; - SENF_PARSER_FINALIZE( GenericTLVPacketParser ); + protected: + size_type length_bytes() const { return length_().bytes(); }; + void length(DynamicTLVLengthParser::value_type &v) { length_() = v; }; }; - - /** \brief generic TLV Packet type + - \todo document me + struct GenericTLVPacketParser : public BaseTLVPacketParser + { +# include SENF_PARSER() + SENF_PARSER_INHERIT( BaseTLVPacketParser ) + SENF_PARSER_FINALIZE( GenericTLVPacketParser ); + + SENF_PARSER_INIT() { + maxLengthValue( DynamicTLVLengthParser::max_value); + } + + senf::PacketInterpreterBase::range value() const; - \ingroup protocolbundle_80221 - */ + template + void value(ForwardReadableRange const &range); + }; + struct GenericTLVPacketType : public PacketTypeBase, public PacketTypeMixin @@ -124,12 +109,11 @@ namespace senf { typedef ConcretePacket packet; typedef GenericTLVPacketParser parser; -// static optional_range nextPacketRange(packet p); using mixin::nextPacketRange; using mixin::init; using mixin::initSize; -// static void finalize(packet p); + static void finalize(packet p); static void dump(packet p, std::ostream & os); }; @@ -139,7 +123,7 @@ namespace senf { ///////////////////////////////hh.e//////////////////////////////////////// //#include "TLVPacket.cci" -//#include "TLVPacket.ct" +#include "TLVPacket.ct" //#include "TLVPacket.cti" #endif diff --git a/Packets/80221Bundle/TLVPacket.test.cc b/Packets/80221Bundle/TLVPacket.test.cc index 2e182d1..f96e3b5 100644 --- a/Packets/80221Bundle/TLVPacket.test.cc +++ b/Packets/80221Bundle/TLVPacket.test.cc @@ -31,7 +31,6 @@ #include "../../Utils/auto_unit_test.hh" #include -#include #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// @@ -39,22 +38,16 @@ using namespace senf; -void check_TLVPacket(GenericTLVPacket &tlvPacket, boost::uint32_t type, boost::uint32_t length) +void check_TLVPacket(GenericTLVPacket &tlvPacket, boost::uint8_t type, boost::uint32_t length) { - BOOST_CHECK_EQUAL( tlvPacket->type(), type ); - BOOST_CHECK_EQUAL( tlvPacket->length(), length ); - - BOOST_CHECK_EQUAL( tlvPacket->value().size(), length); - for (int i=0, j=tlvPacket->value().size(); ivalue()[i], i ); -} - - -BOOST_AUTO_UNIT_TEST(GenericTLVPacket_static) -{ - // check static values: - // number of bytes to allocate for a new GenericTLVPacket should be 2 - BOOST_CHECK_EQUAL( GenericTLVPacket::type::initSize(), 2u ); + BOOST_CHECK_EQUAL( tlvPacket->type(), type ); + BOOST_CHECK_EQUAL( tlvPacket->length(), length ); + BOOST_CHECK_EQUAL( tlvPacket->value().size(), length ); + senf::PacketData::iterator dataIterator (tlvPacket->value().begin()); + for (unsigned i=0; itype() = 42u; - for (uint8_t i=0; i<10; i++) - tlvPacket->value().push_back( i); - tlvPacket.finalizeAll(); + tlvPacket->value( value); + tlvPacket.finalizeThis(); check_TLVPacket( tlvPacket, 42u, 0x0Au ); + + unsigned char data[] = { + 0x2a, // type + 0x0A, // first bit not set, length=10 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 // value + }; + BOOST_CHECK( equal( tlvPacket.data().begin(), tlvPacket.data().end(), data )); } -/** +#if 0 BOOST_AUTO_UNIT_TEST(TLVPacket_create_packet_with_extended_length) { GenericTLVPacket tlvPacket (GenericTLVPacket::create()); @@ -203,8 +206,7 @@ BOOST_AUTO_UNIT_TEST(TLVFixPacket_create_invalid_packet) test_invalid_TLVFixPacket_creating( UInt24Parser::max_value); } -*/ - +#endif ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_