4494691e10f4bf780696cbdedc27095aa675fed4
[senf.git] / senf / Socket / SocketPolicy.hh
1 // $Id:SocketPolicy.hh 218 2007-03-20 14:39:32Z tho $
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.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 /** \file
24     \brief Policy Framework public header
25
26     \idea Creating a new Socket will create 3 new instances (The handle, the body, the policy) of
27         which 2 (argh) (body, policy) live on the heap. This is expensive. We should convert all the
28         policy classes to singletons and assign the same instance to all socket bodies with the same
29         policy. This would reduce the number of heap allocations per socket handle to one (which is
30         already optimized using the pool_alloc_mixin)
31  */
32
33 /** \defgroup policy_group The Policy Framework
34
35     \diaimage SocketPolicy.dia
36
37     \section policy_group_introduction Introduction to the Policy Framework
38
39     The policy framework conceptually implements a list of parallel inheritance hierarchies each
40     covering a specific interface aspect of the socket handle. The socket handle itself only
41     provides minimal functionality. All further functionality is relayed to a policy class, or more
42     precisely, to a group of policy classes, one for each policy axis. The policy axis are
43
44     <dl><dt><em>addressingPolicy</em></dt><dd>configures, whether a socket is addressable and if
45     so, configures the address type</dd>
46
47     <dt><em>framingPolicy</em></dt> <dd>configures the type of framing the socket provides: either
48     no framing providing a simple i/o stream or packet framing</dd>
49
50     <dt><em>communicationPolicy</em></dt><dd>configures,if and how the communication partner is
51     selected</dd>
52
53     <dt><em>readPolicy</em></dt><dd>configures the readability of the socket</dd>
54
55     <dt><em>writePolicy</em></dt><dd>configures the writability of the socket</dd></dl>
56
57     The template senf::SocketPolicy combines these policy axis to form a concrete socket policy. In
58     a concrete policy, each of these policy axis is assigned a value, the policy value. This value
59     is identified by a class type, a policy class. E.g. possible values for <em>framingPolicy</em>
60     are <tt>DatagramFramingPolicy</tt> or <tt>StreamFramingPolicy</tt> which are classes derived
61     from the axis base class <tt>FramingPolicyBase</tt>. This base class also doubles as
62     <tt>UnspecifiedFramingPolicy</tt> (which is just a typedef alias).  If a policy axis is assigned
63     this Unspecified type, the axis is left unspecified, the concrete policy will be incomplete.
64
65     The senf::SocketPolicy template defines the behavior of a socket handle. The socket handle
66     instances do not implement any socket functionality themselves instead deferring the
67     implementation to the policy classes. The SocketHandle interface is therefore \e not implemented
68     using virtual members, all important socket functions can be inlined by the compiler to create
69     highly efficient code.
70
71     A senf::SocketPolicy instance can be incomplete. In this case it does \e not completely specify
72     the socket interface, it leaves some aspects open by assigning the Unspecified value to one or
73     more of the policy axis. A senf::SocketHandle based on such a policy will have a reduced
74     interface: It will only support those members for which the corresponding policies are defined.
75
76     To build a senf::SocketPolicy instance the senf::MakeSocketPolicy helper is provided. This
77     helper template takes any number (it is really limited to 6 Arguments but more arguments don't
78     make sense) of policy classes as it's argument. The MakeSocketPolicy helper will take the
79     arguments in the order they are specified and for each argument will check to which axis the
80     policy class belongs (by checking the base classes of that class) and assign it to the correct
81     policy axis in the senf::SocketPolicy template. If any policy axis are not specified, they are
82     defaulted to their corresponding Unspecified value. This helper frees you to specify the policy
83     classes in any order. An additional feature is, that you may specify a complete policy as a
84     first argument. This policy will then be used to provide default values for unspecified axis.
85
86     Two senf::SocketHandle's with different policies can be \e compatible. If they are, the more
87     specific SocketHandle can be converted (assigned to) the more basic SocketHandle. A SocketHandle
88     is more specific then another SocketHandle if the policy of the former is more specific then
89     that of the latter which means, that for each policy axis separately, the value of that axis of
90     the more specific policy is derived from or the same as the value of that axis in the more basic
91     policy. This is like converting a derived class pointer to a base class pointer, only it happens
92     separately but at the same time for each policy axis:
93
94     \code
95     // This defines an incomplete policy where addressingPolicy and writePolicy
96     // are unspecified
97     typedef senf::MakeSocketPolicy<
98         senf::StreamFramingPolicy,
99         senf::ConnectedCommunicationPolicy,
100         senf::ReadablePolicy
101         >::policy MyReadableSocketPolicy
102
103     typedef senf::ClientSocketHandle<MyReadableSocketPolicy> MyReadableHandle;
104
105     // TCPv4ClientSocketHandle is a socket handle with the policy equivalent to
106     // senf::MakeSocketPolicy<
107     //     INet4AddressingPolicy,
108     //     StreamFramingPolicy,
109     //     ConnectedCommunicationPolicy,
110     //     ReadablePolicy,
111     //     WritablePolicy>::policy
112     senf::TCPv4ClientSocketHandle tcpHandle (...);
113
114     MyReadableHandle myHandle (tcpHandle); // Conversion to more basic socket handle
115     \endcode
116
117     \section policy_group_details The Policy Framework Classes
118
119     In the following discussion, deeper insight into C++ and especially the concepts of template
120     meta-programming are needed. However, this information is only needed if you want to write new
121     policy classes or want to use the policy framework explicitly for your own involved
122     optimizations ... or if you are just plain curious :-)
123
124     In the following discussion we will use the following conventions:
125     \li \e Axis is one or \c AddressingPolicy, \c FramingPolicy, \c CommunicationPolicy, \c
126         ReadPolicy or \c WritePolicy
127     \li \e socketPolicy is any socket policy (that is, an instantiation of the SocketPolicy
128         template)
129     \li \e trait is an any policy class (that is, any class derived from one of the axis base
130         classes)
131
132     Each axis is comprised of a number of classes and templates (all in namespace senf of course):
133
134     <dl><dt>\e Axis \c Base (ex: AddressingPolicyBase)</dt><dd>Baseclass of all policies in this
135     axis</dd>
136
137     <dt>\c Unspecified \e Axis (ex: \ref UnspecifiedAddressingPolicy)</dt> <dd>An alias (typedef)
138     for \e Axis \c Base</dd>
139
140     <dt>\e Axis \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)</dt> <dd>A template
141     metafunction returning \c boost::true_type, if \e trait (any class derived from \e Axis \c
142     Base) is a compatible policy value of the given \e socketPolicy</dd>
143
144     <dt>\c If \e Axis \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)</dt> <dd>This
145     is a combination of \e Axis \c Is and \c boost::enable_if</dd>
146
147     <dt>\c If \e Axis \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)</dt>
148     <dd>The inverse of above</dd> </dl>
149
150     These classes form the basis of the policy framework. To bind the policy axis together, there
151     are some more classes and templates.
152
153     <dl><dt>\c class \c SocketPolicyBase</dt> <dd>This class is the base class of the SocketPolicy
154     template. It is used to validate, that a class is really a SocketPolicy (by checking, that it
155     derives from SocketPolicyBase. This is simpler than checking the template directly).</dd>
156
157     <dt>\c template \c SocketPolicy < \e addressingPolicy, \e framingPolicy, \e communicationPolicy,
158     \e readPolicy, \e writePolicy ></dt> <dd>This is the central SocketPolicy
159     template. It combines a complete set of policy classes, one for each axis.</dd>
160
161     <dt>\c template \c MakeSocketPolicy < \e args ></dt> <dd>\c MakeSocketPolicy is a template
162     metafunction which simplifies building SocketPolicy instantiations. It takes any number (ok, up
163     to a maximum of 6) of policy classes as an argument (in any order). It will sort these arguments
164     into the SocketPolicy template arguments. If for some axis no class is specified, it's slot will
165     be filled with \c Unspecified \e Axis. Additionally, the first Argument may optionally be an
166     arbitrary SocketPolicy. It will provide default values for unspecified axis</dd>
167
168     <dt>\c template \c SocketPolicyIsBaseOf < \e base, \e derived ></dt> <dd>This template
169     metafunction will check, whether the socket policy \e derived is convertible to \e base. This
170     means, that for each axis, the corresponding policy class in \e derived must be derived or be
171     the same as the one on \e base.</dd> </dl>
172
173     \implementation All these classes are created automatically. The \c SENF_SOCKET_POLICIES macro
174     is a Boost.Preprocessor style sequence listing all policy axis. The Boost.Preprocessor library
175     is then used to generate the respective classes.
176
177     \section policy_implement Implementing Policy Classes
178
179     To define a new policy class, derive from the corresponding base class for your policy axes. The
180     only policy axis which might possibly need to be extended is the addressing policy
181     (AddressingPolicyBase). See the Documentation of these classes for more information on which
182     members can be implemented.
183
184     All members you define must be static. For any of the policy classes, you must only define those
185     members which are supported by your implementation. If you leave out a member you automatically
186     disable the corresponding functionality in the ClientSocketHandle/ServerSocketHandle interface.
187
188     The member prototypes given in the base class documentation only specify the call signature not
189     the way, the member must be defined (FileHandle really is not a FileHandle but an arbitrary
190     SocketHandle).
191
192     If the existence of a member depends on other policies, you should use the
193     <code>If</code><i>SomePolicy</i><code>Is</code> and
194     <code>If</code><i>SomePolicy</i><code>IsNot</code> templates to dynamically enable/disable the
195     member depending on some other policy:
196
197     \code
198       struct ExampleAddressingPolicy
199       {
200           template <class SPolicy>
201           void connect(senf::SocketHandle<SPolicy> handle, Address & addr,
202                        typename senf::IfCommmunicationPolicyIs<
203                            SPolicy, senf::ConnectedCommunicationPolicy>::type * = 0);
204       };
205     \endcode
206
207     The \c connect member in this example will only be enabled, it the communication policy of the
208     socket handle is ConnectedCommunicationPolicy (or a derived type). See <a
209     href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">Boost.Enable_If</a>
210     for a discussion of the third argument (\c senf::ConnectedCommunicationPolicyIs is based on
211     the \c boost::enable_if template).
212
213     \see \ref extend_policy \n
214          <a href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">The Boost enable_if utility</a> \n
215          <a href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html">The Boost.MPL library</a> \n
216          <a href="http://www.boost.org/doc/libs/release/libs/preprocessor/doc/index.html">The Boost.Preprocessor library</a>
217
218     \idea We could combine all the \e Axis \c Is templates into a single template. Since the \e
219     trait argument will automatically specify the axis to be used, it is not necessary to specify
220     that axis in the template functor's name. We could even combine this with \c
221     SocketPolicyIsBaseOf.
222  */
223
224 /** \defgroup policy_impl_group Policy Implementation classes
225     \ingroup policy_group
226
227     Here you will find all policy classes. Also included are some supporting classes which are used
228     as base classes to build other policy classes.
229  */
230
231 #ifndef HH_SENF_Socket_SocketPolicy_
232 #define HH_SENF_Socket_SocketPolicy_ 1
233
234 // Custom includes
235
236 //#include "SocketPolicy.mpp"
237 //-/////////////////////////////////////////////////////////////////////////////////////////////////
238
239 namespace senf {
240
241     /// \addtogroup policy_group
242     //\{
243
244     // This may be adapted to change the supported policies (however, ClientSocketHandle and
245     // ServerSocketHandle will probably have to be adjusted accordingly)
246
247     /** \brief List all policy axis
248
249         \internal
250
251         This define symbol is used to configure the policy axis. The base class for each of these
252         axis must be defined explicitly (e.g. AddressingPolicyBase). The implementation files will
253         then automatically generate all the other classes from this list.
254
255         \see policy_group
256      */
257 #   define SENF_SOCKET_POLICIES                 \
258         (AddressingPolicy)                      \
259         (FramingPolicy)                         \
260         (CommunicationPolicy)                   \
261         (ReadPolicy)                            \
262         (WritePolicy)
263
264     // Wer define these classes explicitly (and not with some macro
265     // magic) because
266     // a) AddressingPolicyBase is different from all the others
267     // b) We want to document each one explicitly
268
269     /** \brief Policy defining socket addressing
270
271         AddressingPolicyBase is the baseclass of all addressing policy classes. When defining a new
272         addressing policy, the following members can be defined. All methods must be static.
273
274         <table class="senf">
275         <tr><td>typedef</td> <td><tt>Address</tt></td>                                   <td>Address type</td></tr>
276         <tr><td>method</td>  <td><tt>void local(FileHandle, Address &)</tt></td>         <td>Get local socket address</td></tr>
277         <tr><td>method</td>  <td><tt>void peer(FileHandle, Address &)</tt></td>          <td>Get remote socket address</td></tr>
278         <tr><td>method</td>  <td><tt>void bind(FileHandle, Address const &)</tt></td>    <td>Bind socket to local address</td></tr>
279         <tr><td>method</tr>  <td><tt>void connect(FileHandle, Address const &)</tt></td> <td>Connect to remote address</td></tr>
280         </table>
281
282         \see policy_group
283      */
284     struct AddressingPolicyBase
285     {
286         virtual ~AddressingPolicyBase();
287
288         class Address { Address(); };
289     };
290
291     /** \brief Policy defining the framing format
292
293         This policy does not define any operations since it does have no influence on any method
294         signature. It does however affect the semantics of the \c read() and \c write() operations.
295
296         \note This policy axis probably only has two sensible states: StreamFramingPolicy and
297         DatagramFramingPolicy.
298
299         \see policy_group
300      */
301     struct FramingPolicyBase
302     {
303         virtual ~FramingPolicyBase();
304     };
305
306     /** \brief Policy defining, how peers are selected
307
308         The CommunicationPolicy may define two members:
309
310         <table class="senf">
311         <tr><td>method</td> <td><tt>void listen(FileHandle, unsigned backlog)</tt></td> <td>Switch socket into listening state</td></tr>
312         <tr><td>method</td> <td><tt>int accept(FileHandle, Address &)</tt></td>         <td>Accept a new connection</td></tr>
313         <tr><td>method</td> <td><tt>int accept(FileHandle)</tt></td>                    <td>Accept a new connection</td></tr>
314         </table>
315
316         The \c listen member is straight forward. The \c accept() member must return a new file
317         descriptor (which will be used to create a new SocketHandle of the correct
318         type).
319
320         \note This Policy only has two meaningful states: ConnectedCommunicationPolicy and
321         UnconnectedCommunicationPolicy. It is probably not sensible to define a new
322         CommunicationPolicy type.
323
324         \see policy_group
325      */
326     struct CommunicationPolicyBase
327     {
328         virtual ~CommunicationPolicyBase();
329     };
330
331     /** \brief Policy defining the readability
332
333         The ReadPolicy defines, whether the socket is readable. It may define two members:
334
335         <table class="senf">
336         <tr><td>method</td> <td><tt>unsigned read(FileHandle, char * buffer, unsigned size)</tt></td>                <td>read data from socket</td></tr>
337         <tr><td>method</td> <td><tt>unsigned readfrom(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
338         </table>
339
340         The second member should only be enabled if the communication policy is
341         UnconnectedCommunicationPolicy (otherwise it does not make sense since the communication partner
342         is fixed) (see AddressingPolicyBase on how to do this).
343
344         \note This Policy only has two meaningful states: ReadablePolicy and NotReadablePolicy. It
345         probably does not make sense to define new read policy types.
346
347         \see policy_group
348      */
349     struct ReadPolicyBase
350     {
351         virtual ~ReadPolicyBase();
352     };
353
354     /** \brief Policy defining the writability
355
356         The WritePolicy defines, whether the socket is writable. It may define two members:
357
358         <table class="senf">
359         <tr><td>method</td> <td><tt>unsigned write(FileHandle, char * buffer, unsigned size)</tt></td>              <td>read data from socket</td></tr>
360         <tr><td>method</td> <td><tt>unsigned writeto(FileHandle, char * buffer, unsigned size, Address &)</tt></td> <td>read data from unconnected socket</td></tr>
361         </table>
362
363         The second member should only be enabled if the communication policy is
364         UnconnectedCommunicationPolicy (otherwise it does not make sense since the communication partner
365         is fixed) (see AddressingPolicyBase on how to do this).
366
367         \note This Policy only has two meaningful states: WritablePolicy and NotWritablePolicy. It
368         probably does not make sense to define new write policy types.
369
370         \see policy_group
371      */
372     struct WritePolicyBase
373     {
374         virtual ~WritePolicyBase();
375     };
376
377     // The implementation file will for each Policy declared above
378     // define the following (SomePolicy is one of the above):
379     //
380     // struct SomePolicyBase;
381     // typedef UndefinedSomePolicy;
382     // template SomePolicyIs< SocketPolicy, Axis >
383     // template IfSomePolicyIs< SocketPolicy, Axis >
384     // template IfSomePolicyIsNot< SocketPolicy, Axis >
385     //
386     // Additionally the following are defined:
387     //
388     // class SocketPolicyBase
389     // template SocketPolicy< ..policies.. >
390     // template MakeSocketPolicy< ..args.. >
391     // template SocketPolicyIsBaseOf< Base, Derived >
392
393 #   ifdef DOXYGEN
394
395     // The following stub definitions are only visible to doxygen
396
397     /** \brief Alias of AddressingPolicyBase for better readability
398         \see \ref policy_group
399      */
400     typedef AddressingPolicyBase UnspecifiedAddressingPolicy;
401
402     /** \brief Check single policy axis
403
404         This template is an example of the \e Axis \c Is family of template metafunctions. It will
405         check, whether \c Trait is a valid compatible Policy class of \c SocketPolicy. \c Trait must
406         be derived from AddressingPolicyBase (respectively \c Policy \c Base).
407
408         \see \ref policy_group
409      */
410     template <class SocketPolicy, class Trait>
411     struct AddressingPolicyIs
412     {};
413
414     /** \brief Enable template overload depending on policy value
415
416         This template is an example of the \c If \e Axis \c Is family of templates. It is used like
417         <a href="http://www.boost.org/doc/libs/release/libs/utility/enable_if.html">Boost.enable_if</a>
418         to enable a templated overload only, if the AddressingPolicy of \e Axis is compatible with
419         \c Trait (that is the AddressingPolicy of \c Policy is derived from \c Trait).
420
421         \see policy_group
422      */
423     template <class SocketPolicy, class Trait>
424     struct IfAddressingPolicyIs
425     {};
426
427     /** \brief Inversion of \c IfAddressingPolicyIs
428         \see policy_group
429      */
430     template <class SocketPolicy, class Trait>
431     struct IfAddressingPolicyIsNot
432     {};
433
434     /** \brief Baseclass of all SocketPolicies
435
436         \internal
437
438         This class provides the baseclass of all socket policies (bundles). It serves two purposes:
439         \li It allows us to easily identify a socket policy bundle by checking a classes baseclass.
440         \li It provides an abstract (virtual) interface to access the policy axes
441
442         \see policy_group
443      */
444     struct SocketPolicyBase
445     {
446         /** \brief Polymorphic access to policy axes
447
448             This is an example of a policy axes accessor. It returns a reference to the policy axes
449             used by the concrete protocol bundle. This reference can then be checked using RTTI
450             information.
451          */
452         AddressingPolicyBase const & theAddressingPolicy() const = 0;
453
454         virtual ~SocketPolicyBase();
455     };
456
457     /** \brief Collection of policy classes
458
459         The SocketPolicy template defines the complete Policy used by the socket library. It
460         contains one policy class for each policy axis. This template takes one policy from each
461         axis as it's template arguments (this example implementation only has AddressingPolicy as an
462         argument).
463
464         A SocketPolicy can be complete or incomplete. An incomplete SocketPolicy will have at least
465         one axis set to \c Undefined \e Axis (or a generic derived class which is used to group some
466         other policies but does not (completely) define the policy behavior). A complete
467         SocketPolicy will have a concrete definition of the desired behavior for each policy axis.
468
469         \see policy_group
470      */
471     template < class AddressingPolicy >
472     struct SocketPolicy
473     {
474         /** \brief Check dynamic policy compatibility
475
476             This check will validate, that a socket with \a other as it's policy is convertible to a
477             socket with the current SocketPolicy as it's policy. This is true, if for each policy
478             axis, the policy class of that axis as defined in the \a other policy is convertible to
479             the policy class of that same axis in the current SocketPolicy instance (as is defined
480             by the template arguments). This again is true, if the \a other policy class is derived
481             from (or is the same as) the policy class taken from the current SocketPolicy instance.
482
483             In other words, this call checks, that the current SocketPolicy (as defined via the
484             template arguments) is more generic than the \a other socket policy.
485
486             \param[in] other SocketPolicy to check
487             \throws std::bad_cast if \a other is not a compatible policy
488          */
489         static void checkBaseOf(SocketPolicyBase const & other);
490     };
491
492     /** \brief Metafunction to create SocketPolicy
493
494         This template metafunction simplifies the creation of a SocketPolicy instantiation. It takes
495         any number (that is up to 6) of Policy classes as arguments in any Order. It will create a
496         SocketPolicy from these policy classes. Any axis not specified will be left as \c
497         Unspecified \e Axis.
498
499         \see policy_group
500      */
501     template <class Arg1, class Arg2, class ArgN>
502     struct MakeSocketPolicy
503     {};
504
505     /** \brief Check policy compatibility
506
507         This template metafunction checks, whether the SocketPolicy \c Derived is more specialized
508         than \c Base (and therefore a SocketHandle with policy \c Derived is convertible to a
509         SocketHandle with policy \c Base).
510
511         The metafunction will return true (that is inherits from \c boost::true_type, see the <a
512         href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html">Boost.MPL</a> library documentation for
513         more information) if each policy class in \c Base is a baseclass of (or the same as) the
514         corresponding policy class in \c Derived.
515
516         \see policy_group
517      */
518     template <class Base, class Derived>
519     struct SocketPolicyIsBaseOf
520     {};
521
522 #   endif
523
524     //\}
525 }
526
527 //-/////////////////////////////////////////////////////////////////////////////////////////////////
528 #include "SocketPolicy.ih"
529 //#include "SocketPolicy.cci"
530 #include "SocketPolicy.ct"
531 //#include "SocketPolicy.cti"
532 #endif
533
534 \f
535 // Local Variables:
536 // mode: c++
537 // fill-column: 100
538 // c-file-style: "senf"
539 // indent-tabs-mode: nil
540 // ispell-local-dictionary: "american"
541 // compile-command: "scons -u test"
542 // comment-column: 40
543 // End: