Packets/80221Bundle: extended MIHMessageType / MIHMessageRegistry to validate MIH...
tho [Mon, 10 Jan 2011 16:58:02 +0000 (16:58 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1758 270642c3-0616-0410-b53a-bc976706d245

senf/Packets/80221Bundle/MIHMessageRegistry.cc [new file with mode: 0644]
senf/Packets/80221Bundle/MIHMessageRegistry.ct [new file with mode: 0644]
senf/Packets/80221Bundle/MIHMessageRegistry.hh
senf/Packets/80221Bundle/MIHMessageRegistry.test.cc [new file with mode: 0644]
senf/Packets/80221Bundle/MIHPacket.cc
senf/Packets/80221Bundle/MIHPacket.hh
senf/Packets/80221Bundle/TLVParser.cc
senf/Packets/80221Bundle/TLVParser.hh
senf/Packets/PacketRegistry.hh
senf/Packets/PacketRegistry.ih

diff --git a/senf/Packets/80221Bundle/MIHMessageRegistry.cc b/senf/Packets/80221Bundle/MIHMessageRegistry.cc
new file mode 100644 (file)
index 0000000..61fcb1e
--- /dev/null
@@ -0,0 +1,63 @@
+// $Id$
+//
+// Copyright (C) 2011
+// 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 MIH Message-Registry non-inline non-template implementation */
+
+#include "MIHMessageRegistry.hh"
+//#include "MIHMessageRegistry.ih"
+
+// Custom includes
+
+#define prefix_
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
+// senf::MIHMessageRegistry
+
+#if BOOST_VERSION < 103400
+#   define PTRMAP_GET_CONTENTS(v) (v)
+#else
+#   define PTRMAP_GET_CONTENTS(v) (*(v).second)
+#endif
+
+prefix_ std::pair<bool, std::string> senf::MIHMessageRegistry::validate(key_t messageId, senf::Packet message)
+{
+    Map::const_iterator i (map_.find( messageId));
+    if (i != map_.end())
+        return PTRMAP_GET_CONTENTS(*i).validate( message);
+    return std::make_pair(true, "");
+}
+
+#undef PTRMAP_GET_CONTENTS
+
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
+#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:
diff --git a/senf/Packets/80221Bundle/MIHMessageRegistry.ct b/senf/Packets/80221Bundle/MIHMessageRegistry.ct
new file mode 100644 (file)
index 0000000..4acf800
--- /dev/null
@@ -0,0 +1,57 @@
+// $Id$
+//
+// Copyright (C) 2011
+// 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 MIH Message-Registry non-inline template implementation */
+
+// Custom includes
+
+#define prefix_
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
+// senf::MIHMessageRegistry
+
+template <typename MIHPacket>
+prefix_ void senf::MIHMessageRegistry::registerMessageType()
+{
+    key_t key (MIHPacket::type::MESSAGE_ID+0);
+    map_.insert(key, new detail::MIHMessageRegistryEntry<MIHPacket>() );
+}
+
+template <typename MIHPacket>
+prefix_ senf::MIHMessageRegistry::RegistrationProxy<MIHPacket>::RegistrationProxy()
+{
+    MIHMessageRegistry::instance().registerMessageType<MIHPacket>();
+}
+
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
+#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:
index 8db289e..cf125d6 100644 (file)
@@ -1,6 +1,6 @@
 // $Id$
 //
-// Copyright (C) 2009
+// Copyright (C) 2010
 // Fraunhofer Institute for Open Communication Systems (FOKUS)
 // Competence Center NETwork research (NET), St. Augustin, GERMANY
 //     Thorsten Horstmann <tho@berlios.de>
 #define HH_SENF_Packets_80221Bundle_MIHMessageRegistry_ 1
 
 // Custom includes
+#include <boost/ptr_container/ptr_map.hpp>
+#include <senf/Utils/singleton.hh>
 #include <senf/Packets/Packets.hh>
 
-//#include "MIHPacket.mpp"
+//#include "MIHMessageRegistry.mpp"
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace senf {
 
-    struct MIHMessageRegistry {
-        // MIH messages registry
+    namespace detail {
+
+        template<class T, typename Signature>
+        struct has_static_validate_member
+        {
+            template<Signature *>
+            struct helper;
+
+            template<class U>
+            static char test(helper<&U::validate> *);
+
+            template<class U>
+            static char (&test(...))[2];
+
+            static const bool value = sizeof(test<T>(0))==1;
+        };
+
+        struct MIHMessageRegistry_EntryBase {
+            virtual ~MIHMessageRegistry_EntryBase() {}
+            virtual std::pair<bool, std::string> validate(senf::Packet message) const = 0;
+        };
+
+        template <class MIHPacket,
+            bool use_validate_member = has_static_validate_member<typename MIHPacket::type, std::pair<bool, std::string>(MIHPacket)>::value>
+        struct MIHMessageRegistryEntry : MIHMessageRegistry_EntryBase
+        {
+            virtual std::pair<bool, std::string> validate(senf::Packet message) const {
+                return std::make_pair(true, "");
+            }
+        };
+
+        template <class MIHPacket>
+        struct MIHMessageRegistryEntry<MIHPacket, true> : MIHMessageRegistry_EntryBase
+        {
+            virtual std::pair<bool, std::string> validate(senf::Packet message) const {
+                return MIHPacket::type::validate(message.as<MIHPacket>());
+            }
+        };
+    }
+
+
+    class MIHMessageRegistry
+        : public senf::singleton<MIHMessageRegistry>
+    {
+    public:
         typedef boost::uint16_t key_t;
+
+        using senf::singleton<MIHMessageRegistry>::instance;
+        friend class senf::singleton<MIHMessageRegistry>;
+
+        template <typename MIHPacket>
+        struct RegistrationProxy {
+            RegistrationProxy();
+        };
+
+        template <typename MIHPacket>
+        void registerMessageType();
+
+        std::pair<bool, std::string> validate(key_t messageId, senf::Packet message);
+
+    private:
+        typedef boost::ptr_map<key_t, detail::MIHMessageRegistry_EntryBase > Map;
+        Map map_;
+
+        MIHMessageRegistry() {};
     };
 
-#   define SENF_MIH_PACKET_REGISTRY_REGISTER( packet )                    \
-        SENF_PACKET_REGISTRY_REGISTER(                                    \
-            senf::MIHMessageRegistry, packet::type::MESSAGE_ID, packet )
+
+#   define SENF_MIH_PACKET_REGISTRY_REGISTER( packet )                      \
+        SENF_PACKET_REGISTRY_REGISTER(                                      \
+            senf::MIHMessageRegistry, packet::type::MESSAGE_ID, packet )    \
+        namespace {                                                         \
+            senf::MIHMessageRegistry::RegistrationProxy< packet >           \
+            BOOST_PP_CAT(mihPacketRegistration_, __LINE__);                 \
+        }
 
 }
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
-//#include "MIHPacket.cci"
-//#include "MIHPacket.ct"
-//#include "MIHPacket.cti"
+//#include "MIHMessageRegistry.cci"
+#include "MIHMessageRegistry.ct"
+//#include "MIHMessageRegistry.cti"
 #endif
 
 
diff --git a/senf/Packets/80221Bundle/MIHMessageRegistry.test.cc b/senf/Packets/80221Bundle/MIHMessageRegistry.test.cc
new file mode 100644 (file)
index 0000000..fa8dd62
--- /dev/null
@@ -0,0 +1,134 @@
+// $Id$
+//
+// Copyright (C) 2011
+// 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 MIH Message-Registry unit tests */
+
+//#include "MIHPacket.test.hh"
+//#include "MIHPacket.test.ih"
+
+// Custom includes
+#include "MIHMessageRegistry.hh"
+#include "MIHPacket.hh"
+
+#include <senf/Utils/auto_unit_test.hh>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
+using namespace senf;
+
+namespace {
+
+    class TestMessagePacketParser
+        : public senf::PacketParserBase
+    {
+    #   include SENF_PARSER()
+        SENF_PARSER_FIELD ( registerRequestCodeTLV, senf::MIHRegisterReqCodeTLVParser );
+        SENF_PARSER_FINALIZE ( TestMessagePacketParser );
+    };
+
+
+    struct TestMessagePacketType
+        : public senf::PacketTypeBase,
+          public senf::PacketTypeMixin<TestMessagePacketType>
+    {
+        typedef senf::ConcretePacket<TestMessagePacketType> packet;
+        typedef senf::PacketTypeMixin<TestMessagePacketType> mixin;
+        typedef TestMessagePacketParser parser;
+
+        using mixin::nextPacketRange;
+        using mixin::init;
+        using mixin::initSize;
+
+        static const boost::uint16_t MESSAGE_ID;
+    };
+
+    struct ValidatedTestMessagePacketType
+        : public senf::PacketTypeBase,
+          public senf::PacketTypeMixin<ValidatedTestMessagePacketType>
+    {
+        typedef senf::ConcretePacket<ValidatedTestMessagePacketType> packet;
+        typedef senf::PacketTypeMixin<ValidatedTestMessagePacketType> mixin;
+        typedef TestMessagePacketParser parser;
+
+        using mixin::nextPacketRange;
+        using mixin::init;
+        using mixin::initSize;
+
+        static const boost::uint16_t MESSAGE_ID;
+
+        static std::pair<bool, std::string> validate(packet message) {
+            return std::make_pair(message->registerRequestCodeTLV().value() == 1, "");
+        }
+    };
+
+    typedef senf::ConcretePacket<TestMessagePacketType> TestMessagePacket;
+    typedef senf::ConcretePacket<ValidatedTestMessagePacketType> ValidatedTestMessagePacket;
+
+    const boost::uint16_t TestMessagePacketType::MESSAGE_ID = 42;
+    const boost::uint16_t ValidatedTestMessagePacketType::MESSAGE_ID = 43;
+
+    SENF_MIH_PACKET_REGISTRY_REGISTER( TestMessagePacket );
+    SENF_MIH_PACKET_REGISTRY_REGISTER( ValidatedTestMessagePacket );
+}
+
+
+SENF_AUTO_UNIT_TEST(MIHMessageRegistry_validate)
+{
+    MIHPacket mihPacket (MIHPacket::create());
+    mihPacket->transactionId() = 21;
+    mihPacket->src_mihfId().value( "senf@berlios.de");
+    mihPacket->dst_mihfId().value( "test");
+
+    BOOST_CHECK(! MIHPacketType::validate( mihPacket).first);
+
+    mihPacket.finalizeThis();
+    BOOST_CHECK( MIHPacketType::validate( mihPacket).first);
+
+    {
+        TestMessagePacket testMessage (TestMessagePacket::createAfter(mihPacket));
+        mihPacket.finalizeAll();
+        BOOST_CHECK( MIHPacketType::validate( mihPacket).first);
+    }
+    {
+        ValidatedTestMessagePacket testMessage (ValidatedTestMessagePacket::createAfter(mihPacket));
+        mihPacket.finalizeAll();
+        BOOST_CHECK(! MIHPacketType::validate( mihPacket).first);
+        testMessage->registerRequestCodeTLV().value() << 1;
+        BOOST_CHECK( MIHPacketType::validate( mihPacket).first);
+    }
+}
+
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
+#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 7046412..f4efbeb 100644 (file)
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include <boost/io/ios_state.hpp>
+#include <senf/Utils/String.hh>
 #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
 
 #define prefix_
@@ -77,6 +78,19 @@ prefix_ senf::PacketInterpreterBase::factory_t senf::MIHPacketType::nextPacketTy
     return e ? e->factory() : MIHGenericPayloadPacket::factory();
 }
 
+prefix_ std::pair<bool, std::string> senf::MIHPacketType::validate(packet p)
+{
+    if (p.data().size() < initSize())
+        return std::make_pair(false, "truncated MIH message");
+    if (p->version() != 1)
+        return std::make_pair(false, "invalid MIH version: " + senf::str(p->version()) );
+    if (p->payloadLength() != p.size()-8)
+        return std::make_pair(false, "wrong MIH length: " + senf::str(p->payloadLength()) );
+    if (p.next(senf::nothrow))
+        return MIHMessageRegistry::instance().validate( p->messageId(), p.next());
+    return std::make_pair(true, "");
+}
+
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // MIHGenericPayloadPacketType
 
index 8705a65..385b2ff 100644 (file)
@@ -97,9 +97,7 @@ namespace senf {
         : public PacketTypeBase,
           public PacketTypeMixin<MIHPacketType, MIHMessageRegistry>
     {
-#ifndef DOXYGEN
         typedef PacketTypeMixin<MIHPacketType, MIHMessageRegistry> mixin;
-#endif
         typedef ConcretePacket<MIHPacketType> packet; ///< MIH packet typedef
         typedef MIHPacketParser parser;               ///< typedef to the parser of MIH packet
 
@@ -111,6 +109,8 @@ namespace senf {
         static void dump(packet p, std::ostream &os);
         static void finalize(packet p);
         static factory_t nextPacketType(packet p);
+
+        static std::pair<bool, std::string> validate(packet p);
     };
 
     /** \brief MIH packet typedef
@@ -130,9 +130,7 @@ namespace senf {
         : public PacketTypeBase,
           public PacketTypeMixin<MIHGenericPayloadPacketType>
     {
-#ifndef DOXYGEN
         typedef PacketTypeMixin<MIHGenericPayloadPacketType> mixin;
-#endif
         typedef ConcretePacket<MIHGenericPayloadPacketType> packet; ///< MIH Payload packet typedef
         typedef MIHGenericPayloadPacketParser parser; ///< typedef to the parser of MIH Payload packet
 
index cf2e41d..ad14cb5 100644 (file)
@@ -30,6 +30,7 @@
 #include <iomanip>
 #include <senf/Utils/hexdump.hh>
 #include <senf/Utils/Format.hh>
+#include <senf/Utils/String.hh>
 
 #define prefix_
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -233,6 +234,14 @@ prefix_ void senf::MIHRegisterReqCodeTLVParser::dump(std::ostream & os)
     os << " (???; invalid value!)" << std::endl;
 }
 
+prefix_ std::pair<bool, std::string> senf::MIHRegisterReqCodeTLVParser::validate()
+    const
+{
+    if (length() != 1) return std::make_pair(false, "invalid length in MIHRegisterReqCodeTLV " + senf::str(length()));
+    if (value()  >= 2) return std::make_pair(false, "invalid value in MIHRegisterReqCodeTLV " + senf::str(value()));
+    return std::make_pair(true, "");
+}
+
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::MIHValidTimeIntervalTLVParser
 
@@ -248,6 +257,13 @@ prefix_ void senf::MIHValidTimeIntervalTLVParser::dump(std::ostream & os)
        << ( value()==0 ? " (infinite)" : " seconds") << std::endl;
 }
 
+prefix_ std::pair<bool, std::string> senf::MIHValidTimeIntervalTLVParser::validate()
+    const
+{
+    if (length() != 4) return std::make_pair(false, "invalid length in MIHValidTimeIntervalTLV " + senf::str(length()));
+    return std::make_pair(true, "");
+}
+
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::MIHTLVLengthParser
 
index 2c4fc7d..601207f 100644 (file)
@@ -343,6 +343,7 @@ namespace senf {
         }
         static type_t::value_type const typeId = 11;
         void dump(std::ostream & os) const; ///< dump string representation to given stream
+        std::pair<bool, std::string> validate() const;
 
         enum RequestCode { Registration, ReRegistration };
     };
@@ -361,6 +362,7 @@ namespace senf {
         }
         static type_t::value_type const typeId = 12;
         void dump(std::ostream & os) const; ///< dump string representation to given stream
+        std::pair<bool, std::string> validate() const;
     };
 
 }
index 491c738..f69d4f9 100644 (file)
@@ -27,8 +27,6 @@
 #define HH_SENF_Packets_PacketRegistry_ 1
 
 // Custom includes
-#include <map>
-#include <boost/utility.hpp> // for boost::noncopyable
 #include <boost/optional.hpp>
 #include <boost/preprocessor/cat.hpp>
 #include <senf/Utils/Exception.hh>
index 382ff30..746281d 100644 (file)
@@ -27,7 +27,6 @@
 #define IH_SENF_Packets_PacketRegistry_ 1
 
 // Custom includes
-#include <ext/functional>
 #include <limits>
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/ordered_index.hpp>
@@ -35,7 +34,7 @@
 #include <boost/multi_index/member.hpp>
 #include <boost/multi_index/mem_fun.hpp>
 #include <boost/intrusive_ptr.hpp>
-#include <boost/iterator/transform_iterator.hpp>
+#include <boost/utility.hpp> // for boost::noncopyable
 #include <senf/Utils/TypeIdValue.hh>
 
 //-/////////////////////////////////////////////////////////////////////////////////////////////////