4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Thorsten Horstmann <tho@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief GenericTLV public header */
26 #ifndef HH_SENF_Packets_GenericTLV_
27 #define HH_SENF_Packets_GenericTLV_ 1
30 #include <boost/ptr_container/ptr_map.hpp>
31 #include <senf/Packets/Packets.hh>
32 #include <senf/Utils/type_traits.hh>
33 #include <senf/Utils/singleton.hh>
35 //#include "GenericTLV.hh.mpp"
36 ///////////////////////////////hh.p////////////////////////////////////////
40 /** \brief Base class for generic TLV parsers
42 This abstract base class can be used to define generic TLV parsers. The following
43 class structure is assumed:
44 \image html GenericTLV.png
46 Your TLVParser base class has to define a \c type and a \c length field:
48 struct MyTLVParserBase : public senf::PacketParserBase
50 # include SENF_PARSER()
51 SENF_PARSER_FIELD ( type, senf::UInt8Parser );
52 SENF_PARSER_FIELD_RO ( length, senf::UInt8Parser );
53 SENF_PARSER_FINALIZE ( MyTLVParserBase );
57 Your concrete TLV parsers will inherit from this base class and have to define a specific
58 value field and a \c typeId member:
60 struct MyConcreteTLVParser : public MyTLVParserBase
62 # include SENF_PARSER()
63 SENF_PARSER_INHERIT ( MyTLVParserBase );
64 SENF_PARSER_FIELD ( myValue, senf::UInt32Parser );
65 SENF_PARSER_FINALIZE ( MyConcreteTLVParser );
71 static const type_t::value_type typeId = 0x42;
75 With GenericTLVParserBase you can define a generic parser class which provides
76 members to access the value data and and to cast the parser to a concrete tlv
79 struct MyGenericTLVParser : public senf::GenericTLVParserBase<MyTLVParserBase>
81 typedef senf::GenericTLVParserBase<MyTLVParserBase> base;
82 MyGenericTLVParser(data_iterator i, state_type s) : base(i,s) {}
84 // members for your generic TLV parser...
88 If your generic TLV parser just inherits from GenericTLVParserBase and doesn't
89 add any additional functionality you can use a simple \c typedef as well:
91 typedef senf::GenericTLVParserBase<MyTLVParserBase> MyGenericTLVParser;
94 This generic tlv parser can now be used for example in a list:
96 class MyTestPacketParser : public senf::PacketParserBase
98 # include SENF_PARSER()
99 SENF_PARSER_FIELD_RO ( list_length, senf::UInt8Parser );
100 SENF_PARSER_LIST ( tlv_list, list_length, MyGenericTLVParser );
101 SENF_PARSER_FINALIZE ( MyTestPacketParser );
105 Now, you can access the TLV parsers in the list in a generic way or you
106 can cast the parsers to some concrete tlv parser:
109 typedef MyTestPacket::Parser::tlv_list_t::container container_t;
110 container_t tlvContainer (p->tlv_list() );
111 optContainer_t::iterator listIter (tlvContainer.begin());
113 // listIter points to a MyGenericTLVParser, so you have generic access:
114 listIter->type() = 0x42;
115 listIter->value( someRangeOfValueData);
117 // cast to an instance of MyConcreteTLVParser:
118 if (listIter->is<MyConcreteTLVParser>()) {
119 MyConcreteTLVParser concreteTLVParser ( listIter->as<MyConcreteTLVParser>());
120 concreteTLVParser.myValue() = 0xabababab;
123 // add a MyConcreteTLV to the list:
124 MyConcreteTLVParser tlv ( tlvContainer.push_back_space().init<MyConcreteTLVParser>());
125 tlv.myValue() = 0xffff;
129 IPv6GenericOptionParser, WLANGenericInfoElementParser, MIHGenericTLVParser \n
130 GenericTLVParserRegistry
132 template <class Base>
133 class GenericTLVParserBase : public Base
136 GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s)
139 senf::PacketParserBase::size_type bytes() const;
142 template <class Parser>
145 template <class Parser>
148 template <class Parser>
151 senf::PacketInterpreterBase::range value() const;
153 void dump(std::ostream & os) const;
156 template<class ForwardReadableRange>
157 void value(ForwardReadableRange const & val,
158 typename boost::disable_if<senf::is_pair<ForwardReadableRange> >::type * = 0);
160 template<class First, class Second>
161 void value(std::pair<First, Second> const & val,
162 typename boost::disable_if<boost::is_convertible<First, typename Base::type_t::value_type> >::type * = 0);
164 template <class Type, class ForwardReadableRange>
165 void value(std::pair<Type, ForwardReadableRange> const & val,
166 typename boost::enable_if<boost::is_convertible<Type, typename Base::type_t::value_type> >::type * = 0);
168 template<class ForwardReadableRange>
169 void value(ForwardReadableRange const & val);
171 template <class ForwardReadableRange>
172 void value(std::pair<typename Base::type_t::value_type, ForwardReadableRange> const & val);
176 template<class ForwardReadableRange>
177 void value_(ForwardReadableRange const &range);
180 Base const & self() const;
185 template <class BaseParser>
186 struct GenericTLVParserRegistry_EntryBase {
187 virtual ~GenericTLVParserRegistry_EntryBase() {}
188 virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const = 0;
189 virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const = 0;
192 template <class BaseParser, class Parser>
193 struct GenericTLVParserRegistry_Entry
194 : GenericTLVParserRegistry_EntryBase<BaseParser>
196 virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const;
197 virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const;
200 //Helper Functor for STL-compatible predicate (E.g. find_if, for_each ...)
201 template <class BaseParser, class Parser>
205 bool operator() (BaseParser const &p) const {
206 return p.template is<Parser>();
211 /** \brief TLV parser registration facility
213 The %GenericTLVParserRegistry provides a generic facility to globally register concrete
214 TLV parser by the type value. The concrete TLV parser must therefore provide a \c typeId
215 member. See GenericTLVParserBase for details about the assumed class structure.
217 Every registry is identified by the base tlv parser class. Parsers can be registered
220 GenericTLVParserRegistry<MyTLVParserBase>::RegistrationProxy<ConcreteTLVParser>
221 registerConcreteTLVParser;
223 This global variable declaration will register ConcreteTLVParser. The variable
224 registerConcreteTLVParser is a dummy. It's only function is to force the call of
225 it's constructor during global construction time. This static registration only
226 works when the symbol is included into the final binary.
228 To simplify the registration the \ref SENF_PACKET_TLV_REGISTRY_REGISTER macro can be used.
229 The \c ConreteTLVParser must therefore provide a \c Registry typedef pointing to the
230 %GenericTLVParserRegistry; typically you put this typedef to the TLVBaseParser class.
232 struct MyTLVParserBase : public senf::PacketParserBase
235 typedef GenericTLVParserRegistry<MyTLVParserBase> Registry;
237 struct MyConcreteTLVParser : public MyTLVParserBase
240 static const type_t::value_type typeId = 0x42;
241 void dump(std::ostream & os) const;
244 // register MyConcreteTLVParser to the MyTLVParserBase-Registry with the type id 0x42:
245 SENF_PACKET_TLV_REGISTRY_REGISTER( MyConcreteTLVParser );
248 The registry provides a dump() member to dump an instance of a generic TLV parser.
249 If the type value of the given TLV parser is registered the generic tlv will be
250 casted to the registered concrete TLV parser and the dump member from this parser
254 GenericTLVParserBase for the general TLV class structure \n
255 IPv6OptionParser::Registry, WLANInfoElementParser::Registry,
256 MIHBaseTLVParser::Registry
258 template <class BaseParser, class Keytype = typename BaseParser::type_t::value_type>
259 class GenericTLVParserRegistry
260 : public senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >
262 typedef boost::ptr_map<Keytype,
263 detail::GenericTLVParserRegistry_EntryBase<BaseParser> > Map;
266 GenericTLVParserRegistry() {};
268 using senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >::instance;
269 friend class senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >;
271 template <class PacketParser>
272 struct RegistrationProxy {
276 template <typename Parser>
277 void registerParser();
279 typedef GenericTLVParserBase<BaseParser> GenericTLVParser;
281 bool isRegistered(GenericTLVParserBase<BaseParser> const & parser) const;
282 bool isRegistered(Keytype const & key) const;
284 void dump(GenericTLVParser const & parser, std::ostream & os) const;
285 void dump(GenericTLVParser const & parser, Keytype const & key, std::ostream & os) const;
287 PacketParserBase::size_type bytes(GenericTLVParser const & parser) const;
288 PacketParserBase::size_type bytes(GenericTLVParser const & parser, Keytype const & key) const;
291 struct TLVParserNotRegisteredException : public senf::Exception
293 TLVParserNotRegisteredException() : senf::Exception("tlv parser not registered") {}
297 /** \brief Statically add an entry to a TLV parser registry
299 This macro will declare an anonymous global variable in such a way, that constructing
300 this variable will register the given tlv parser.
303 \see senf::GenericTLVParserRegistry
305 # define SENF_PACKET_TLV_REGISTRY_REGISTER( ConreteTLVParser ) \
307 ConreteTLVParser::Registry::RegistrationProxy<ConreteTLVParser> \
308 BOOST_PP_CAT(tlvparserRegistration_, __LINE__); \
313 ///////////////////////////////hh.e////////////////////////////////////////
314 //#include "GenericTLV.cci"
315 #include "GenericTLV.ct"
316 #include "GenericTLV.cti"
323 // comment-column: 40
324 // c-file-style: "senf"
325 // indent-tabs-mode: nil
326 // ispell-local-dictionary: "american"
327 // compile-command: "scons -u test"