3.2.2 Event based API
The library main programming interface is event based. Event objects are used to pass data between the library and the application. The application have to perform pairs of calls to the assh_event_get and assh_event_done functions in order to run a session. These functions actually run the protocol state machines. The code below shows a simple construct that can be used for that purpose.
struct assh_event_s ev;
while (assh_event_get(session, &ev, time(0)))
{
assh_status_t err = ASSH_OK;
switch (ev.id)
{
...
}
assh_event_done(&session, &ev, err);
}
A processing error code can be reported to the library when acknowledging an event.
The event structure contains const fields and writable fields. Constant fields are meant to pass values from the library to the application and writable fields are meant to pass values back to the library. All event writable fields are initialized with default values so that any event not handled by the application can be acknowledged directly.
The code below handles the ASSH_EVENT_READ event by retrieving the ssh stream from a network socket using the read system call.
switch (ev.id)
{
case ASSH_EVENT_READ: {
ssize_t r = read(socket, ev.transport.read.buf.data,
ev.transport.read.buf.size);
if (r > 0)
ev.transport.read.transferred = r;
else
err = ASSH_ERR_IO;
break;
}
...
default:
break;
}
Because the event API is designed to let the application access most features of the ssh protocol, specified events reflect concepts used at the protocol level. Handling most of them involve some work in order to behave as a usual client or server application. In order to handle those events, the application may either rely on the provided helper functions or implement the whole thing. In the code below, helper functions are used:
switch (ev.id)
{
case ASSH_EVENT_READ:
case ASSH_EVENT_WRITE:
asshh_fd_event(&session, &ev, socket);
continue;
case ASSH_EVENT_KEX_HOSTKEY_LOOKUP:
asshh_client_event_hk_lookup(&session, ..., &ev);
continue;
...
default:
assh_event_done(&session, &ev, err);
}
This is how events reported by the library can be handled in a loop. Depending on the software design and programming model of the application, other programming constructs may be used. For instance, the application may start an asynchronous operation in response to an event, then call the assh_event_done function from one of its callback when the operation completes. Any model will work provided that an event reported by the library is acknowledged by the application at any later time.
Most example applications provided with the library do implement handling of libassh events.