The Truth About Types

Cleansocks uses the C++ type system to make a networking API that is more straightforward to use than sockets, while retaining many of its concepts.

Sockets

The sockets form an inheritance hierarchy. It's not large, but may be extended in the future. The class socket is base for each of TCPsocket and UDPsocket. These wrap the O/S socket of the particular type, and the user creates the socket objects of the correct type.

Cleansocks allows sockets of any type to be copied or assigned, but assignments between different types are checked dynamically that the underlying sockets are the same. This is done mainly because sockets returned by the system (such as from accept) have to be created as base class objects. If they are copied or assigned to TCPsocket or UDPsocket, the type is checked. If necessary, the socket type is recovered from the native getsockopt call.

Likewise, IPendpoint is derived from endpoint.

Socketish

The ability to send, receive and close is represented by three abstract classes, sr_obj, srf_obj and srfln_obj, each derived from the previous. These are like java interfaces, containing only abstract methods, send, recv and close. The sr_obj versions lack the flags parameter, which srf_obj possesses, and srfln_obj adds the recvln. The socket, buffered_socket and client_tls_socket objects are all derived from the appropriate of these interfaces, and implement the required abstract methods.

Then the top-level functions send, recv, recvln and close take the appropriate abstract type by reference and call the associated method. Then they can be sent sockets or extension objects, and they do the right thing. The documentation sections for sockets and the extension objects describe send et. al. as taking the object being described. That's not actually so; there is not one version of recv for TCPsocket and another for client_tls_socket, etc. There are two (with and without flags) and they take the appropriat abstract type as their first parameter.

Flags

There are two sets of flags: clean_flags and cleantlsc_flags. Both are just wrappers for integer values which represent sets of flags by assigning a power of two to each one, and combining them with bit-wise or. The clean_flags type wraps whatever values are present in the native sockets implementation, while cleantlsc_flags wraps a set of values defined by Cleansocks. The | operator is defined for the wrapper classes to perform the or on the contained values, so they can be built as usual. But implicit conversion from integer is not allowed. This avoids possible ambiguities between the various send and recv versions, since the buffer size is a distinct type from the flags, and requires the programmer to put a bit more work into certain risky things like using native flags.

The system is actually defined as a template with a single integer template perameter whose only purpose is to make the different groups of flags distinct types, so that MSG_PEEK|NO_CERT_CHECK won't compile. For all the gory details, consult cleanflags.h.