uff. nearly completely new TLVPacket implementation.
tho [Thu, 8 Jan 2009 17:11:04 +0000 (17:11 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1047 270642c3-0616-0410-b53a-bc976706d245

Packets/80221Bundle/MIHPacket.hh
Packets/80221Bundle/TLVPacket.cc
Packets/80221Bundle/TLVPacket.ct [new file with mode: 0644]
Packets/80221Bundle/TLVPacket.hh
Packets/80221Bundle/TLVPacket.test.cc

index a7dcc78..b84bbe9 100644 (file)
@@ -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;
         }
     };
     
index 42ccd70..177a2e1 100644 (file)
@@ -47,52 +47,46 @@ prefix_ senf::DynamicTLVLengthParser::value_type senf::DynamicTLVLengthParser::v
     case 5:
         return parse<UInt32Parser>( 1 ).value();
     default:
-        throw(UnsuportedTLVPacketException());
+        throw(TLVLengthException());
     };
 }
 
+
 prefix_ void senf::DynamicTLVLengthParser::value(value_type const & v) 
 {
-    SafePacketParserWrapper<DynamicTLVLengthParser> 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<UInt8Parser>(1) = v;
+    case 2:
+        if (v > UInt8Parser::max_value) throw( TLVLengthException());
+        parse<UInt8Parser>(1) = v;
         return;
-    }
-    if (v <= UInt16Parser::max_value) {
-        if (bytes() != 3)
-            resize(3, safeThis);
-        safeThis->parse<UInt16Parser>(1) = v;
+    case 3:
+        if (v > UInt16Parser::max_value) throw( TLVLengthException());
+        parse<UInt16Parser>(1) = v;
         return;
-    }
-    if (v <= UInt24Parser::max_value) {
-        if (bytes() != 4)
-            resize(4, safeThis);
-        safeThis->parse<UInt24Parser>(1) = v;
+    case 4:
+        if (v > UInt24Parser::max_value) throw( TLVLengthException());
+        parse<UInt24Parser>(1) = v;
         return;
-    }
-    if (v <= UInt32Parser::max_value) {
-        if (bytes() != 5)
-            resize(5, safeThis);
-        safeThis->parse<UInt32Parser>(1) = v;
+    case 5:
+        parse<UInt32Parser>(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<DynamicTLVLengthParser> &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<DynamicTLVLengthParser> 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 <class TypeParser, class LengthParser>
-//prefix_ senf::PacketInterpreterBase::optional_range 
-//senf::TLVPacketType<TypeParser, LengthParser>::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 (file)
index 0000000..26e53f3
--- /dev/null
@@ -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 <tho@berlios.de>
+//
+// 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 <class ForwardReadableRange>
+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_
+
+\f
+// 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:
index 1180839..f2fdc36 100644 (file)
 
 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<DynamicTLVLengthParser, boost::uint32_t>,
           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<ExtendedLengthFlagParser>( 0 );
-//        }
-//
-//        FixedLengthParser fixed_length_field() const {
-//            return parse<FixedLengthParser>( 0 );
-//        }
-        
-        void resize(size_type size, SafePacketParserWrapper<DynamicTLVLengthParser> &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 <class ForwardReadableRange>
+        void value(ForwardReadableRange const &range);
+    };
+    
     struct GenericTLVPacketType
         : public PacketTypeBase,
           public PacketTypeMixin<GenericTLVPacketType>
@@ -124,12 +109,11 @@ namespace senf {
         typedef ConcretePacket<GenericTLVPacketType> 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
 
index 2e182d1..f96e3b5 100644 (file)
@@ -31,7 +31,6 @@
 
 #include "../../Utils/auto_unit_test.hh"
 #include <boost/test/test_tools.hpp>
-#include <vector>
 
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 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(); i<j; i++)
-        BOOST_CHECK_EQUAL( tlvPacket->value()[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; i<length; i++) {
+        BOOST_CHECK_EQUAL( *dataIterator, i );
+        dataIterator++;
+    }
 }
 
 
@@ -69,6 +62,7 @@ BOOST_AUTO_UNIT_TEST(GenericTLVPacket_parse_packet_with_simple_length)
     check_TLVPacket( tlvPacket, 0x01, 0x0Au );
 }
 
+
 BOOST_AUTO_UNIT_TEST(GenericTLVPacket_parse_packet_with_extended_length)
 {
     unsigned char data[] = { 
@@ -84,16 +78,25 @@ BOOST_AUTO_UNIT_TEST(GenericTLVPacket_parse_packet_with_extended_length)
 
 BOOST_AUTO_UNIT_TEST(GenericTLVPacket_create_packet_with_simple_length)
 {
+    unsigned char value[] = { 
+           0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
+    };
     GenericTLVPacket tlvPacket (GenericTLVPacket::create());
     tlvPacket->type() = 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<TestTLVPacket24>( UInt24Parser::max_value);
 }
 
-*/
-
+#endif
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_