X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Socket%2FMainpage.dox;h=4802f4af5294eb641f8417db998c4bec13322158;hb=9a988902090d28007578e93bffd809f6bd913155;hp=2721d3696778685f2e6d12b66b802baf87efeabb;hpb=032707d24b1059febe83ce56b11fd79df106c6e2;p=senf.git diff --git a/Socket/Mainpage.dox b/Socket/Mainpage.dox index 2721d36..4802f4a 100644 --- a/Socket/Mainpage.dox +++ b/Socket/Mainpage.dox @@ -1,257 +1,286 @@ +namespace senf { + /** \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 + 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 \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 \link + protocol_group protocol classes \endlink + + 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 structure \n + \ref usage \n + \ref handle_group \n + \ref policy_group \n + \ref protocol_group \n \ref extend \n \ref implementation */ +/** \page structure Overview of the Socket Library Structure + + \image html Handle.png + + This diagram tries to give a structural overview of the Socket Library, it does \e not directly + show, how the library is implemented. This will be explained later. + + The outside interface to the library is a Handle object. This is the only object, the library + user directly interacts with. Every handle references some socket. This is like the ordinary + POSIX API: the file descriptor (also called file handle, an integer number) references a socket + structure which lives in kernel space. In this library, the Handle object (which is not a simple + integer any more but an object) references the Socket (which is part of the + implementation). Several handles may reference the same Socket. In contrast to the kernel API, + the library employs reference counting to release a socket when the last Handle to it goes out + of scope. + + The behavior of a Socket is defined by it's Protocol. It is divided into two parts: the + policy interface and the protocol interface. Together they provide the + complete API for a specific type of Socket as defined by the Protocol. The policy + interface provides highly efficient access to the most frequently used operations whereas + the protocol interface completes the interface by providing a complete set of all + protocol specific operations not found in the policy interface. This structure allows us to + combine the benefits of two design methodologies: The policy interface utilizes a policy based + design technique and is highly efficient albeit more complex to implement, whereas the protocol + interface is based on a more common inheritance architecture which is not as optimized for + performance but much simpler to implement. We reduce the complexity of the implementation by + reducing the policy interface to a minimal sensible subset of the complete API. + + \section over_policy The Policy Interface + + The policy of a Socket consists of several parts, called policy axis. Each axis + corresponds to one specific interface aspect of the Socket. The exact meaning of the policy axis + are defined elsewhere (see \ref policy_group). The Protocol will always provide a complete set + of policy classes, one for each axis. + + This complete socket policy defines the policy interface of the protocol. This + interface is carried over into the Handle. The socket policy as defined in the Handle however + may be incomplete. This mans, that the \e accessible interface of the Socket depends on + the type of Handle used. The inherent interface does not change but the view of this interface + does if the Handle does not provide the \e complete policy interface. This feature is very + important. It allows to define generic Handle types. A generic Handle with an incompletely + defined policy can point to an arbitrary Socket as long as all those policy axis which \e are + defined match those defined in that Socket's protocol. Using such a generic handle decouples the + implementation parts using this handle from the other socket aspects (e.g. you may define a + generic socket handle for TCP based communication leaving the addressingPolicy undefined which + makes your code independent of the type of addressing, IPv4 or IPv6). + + This can be described as generalized compile-time polymorphism: A base class reference to some + derived class will only give access to a reduced interface (the base class interface) of a + class. The class still is of it's derived type (and inherently has the complete interface) but + only part of it is accessible via the base class reference. Likewise a generic handle (aka base + class reference) will only provide a reduced interface (aka base class interface) to the derived + class instance (aka socket). + + \section over_protocol The Protocol Interface + + The protocol interface is provided by a set of protocol facets. Each facet provides a + part of the interface. Whereas the policy interface is strictly defined (the number and type of + policy axis is fixed and also the possible members provided by the policy interface are fixed), + the protocol interface is much more flexible. Any member needed to provide a complete API for + the specific protocol may be defined, the number and type of facets combined to provide the + complete interface is up to the Protocol implementor. This flexibility is necessary to provide a + complete API for every possible protocol. + + However this flexibility comes at a cost: To access the protocol interface the user must know + the exact protocol of the socket. With other words, the protocol is only accessible if the + handle you use is a protocol specific handle. A protocol specific Handle differs from a + generic Handle in two ways: It always has a complete policy and it knows the exact protocol type + of the socket (which generic handles don't). This allows to access to the complete protocol + interface. + + \section over_impl Implementation of the Socket Libarary Structure + + In the Implementation, the socket policy is identified by an instance of the senf::SocketPolicy + template. The Socket representation is internally represented in a senf::SocketBody which is not + outside visible. The Handle is provided by a hierarchy of handle templates. Each Handle template + uses template arguments for the policy and/or protocol as needed (see \ref handle_group). + + The Handle hierarchy divides the interface into two separate strains: the client interface + (senf::ClientSocketHandle and senf::ProtocolClientSocketHandle) provides the interface of a + client socket whereas the server interface (senf::ServerSocketHandle and + senf::ProtocolServerSocketHandle) provides the interface as used by server sockets. + + The protocol interface is implemented using inheritance: The Protocol class inherits from each + protocol facet using multiple (virtual public) inheritance. The Protocol class therefore + provides the complete protocol API in a unified (see \ref protocol_group). + */ + /** \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 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. - 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. + \section usage_create Creating a Socket Handle + + To create a new socket handle (opening a socket), you will need to use + ProtocolClientSocketHandle or ProtocolServerSocketHandle. You will probably not use these + templates as is but use proper typedefs (for example TCPv4ClientSocketHandle or + PacketSocketHandle). The documentation for these socket handles are found in the protocol class + (for example TCPv4SocketProtocol or 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 ProtocolClientSocketHandle or + 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 sockets which fulfill the minimal requirements of your code. These + types are based on the ClientSocketHandle and ServerSocketHandle templates which implement the + policy interface without providing the concrete protocol interface. To use those templates you + may define a special reduced policy or handle for your code. By giving only an incomplete policy + you thereby reduce the interface to that required by your module: + + \code + typedef ClientSocketHandle< + MakeSocketPolicy< + ReadablePolicy, + StreamFramingPolicy, + ConnectedCommunicationPolicy > > MyReadableHandle; + + \endcode + + This defines \c MyReadableHandle as a 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 + ConnectedCommunicationPolicy does not have a \c readfrom member. + + \see + \ref policy_group \n + \ref handle_group \n + \ref protocol_group */ /** \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. + + 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 - - 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; - + + Most protocols can be implemented by just implementing a new protocol class. The protocol class + must be derived from ConcreteSocketProtocol and takes the socket policy (as created by + 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_group). You must however be extra careful to ensure, that + every class ultimately has 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 + \code + typedef ProtocolClientSocketHandle MyProtocolClientSocketHandle; + typedef ProtocolServerSocketHandle MyProtocolServerSocketHandle; + \endcode \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)
+ 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 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 ClientSocketHandle and/or + ServerSocketHandle members you want to change (see \ref ClientSocketHandle and \ref + ServerSocketHandle). 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 glossary Glossary + + + + + + + + + + + + + + - 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). + + + + + + +
policy collection of policy classes, one for each policy axis, instantiation of + the SocketPolicy template
policy axis one aspect defined in the socket policy, typedef and member of the + SocketPolicy template
policy class implementation of a single policy axis, class derived from the + axis base class
complete policy socket policy where each axis is specified completely
incomplete policy socket policy, where at least one axis is not fully + specified
protocol class definition of a protocol as a class, class inheriting from + ConcreteSocketProtocol.
protocol facet a class providing some subset of the protocol interface, class + derived from SocketProtocol but not from ConcreteSocketProtocol
policy interface interface directly provided by + ClientSocketHandle/ServerSocketHandle and defined through the policy
protocol interface interface provided by the protocol class and accessible via + the ProtocolClientSocketHandle::protocol()/ProtocolServerSocketHandle::protocol() + member
*/ /** \page implementation Implementation notes + \section class_diagram Class Diagram + \image html SocketLibrary-classes.png + + \section impl_notes Arbitrary Implementation Notes + + \li The implementation tries to isolate the library user as much as possible from the system + header files since those headers define a lot of define symbols and introduce a host of + symbols into the global namespace. This is, why some classes define their own \c enum types + to replace system defined define constants. This also precludes inlining some functionality. + + \li To reduce overhead, template functions/members which are more than one-liners are often + implemented in terms of a non-template function/member. This is also used to further the + isolation from system headers as defined above (template code must always be included into + every compilation unit together with all headers need for the implementation). */ +} + // Local Variables: // mode: c++ +// fill-column: 100 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" // mode: flyspell // mode: auto-fill -// ispell-local-dictionary: "american" // End: