1 // $Id:SocketPolicy.hh 218 2007-03-20 14:39:32Z tho $
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief Policy Framework public header
31 \idea Creating a new Socket will create 3 new instances (The handle, the body, the policy) of
32 which 2 (argh) (body, policy) live on the heap. This is expensive. We should convert all the
33 policy classes to singletons and assign the same instance to all socket bodies with the same
34 policy. This would reduce the number of heap allocations per socket handle to one (which is
35 already optimized using the pool_alloc_mixin)
38 /** \defgroup policy_group The Policy Framework
40 \diaimage SocketPolicy.dia
42 \section policy_group_introduction Introduction to the Policy Framework
44 The policy framework conceptually implements a list of parallel inheritance hierarchies each
45 covering a specific interface aspect of the socket handle. The socket handle itself only
46 provides minimal functionality. All further functionality is relayed to a policy class, or more
47 precisely, to a group of policy classes, one for each policy axis. The policy axis are
49 <dl><dt><em>addressingPolicy</em></dt><dd>configures, whether a socket is addressable and if
50 so, configures the address type</dd>
52 <dt><em>framingPolicy</em></dt> <dd>configures the type of framing the socket provides: either
53 no framing providing a simple i/o stream or packet framing</dd>
55 <dt><em>communicationPolicy</em></dt><dd>configures,if and how the communication partner is
58 <dt><em>readPolicy</em></dt><dd>configures the readability of the socket</dd>
60 <dt><em>writePolicy</em></dt><dd>configures the writability of the socket</dd></dl>
62 The template senf::SocketPolicy combines these policy axis to form a concrete socket policy. In
63 a concrete policy, each of these policy axis is assigned a value, the policy value. This value
64 is identified by a class type, a policy class. E.g. possible values for <em>framingPolicy</em>
65 are <tt>DatagramFramingPolicy</tt> or <tt>StreamFramingPolicy</tt> which are classes derived
66 from the axis base class <tt>FramingPolicyBase</tt>. This base class also doubles as
67 <tt>UnspecifiedFramingPolicy</tt> (which is just a typedef alias). If a policy axis is assigned
68 this Unspecified type, the axis is left unspecified, the concrete policy will be incomplete.
70 The senf::SocketPolicy template defines the behavior of a socket handle. The socket handle
71 instances do not implement any socket functionality themselves instead deferring the
72 implementation to the policy classes. The SocketHandle interface is therefore \e not implemented
73 using virtual members, all important socket functions can be inlined by the compiler to create
74 highly efficient code.
76 A senf::SocketPolicy instance can be incomplete. In this case it does \e not completely specify
77 the socket interface, it leaves some aspects open by assigning the Unspecified value to one or
78 more of the policy axis. A senf::SocketHandle based on such a policy will have a reduced
79 interface: It will only support those members for which the corresponding policies are defined.
81 To build a senf::SocketPolicy instance the senf::MakeSocketPolicy helper is provided. This
82 helper template takes any number (it is really limited to 6 Arguments but more arguments don't
83 make sense) of policy classes as it's argument. The MakeSocketPolicy helper will take the
84 arguments in the order they are specified and for each argument will check to which axis the
85 policy class belongs (by checking the base classes of that class) and assign it to the correct
86 policy axis in the senf::SocketPolicy template. If any policy axis are not specified, they are
87 defaulted to their corresponding Unspecified value. This helper frees you to specify the policy
88 classes in any order. An additional feature is, that you may specify a complete policy as a
89 first argument. This policy will then be used to provide default values for unspecified axis.
91 Two senf::SocketHandle's with different policies can be \e compatible. If they are, the more
92 specific SocketHandle can be converted (assigned to) the more basic SocketHandle. A SocketHandle
93 is more specific then another SocketHandle if the policy of the former is more specific then
94 that of the latter which means, that for each policy axis separately, the value of that axis of
95 the more specific policy is derived from or the same as the value of that axis in the more basic
96 policy. This is like converting a derived class pointer to a base class pointer, only it happens
97 separately but at the same time for each policy axis:
100 // This defines an incomplete policy where addressingPolicy and writePolicy
102 typedef senf::MakeSocketPolicy<
103 senf::StreamFramingPolicy,
104 senf::ConnectedCommunicationPolicy,
106 >::policy MyReadableSocketPolicy
108 typedef senf::ClientSocketHandle<MyReadableSocketPolicy> MyReadableHandle;
110 // TCPv4ClientSocketHandle is a socket handle with the policy equivalent to
111 // senf::MakeSocketPolicy<
112 // INet4AddressingPolicy,
113 // StreamFramingPolicy,
114 // ConnectedCommunicationPolicy,
116 // WritablePolicy>::policy
117 senf::TCPv4ClientSocketHandle tcpHandle (...);
119 MyReadableHandle myHandle (tcpHandle); // Conversion to more basic socket handle
122 \section policy_group_details The Policy Framework Classes
124 In the following discussion, deeper insight into C++ and especially the concepts of template
125 meta-programming are needed. However, this information is only needed if you want to write new
126 policy classes or want to use the policy framework explicitly for your own involved
127 optimizations ... or if you are just plain curious :-)
129 In the following discussion we will use the following conventions:
130 \li \e Axis is one or \c AddressingPolicy, \c FramingPolicy, \c CommunicationPolicy, \c
131 ReadPolicy or \c WritePolicy
132 \li \e socketPolicy is any socket policy (that is, an instantiation of the SocketPolicy
134 \li \e trait is an any policy class (that is, any class derived from one of the axis base
137 Each axis is comprised of a number of classes and templates (all in namespace senf of course):
139 <dl><dt>\e Axis \c Base (ex: AddressingPolicyBase)</dt><dd>Baseclass of all policies in this
142 <dt>\c Unspecified \e Axis (ex: \ref UnspecifiedAddressingPolicy)</dt> <dd>An alias (typedef)
143 for \e Axis \c Base</dd>
145 <dt>\e Axis \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)</dt> <dd>A template
146 metafunction returning \c boost::true_type, if \e trait (any class derived from \e Axis \c
147 Base) is a compatible policy value of the given \e socketPolicy</dd>
149 <dt>\c If \e Axis \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)</dt> <dd>This
150 is a combination of \e Axis \c Is and \c boost::enable_if</dd>
152 <dt>\c If \e Axis \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)</dt>
153 <dd>The inverse of above</dd> </dl>
155 These classes form the basis of the policy framework. To bind the policy axis together, there
156 are some more classes and templates.
158 <dl><dt>\c class \c SocketPolicyBase</dt> <dd>This class is the base class of the SocketPolicy
159 template. It is used to validate, that a class is really a SocketPolicy (by checking, that it
160 derives from SocketPolicyBase. This is simpler than checking the template directly).</dd>
162 <dt>\c template \c SocketPolicy < \e addressingPolicy, \e framingPolicy, \e communicationPolicy,
163 \e readPolicy, \e writePolicy ></dt> <dd>This is the central SocketPolicy
164 template. It combines a complete set of policy classes, one for each axis.</dd>
166 <dt>\c template \c MakeSocketPolicy < \e args ></dt> <dd>\c MakeSocketPolicy is a template
167 metafunction which simplifies building SocketPolicy instantiations. It takes any number (ok, up
168 to a maximum of 6) of policy classes as an argument (in any order). It will sort these arguments
169 into the SocketPolicy template arguments. If for some axis no class is specified, it's slot will
170 be filled with \c Unspecified \e Axis. Additionally, the first Argument may optionally be an
171 arbitrary SocketPolicy. It will provide default values for unspecified axis</dd>
173 <dt>\c template \c SocketPolicyIsBaseOf < \e base, \e derived ></dt> <dd>This template
174 metafunction will check, whether the socket policy \e derived is convertible to \e base. This
175 means, that for each axis, the corresponding policy class in \e derived must be derived or be
176 the same as the one on \e base.</dd> </dl>
178 \implementation All these classes are created automatically. The \c SENF_SOCKET_POLICIES macro
179 is a Boost.Preprocessor style sequence listing all policy axis. The Boost.Preprocessor library
180 is then used to generate the respective classes.
182 \section policy_implement Implementing Policy Classes
184 To define a new policy class, derive from the corresponding base class for your policy axes. The
185 only policy axis which might possibly need to be extended is the addressing policy
186 (AddressingPolicyBase). See the Documentation of these classes for more information on which
187 members can be implemented.
189 All members you define must be static. For any of the policy classes, you must only define those
190 members which are supported by your implementation. If you leave out a member you automatically
191 disable the corresponding functionality in the ClientSocketHandle/ServerSocketHandle interface.
193 The member prototypes given in the base class documentation only specify the call signature not
194 the way, the member must be defined (FileHandle really is not a FileHandle but an arbitrary
197 If the existence of a member depends on other policies, you should use the
198 <code>If</code><i>SomePolicy</i><code>Is</code> and
199 <code>If</code><i>SomePolicy</i><code>IsNot</code> templates to dynamically enable/disable the
200 member depending on some other policy:
203 struct ExampleAddressingPolicy
205 template <class SPolicy>
206 void connect(senf::SocketHandle<SPolicy> handle, Address & addr,
207 typename senf::IfCommmunicationPolicyIs<
208 SPolicy, senf::ConnectedCommunicationPolicy>::type * = 0);
212 The \c connect member in this example will only be enabled, it the communication policy of the
213 socket handle is ConnectedCommunicationPolicy (or a derived type). See <a
214 href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">Boost.Enable_If</a>
215 for a discussion of the third argument (\c senf::ConnectedCommunicationPolicyIs is based on
216 the \c boost::enable_if template).
218 \see \ref extend_policy \n
219 <a href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">The Boost enable_if utility</a> \n
220 <a href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html">The Boost.MPL library</a> \n
221 <a href="http://www.boost.org/doc/libs/release/libs/preprocessor/doc/index.html">The Boost.Preprocessor library</a>
223 \idea We could combine all the \e Axis \c Is templates into a single template. Since the \e
224 trait argument will automatically specify the axis to be used, it is not necessary to specify
225 that axis in the template functor's name. We could even combine this with \c
226 SocketPolicyIsBaseOf.
229 /** \defgroup policy_impl_group Policy Implementation classes
230 \ingroup policy_group
232 Here you will find all policy classes. Also included are some supporting classes which are used
233 as base classes to build other policy classes.
236 #ifndef HH_SENF_Socket_SocketPolicy_
237 #define HH_SENF_Socket_SocketPolicy_ 1
241 //#include "SocketPolicy.mpp"
242 //-/////////////////////////////////////////////////////////////////////////////////////////////////
246 /// \addtogroup policy_group
249 // This may be adapted to change the supported policies (however, ClientSocketHandle and
250 // ServerSocketHandle will probably have to be adjusted accordingly)
252 /** \brief List all policy axis
256 This define symbol is used to configure the policy axis. The base class for each of these
257 axis must be defined explicitly (e.g. AddressingPolicyBase). The implementation files will
258 then automatically generate all the other classes from this list.
262 # define SENF_SOCKET_POLICIES \
265 (CommunicationPolicy) \
269 // Wer define these classes explicitly (and not with some macro
271 // a) AddressingPolicyBase is different from all the others
272 // b) We want to document each one explicitly
274 /** \brief Policy defining socket addressing
276 AddressingPolicyBase is the baseclass of all addressing policy classes. When defining a new
277 addressing policy, the following members can be defined. All methods must be static.
280 <tr><td>typedef</td> <td><tt>Address</tt></td> <td>Address type</td></tr>
281 <tr><td>method</td> <td><tt>void local(FileHandle, Address &)</tt></td> <td>Get local socket address</td></tr>
282 <tr><td>method</td> <td><tt>void peer(FileHandle, Address &)</tt></td> <td>Get remote socket address</td></tr>
283 <tr><td>method</td> <td><tt>void bind(FileHandle, Address const &)</tt></td> <td>Bind socket to local address</td></tr>
284 <tr><td>method</tr> <td><tt>void connect(FileHandle, Address const &)</tt></td> <td>Connect to remote address</td></tr>
289 struct AddressingPolicyBase
291 virtual ~AddressingPolicyBase();
293 class Address { Address(); };
296 /** \brief Policy defining the framing format
298 This policy does not define any operations since it does have no influence on any method
299 signature. It does however affect the semantics of the \c read() and \c write() operations.
301 \note This policy axis probably only has two sensible states: StreamFramingPolicy and
302 DatagramFramingPolicy.
306 struct FramingPolicyBase
308 virtual ~FramingPolicyBase();
311 /** \brief Policy defining, how peers are selected
313 The CommunicationPolicy may define two members:
316 <tr><td>method</td> <td><tt>void listen(FileHandle, unsigned backlog)</tt></td> <td>Switch socket into listening state</td></tr>
317 <tr><td>method</td> <td><tt>int accept(FileHandle, Address &)</tt></td> <td>Accept a new connection</td></tr>
318 <tr><td>method</td> <td><tt>int accept(FileHandle)</tt></td> <td>Accept a new connection</td></tr>
321 The \c listen member is straight forward. The \c accept() member must return a new file
322 descriptor (which will be used to create a new SocketHandle of the correct
325 \note This Policy only has two meaningful states: ConnectedCommunicationPolicy and
326 UnconnectedCommunicationPolicy. It is probably not sensible to define a new
327 CommunicationPolicy type.
331 struct CommunicationPolicyBase
333 virtual ~CommunicationPolicyBase();
336 /** \brief Policy defining the readability
338 The ReadPolicy defines, whether the socket is readable. It may define two members:
341 <tr><td>method</td> <td><tt>unsigned read(FileHandle, char * buffer, unsigned size)</tt></td> <td>read data from socket</td></tr>
342 <tr><td>method</td> <td><tt>unsigned readfrom(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
345 The second member should only be enabled if the communication policy is
346 UnconnectedCommunicationPolicy (otherwise it does not make sense since the communication partner
347 is fixed) (see AddressingPolicyBase on how to do this).
349 \note This Policy only has two meaningful states: ReadablePolicy and NotReadablePolicy. It
350 probably does not make sense to define new read policy types.
354 struct ReadPolicyBase
356 virtual ~ReadPolicyBase();
359 /** \brief Policy defining the writability
361 The WritePolicy defines, whether the socket is writable. It may define two members:
364 <tr><td>method</td> <td><tt>unsigned write(FileHandle, char * buffer, unsigned size)</tt></td> <td>read data from socket</td></tr>
365 <tr><td>method</td> <td><tt>unsigned writeto(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
368 The second member should only be enabled if the communication policy is
369 UnconnectedCommunicationPolicy (otherwise it does not make sense since the communication partner
370 is fixed) (see AddressingPolicyBase on how to do this).
372 \note This Policy only has two meaningful states: WritablePolicy and NotWritablePolicy. It
373 probably does not make sense to define new write policy types.
377 struct WritePolicyBase
379 virtual ~WritePolicyBase();
382 // The implementation file will for each Policy declared above
383 // define the following (SomePolicy is one of the above):
385 // struct SomePolicyBase;
386 // typedef UndefinedSomePolicy;
387 // template SomePolicyIs< SocketPolicy, Axis >
388 // template IfSomePolicyIs< SocketPolicy, Axis >
389 // template IfSomePolicyIsNot< SocketPolicy, Axis >
391 // Additionally the following are defined:
393 // class SocketPolicyBase
394 // template SocketPolicy< ..policies.. >
395 // template MakeSocketPolicy< ..args.. >
396 // template SocketPolicyIsBaseOf< Base, Derived >
400 // The following stub definitions are only visible to doxygen
402 /** \brief Alias of AddressingPolicyBase for better readability
403 \see \ref policy_group
405 typedef AddressingPolicyBase UnspecifiedAddressingPolicy;
407 /** \brief Check single policy axis
409 This template is an example of the \e Axis \c Is family of template metafunctions. It will
410 check, whether \c Trait is a valid compatible Policy class of \c SocketPolicy. \c Trait must
411 be derived from AddressingPolicyBase (respectively \c Policy \c Base).
413 \see \ref policy_group
415 template <class SocketPolicy, class Trait>
416 struct AddressingPolicyIs
419 /** \brief Enable template overload depending on policy value
421 This template is an example of the \c If \e Axis \c Is family of templates. It is used like
422 <a href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">Boost.enable_if</a>
423 to enable a templated overload only, if the AddressingPolicy of \e Axis is compatible with
424 \c Trait (that is the AddressingPolicy of \c Policy is derived from \c Trait).
428 template <class SocketPolicy, class Trait>
429 struct IfAddressingPolicyIs
432 /** \brief Inversion of \c IfAddressingPolicyIs
435 template <class SocketPolicy, class Trait>
436 struct IfAddressingPolicyIsNot
439 /** \brief Baseclass of all SocketPolicies
443 This class provides the baseclass of all socket policies (bundles). It serves two purposes:
444 \li It allows us to easily identify a socket policy bundle by checking a classes baseclass.
445 \li It provides an abstract (virtual) interface to access the policy axes
449 struct SocketPolicyBase
451 /** \brief Polymorphic access to policy axes
453 This is an example of a policy axes accessor. It returns a reference to the policy axes
454 used by the concrete protocol bundle. This reference can then be checked using RTTI
457 AddressingPolicyBase const & theAddressingPolicy() const = 0;
459 virtual ~SocketPolicyBase();
462 /** \brief Collection of policy classes
464 The SocketPolicy template defines the complete Policy used by the socket library. It
465 contains one policy class for each policy axis. This template takes one policy from each
466 axis as it's template arguments (this example implementation only has AddressingPolicy as an
469 A SocketPolicy can be complete or incomplete. An incomplete SocketPolicy will have at least
470 one axis set to \c Undefined \e Axis (or a generic derived class which is used to group some
471 other policies but does not (completely) define the policy behavior). A complete
472 SocketPolicy will have a concrete definition of the desired behavior for each policy axis.
476 template < class AddressingPolicy >
479 /** \brief Check dynamic policy compatibility
481 This check will validate, that a socket with \a other as it's policy is convertible to a
482 socket with the current SocketPolicy as it's policy. This is true, if for each policy
483 axis, the policy class of that axis as defined in the \a other policy is convertible to
484 the policy class of that same axis in the current SocketPolicy instance (as is defined
485 by the template arguments). This again is true, if the \a other policy class is derived
486 from (or is the same as) the policy class taken from the current SocketPolicy instance.
488 In other words, this call checks, that the current SocketPolicy (as defined via the
489 template arguments) is more generic than the \a other socket policy.
491 \param[in] other SocketPolicy to check
492 \throws std::bad_cast if \a other is not a compatible policy
494 static void checkBaseOf(SocketPolicyBase const & other);
497 /** \brief Metafunction to create SocketPolicy
499 This template metafunction simplifies the creation of a SocketPolicy instantiation. It takes
500 any number (that is up to 6) of Policy classes as arguments in any Order. It will create a
501 SocketPolicy from these policy classes. Any axis not specified will be left as \c
506 template <class Arg1, class Arg2, class ArgN>
507 struct MakeSocketPolicy
510 /** \brief Check policy compatibility
512 This template metafunction checks, whether the SocketPolicy \c Derived is more specialized
513 than \c Base (and therefore a SocketHandle with policy \c Derived is convertible to a
514 SocketHandle with policy \c Base).
516 The metafunction will return true (that is inherits from \c boost::true_type, see the <a
517 href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html">Boost.MPL</a> library documentation for
518 more information) if each policy class in \c Base is a baseclass of (or the same as) the
519 corresponding policy class in \c Derived.
523 template <class Base, class Derived>
524 struct SocketPolicyIsBaseOf
532 //-/////////////////////////////////////////////////////////////////////////////////////////////////
533 #include "SocketPolicy.ih"
534 //#include "SocketPolicy.cci"
535 #include "SocketPolicy.ct"
536 //#include "SocketPolicy.cti"
543 // c-file-style: "senf"
544 // indent-tabs-mode: nil
545 // ispell-local-dictionary: "american"
546 // compile-command: "scons -u test"
547 // comment-column: 40