/** \mainpage The SENF Socket Library The Socket library provides a high level and object oriented 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 rest of the socket API is accessible using a classic inheritance hierarchy of protocol classes The handle/body architecture provides automatic reference counted management of socket instances, the policy framework provides highly efficient access to the most important socket functions (like reading and writing) and the inheritance hierarchy provides convenient access to the multitude of special and protocol dependent options. \see \ref usage \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 socket_hierarchy The FileHandle hierarchy \image html FhHierarchy.png The senf::FileHandle class is the base of a hierarchy of socket handle classes (realized as templates). These classes provide an interface to the complete socket API. While going down the inheritance hierarchy, the interface will be more and more complete. The most complete interface is provided by senf::ProtocolClientSocketHandle and senf::ProtocolServerSocketHandle. The template Arguments specifies the Protocol class of the underlying socket type. These are the \e only classes having public constructors and are therefore the only classes, which may be created by the library user. You will normally use these classes by naming a specific socket typedef (e.g. senf::TCPv4ClientSocketHandle). However, to aid writing flexible and generic code, the socket library provides the senf::ClientSocketHandle and senf::ServerSocketHandle class templates. These templates implement a family of closely related classes based on the specification of the socket policy. This policy specification may be \e incomplete (see below). Instances of senf::ClientSocketHandle/senf::ServerSocketHandle can be assigned and converted to different ClientSocketHandle/ServerSocketHandle types as long as the policy specifications are compatible. \attention It is very important, to (almost) always pass the socket handle by value. 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 \image html SocketPolicy.png 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
addressingPolicy
configures, whether a socket is addressable and if so, configures the address type
framingPolicy
configures the type of framing the socket provides: either no framing providing a simple i/o stream or packet framing
communicationPolicy
configures,if and how the communication partner is selected
readPolicy
configures the readability of the socket
writePolicy
configures the writability of the socket
bufferingPolicy
configures, if and how buffering is configured for a socket
Every Policy value is identified by a class type. The policy types themselves built an inheritance hierarchy for each policy axis. For each policy axis, the root of this tree is the class named '(axis name)Base' (e.g. \p FramingPolicyBase or \p CommunicationPolicyBase) which is aliased to 'Unspecified(axis name)' (e.g. \p UnspecifiedFramingPolicy or \p UnspecifiedCommunicationPolicy). The senf::SocketPolicy template combines a set of policy classes, one for each policy axis. Together, they define the behavior of a socket handle. The socket handle instances do net implement any socket functionality themselves, instead defering the implementation to the socket classes. The interface is therefore \e not implemented using virtual members, all important socket functions can be inlined by the compiler to create highly efficient code. Two SocketPolicy instances are considered compatible, if all policy axis are compatible. A policy axis is compatible, if one policy class is either the same as the other or derived from it. Two SocketHandle instances can be converted into each other, as long as the SocketPolicies are compatible. \section protocol_interface The protocol interface \image html Protocols.png The socket handle classes and templates only implement the most important socket API methods using the policy framework. To access the complete API, the protocol interface is provided. Access to the protocol interface is only possible via senf::ProtocolClientSocketHandle and senf::ProtocolServerSocketHandle which have the necessary \c protocol() member. This member returns a reference to the protocol class instance which contains members covering all the API function (mostly setsockopt/getsockopt related calls) not found in the SocketHandle interface. The protocol interface is specific to the protocol. It's implementation is quite free. The standard protocols are implemented using a simple multiple-inheritance hierarchy as shown above. Since the protocol class is protocol specific (how intelligent ...), the protocol class also defines the complete socket policy to be used with it's protocol. Complete meaning, that every policy axis must be assigned it's the most specific (that is derived) policy class to be used with the protocol. */ /** \page extend Extending the Library 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 ordinere 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 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. 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 typedef senf::ProtocolClientSocketHandle MyProtocolClientSocketHandle; typedef senf::ProtocolServerSocketHandle MyProtocolServerSocketHandle; \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 must not 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.
SocketHandle member Policy member
senf::ClientSocketHandle::read ReadPolicy::read (\ref senf::ReadPolicyBase)
senf::ClientSocketHandle::readfrom ReadPolicy::readfrom (\ref senf::ReadPolicyBase)
senf::ClientSocketHandle::write WritePolicy::write (\ref senf::WritePolicyBase)
senf::ClientSocketHandle::writeto WritePolicy::writeto (\ref senf::WritePolicyBase)
senf::ClientSocketHandle::connect AddressingPolicy::connect (\ref senf::AddressingPolicyBase)
senf::ClientSocketHandle::bind AddressingPolicy::bind (\ref senf::AddressingPolicyBase)
senf::ClientSocketHandle::peer AddressingPolicy::peer (\ref senf::AddressingPolicyBase)
senf::ClientSocketHandle::local AddressingPolicy::local (\ref senf::AddressingPolicyBase)
senf::ClientSocketHandle::rcvbuf BufferingPolicy::sndbuf (\ref senf::BufferingPolicyBase)
senf::ClientSocketHandle::sndbuf BufferingPolicy::rcvbuf (\ref senf::BufferingPolicyBase)
senf::ServerSocketHandle::bind AddressingPolicy::bind (\ref senf::AddressingPolicyBase)
senf::ServerSocketHandle::listen CommunicationPolicy::listen (\ref senf::CommunicationPolicyBase)
senf::ServerSocketHandle::local AddressingPolicy::local (\ref senf::AddressingPolicyBase)
senf::ServerSocketHandle::accept CommunicationPolicy::accept (\ref senf::CommunicationPolicyBase)
senf::ServerSocketHandle::acceptfrom CommunicationPolicy::accept (\ref senf::CommunicationPolicyBase)
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). */ /** \page implementation Implementation notes \image html SocketLibrary-classes.png */ // Local Variables: // mode: c++ // mode: flyspell // mode: auto-fill // ispell-local-dictionary: "american" // End: