X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=senf%2FPackets%2FGenericTLV.hh;h=5ba18471f6f26fb89b0fcc2e2078bce7659aa833;hb=ddb2132be4265f8a0d7d4c954c7c9401e59d027c;hp=b0dab34c8b252ce728a337edc19ecd7d5dbd845a;hpb=9ffdaae4804503c4f36a53747c852a87ee626b9e;p=senf.git diff --git a/senf/Packets/GenericTLV.hh b/senf/Packets/GenericTLV.hh index b0dab34..5ba1847 100644 --- a/senf/Packets/GenericTLV.hh +++ b/senf/Packets/GenericTLV.hh @@ -2,23 +2,28 @@ // // Copyright (C) 2009 // 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. +// The contents of this file are subject to the Fraunhofer FOKUS Public License +// Version 1.0 (the "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://senf.berlios.de/license.html // -// 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. +// The Fraunhofer FOKUS Public License Version 1.0 is based on, +// but modifies the Mozilla Public License Version 1.1. +// See the full license text for the amendments. // -// 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. +// Software distributed under the License is distributed on an "AS IS" basis, +// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +// for the specific language governing rights and limitations under the License. +// +// The Original Code is Fraunhofer FOKUS code. +// +// The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. +// (registered association), Hansastraße 27 c, 80686 Munich, Germany. +// All Rights Reserved. +// +// Contributor(s): +// Thorsten Horstmann /** \file \brief GenericTLV public header */ @@ -33,16 +38,16 @@ #include //#include "GenericTLV.hh.mpp" -///////////////////////////////hh.p//////////////////////////////////////// +//-///////////////////////////////////////////////////////////////////////////////////////////////// namespace senf { - + /** \brief Base class for generic TLV parsers - + This abstract base class can be used to define generic TLV parsers. The following class structure is assumed: \image html GenericTLV.png - + Your TLVParser base class has to define a \c type and a \c length field: \code struct MyTLVParserBase : public senf::PacketParserBase @@ -53,7 +58,7 @@ namespace senf { SENF_PARSER_FINALIZE ( MyTLVParserBase ); }; \endcode - + Your concrete TLV parsers will inherit from this base class and have to define a specific value field and a \c typeId member: \code @@ -63,34 +68,34 @@ namespace senf { SENF_PARSER_INHERIT ( MyTLVParserBase ); SENF_PARSER_FIELD ( myValue, senf::UInt32Parser ); SENF_PARSER_FINALIZE ( MyConcreteTLVParser ); - + SENF_PARSER_INIT() { type() = typeId; length_() = 4; - } + } static const type_t::value_type typeId = 0x42; }; \endcode - + With GenericTLVParserBase you can define a generic parser class which provides members to access the value data and and to cast the parser to a concrete tlv - parser: + parser: \code struct MyGenericTLVParser : public senf::GenericTLVParserBase { typedef senf::GenericTLVParserBase base; MyGenericTLVParser(data_iterator i, state_type s) : base(i,s) {} - + // members for your generic TLV parser... }; \endcode - + If your generic TLV parser just inherits from GenericTLVParserBase and doesn't add any additional functionality you can use a simple \c typedef as well: \code typedef senf::GenericTLVParserBase MyGenericTLVParser; \endcode - + This generic tlv parser can now be used for example in a list: \code class MyTestPacketParser : public senf::PacketParserBase @@ -101,7 +106,7 @@ namespace senf { SENF_PARSER_FINALIZE ( MyTestPacketParser ); }; \endcode - + Now, you can access the TLV parsers in the list in a generic way or you can cast the parsers to some concrete tlv parser: \code @@ -109,48 +114,49 @@ namespace senf { typedef MyTestPacket::Parser::tlv_list_t::container container_t; container_t tlvContainer (p->tlv_list() ); optContainer_t::iterator listIter (tlvContainer.begin()); - + // listIter points to a MyGenericTLVParser, so you have generic access: listIter->type() = 0x42; listIter->value( someRangeOfValueData); - + // cast to an instance of MyConcreteTLVParser: if (listIter->is()) { MyConcreteTLVParser concreteTLVParser ( listIter->as()); concreteTLVParser.myValue() = 0xabababab; } - + // add a MyConcreteTLV to the list: MyConcreteTLVParser tlv ( tlvContainer.push_back_space().init()); tlv.myValue() = 0xffff; - \endcode + \endcode - \see - IPv6GenericOptionTLVParser, WLANGenericInfoElementParser, MIHGenericTLVParser + \see + IPv6GenericOptionParser, WLANGenericInfoElementParser, MIHGenericTLVParser \n + GenericTLVParserRegistry */ template class GenericTLVParserBase : public Base { public: - GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s) + GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s) : Base(i,s) {} - - senf::PacketParserBase::size_type bytes(); + + senf::PacketParserBase::size_type bytes() const; void init() const; template Parser init(); - + template Parser as() const; - + template bool is() const; senf::PacketInterpreterBase::range value() const; - + void dump(std::ostream & os) const; - + #ifndef DOXYGEN template void value(ForwardReadableRange const & val, @@ -162,52 +168,111 @@ namespace senf { template void value(std::pair const & val, - typename boost::enable_if >::type * = 0); + typename boost::enable_if >::type * = 0); #else template void value(ForwardReadableRange const & val); - + template void value(std::pair const & val); -#endif - +#endif + private: template void value_(ForwardReadableRange const &range); - + Base & self(); Base const & self() const; }; - - + + namespace detail { template struct GenericTLVParserRegistry_EntryBase { - virtual void dump(GenericTLVParserBase const & parser, std::ostream & os) = 0; + virtual ~GenericTLVParserRegistry_EntryBase() {} + virtual void dump(GenericTLVParserBase const & parser, std::ostream & os) const = 0; + virtual PacketParserBase::size_type bytes(GenericTLVParserBase const & parser) const = 0; }; - + template struct GenericTLVParserRegistry_Entry : GenericTLVParserRegistry_EntryBase { - virtual void dump(GenericTLVParserBase const & parser, std::ostream & os); + virtual void dump(GenericTLVParserBase const & parser, std::ostream & os) const; + virtual PacketParserBase::size_type bytes(GenericTLVParserBase const & parser) const; + }; + + //Helper Functor for STL-compatible predicate (E.g. find_if, for_each ...) + template + class Predicate + { + public: + bool operator() (BaseParser const &p) const { + return p.template is(); + } }; } - - template + + /** \brief TLV parser registration facility + + The %GenericTLVParserRegistry provides a generic facility to globally register concrete + TLV parser by the type value. The concrete TLV parser must therefore provide a \c typeId + member. See GenericTLVParserBase for details about the assumed class structure. + + Every registry is identified by the base tlv parser class. Parsers can be registered + statically only: + \code + GenericTLVParserRegistry::RegistrationProxy + registerConcreteTLVParser; + \endcode + This global variable declaration will register ConcreteTLVParser. The variable + registerConcreteTLVParser is a dummy. It's only function is to force the call of + it's constructor during global construction time. This static registration only + works when the symbol is included into the final binary. + + To simplify the registration the \ref SENF_PACKET_TLV_REGISTRY_REGISTER macro can be used. + The \c ConreteTLVParser must therefore provide a \c Registry typedef pointing to the + %GenericTLVParserRegistry; typically you put this typedef to the TLVBaseParser class. + \code + struct MyTLVParserBase : public senf::PacketParserBase + { + ... + typedef GenericTLVParserRegistry Registry; + }; + struct MyConcreteTLVParser : public MyTLVParserBase + { + .... + static const type_t::value_type typeId = 0x42; + void dump(std::ostream & os) const; + }; + + // register MyConcreteTLVParser to the MyTLVParserBase-Registry with the type id 0x42: + SENF_PACKET_TLV_REGISTRY_REGISTER( MyConcreteTLVParser ); + \endcode + + The registry provides a dump() member to dump an instance of a generic TLV parser. + If the type value of the given TLV parser is registered the generic tlv will be + casted to the registered concrete TLV parser and the dump member from this parser + will be called. + + \see + GenericTLVParserBase for the general TLV class structure \n + IPv6OptionParser::Registry, WLANInfoElementParser::Registry, + MIHBaseTLVParser::Registry + */ + template class GenericTLVParserRegistry - : public senf::singleton > + : public senf::singleton > { - typedef boost::ptr_map< - typename BaseParser::type_t::value_type, + typedef boost::ptr_map > Map; Map map_; - + GenericTLVParserRegistry() {}; public: - using senf::singleton >::instance; - friend class senf::singleton >; - + using senf::singleton >::instance; + friend class senf::singleton >; + template struct RegistrationProxy { RegistrationProxy(); @@ -215,20 +280,42 @@ namespace senf { template void registerParser(); - - void dump(GenericTLVParserBase const & parser, std::ostream & os); + + typedef GenericTLVParserBase GenericTLVParser; + + bool isRegistered(GenericTLVParserBase const & parser) const; + bool isRegistered(Keytype const & key) const; + + void dump(GenericTLVParser const & parser, std::ostream & os) const; + void dump(GenericTLVParser const & parser, Keytype const & key, std::ostream & os) const; + + PacketParserBase::size_type bytes(GenericTLVParser const & parser) const; + PacketParserBase::size_type bytes(GenericTLVParser const & parser, Keytype const & key) const; + }; + + struct TLVParserNotRegisteredException : public senf::Exception + { + TLVParserNotRegisteredException() : senf::Exception("tlv parser not registered") {} }; - -# define SENF_PACKET_TLV_REGISTRY_REGISTER( BaseTLVParser, ConreteTLVParser ) \ - namespace { \ - senf::GenericTLVParserRegistry \ - ::RegistrationProxy \ - BOOST_PP_CAT(tlvparserRegistration_, __LINE__); \ + + + /** \brief Statically add an entry to a TLV parser registry + + This macro will declare an anonymous global variable in such a way, that constructing + this variable will register the given tlv parser. + + \hideinitializer + \see senf::GenericTLVParserRegistry + */ +# define SENF_PACKET_TLV_REGISTRY_REGISTER( ConreteTLVParser ) \ + namespace { \ + ConreteTLVParser::Registry::RegistrationProxy \ + BOOST_PP_CAT(tlvparserRegistration_, __LINE__); \ } - + } -///////////////////////////////hh.e//////////////////////////////////////// +//-///////////////////////////////////////////////////////////////////////////////////////////////// //#include "GenericTLV.cci" #include "GenericTLV.ct" #include "GenericTLV.cti"