abstraction of the BSD socket API. The abstraction is based on
several concepts:
- \li The basic visible interface is a handle object
- (senf::FileHandle and it's derived classes)
- \li The socket interface relies on a policy framework to configure
- it's functionality
+ \li The basic visible interface is a \link handle_group handle
+ object \endlink
+ \li The socket interface relies on a \link policy_group policy
+ framework \endlink to configure it's functionality
\li The rest of the socket API is accessible using a classic
- inheritance hierarchy of protocol classes
+ inheritance hierarchy of \link protocol_group protocol classes
+ \endlink
The handle/body architecture provides automatic reference counted
management of socket instances, the policy framework provides
dependent options.
\see \ref usage \n
- \ref extend \n
+ \ref handle_group \n
+ \ref policy_group \n
+ \ref protocol_group \n
+ \ref extend \n
\ref implementation
*/
/** \page usage Using the Socket Library
- \section socket_handle The socket handle
-
Whenever you use the socket library, what you will be dealing with
are senf::FileHandle derived instances. The socket library relies
on reference counting to automatically manage the underlying
socket representation. This frees you of having to manage the
socket lifetime explicitly.
+
+ \section usage_create Creating a Socket Handle
+
+ To create a new socket handle (opening a socket), you will need to
+ use senf::ProtocolClientSocketHandle or
+ senf::ProtocolServerSocketHandle. You will probably not use these
+ templates as is but use proper typedefs (for example
+ senf::TCPv4ClientSocketHandle or senf::PacketSocketHandle). The
+ documentation for these socket handles are found in the protocol
+ class (for example senf::TCPv4SocketProtocol or
+ senf::PacketProtocol).
+
+ \section usage_reusable Writing Reusable Components
+
+ To make your code more flexible, you should not pass around your
+ socket in this form. Most of your code will be using only a small
+ subset of the senf::ProtocolClientSocketHandle or
+ senf::ProtocolServerSocketHandle API. If instead of using the
+ fully specified handle type you use a more incomplete type, you
+ allow your code to be used with all socket which fulfill the
+ minimal requirements of your code.
+
+ This works, by defining a special reduced policy or handle for
+ your code:
+
+ \code
+ typedef senf::ClientSocketHandle<
+ senf::MakeSocketPolicy<
+ senf::ReadablePolicy,
+ senf::StreamFramingPolicy,
+ senf::ConnectedCommunicationPolicy > > MyReadableHandle;
+
+ \endcode
+
+ This defines \c MyReadableHandle as a senf::ClientSocketHandle
+ which will have only read functionality. Your code expects a
+ stream interface (in contrast to a packet or datagram based
+ interface). You will not have \c write or \c readfrom members. \c
+ write will be disabled since the WritePolicy is unknown, \c
+ readfrom will be disabled since a socket with the
+ senf::ConnectedCommunicationPolicy does not have a \c readfrom
+ member.
+ */
- \attention It is very important, to (almost) always pass the socket
- handle <em>by value</em>. The socket handle is a very lightweight
- class and designed to be used like an ordinary built-in type. This
- is very important in combination with the policy interface.
-
- \section policy_framework The policy framework
-
- The policy framework conceptually implements a list of parallel
- inheritance hierarchies each covering a specific interface aspect
- of the socket handle. The socket handle itself only provides
- minimal functionality. All further functionality is relayed to a
- policy class, or more precisely, to a group of policy classes, one
- for each policy axis. The policy axis are
-
- <dl>
- <dt><em>addressingPolicy</em></dt>
- <dd>configures, whether a socket is
- addressable and if so, configures the address type</dd>
-
- <dt><em>framingPolicy</em></dt>
- <dd>configures the type of framing the socket provides: either no
- framing providing a simple i/o stream or packet framing</dd>
-
- <dt><em>communicationPolicy</em></dt>
- <dd>configures,if and how the communication partner is
- selected</dd>
-
- <dt><em>readPolicy</em></dt>
- <dd>configures the readability of the socket</dd>
+
+
+/** \page extend Extending the Library
- <dt><em>writePolicy</em></dt>
- <dd>configures the writability of the socket</dd>
+ There are two layers, on which the socket library can be
+ extended: On the protocol layer and on the policy layer. Extending
+ the protocol layer is quite simple and works as long as the
+ desired protocol does use the same BSD API used by the standard
+ internet protocols as implemented in the standard policies
+ (i.e. it uses ordinary read() and write() or rcvfrom() or sendto()
+ calls and so on).
+
+ If however the implementation of a policy feature needs to be
+ changed, a new policy class has to be written. This also is not
+ very complicated however the integration is more complex.
+
+ \section extend_protocol Writing a new protocol class
- <dt><em>bufferingPolicy</em></dt>
- <dd>configures, if and how buffering is configured for a socket</dd>
- </dl>
+ Most protocols can be implemented by just implementing a new
+ protocol class. The protocol class must be derived from
+ senf::ConcreteSocketProtocol and takes the socket policy (as
+ created by senf::MakeSocketPolicy) as a template argument. See the
+ documentation of this class for the interface.
- */
+ \attention
+ You may want to use multiple inheritance as it is used in the
+ implementation of the standard protocols (See \ref
+ protocol_interface). You must however be extra careful to ensure,
+ that every class ultimately has senf::SocketPolicy as a public
+ \e virtual base.
-/** \page extend Extending the Library
+ After the protocol class has been defined, you will probably want to
+ provide typedefs for the new protocol sockets. If the new protocol
+ is connection oriented, this will be like
+ <code>
+ typedef senf::ProtocolClientSocketHandle<MyProtocolClass> MyProtocolClientSocketHandle;
+ typedef senf::ProtocolServerSocketHandle<MyProtocolClass> MyProtocolServerSocketHandle;
+ </code>
+
+ \section extend_policy Extending the policy framework
+
+ If you have to extend the policy framework, you will need to be
+ aware of some important limitations of the socket library:
+
+ \li When you define a new policy for some axis, this new policy
+ <em>must not</em> be derived from one of the existing concrete
+ policy classes (except of course the respective policy axis
+ base class). This is important since the policy type is \e not
+ polymorphic. The policy to be used is selected by the compiler
+ using the \e static type, which is exactly what is desired,
+ since this allows calls to be efficiently inlined.
+
+ \li Therefore, extending the policy framework will make the new
+ socket probably \e incompatible with generic code which relies
+ on the policy axis which is extended. Example: If you write a
+ new write policy because your protocol does not use ordinary
+ write() system calls but some protocol specific API, Then any
+ generic function relying on senf::WritablePolicy will \e not
+ work with the new socket, since the socket does \e not have
+ this policy, it has some other kind of write policy.
+
+ Therefore you need to be careful of what you are doing. The first
+ step is to find out, which policy you will have to implement. For
+ this, find the senf::ClientSocketHandle and/or
+ senf::ServerSocketHandle members you want to change. The following
+ table shows, which policy axis is responsible for which
+ members. The policy axis base class documentation contains further
+ information on how to implement that policy.
+
+ <table class="senf">
+ <tr><th>SocketHandle member</th> <th>Policy member</th></tr>
+ <tr><td>senf::ClientSocketHandle::read</td> <td>ReadPolicy::read (\ref senf::ReadPolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::readfrom</td> <td>ReadPolicy::readfrom (\ref senf::ReadPolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::write</td> <td>WritePolicy::write (\ref senf::WritePolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::writeto</td> <td>WritePolicy::writeto (\ref senf::WritePolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::connect</td> <td>AddressingPolicy::connect (\ref senf::AddressingPolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::bind</td> <td>AddressingPolicy::bind (\ref senf::AddressingPolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::peer</td> <td>AddressingPolicy::peer (\ref senf::AddressingPolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::local</td> <td>AddressingPolicy::local (\ref senf::AddressingPolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::rcvbuf</td> <td>BufferingPolicy::sndbuf (\ref senf::BufferingPolicyBase)</td></tr>
+ <tr><td>senf::ClientSocketHandle::sndbuf</td> <td>BufferingPolicy::rcvbuf (\ref senf::BufferingPolicyBase)</td></tr>
+ <tr><td>senf::ServerSocketHandle::bind</td> <td>AddressingPolicy::bind (\ref senf::AddressingPolicyBase)</td></tr>
+ <tr><td>senf::ServerSocketHandle::listen</td> <td>CommunicationPolicy::listen (\ref senf::CommunicationPolicyBase)</td></tr>
+ <tr><td>senf::ServerSocketHandle::local</td> <td>AddressingPolicy::local (\ref senf::AddressingPolicyBase)</td></tr>
+ <tr><td>senf::ServerSocketHandle::accept</td> <td>CommunicationPolicy::accept (\ref senf::CommunicationPolicyBase)</td></tr>
+ <tr><td>senf::ServerSocketHandle::acceptfrom</td> <td>CommunicationPolicy::accept (\ref senf::CommunicationPolicyBase)</td></tr>
+ </table>
+
+ As you can see from this list, not all policy axis directly
+ contribute to the SocketHandle interface. However, some policy
+ members additionally depend on other policy axis (example:
+ AddressingPolicy::connect is only defined if the communication
+ policy is ConnectedCommunication).
+
+ \see policy_group
*/
/** \page implementation Implementation notes
- \image html "../../SocketLibrary-classes.png" Class hierarchy
+ \image html SocketLibrary-classes.png
*/
-
\f
// Local Variables:
// mode: c++