Packets/80221Bundle: fix for TLVs to support latest version of the standard :-/
tho [Thu, 9 Jul 2009 16:23:38 +0000 (16:23 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1265 270642c3-0616-0410-b53a-bc976706d245

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

index e221b59..d4e2e61 100644 (file)
@@ -46,7 +46,7 @@ prefix_ void senf::MIHFId_TLVParser::setString(std::string const &id)
     // 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);   
+    safe_data_iterator si = resizeValueField( str_size);   
     std::copy( id.begin(), id.end(), si);
 }
 
@@ -59,7 +59,7 @@ prefix_ senf::MACAddress senf::MIHFId_TLVParser::asMACAddress()
 
 prefix_ void senf::MIHFId_TLVParser::setMACAddress(senf::MACAddress const &mac)
 {
-    safe_data_iterator si = resizeValue(12);
+    safe_data_iterator si = resizeValueField(12);
     std::copy( mac.begin(), mac.end(), getNAIEncodedOutputIterator(si));
 }
 
@@ -73,7 +73,7 @@ prefix_ senf::INet4Address senf::MIHFId_TLVParser::asINet4Address()
 
 prefix_ void senf::MIHFId_TLVParser::setINet4Address(senf::INet4Address const &addr)
 {
-    safe_data_iterator si = resizeValue(8);
+    safe_data_iterator si = resizeValueField(8);
     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
 }
 
@@ -86,7 +86,7 @@ prefix_ senf::INet6Address senf::MIHFId_TLVParser::asINet6Address()
 
 prefix_ void senf::MIHFId_TLVParser::setINet6Address(senf::INet6Address const &addr)
 {
-    safe_data_iterator si = resizeValue(32);
+    safe_data_iterator si = resizeValueField(32);
     std::copy( addr.begin(), addr.end(), getNAIEncodedOutputIterator(si));
 }
 
index 90765c3..b5c7f94 100644 (file)
@@ -46,11 +46,9 @@ namespace senf {
         typedef boost::uint16_t key_t;
     };
     
-#   define SENF_MIH_PACKET_REGISTRY_REGISTER( sid, opcode, aid, type )                             \
+#   define SENF_MIH_PACKET_REGISTRY_REGISTER( packetType )                                         \
         SENF_PACKET_REGISTRY_REGISTER(                                                             \
-            senf::MIHMessageRegistry,                                                              \
-            boost::uint16_t((boost::uint16_t(sid) << 12) | (boost::uint16_t(opcode) << 10) | aid), \
-            type )
+            senf::MIHMessageRegistry, packetType::type::MESSAGE_ID, packetType )
     
     /** \brief Parse a MIHF_ID
 
@@ -138,7 +136,8 @@ namespace senf {
         SENF_PARSER_SKIP_BITS ( 4                           );
         SENF_PARSER_BITFIELD  ( transactionId, 12, unsigned );
         SENF_PARSER_FIELD_RO  ( payloadLength, UInt16Parser );
-
+        
+        SENF_PARSER_GOTO_OFFSET( 8, 8); // just to limit the offset calculation
         
         // Source MIHF Id
         SENF_PARSER_FIELD ( src_mihfId, MIHFId_TLVParser );
index 12d9bfd..0b94056 100644 (file)
@@ -33,7 +33,7 @@
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ senf::safe_data_iterator senf::BaseTLVPacketParser::resizeValue(
+prefix_ senf::safe_data_iterator senf::BaseTLVPacketParser::resizeValueField(
         DynamicTLVLengthParser::value_type size) 
 {
     DynamicTLVLengthParser::value_type current_length ( length());
@@ -52,15 +52,15 @@ prefix_ senf::DynamicTLVLengthParser::value_type senf::DynamicTLVLengthParser::v
 {
     switch (bytes() ) {
     case 1:
-        return fixed_length_field().value();
+        return length_field().value();
     case 2:
-        return parse<UInt8Parser>( 1 ).value();
+        return parse<UInt8Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
     case 3:
-        return parse<UInt16Parser>( 1 ).value();
+        return parse<UInt16Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
     case 4:
-        return parse<UInt24Parser>( 1 ).value();
+        return parse<UInt24Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
     case 5:
-        return parse<UInt32Parser>( 1 ).value();
+        return parse<UInt32Parser>( 1 ).value() + (underflow_flag() ? 0 : 128u);
     default:
         throw(TLVLengthException());
     };
@@ -71,27 +71,28 @@ prefix_ void senf::DynamicTLVLengthParser::value(value_type const & v)
 {
     switch (bytes() ) {
     case 1:
-        if (v > 127) throw( TLVLengthException());
+        if (v > 128) throw( TLVLengthException());
         fixed_length_field() = v;
         return;
     case 2:
-        if (v > UInt8Parser::max_value) throw( TLVLengthException());
-        parse<UInt8Parser>(1) = v;
-        return;
+        if (v > UInt8Parser::max_value + 128) throw( TLVLengthException());
+        parse<UInt8Parser>(1) = v - (v>128 ? 128 : 0);
+        break;
     case 3:
-        if (v > UInt16Parser::max_value) throw( TLVLengthException());
-        parse<UInt16Parser>(1) = v;
-        return;
+        if (v > UInt16Parser::max_value + 128) throw( TLVLengthException());
+        parse<UInt16Parser>(1) = v - (v>128 ? 128 : 0);
+        break;;
     case 4:
-        if (v > UInt24Parser::max_value) throw( TLVLengthException());
-        parse<UInt24Parser>(1) = v;
-        return;
+        if (v > UInt24Parser::max_value + 128) throw( TLVLengthException());
+        parse<UInt24Parser>(1) = v - (v>128 ? 128 : 0);
+        break;
     case 5:
-        parse<UInt32Parser>(1) = v;
-        return;
+        parse<UInt32Parser>(1) = v - (v>128 ? 128 : 0);
+        break;
     default:
         throw( TLVLengthException());
     };
+    underflow_flag() = v < 128;
 }
 
 
@@ -102,15 +103,6 @@ prefix_ senf::DynamicTLVLengthParser const & senf::DynamicTLVLengthParser::opera
 }
 
 
-prefix_ senf::DynamicTLVLengthParser::size_type senf::DynamicTLVLengthParser::bytes() const 
-{
-    if ( extended_length_flag() )
-        return 1 + fixed_length_field();
-    else
-        return 1;
-}
-    
-
 prefix_ void senf::DynamicTLVLengthParser::init() const 
 {
     defaultInit();
@@ -122,19 +114,19 @@ prefix_ void senf::DynamicTLVLengthParser::shrink()
 {
     value_type v = value();
     size_type b = bytes();
-    if (v <= 127) {
+    if (v <= 128) {
         if (b != 1) resize(1);
         return;
     }
-    if (v <= UInt8Parser::max_value) {
+    if (v <= UInt8Parser::max_value + 128) {
         if (b != 2) resize(2);
         return;
     }
-    if (v <= UInt16Parser::max_value) {
+    if (v <= UInt16Parser::max_value + 128) {
         if (b != 3) resize(3);
         return;
     }
-    if (v <= UInt24Parser::max_value) {
+    if (v <= UInt24Parser::max_value + 128 ){
         if (b != 4) resize(4);
         return;
     }
@@ -144,18 +136,18 @@ prefix_ void senf::DynamicTLVLengthParser::shrink()
 
 prefix_ void senf::DynamicTLVLengthParser:: maxValue(DynamicTLVLengthParser::value_type v)
 {
-    if (v <= 127)
+    if (v <= 128)
         return;
     size_type b = bytes();
-    if (v <= UInt8Parser::max_value) {
+    if (v <= UInt8Parser::max_value + 128) {
         if (b < 2) resize(2);
         return;
     }
-    if (v <= UInt16Parser::max_value) {
+    if (v <= UInt16Parser::max_value + 128) {
         if (b < 3) resize(3);
         return;
     }
-    if (v <= UInt24Parser::max_value) {
+    if (v <= UInt24Parser::max_value + 128) {
         if (b < 4) resize(4);
         return;
     }
diff --git a/Packets/80221Bundle/TLVPacket.cci b/Packets/80221Bundle/TLVPacket.cci
new file mode 100644 (file)
index 0000000..1ca1885
--- /dev/null
@@ -0,0 +1,51 @@
+// $Id$
+//
+// 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 inline non-template implementation */
+
+//#include "TLVPacket.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p////////////////////////////////////////
+
+prefix_ senf::DynamicTLVLengthParser::size_type senf::DynamicTLVLengthParser::bytes() const 
+{
+    return 1 + ( length_field()<=128 ? 0 : fixed_length_field());
+}
+
+
+///////////////////////////////cci.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 efae0f6..41276ad 100644 (file)
@@ -33,7 +33,7 @@
 template <class ForwardReadableRange>
 prefix_ void senf::GenericTLVPacketParser::value(ForwardReadableRange const &range)
 {
-    safe_data_iterator si = resizeValue( boost::size(range) );   
+    safe_data_iterator si = resizeValueField( boost::size(range) );   
     std::copy( boost::begin(range), boost::end(range), si);
 }
 
index 4c1a588..ac2ece4 100644 (file)
@@ -62,8 +62,11 @@ namespace senf {
         void init() const;
 
 #       include SENF_PARSER()
+        SENF_PARSER_PRIVATE_FIELD ( length_field, UInt8Parser );
+        SENF_PARSER_GOTO( length_field );
         SENF_PARSER_PRIVATE_BITFIELD ( extended_length_flag, 1,  bool     );
-        SENF_PARSER_PRIVATE_BITFIELD ( fixed_length_field,   7,  unsigned );
+        SENF_PARSER_PRIVATE_BITFIELD ( underflow_flag,       1,  bool     );
+        SENF_PARSER_PRIVATE_BITFIELD ( fixed_length_field,   6,  unsigned );
 
         void shrink();
         void maxValue(DynamicTLVLengthParser::value_type v);
@@ -138,7 +141,7 @@ namespace senf {
         /// set length field to given value
         void length(DynamicTLVLengthParser::value_type &v) { length_() = v; };
         /// resize the Packet after the length field to given size
-        senf::safe_data_iterator resizeValue(DynamicTLVLengthParser::value_type size);
+        senf::safe_data_iterator resizeValueField(DynamicTLVLengthParser::value_type size);
     };
 
         
@@ -200,7 +203,7 @@ namespace senf {
 
 
 ///////////////////////////////hh.e////////////////////////////////////////
-//#include "TLVPacket.cci"
+#include "TLVPacket.cci"
 #include "TLVPacket.ct"
 //#include "TLVPacket.cti"
 #endif
index 8dc8df2..4e5af46 100644 (file)
@@ -40,18 +40,18 @@ using namespace senf;
 
 namespace {
 
-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(), int(length) );
-    std::ostringstream oss (std::ostringstream::out);
-    SENF_CHECK_NO_THROW( tlvPacket.dump( oss));
-    senf::PacketData::iterator dataIterator (tlvPacket->value().begin());
-    for (unsigned i=0; i<length; i++) {
-        BOOST_CHECK_EQUAL( *dataIterator, i );
-        dataIterator++;
-    }
+#define CHECK_TLVPacket(tlvPacket, ptype, plength)                            \
+{                                                                             \
+    BOOST_CHECK_EQUAL( tlvPacket->type(),         ptype   );                  \
+    BOOST_CHECK_EQUAL( tlvPacket->length(),       plength );                  \
+    BOOST_CHECK_EQUAL( tlvPacket->value().size(), int(plength) );             \
+    std::ostringstream oss (std::ostringstream::out);                         \
+    SENF_CHECK_NO_THROW( tlvPacket.dump( oss));                               \
+    senf::PacketData::iterator dataIterator (tlvPacket->value().begin());     \
+    for (unsigned i=0; i<plength; i++) {                                      \
+        BOOST_CHECK_EQUAL( *dataIterator, i );                                \
+        dataIterator++;                                                       \
+    }                                                                         \
 }
 }
 
@@ -64,7 +64,7 @@ BOOST_AUTO_UNIT_TEST(GenericTLVPacket_parse_packet_with_simple_length)
         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 // value
     };
     GenericTLVPacket tlvPacket (GenericTLVPacket::create(data));
-    check_TLVPacket( tlvPacket, 0x01, 0x0Au );
+    CHECK_TLVPacket( tlvPacket, 0x01, 0x0Au );
 }
 
 
@@ -73,11 +73,24 @@ BOOST_AUTO_UNIT_TEST(GenericTLVPacket_parse_packet_with_extended_length)
     unsigned char data[] = {
         0x01, // type
         0x81, // first and last bit set => one byte length following
-        0x0A, // length (10 bytes value)
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 // value
+        0x0A, // length (10 = 138 bytes value follows)
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
+        0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 
+        0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+        0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
+        0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 
+        0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+        0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 
+        0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
+        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 
+        0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 
+        0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
+        0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
+        0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 
+        0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89
     };
     GenericTLVPacket tlvPacket (GenericTLVPacket::create(data));
-    check_TLVPacket( tlvPacket, 0x01, 0x0Au );
+    CHECK_TLVPacket( tlvPacket, 0x01, 0x8au );
 }
 
 
@@ -91,7 +104,7 @@ BOOST_AUTO_UNIT_TEST(GenericTLVPacket_create_packet_with_simple_length)
     tlvPacket->value( value);
     tlvPacket.finalizeThis();
 
-    check_TLVPacket( tlvPacket, 42u, 0x0Au );
+    CHECK_TLVPacket( tlvPacket, 42u, 0x0Au );
 
     unsigned char data[] = {
         0x2a, // type
@@ -109,16 +122,16 @@ BOOST_AUTO_UNIT_TEST(GenericTLVPacket_create_packet_with_extended_length)
         value[i] = i;
     GenericTLVPacket tlvPacket (GenericTLVPacket::create());
     tlvPacket->maxLengthValue( DynamicTLVLengthParser::max_value);
-    tlvPacket->type() = 42u;
-    tlvPacket->value( value);
-    tlvPacket.finalizeThis();
+    SENF_CHECK_NO_THROW( tlvPacket->type() = 42u);
+    SENF_CHECK_NO_THROW( tlvPacket->value( value));
+    SENF_CHECK_NO_THROW( tlvPacket.finalizeThis());
 
-    check_TLVPacket( tlvPacket, 42u, sizeof(value) );
+    CHECK_TLVPacket( tlvPacket, 42u, sizeof(value) );
 
     unsigned char data[] = {
         0x2a, // type
         0x81, // first and last bit set => one byte length following
-        0xff, // length (255 bytes value)
+        0x7f, // length (127 = 255 bytes value)
         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 // first bytes of value
     };
     BOOST_CHECK( equal(
@@ -142,7 +155,7 @@ BOOST_AUTO_UNIT_TEST(GenericTLVPacket_create_invalid_packet)
     tlvPacket->maxLengthValue( sizeof(value));
     tlvPacket->value( value);
     tlvPacket.finalizeThis();
-    check_TLVPacket( tlvPacket, 42u, sizeof(value) );
+    CHECK_TLVPacket( tlvPacket, 42u, sizeof(value) );
 }