Previous: , Up: External I/O Loop   [Contents][Index]

8.2 External I/O event loops in the server.

Currently, no Assuan server exists which uses external I/O event loops. However, the following guidelines should lead to a usable implementation:

  1. For socket servers: You can not use assuan_accept, so you should just implement the bind/connect/listen/accept stage yourself. You can register the listen FD with your main event loop, accept the connection when it becomes ready, and finally call assuan_init_socket_server with the final argument being ASSUAN_SOCKET_SERVER_ACCEPTED to create an Assuan context for this connection. This way you can also handle multiple connections in parallel. The reference implementation for this approach is DirMngr.

    For pipe servers: assuan_init_pipe_server creates an Assuan context valid for the pipe FDs.

  2. Once you have a context for a single connection, you can 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. Every time the inbound status FD is readable, you should invoke the function assuan_process_next (see below) to process the next incoming message. assuan_process_next processes as many status lines as can be received by a single read operation. When it returns, the inbound status FD may still be readable, but Assuan does not check this.

    The function assuan_process_next returns 0 if it can not make progress reliably, and it returns true in done if the client closed the connection. See below for more information on this function.

  3. The command will be dispatched by assuan_process_next just as with assuan_process, however, you will want to implement the command handlers in such a way that they do not block. For example, the command handler may just register the bulk data FDs with the main event loop and return.

    When the command is finished, irregardless if this happens directly in the command handler or later, you must call assuan_process_done with an appropriate error value (or 0 for success) to return an appropriate status line to the client. You can do this at the end of the command handler, for example by ending it with return assuan_process_done (error_code);. Another possibility is to invoke assuan_process_done from the place in the code which closes the last active bulk FD registered with the main event loop for this operation.

It is not possible to use assuan_inquire in a command handler, as this function blocks on receiving the inquired data from the client. Instead, the asynchronous version assuan_inquire_ext needs to be used (see below), which invokes a callback when the client provided the inquired data. A typical usage would be for the command handler to register a continuation with assuan_inquire_ext and return 0. Eventually, the continuation would be invoked by assuan_process_next when the client data arrived. The continuation could complete the command and eventually call assuan_process_done.

Cancellation is supported by returning an appropriate error value to the client with assuan_process_done. For long running operations, the server should send progress status messages to the client in regular intervals to notice when the client disconnects.

Function: gpg_error_t assuan_process_next (assuan_context_t ctx, int *done)

This is the same as assuan_process but the caller has to provide the outer loop. He should loop as long as the return code is zero and done is false.

Function: gpg_error_t assuan_process_done (assuan_context_t ctx, gpg_error_t rc)

Finish a pending command and return the error code rc to the client.

Function: gpg_error_t assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen, gpg_error_t (*cb) (void *cb_data, gpg_error_t rc, unsigned char *buffer, size_t buffer_len), void *cb_data)

This is similar to assuan_inquire but the caller has to provide the outer loop (using assuan_process_next). The caller should specify a continuation with cb, which receives cb_data as its first argument, and the error value as well as the inquired data as its remaining arguments.

Previous: , Up: External I/O Loop   [Contents][Index]