[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Async Socket Interface

Aris et al,

Here is the interface I conceived of for a communications layer that is
both a) replaceable and b) easy to adapt to any situation (including not
using TCP sockets for communications).  Not to mention easy to implement
;)  I posted this in IRC a while back, but you mentioned you lost it.

Two key concepts here are that there is a handle provided by the comms
implementation to libssl upon a connection being established, and libssl
provides back another handle (ssh_session) back to the comms layer which
is used for future communications.  Both of these handles should be
opaque to the other (ie. the imeplementation does not matter).  This
allows libssl to change the implementation of ssh_session, or the comms
implementor to change the implementation of their handle at will without
affecting the other at all.

The interface itself consists of only 3 function calls and 2 callbacks. 
ALL the details regarding how to setup the socket, whether it's blocking
or not, how to send or receive data, or anything of the like are in the
complete control of the comms layer implementor.  I also made sure that
all buffering (in both directions) of data is done in the comms layer.

This, though, requires that libssl itself must be 'reactionary' to
received data, and not have any wait calls or anything that will require
libssl to have to block waiting for more data to arrive before being
able to do anything.  This may mean some functions such as ssh_accept
need to be split up and/or rewritten to be able to handle that the send
and receive operations are separate entities.

Proposed Interface:

// ---------------------------------------------------------------------
// Callbacks
// ---------------------------------------------------------------------

// Description:
//     Callback to have data sent over the wire to the other side.
//     It is the implementor's responsibility to ensure that all data
//     gets to the other side.  This could mean blocking while waiting
//     for the send to complete, or it could mean the data has been
//     buffered and will be sent asynchronously.
// Arguments:
//     void * handle  - Opaque (to libssl) handle for socket.
//     void * buffer  - Raw buffer to be sent over the wire.
//     size_t size    - Size of raw buffer.
// Return:
//     int            - 0 on success, otherwise -1
typedef int (*comm_send_data)(void *, void *, size_t);

// Description:
//     Callback to request the communications channel be closed.
// Arguments:
//     void * handle   - Opaque (to libssl) handle for socket.
typedef void (*comm_close)(void *);

// ---------------------------------------------------------------------
// ---------------------------------------------------------------------

// Description:
//     Create a libssl session from a newly created comms channel.
// Arguments:
//     handle         - Opaque (to libssl) handle for socket.
//     send_func      - Function pointer (see above) for sending data.
//     close_func     - Function pointer (see above) for closing socket.
// Return:
//     ssl_esssion *  - Opaque (to comms implementation) handle for an
//                      OpenSSL session.
ssl_session *session_create(void *handle, comm_send_data send_func,
                            comm_close close_func);

// Description:
//     Process data received over the wire.
//     It is expected that LibSSL will take what it wants from the
//     buffer and tell you how much it has taken.  It is then assumed
//     the caller will, if the entire buffer was not consumed, prepend
//     the unconsumed data to the next invocation of this function call.
//     The next invocation only need be made when there is additional
//     date come over the wire (ie. there is no need to call this in a
//     loop until 0 is returned), LibSSL will always consume as much as
//     it can while still having fully-formed messages.
// Arguments:
//     handle         - Opaque (to comms implementation) handle for an
//                      OpenSSL session.
//     buffer         - Raw buffer received over the wire.
//     size           - Size of raw buffer.
// Return:
//     int            - The amount of data consumed.  Or -1 on error.
int session_receive(ssl_session *handle, void *data, size_t sz);

// Description:
//     Callback to indicate the comms channel has been closed by the
//     other side (ie. unsolicited closure).
// Arguments:
//     handle         - Opaque (to comms implementation) handle for an
//                      OpenSSL session.
void session_close(ssl_session *handle);

Re: Async Socket Interface"Preston A. Elder" <prez@xxxxxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org