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

Re: Async Socket Interface


Hello there,

I made a little graph of how I see the flow of calls, from socket to
user program. The upward direction (^) shows a forward call (std call).
A bottom one (v) indicates a reverse call, ie a callback.

Each layer will provide functions to registers callbacks (reverse
function calls) and ideally each layer will also provide its interface
(forward function calls) in a structure so it's easy to replace (socket
comes to mind).

Also, look how channel and socket are similar. Idealy one could do ssh
over ssh easily with this... I also have glibnet integration in mind.

Feel free to comment.

Regards,

Aris
Aris Adamantiadis a écrit :
> Hello Preston,
> 
> I did some work during the holiday and as you will see I have made some
> work in this direction.
> 
> Just check out the branch libssh_async which can be found on
> git clone http://www.0xbadc0de.be/git/libssh/libssh_async.git
> (or some git add trickery if you manage to make it work.)
> It's the skeleton of the future asyncronous libssh. Don't try to run it,
> it doesn't really work (only some part of the calls have been made async
> and there is not yet an integrated main loop provider).
> 
> The callback systems (that is, reverse calls) are all made virtual
> through function pointers, between the different layers of the library.
> The forward calls (ie. send_packet() and al) are still hardcoded but
> could be set the same way.
> 
> Please feel free to comment on what you think about this, if I am going
> in the good direction or not. I really think it is.
> 
> Regards,
> 
> Aris
> 
> Preston A. Elder a écrit :
>> I just realized in the below code I refer to 'OpenSSL' and 'LibSSL'.
>> Both should be 'libssh'.
>>
>> Sorry for the confusion.
>>
>> PreZ :)
>>
>> Preston A. Elder wrote:
>>> 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 *);
>>>
>>> // ---------------------------------------------------------------------
>>> // LibSSL API
>>> // ---------------------------------------------------------------------
>>>
>>> // 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);
>>>
>>>
>>>
>>>   
>>
>>
> 

PNG image


Archive administrator: postmaster@lists.cynapses.org