1 // $Id:SocketPolicy.hh 218 2007-03-20 14:39:32Z tho $
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 // Stefan Bund <stefan.bund@fokus.fraunhofer.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 Policy Framework public header
26 \todo We should probably remove BufferingPolicy from the interface, it does not make much sense
27 (how did I come to include it ??)
29 \todo Do we want to support separate read and write policies. This allows to treat pipes within
30 this framework however, is this worth the effort?
32 \idea Creating a new Socket will create 4 (!) new instances (The handle, the body, the policy
33 and the protocol) of which 3 (argh) (body, policy and protocol) live on the heap. This is
34 expensive. We should convert all the policy classes to singletons and assign the same
35 instance to all socket bodies with the same policy. This would reduce the number of heap
36 allocations per socket handle to two.
39 /** \defgroup policy_group The Policy Framework
41 \image html SocketPolicy.png
43 \section policy_group_introduction Introduction to the Policy Framework
45 The policy framework conceptually implements a list of parallel inheritance hierarchies each
46 covering a specific interface aspect of the socket handle. The socket handle itself only
47 provides minimal functionality. All further functionality is relayed to a policy class, or more
48 precisely, to a group of policy classes, one for each policy axis. The policy axis are
50 <dl><dt><em>addressingPolicy</em></dt><dd>configures, whether a socket is addressable and if
51 so, configures the address type</dd>
53 <dt><em>framingPolicy</em></dt> <dd>configures the type of framing the socket provides: either
54 no framing providing a simple i/o stream or packet framing</dd>
56 <dt><em>communicationPolicy</em></dt><dd>configures,if and how the communication partner is
59 <dt><em>readPolicy</em></dt><dd>configures the readability of the socket</dd>
61 <dt><em>writePolicy</em></dt><dd>configures the writability of the socket</dd>
63 <dt><em>bufferingPolicy</em></dt><dd>configures, if and how buffering is configured for a
66 The template senf::SocketPolicy combines these policy axis to form a concrete socket policy. In
67 a concrete policy, each of these policy axis is assigned a value, the policy value. This value
68 is identified by a class type, a policy class. E.g. possible values for <em>framingPolicy</em>
69 are <tt>DatagramFramingPolicy</tt> or <tt>StreamFramingPolicy</tt> which are classes derived
70 from the axis base class <tt>FramingPolicyBase</tt>. This base class also doubles as
71 <tt>UnspecifiedFramingPolicy</tt> (which is just a typedef alias). If a policy axis is assigned
72 this Unspecified type, the axis is left unspecified, the concrete policy will be incomplete.
74 The senf::SocketPolicy template defines the behavior of a socket handle. The socket handle
75 instances do not implement any socket functionality themselves instead deferring the
76 implementation to the policy classes. The SocketHandle interface is therefore \e not implemented
77 using virtual members, all important socket functions can be inlined by the compiler to create
78 highly efficient code.
80 A senf::SocketPolicy instance can be incomplete. In this case it does \e not completely specify
81 the socket interface, it leaves some aspects open by assigning the Unspecified value to one or
82 more of the policy axis. A senf::SocketHandle based on such a policy will have a reduced
83 interface: It will only support those members for which the corresponding policies are defined.
85 To build a senf::SocketPolicy instance the senf::MakeSocketPolicy helper is provided. This
86 helper template takes any number (it is really limited to 6 Arguments but more arguments don't
87 make sense) of policy classes as it's argument. The MakeSocketPolicy helper will take the
88 arguments in the order they are specified and for each argument will check to which axis the
89 policy class belongs (by checking the base classes of that class) and assign it to the correct
90 policy axis in the senf::SocketPolicy template. If any policy axis are not specified, they are
91 defaulted to their corresponding Unspecified value. This helper frees you to specify the policy
92 classes in any order. An additional feature is, that you may specify a complete policy as a
93 first argument. This policy will then be used to provide default values for unspecified axis.
95 Two senf::SocketHandle's with different policies can be \e compatible. If they are, the more
96 specific SocketHandle can be converted (assigned to) the more basic SocketHandle. A SocketHandle
97 is more specific then another SocketHandle if the policy of the former is more specific then
98 that of the latter which means, that for each policy axis separately, the value of that axis of
99 the more specific policy is derived from or the same as the value of that axis in the more basic
100 policy. This is like converting a derived class pointer to a base class pointer, only it happens
101 separately but at the same time for each policy axis:
104 // This defines an incomplete policy where addressingPolicy, writePolicy and bufferingPolicy
106 typedef senf::MakeSocketPolicy<
107 senf::StreamFramingPolicy,
108 senf::ConnectedCommunicationPolicy,
110 >::policy MyReadableSocketPolicy
112 typedef senf::ClientSocketHandle<MyReadableSocketPolicy> MyReadableHandle;
114 // TCPv4ClientSocketHandle is a socket handle with the policy equivalent to
115 // senf::MakeSocketPolicy<
116 // INet4AddressingPolicy,
117 // StreamFramingPolicy,
118 // ConnectedCommunicationPolicy,
121 // SocketBufferingPolicy>::policy
122 senf::TCPv4ClientSocketHandle tcpHandle (...);
124 MyReadableHandle myHandle (tcpHandle); // Conversion to more basic socket handle
127 \section policy_group_details The Policy Framework Classes
129 In the following discussion, deeper insight into C++ and especially the concepts of template
130 meta-programming are needed. However, this information is only needed if you want to write new
131 policy classes or want to use the policy framework explicitly for your own involved
132 optimizations ... or if you are just plain curious :-)
134 In the following discussion we will use the following conventions:
135 \li \e Axis is one or \c AddressingPolicy, \c FramingPolicy, \c CommunicationPolicy, \c
136 ReadPolicy, \c WritePolicy or \c BufferingPolicy
137 \li \e socketPolicy is any socket policy (that is, an instantiation of the SocketPolicy
139 \li \e trait is an any policy class (that is, any class derived from one of the axis base
142 Each axis is comprised of a number of classes and templates (all in namespace senf of course):
144 <dl><dt>\e Axis \c Base (ex: AddressingPolicyBase)</dt><dd>Baseclass of all policies in this
147 <dt>\c Unspecified \e Axis (ex: \ref UnspecifiedAddressingPolicy)</dt> <dd>An alias (typedef)
148 for \e Axis \c Base</dd>
150 <dt>\e Axis \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)</dt> <dd>A template
151 metafunction returning \c boost::true_type, if \e trait (any class derived from \e Axis \c
152 Base) is a compatible policy value of the given \e socketPolicy</dd>
154 <dt>\c If \e Axis \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)</dt> <dd>This
155 is a combination of \e Axis \c Is and \c boost::enable_if</dd>
157 <dt>\c If \e Axis \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)</dt>
158 <dd>The inverse of above</dd> </dl>
160 These classes form the basis of the policy framework. To bind the policy axis together, there
161 are some more classes and templates.
163 <dl><dt>\c class \c SocketPolicyBase</dt> <dd>This class is the base class of the SocketPolicy
164 template. It is used to validate, that a class is really a SocketPolicy (by checking, that it
165 derives from SocketPolicyBase. This is simpler than checking the template directly).</dd>
167 <dt>\c template \c SocketPolicy < \e addressingPolicy, \e framingPolicy, \e communicationPolicy,
168 \e readPolicy, \e writePolicy, \e bufferingPolicy ></dt> <dd>This is the central SocketPolicy
169 template. It combines a complete set of policy classes, one for each axis.</dd>
171 <dt>\c template \c MakeSocketPolicy < \e args ></dt> <dd>\c MakeSocketPolicy is a template
172 metafunction which simplifies building SocketPolicy instantiations. It takes any number (ok, up
173 to a maximum of 6) of policy classes as an argument (in any order). It will sort these arguments
174 into the SocketPolicy template arguments. If for some axis no class is specified, it's slot will
175 be filled with \c Unspecified \e Axis. Additionally, the first Argument may optionally be ab
176 arbitrary SocketPolicy. It will provide default values for unspecified axis</dd>
178 <dt>\c template \c SocketPolicyIsBaseOf < \e base, \e derived ></dt> <dd>This template
179 metafunction will check, whether the socket policy \e derived is convertible to \e base. This
180 means, that for each axis, the corresponding policy class in \e derived must be derived or be
181 the same as the one on \e base.</dd> </dl>
183 \implementation All these classes are created automatically. The \c SENF_SOCKET_POLICIES macro
184 is a Boost.Preprocessor style sequence listing all policy axis. The Boost.Preprocessor library
185 is then used to generate the respective classes.
187 \section policy_implement Implementing Policy Classes
189 To define a new policy class, derive from the corresponding base class for your policy
190 axes. The only policy axis which might possibly need to be extended are the addressing policy
191 (AddressingPolicyBase) and the buffering policy (BufferingPolicyBase). See the Documentation of
192 these classes for more information on which members can be implemented.
194 All members you define must be static. For any of the policy classes, you must only define those
195 members which are supported by your implementation. If you leave out a member you automatically
196 disable the corresponding functionality in the ClientSocketHandle/ServerSocketHandle interface.
198 The member prototypes given in the base class documentation only specify the call signature not
199 the way, the member must be defined (FileHandle really is not a FileHandle but an arbitrary
202 If the existence of a member depends on other policies, you should use the
203 <code>If</code><i>SomePolicy</i><code>Is</code> and
204 <code>If</code><i>SomePolicy</i><code>IsNot</code> templates to dynamically enable/disable the
205 member depending on some other policy:
208 struct ExampleAddressingPolicy
210 template <class Policy>
211 void connect(senf::SocketHandle<Policy> handle, Address & addr,
212 typename senf::IfCommmunicationPolicyIs<
213 Policy, senf::ConnectedCommunicationPolicy>::type * = 0);
217 The \c connect member in this example will only be enabled, it the communication policy of the
218 socket handle is ConnectedCommunicationPolicy (or a derived type). See <a
219 href="http://www.boost.org/libs/utility/enable_if.html">Boost.Enable_If</a> for a discussion of
220 the third argument (\c senf::ConnectedCommunicationPolicyIs is based on the \c boost::enable_if
223 \see \ref extend_policy \n
224 <a href="http://www.boost.org/libs/utility/enable_if.html">The Boost enable_if utility</a> \n
225 <a href="http://www.boost.org/libs/mpl/doc/index.html">The Boost.MPL library</a> \n
226 <a href="http://www.boost.org/libs/preprocessor/doc/index.html">The Boost.Preprocessor library</a>
228 \idea We could combine all the \e Axis \c Is templates into a single template. Since the \e
229 trait argument will automatically specify the axis to be used, it is not necessary to specify
230 that axis in the template functor's name. We could even combine this with \c
231 SocketPolicyIsBaseOf.
234 /** \defgroup policy_impl_group Policy Implementation classes
235 \ingroup policy_group
237 Here you will find all policy classes. Also included are some supporting classes which are used
238 as base classes to build other policy classes.
241 #ifndef HH_SocketPolicy_
242 #define HH_SocketPolicy_ 1
246 #include "GenericSockAddr.hh"
248 //#include "SocketPolicy.mpp"
249 ///////////////////////////////hh.p////////////////////////////////////////
253 /// \addtogroup policy_group
256 // This may be adapted to change the supported policies (however, ClientSocketHandle and
257 // ServerSocketHandle will probably have to be adjusted accordingly)
259 /** \brief List all policy axis
263 This define symbol is used to configure the policy axis. The base class for each of these
264 axis must be defined explicitly (e.g. AddressingPolicyBase). The implementation files will
265 then automatically generate all the other classes from this list.
269 # define SENF_SOCKET_POLICIES \
272 (CommunicationPolicy) \
277 // Wer define these classes explicitly (and not with some macro
279 // a) AddressingPolicyBase is different from all the others
280 // b) We want to document each one explicitly
282 /** \brief Policy defining socket addressing
284 AddressingPolicyBase is the baseclass of all addressing policy classes. When defining a new
285 addressing policy, the following members can be defined. All methods must be static.
288 <tr><td>typedef</td> <td><tt>Address</tt></td> <td>Address type</td></tr>
289 <tr><td>method</td> <td><tt>void local(FileHandle, Address &)</tt></td> <td>Get local socket address</td></tr>
290 <tr><td>method</td> <td><tt>void peer(FileHandle, Address &)</tt></td> <td>Get remote socket address</td></tr>
291 <tr><td>method</td> <td><tt>void bind(FileHandle, Address const &)</tt></td> <td>Bind socket to local address</td></tr>
292 <tr><td>method</tr> <td><tt>void connect(FileHandle, Address const &)</tt></td> <td>Connect to remote address</td></tr>
297 struct AddressingPolicyBase
299 virtual ~AddressingPolicyBase() {}
301 typedef GenericSockAddr Address;
304 /** \brief Policy defining the framing format
306 This policy does not define any operations since it does have no influence on any method
307 signature. It does however affect the semantics of the \c read() and \c write() operations.
309 \note This policy axis probably only has two sensible states: StreamFramingPolicy and
310 DatagramFramingPolicy.
314 struct FramingPolicyBase
316 virtual ~FramingPolicyBase() {}
319 /** \brief Policy defining, how peers are selected
321 The CommunicationPolicy may define two members:
324 <tr><td>method</td> <td><tt>void listen(FileHandle, unsigned backlog)</tt></td> <td>Switch socket into listening state</td></tr>
325 <tr><td>method</td> <td><tt>int accept(FileHandle, Address &)</tt></td> <td>Accept a new connection</td></tr>
328 The \c listen member is straight forward. The \c accept() member must return a new file
329 descriptor (which will be used to create a new SocketHandle of the correct
330 type). Additionally, accept() should only be defined, if the Addressing policy is not \c
331 NoAddressingPolicy (which together with ConnectedCommunicationPolicy would identify a
332 point-to-point link with fixed communication partners).
334 \note This Policy only has two meaningful states: ConnectedCommunicationPolicy and
335 UnconnectedCommunicationPolicy. It is probably not sensible to define a new
336 CommunicationPolicy type.
340 struct CommunicationPolicyBase
342 virtual ~CommunicationPolicyBase() {}
345 /** \brief Policy defining the readability
347 The ReadPolicy defines, whether the socket is readable. It may define two members:
350 <tr><td>method</td> <td><tt>unsigned read(FileHandle, char * buffer, unsigned size)</tt></td> <td>read data from socket</td></tr>
351 <tr><td>method</td> <td><tt>unsigned readfrom(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
354 The second member should only be enabled if the communication policy is
355 UnconnectedCommunication (otherwise it does not make sense since the communication partner
356 is fixed) (see AddressingPolicyBase on how to do this).
358 \note This Policy only has two meaningful states: ReadablePolicy and NotReadablePolicy. It
359 probably does not make sense to define new read policy types.
363 struct ReadPolicyBase
365 virtual ~ReadPolicyBase() {}
368 /** \brief Policy defining the writability
370 The WritePolicy defines, whether the socket is writable. It may define two members:
373 <tr><td>method</td> <td><tt>unsigned write(FileHandle, char * buffer, unsigned size)</tt></td> <td>read data from socket</td></tr>
374 <tr><td>method</td> <td><tt>unsigned writeto(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
377 The second member should only be enabled if the communication policy is
378 UnconnectedCommunication (otherwise it does not make sense since the communication partner
379 is fixed) (see AddressingPolicyBase on how to do this).
381 \note This Policy only has two meaningful states: WritablePolicy and NotWritablePolicy. It
382 probably does not make sense to define new write policy types.
386 struct WritePolicyBase
388 virtual ~WritePolicyBase() {}
391 /** \brief Policy defining the buffering interface
393 The BufferingPolicy defines the buffer handling of the socket. It may provide the following
398 struct BufferingPolicyBase
400 virtual ~BufferingPolicyBase() {}
403 // The implementation file will for each Policy declared above
404 // define the following (SomePolicy is one of the above):
406 // struct SomePolicyBase;
407 // typedef UndefinedSomePolicy;
408 // template SomePolicyIs< SocketPolicy, Axis >
409 // template IfSomePolicyIs< SocketPolicy, Axis >
410 // template IfSomePolicyIsNot< SocketPolicy, Axis >
412 // Additionally the following are defined:
414 // class SocketPolicyBase
415 // template SocketPolicy< ..policies.. >
416 // template MakeSocketPolicy< ..args.. >
417 // template SocketPolicyIsBaseOf< Base, Derived >
421 // The following stub definitions are only visible to doxygen
423 /** \brief Alias of AddressingPolicyBase for better readability
424 \see \ref policy_group
426 typedef AddressingPolicyBase UnspecifiedAddressingPolicy;
428 /** \brief Check single policy axis
430 This template is an example of the \e Axis \c Is family of template metafunctions. It will
431 check, whether \c Trait is a valid compatible Policy class of \c SocketPolicy. \c Trait must
432 be derived from AddressingPolicyBase (respectively \c Policy \c Base).
434 \see \ref policy_group
436 template <class SocketPolicy, class Trait>
437 struct AddressingPolicyIs
440 /** \brief Enable template overload depending on policy value
442 This template is an example of the \c If \e Axis \c Is family of templates. It is used like
443 <a href="http://www.boost.org/libs/utility/enable_if.html">Boost.enable_if</a> to enable a
444 templated overload only, if the AddressingPolicy of \e Axis is compatible with \c Trait
445 (that is the AddressingPolicy of \c Policy is derived from \c Trait).
449 template <class SocketPolicy, class Trait>
450 struct IfAddressingPolicyIs
453 /** \brief Inversion of \c IfAddressingPolicyIs
456 template <class SocketPolicy, class Trait>
457 struct IfAddressingPolicyIsNot
460 /** \brief Baseclass of all SocketPolicies
464 This class provides the baseclass of all socket policies (bundles). It serves two purposes:
465 \li It allows us to easily identify a socket policy bundle by checking a classes baseclass.
466 \li It provides an abstract (virtual) interface to access the policy axes
470 struct SocketPolicyBase
472 /** \brief Polymorphic access to policy axes
474 This is an example of a policy axes accessor. It returns a reference to the policy axes
475 used by the concrete protocol bundle. This reference can then be checked using RTTI
478 AddressingPolicyBase const & theAddressingPolicy() const = 0;
481 /** \brief Collection of policy classes
483 The SocketPolicy template defines the complete Policy used by the socket library. It
484 contains one policy class for each policy axis. This template takes one policy from each
485 axis as it's template arguments (this example implementation only has AddressingPolicy as an
488 A SocketPolicy can be complete or incomplete. An incomplete SocketPolicy will have at least
489 one axis set to \c Undefined \e Axis (or a generic derived class which is used to group some
490 other policies but does not (completely) define the policy behavior). A complete
491 SocketPolicy will have a concrete definition of the desired behavior for each policy axis.
495 template < class AddressingPolicy >
498 /** \brief Check dynamic policy compatibility
500 This method will check the socket policy \a other against this policy. It will check,
501 whether \a other is a base policy (or the same) of this policy. This check is done
502 against the \e dynamic type of \a other using RTTI. It will throw \c std::bad_cast, if
503 the policy is not compatible.
505 \param[in] other SocketPolicy to check
506 \throws std::bad_cast if \a other is not a compatible policy
508 static void checkBaseOf(SocketPolicyBase const & other);
511 /** \brief Metafunction to create SocketPolicy
513 This template metafunction simplifies the creation of a SocketPolicy instantiation. It takes
514 any number (that is up to 6) of Policy classes as arguments in any Order. It will create a
515 SocketPolicy from these policy classes. Any axis not specified will be left as \c
520 template <class Arg1, class Arg2, class ArgN>
521 struct MakeSocketPolicy
524 /** \brief Check policy compatibility
526 This template metafunction checks, whether the SocketPolicy \c Derived is more specialized
527 than \c Base (and therefore a SocketHandle with policy \c Derived is convertible to a
528 SocketHandle with policy \c Base).
530 The metafunction will return true (that is inherits from \c boost::true_type, see the <a
531 href="http://www.boost.org/libs/mpl/doc/index.html">Boost.MPL</a> library documentation for
532 more information) if each policy class in \c Base is a baseclass of (or the same as) the
533 corresponding policy class in \c Derived.
537 template <class Base, class Derived>
538 struct SocketPolicyIsBaseOf
546 //////////////////////////////hh.e////////////////////////////////////////
547 #include "SocketPolicy.ih"
548 //#include "SocketPolicy.cci"
549 #include "SocketPolicy.ct"
550 //#include "SocketPolicy.cti"
557 // c-file-style: "senf"
558 // indent-tabs-mode: nil
559 // ispell-local-dictionary: "american"