Utils: Implement IpChecksum helper class
g0dil [Mon, 8 Oct 2007 09:35:33 +0000 (09:35 +0000)]
Packets: Implemnet generic assignment of boost::optional's to parsers
Packets: Fix <n>_offset field definition in BOOST_PACKET_PARSER_DEFINE_FIELDS
Packets: Implement PacketTypeMixin::key() helper
Packets: Clarify documentation regiarding valid()/in-valid() packets
Packets/DefaultBundle: Implement EthernetPacket, EthVLanPacket and IpV4Packet's finalize()

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@456 270642c3-0616-0410-b53a-bc976706d245

17 files changed:
Packets/DefaultBundle/EthernetPacket.cc
Packets/DefaultBundle/EthernetPacket.hh
Packets/DefaultBundle/EthernetPacket.test.cc
Packets/DefaultBundle/IpV4Packet.cc
Packets/DefaultBundle/IpV4Packet.hh
Packets/DefaultBundle/IpV4Packet.test.cc
Packets/Packet.hh
Packets/PacketParser.cti
Packets/PacketParser.hh
Packets/PacketParser.mpp
Packets/PacketType.cti
Packets/PacketType.hh
SConstruct
Utils/IpChecksum.cci [new file with mode: 0644]
Utils/IpChecksum.cti [new file with mode: 0644]
Utils/IpChecksum.hh [new file with mode: 0644]
Utils/IpChecksum.test.cc [new file with mode: 0644]

index 937f219..907d4bf 100644 (file)
@@ -53,10 +53,15 @@ prefix_ void senf::EthernetPacketType::dump(packet p, std::ostream & os)
     os << ": \n"
        << "  destination   : " << p->destination() << "\n"
        << "  source        : " << p->source() << "\n"
-       << "  ethertype     : " 
+       << "  ethertype     : 0x" 
        << std::hex << std::setw(4) << std::setfill('0') << p->type() << "\n";
 }
 
+prefix_ void senf::EthernetPacketType::finalize(packet p)
+{
+    p->type() << key(p.next());
+}
+
 prefix_ void senf::EthVLanPacketType::dump(packet p, std::ostream & os)
 {
     boost::io::ios_all_saver ias(os);
@@ -64,10 +69,15 @@ prefix_ void senf::EthVLanPacketType::dump(packet p, std::ostream & os)
        << "  priority      : " << p->priority() << "\n"
        << "  cfi           : " << p->cfi() << "\n"
        << "  vlan-ID       : " << p->vlanId() << "\n"
-       << "  ethertype     : " 
+       << "  ethertype     : 0x" 
        << std::hex << std::setw(4) << std::setfill('0') << p->type() << "\n";
 }
 
+prefix_ void senf::EthVLanPacketType::finalize(packet p)
+{
+    p->type() << key(p.next());
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 18f37a9..359f05d 100644 (file)
@@ -132,6 +132,7 @@ namespace senf {
             { return p->type(); }
 
         static void dump(packet p, std::ostream & os);
+        static void finalize(packet p);
     };
 
     /** \brief Ethernet packet typedef */
@@ -202,6 +203,7 @@ namespace senf {
             { return p->type(); }
 
         static void dump(packet p, std::ostream & os);
+        static void finalize(packet p);
     };
 
     /** \brief Ethernet VLAN tag typedef */
index 48f5500..397f6f5 100644 (file)
@@ -27,6 +27,7 @@
 
 // Custom includes
 #include "EthernetPacket.hh"
+#include "IpV4Packet.hh"
 
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/test_tools.hpp>
@@ -68,6 +69,26 @@ BOOST_AUTO_UNIT_TEST(ethernetPacket_chain)
     BOOST_CHECK_EQUAL( *v.next().data().begin(), 0xf0 );
 }
 
+BOOST_AUTO_UNIT_TEST(ethernetPacket_create)
+{
+    senf::EthernetPacket eth (senf::EthernetPacket::create());
+    eth->source() = senf::MACAddress::from_string("01:02:03:04:05:06");
+    eth->destination() = senf::MACAddress::from_string("07:08:09:0a:0b:0c");
+    
+    senf::EthVLanPacket vlan (senf::EthVLanPacket::createAfter(eth));
+    vlan->priority() = 9u;
+    vlan->cfi() = true;
+    vlan->vlanId() = 0x234u;
+
+    eth.finalize();
+    BOOST_CHECK_EQUAL(eth->type(), 0x8100u);
+    BOOST_CHECK_EQUAL(vlan->type(), 0u);
+
+    senf::IpV4Packet ip (senf::IpV4Packet::createAfter(vlan));
+    eth.finalize();
+    BOOST_CHECK_EQUAL(vlan->type(), 0x0800u);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index b88987b..8c55752 100644 (file)
 //#include "IpV4Packet.ih"
 
 // Custom includes
+#include <iomanip>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <boost/io/ios_state.hpp>
+#include "../../Utils/IpChecksum.hh"
 #include "EthernetPacket.hh"
 
 #define prefix_
@@ -43,8 +46,27 @@ namespace {
         regsiterIpV4Packet2 (4); // IP-in-IP encapsulation
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::Parse_IpV4
+
+prefix_ boost::uint16_t senf::Parse_IpV4::calcChecksum()
+    const
+{
+    IpChecksum summer;
+    summer.feed( i(),                   i()+checksum_offset );
+    // Not needed since the number of 0-bytes is even
+    // summer.feed( 0u );
+    // summer.feed( 0u );
+    summer.feed( i()+checksum_offset+2, i()+bytes(*this)    );
+    return summer.sum();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::IpV4PacketType
+
 prefix_ void senf::IpV4PacketType::dump(packet p, std::ostream & os)
 {
+    boost::io::ios_all_saver ias(os);
     os << "Internet protocol Version 4:\n"
        << "  version       : " << p->version() << "\n"
        << "  IHL           : " << p->ihl() << "\n"
@@ -56,11 +78,19 @@ prefix_ void senf::IpV4PacketType::dump(packet p, std::ostream & os)
        << "  fragment      : " << p->frag() << "\n"
        << "  TTL           : " << unsigned(p->ttl()) << "\n"
        << "  protocol      : " << unsigned(p->protocol()) << "\n"
-       << "  CRC           : " << std::hex << p->crc() << std::dec << "\n"
+       << "  checksum      : 0x" 
+         << std::hex << std::setw(4) << std::setfill('0') << p->checksum() << std::dec << "\n"
        << "  source        : " << p->source() << "\n"
        << "  destination   : " << p->destination() << "\n";
 }
 
+prefix_ void senf::IpV4PacketType::finalize(packet p)
+{
+    p->length()   << p.size();
+    p->protocol() << key(p.next());
+    p->checksum() << p->calcChecksum();
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 5fc143e..855f957 100644 (file)
@@ -94,7 +94,7 @@ namespace senf {
             ((Field       )( frag,        Parse_Frag    ))
             ((Field       )( ttl,         Parse_8bit    ))
             ((Field       )( protocol,    Parse_8bit    ))
-            ((Field       )( crc,         Parse_16bit   ))
+            ((Field       )( checksum,    Parse_16bit   ))
             ((Field       )( source,      Parse_Addr    ))
             ((Field       )( destination, Parse_Addr    )) );
 
@@ -111,7 +111,7 @@ namespace senf {
         Parse_Frag    frag() const;
         Parse_8bit    ttl() const;
         Parse_8bit    protocol() const;
-        Parse_16bit   crc() const;
+        Parse_16bit   checksum() const;
         Parse_Addr    source() const;
         Parse_Addr    destination() const;
 
@@ -119,6 +119,13 @@ namespace senf {
 
         void init() {
             version() = 4;
+            // We don't support option headers at the moment ...
+            ihl() = 5;
+        }
+        
+        boost::uint16_t calcChecksum() const;
+        bool validateChecksum() const {
+            return checksum() == calcChecksum();
         }
     };
 
@@ -163,6 +170,7 @@ namespace senf {
             { return p->protocol(); }
 
         static void dump(packet p, std::ostream & os);
+        static void finalize(packet p);
     };
         
     /** \brief IpV4 packet typedef */
index 9cc976b..eee06a1 100644 (file)
@@ -27,6 +27,7 @@
 
 // Custom includes
 #include "IpV4Packet.hh"
+#include "UDPPacket.hh"
 
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/test_tools.hpp>
@@ -59,11 +60,35 @@ BOOST_AUTO_UNIT_TEST(ipV4Packet_packet)
     BOOST_CHECK_EQUAL( p->frag(),        0x0708u     );
     BOOST_CHECK_EQUAL( p->ttl(),         0x09u       );
     BOOST_CHECK_EQUAL( p->protocol(),    0x0Au       );
-    BOOST_CHECK_EQUAL( p->crc(),         0x0B0Cu     );
+    BOOST_CHECK_EQUAL( p->checksum(),    0x0B0Cu     );
     BOOST_CHECK_EQUAL( p->source().value(), senf::INet4Address(0x11121314u) );
     BOOST_CHECK_EQUAL( p->destination().value(), senf::INet4Address(0x15161718u) );
 }
 
+BOOST_AUTO_UNIT_TEST(ipV4Packet_create)
+{
+    senf::IpV4Packet ip (senf::IpV4Packet::create());
+
+    BOOST_CHECK_EQUAL( ip->version(), 4u );
+    BOOST_CHECK_EQUAL( ip->ihl(), 5u );
+    BOOST_CHECK_EQUAL( ip.size(), 20u );
+
+    senf::UDPPacket udp (senf::UDPPacket::createAfter(ip));
+
+    BOOST_CHECK( ! ip->validateChecksum() );
+
+    ip.finalize();
+    BOOST_CHECK_EQUAL( ip->length(), 28u );
+    BOOST_CHECK_EQUAL( ip->protocol(), 17u );
+    BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
+
+    // Check, that the checksum field is correctly skipped
+    ip.finalize();
+    BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
+
+    BOOST_CHECK( ip->validateChecksum() );
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 8f8dad5..206b8c8 100644 (file)
@@ -184,6 +184,8 @@ namespace senf {
 
                                      Packet      next() const; 
                                         ///< Get next packet in chain
+                                        /**< \returns in - valid() packet, if no next packet 
+                                             exists */
         template <class OtherPacket> OtherPacket next() const; 
                                         ///< Get next packet of given type in chain
                                         /**< \throws InvalidPacketChainException if no such packet
@@ -192,7 +194,8 @@ namespace senf {
                                         ///< Get next packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
         template <class OtherPacket> OtherPacket findNext() const;
                                         ///< Find next packet of given type in chain
                                         /**< findNext() is like next(), it will however return \c
@@ -205,11 +208,14 @@ namespace senf {
                                              *this if it is of the given type.
                                              \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
         
 
                                      Packet      prev() const; 
                                         ///< Get previous packet in chain
+                                        /**< \returns in - valid() packet, if no previous packet 
+                                             exists */
         template <class OtherPacket> OtherPacket prev() const; 
                                         ///< Get previous packet of given type in chain
                                         /**< \throws InvalidPacketChainException if no such packet
@@ -218,7 +224,8 @@ namespace senf {
                                         ///< Get previous packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
         template <class OtherPacket> OtherPacket findPrev() const;
                                         ///< Find previous packet of given type in chain
                                         /**< findPrev() is like prev(), it will however return \c
@@ -231,7 +238,8 @@ namespace senf {
                                              *this if it is of the type 
                                              \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
 
 
                                      Packet      first() const;
@@ -244,7 +252,8 @@ namespace senf {
                                         ///< Return first packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
 
                                      Packet      last() const;
                                         ///< Return last packet in chain
@@ -256,7 +265,8 @@ namespace senf {
                                         ///< Return last packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
 
 
         template <class OtherPacket> OtherPacket parseNextAs() const;
@@ -321,10 +331,12 @@ namespace senf {
         bool boolean_test() const;      ///< Check, whether the packet is valid()
                                         /**< \see valid() */
         bool valid() const;             ///< Check, whether the packet is valid()
-                                        /**< An in-valid() packet does not allow any operation
-                                             except checking for validity and assignment. in-valid()
-                                             packets serve the same role as 0-pointers. */
-        
+                                        /**< An in - valid() packet does not allow any operation
+                                             except checking for validity and assignment. in -
+                                             valid() packets serve the same role as 0-pointers. 
+                                             
+                                             This is an alias for boolean_test() which is called
+                                             when using a packet in a boolean context. */
 
         void finalize() const;          ///< Update calculated fields
                                         /**< This call will update all calculated fields of the
index 7413037..28b71c2 100644 (file)
@@ -75,6 +75,24 @@ prefix_ Parser senf::operator<<(Parser target, Value const & value)
 {}
 #endif
 
+#ifndef DOXYGEN
+template <class Parser, class Value>
+prefix_ typename boost::enable_if_c < 
+        boost::is_base_of<senf::PacketParserBase, Parser>::value 
+            && ! boost::is_base_of<senf::PacketParserBase, Value>::value,
+        Parser >::type senf::operator<<(Parser target, boost::optional<Value> const & value)
+{
+    if (value)
+        target.value(*value);
+    return target;
+}
+#else
+template <class Parser, class Value>
+prefix_ Parser senf::operator<<(Parser target, Value const & value)
+{}
+#endif
+
+
 template <class Parser>
 prefix_ senf::PacketParserBase::size_type
 senf::detail::packetParserSize(Parser p, int, senf::mpl::take_uint<Parser::fixed_bytes> *)
index 6871d1d..c6a38e8 100644 (file)
@@ -370,6 +370,7 @@ namespace senf {
 #   else
     /** \brief Generic parser copying
 
+
         This operator allows to copy the values of identical parsers. This operation does \e not
         depend on the parsers detailed implementation, it will just replace the data bytes of the
         target parser with those from the source parser. This allows to easily copy around complex
@@ -404,6 +405,28 @@ namespace senf {
     Parser operator<<(Parser target, Value const & value);
 #   endif
 
+#   ifndef DOXYGEN
+    template <class Parser, class Value>
+    typename boost::enable_if_c < 
+        boost::is_base_of<PacketParserBase, Parser>::value 
+            && ! boost::is_base_of<PacketParserBase, Value>::value,
+        Parser >::type
+    operator<<(Parser target, boost::optional<Value> const & value);
+#   else 
+    /** \brief Generic parser value assignment
+
+        This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
+        value<tt>)</tt> member. This special version allows to assign optional values: IF the
+        optional value is not set, the assignment will be skipped. 
+
+        This operator allows to use a common syntax for assigning values or parsers to a parser.
+
+        \ingroup packetparser
+     */
+    template <class Parser, class Value>
+    Parser operator<<(Parser target, boost::optional<Value> const & value);
+#   endif
+
     /** \defgroup packetparsermacros Helper macros for defining new packet parsers
         
         To simplify the definition of simple packet parsers, several macros are provided. Before
index d445ebf..c9c112e 100644 (file)
          return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () + senf::bytes( name () );              \
      }                                                                                            \
      size_type BOOST_PP_CAT(name, _offset) () const {                                             \
-         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) () ;                        \
+         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () ;                                      \
      }
 # 
 # define SENF_PACKET_PARSER_I_FIXED_Field(n,name,type)                                            \
      static const size_type BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) =               \
          BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) + type::fixed_bytes;                             \
      static const size_type BOOST_PP_CAT(name,_offset) =                                          \
-         BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_));
+         BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));
 # 
 # define SENF_PACKET_PARSER_I_OverlayField(n,name,type)                                           \
      typedef type BOOST_PP_CAT(name,_t) ;                                                         \
          return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) ();                                       \
      }                                                                                            \
      size_type BOOST_PP_CAT(name, _offset) () const {                                             \
-         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) () ;                        \
+         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () ;                        \
      }
 # 
 # define SENF_PACKET_PARSER_I_FIXED_OverlayField(n,name,type)                                     \
      static const size_type BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) =               \
          BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));                                                 \
      static const size_type BOOST_PP_CAT(name,_offset) =                                          \
-         BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_));
+         BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));
 # 
 # ///////////////////////////////mpp.e///////////////////////////////////////
 # endif
index 4f01389..e79d6b8 100644 (file)
@@ -73,6 +73,13 @@ prefix_ void senf::PacketTypeMixin<Self,Registry>::init(Packet p)
     p.as< ConcretePacket<Self> >()->init();
 }
 
+template <class Self, class Registry>
+prefix_ typename senf::PacketTypeMixin<Self,Registry>::optional_registry_key_t
+senf::PacketTypeMixin<Self,Registry>::key(Packet p)
+{
+    return p ? PacketRegistry<Registry>::key(p, nothrow) : optional_registry_key_t();
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::PacketTypeMixin<Self,void>
 
index 7146d08..53c17c1 100644 (file)
@@ -271,6 +271,11 @@ namespace senf {
 
             static void finalize(packet p)
             {
+                // Set the type field by querying the type of the next packet. This is an 
+                // optional assignment: If the key is not found, the value returned by 'key'
+                // is an empty optional and the assignment will be skipped.
+                p->typeField << key(p.next());
+
                 // optionally complete the packet by generating auto-generated information
                 // (like checksums)
             }
@@ -300,7 +305,7 @@ namespace senf {
             using mixin::init;         
 
             static registry_key_t nextPacketKey(packet p)
-            { return i.fields().typeField(); }
+            { return p->typeField(); }
         };
         \endcode
 
@@ -314,11 +319,30 @@ namespace senf {
     {
     public:
         typedef typename Registry::key_t registry_key_t;
+        typedef boost::optional<registry_key_t> optional_registry_key_t;
+
+        static optional_registry_key_t key (Packet p); ///< Find key of packet from registry
+                                        /**< key() will query the registry to find the key of the
+                                             given packet. Whereas \c nextPacketKey() as implemented
+                                             by the mixin user will provide the registry key of the
+                                             next packet from information stored in the current
+                                             packets header, the key() member will look up the type
+                                             of packet \a p in the registry and return it's
+                                             key. 
+                                             
+                                             If either \a p is an in - valid() packet or the packet
+                                             type is not found in the registry, the returned
+                                             optional value will be empty. */
+
+        ///@{
+        ///\name PacketType interface implementation
 
         static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
         static PacketInterpreterBase::factory_t      nextPacketType  (Packet p);
         static PacketInterpreterBase::size_type      initSize        ();
         static void                                  init            (Packet p);
+        
+        ///@}
     };
 
 #   ifndef DOXYGEN
index 5fd8c88..9870f20 100644 (file)
@@ -41,12 +41,16 @@ def nonemptyFile(f):
 def checkLocalConf(target, source, env):
     if [ True for f in env['CONFIG_FILES'] if nonemptyFile(f) ]:
         print
-        print "You have made local modifications to 'SConfig' and/or 'Doxyfile.local'."
+        print "You have made local modifications to one of the following local configuration"
+        print "files:"
+        for f in env['CONFIG_FILES']:
+            print "    ",f
+        print
         print "Building a debian package would remove those files."
         print
         print "To continue, remove the offending file(s) and try again. Alternatively,"
         print "build a source package using 'scons debsrc' and may then build debian"
-        print "binary packages from this source-package without disrupting your print local"
+        print "binary packages from this source-package without disrupting your local"
         print "configuration."
         print
         return 1
@@ -172,7 +176,7 @@ PhonyTarget(env, 'debbin', [
 
 PhonyTarget(env, 'linklint', [
     'rm -rf linklint',
-    'linklint -doc linklint -net -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
+    'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
     '[ ! -r linklint/errorX.html ] || python linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
     '[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
     '[ ! -r linklint/errorAX.html ] || python linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
diff --git a/Utils/IpChecksum.cci b/Utils/IpChecksum.cci
new file mode 100644 (file)
index 0000000..300b097
--- /dev/null
@@ -0,0 +1,62 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@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 IpChecksum inline non-template implementation */
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::IpChecksum::IpChecksum()
+    : sum_(0), odd_(false)
+{}
+
+prefix_ void senf::IpChecksum::feed(boost::uint8_t byte)
+{
+    sum_ += odd_ ? byte : (byte<<8);
+    odd_ = ! odd_;
+}
+
+prefix_ boost::uint16_t senf::IpChecksum::sum()
+    const
+{
+    boost::uint32_t v (sum_);
+    while (v >> 16)
+        v = (v & 0xffff) + (v >> 16);
+    return ~ v;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/IpChecksum.cti b/Utils/IpChecksum.cti
new file mode 100644 (file)
index 0000000..5d9ca90
--- /dev/null
@@ -0,0 +1,52 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@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 IpChecksum inline template implementation */
+
+//#include "IpChecksum.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class InputIterator>
+prefix_ void senf::IpChecksum::feed(InputIterator b, InputIterator e)
+{
+    for (; b != e; ++b)
+        feed(*b);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/IpChecksum.hh b/Utils/IpChecksum.hh
new file mode 100644 (file)
index 0000000..7efb55d
--- /dev/null
@@ -0,0 +1,86 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@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 IpChecksum public header */
+
+#ifndef HH_IpChecksum_
+#define HH_IpChecksum_ 1
+
+// Custom includes
+#include <boost/cstdint.hpp>
+
+//#include "IpChecksum.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+    
+    /** \brief
+      */
+    class IpChecksum
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        IpChecksum();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void feed(boost::uint8_t byte);
+
+        template <class InputIterator>
+        void feed(InputIterator b, InputIterator e);
+
+        boost::uint16_t sum() const;
+    
+    protected:
+
+    private:
+        boost::uint32_t sum_;
+        bool odd_;
+    };
+
+    
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "IpChecksum.cci"
+//#include "IpChecksum.ct"
+#include "IpChecksum.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/IpChecksum.test.cc b/Utils/IpChecksum.test.cc
new file mode 100644 (file)
index 0000000..24319d0
--- /dev/null
@@ -0,0 +1,62 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@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 IpChecksum.test unit tests */
+
+//#include "IpChecksum.test.hh"
+//#include "IpChecksum.test.ih"
+
+// Custom includes
+#include "IpChecksum.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(ipChecksum)
+{
+    char data[] = { 0x45, 0x00, 0x00, 0x28, 0x49, 0x44, 0x40, 0x00,
+                    0x40, 0x06, 0x00, 0x00, 0x0a, 0xc1, 0x01, 0x06,
+                    0xc2, 0x9f, 0xa4, 0xc3 };
+
+    senf::IpChecksum summer;
+    summer.feed(data, data+sizeof(data));
+    BOOST_CHECK_EQUAL( summer.sum(), 0x7e62u );
+}
+
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End: