Merged revisions 262,264-265,267-282,284-298,300-311 via svnmerge from
[senf.git] / Packets / PacketRegistry.hh
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.de>
7 //
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.
12 //
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.
17 //
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.
22
23
24 #ifndef HH_PacketRegistryImpl_
25 #define HH_PacketRegistryImpl_ 1
26
27 // Custom includes
28 #include <map>
29 #include <boost/utility.hpp> // for boost::noncopyable
30 #include <boost/optional.hpp>
31 #include "Utils/Exception.hh"
32 #include "PacketInterpreter.hh"
33 #include "Packet.hh"
34
35 //#include "PacketRegistry.mpp"
36 ///////////////////////////////hh.p////////////////////////////////////////
37
38 namespace senf {
39
40     struct PkReg_Entry 
41         : public intrusive_refcount
42     {
43         virtual ~PkReg_Entry();
44         virtual PacketInterpreterBase::factory_t factory() const = 0;
45     };
46
47     namespace detail { template <class Key> class PacketRegistryImpl; }
48
49     /** \brief Packet registration facility
50
51         The PacketRegistry provides a generic facility to associate an
52         arbitrary key with Packets. Example keys are Ethertype or IP
53         protocols.
54
55         Every PacketRegistry is identified by a type tag:
56         \code
57           struct SomeTag {
58               typedef some_key_type key_t;
59           };
60         \endcode
61         The key type can be an arbitrary value type. The PacketRegistry
62         for this Tag can then be accessed using
63         <code>PacketRegistry<SomeTag>::</code>.
64
65         The PacketRegistry class has only static members and provides
66         access to the packet registry. It allows to register Packet
67         classes and to create new Packets given a key. Methods are
68         also provided to find the key of a Packet type.
69
70         \code
71             PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
72             p = PacketRegistry<SomeTag>::create(some_key,begin,end);
73             SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>();
74         \endcode
75
76         Normally, packet classes are registered statically and not
77         procedurally. To this end, the RegistrationProxy is provided:
78         \code
79           PacketRegistry<SomeTag>::RegistrationProxy<SomePacket>
80               registerSomePacket (key_of_somePacket);
81         \endcode
82         This global variable declaration will register \c SomePacket
83         with the \c SomeTag registry under the key \c
84         key_of_somePacket. The variable \c registerSomePacket is a
85         dummy. It's only function is to force the call of it's
86         constructor during global construction time.
87
88         The PacketRegistry's purpose is mostly to assist in
89         implementing the v_nextInterpreter() member of packet
90         facades. This is further supported by the PacketRegistryMixin
91         class.
92
93         \todo Add parameterless create() method
94      */
95     template <class Tag>
96     class PacketRegistry
97     {
98     public:
99         /** \brief Statically register a packet type in a PacketRegistry
100          */
101         template <class PacketType>
102         struct RegistrationProxy
103         {
104             RegistrationProxy(typename Tag::key_t key);
105         };
106
107         /** \brief Register new packet type
108
109             Register \c PacketType in the packet registry \c Tag
110             under the given \c key.
111
112             \par Preconditions:
113                 The given \c key must be unique and not be assigned to
114                 any other packet class in this registry.
115                 The Packet must not already be registered in the registry.
116
117             \param PacketType packet to register
118             \param key key of the packet
119          */
120         template <class PacketType>
121         static void registerPacket(typename Tag::key_t key);
122
123         /** \brief Find key of a packet
124
125             Return the key of \c PacketType as registered in the \c
126             Tag registry
127
128             \param PacketType packet of which the key is requested
129             \returns key of the packet
130             \throws PacketTypeNotRegistered if the packet type is not
131                 found in the registry.
132          */
133         template <class PacketType>
134         static typename Tag::key_t key();
135
136         template <class PacketType>
137         static typename boost::optional<typename Tag::key_t> key(NoThrow_t);
138
139         static typename Tag::key_t key(Packet packet);
140         static typename Tag::key_t key(Packet packet, NoThrow_t);
141
142         /** \brief Lookup a packet by it's key
143
144             Returns the packet registration registered under \a key in the \a Tag registry
145
146             \param key Key of the packet registered
147             \returns Registration entry of the packet
148             \throws PacketTypeNotRegistered if the packet type is not found in the registry
149          */
150         static PkReg_Entry const & lookup(typename Tag::key_t key);
151
152         static PkReg_Entry const * lookup(typename Tag::key_t key, NoThrow_t);
153
154     private:
155         typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
156         static Registry & registry();
157     };
158
159     struct PacketTypeNotRegisteredException : public std::exception
160     { virtual char const * what() const throw() { return "packet type not registered"; } };
161
162 }
163
164 ///////////////////////////////hh.e////////////////////////////////////////
165 //#include "PacketRegistry.cci"
166 #include "PacketRegistry.ct"
167 #include "PacketRegistry.cti"
168 #endif
169
170 \f
171 // Local Variables:
172 // mode: c++
173 // fill-column: 100
174 // c-file-style: "senf"
175 // indent-tabs-mode: nil
176 // ispell-local-dictionary: "american"
177 // compile-command: "scons -u test"
178 // comment-column: 40
179 // End: