8.1 External I/O event loops in the client.
The reference implementation for using external I/O event loops in the
client is the GPGME library, which exports its own external I/O event
loop mechanism and utilizes the Assuan library transparently for the
user. The following steps document how GPGME achieves this.
- Before connecting, set up pipes for bulk data transfer (using the
INPUT/OUTPUT commands, for example). These are passed to the server
either by inheritance (using a pipe server) or by FD passing (using a
socket server).
- Then you need to connect to the server. GPGME uses a pipe server, so
it just spawns a server process, which is a non-blocking operation.
FIXME: Currently, using a client with external event loop over a
socket connection is not supported. It is easy to support (we just
need a variation of
assuan_socket_connect
which takes an
already connected socket FD and turns it into an Assuan context), so
if you need this let us know.
- After connecting, get the inbound status FD with
assuan_get_active_fds
(the first one returned is the status
FD). This FD can be duplicated if it is convenient (GPGME does this
to be able to close this FD and associated callback handlers without
disrupting Assuan's internals).
- Then register the Assuan inbound status FD and all bulk data FDs with
the I/O event mechanism. In general, this requires setting up
callback handlers for these FDs and registering them with the main
event loop.
- When bulk data FDs become ready, you can simply perform the
corresponding read or write operations. When the inbound status FD
becomes ready, you can receive the next server line with
assuan_read_line().
- You should close and unregister the bulk data FDs when you wrote all
data (for outbound FDs) or receive an EOF (for inbound FDs). When you
receive an ERR from the server, or an OK for the final operation, you
can unregister the inbound status FD and call
assuan_disconnect
to close it.
- As noted above, all send operations on the outbound status FD are done
immediate with blocking. In GPGME, this has never caused any problems.
- The
INQUIRE
function can be handled in two ways: If the
requested data is immediately available, the client can just send the
data blockingly. If the requested data needs to be fetched from a
blocking source, a callback handler can be registered for the FD with
the main event loop. GPGME does not support the INQUIRE
function, so we do not have any practical experience with this.
Currently, the client can not cancel a pending operation gracefully.
It can, however, disconnect from the server at any time. It is the
responsibility of the server to periodically send status messages to
the client to probe if the connection remains alive.