Next: , Up: Setting up the transport layer   [Contents][Index]

6.5.1 Asynchronous operation

GnuTLS can be used with asynchronous socket or event-driven programming. The approach is similar to using Berkeley sockets under such an environment. The blocking, due to network interaction, calls such as gnutls_handshake, gnutls_record_recv, can be set to non-blocking by setting the underlying sockets to non-blocking. If other push and pull functions are setup, then they should behave the same way as recv and send when used in a non-blocking way, i.e., return -1 and set errno to EAGAIN. Since, during a TLS protocol session GnuTLS does not block except for network interaction, the non blocking EAGAIN errno will be propagated and GnuTLS functions will return the GNUTLS_E_AGAIN error code. Such calls can be resumed the same way as a system call would. The only exception is gnutls_record_send, which if interrupted subsequent calls need not to include the data to be sent (can be called with NULL argument).

When using the poll or select system calls though, one should remember that they only apply to the kernel sockets API. To check for any available buffered data in a GnuTLS session, utilize gnutls_record_check_pending, either before the poll system call, or after a call to gnutls_record_recv. Data queued by gnutls_record_send (when interrupted) can be discarded using gnutls_record_discard_queued.

An example of GnuTLS’ usage with asynchronous operation can be found in doc/examples/tlsproxy.

The following paragraphs describe the detailed requirements for non-blocking operation when using the TLS or DTLS protocols. TLS protocol

There are no special requirements for the TLS protocol operation in non-blocking mode if a non-blocking socket is used.

It is recommended, however, for future compatibility, when in non-blocking mode, to call the gnutls_init function with the GNUTLS_NONBLOCK flag set (see Session initialization). Datagram TLS protocol

When in non-blocking mode the function, the gnutls_init function must be called with the GNUTLS_NONBLOCK flag set (see Session initialization).

In contrast with the TLS protocol, the pull timeout function is required, but will only be called with a timeout of zero. In that case it should indicate whether there are data to be received or not. When not using the default pull function, then gnutls_transport_set_pull_timeout_function should be called.

Although in the TLS protocol implementation each call to receive or send function implies to restoring the same function that was interrupted, in the DTLS protocol this requirement isn’t true. There are cases where a retransmission is required, which are indicated by a received message and thus gnutls_record_get_direction must be called to decide which direction to check prior to restoring a function call.

Function: int gnutls_record_get_direction (gnutls_session_t session)

session: is a gnutls_session_t type.

This function is useful to determine whether a GnuTLS function was interrupted while sending or receiving, so that select() or poll() may be called appropriately.

It provides information about the internals of the record protocol and is only useful if a prior gnutls function call, e.g. gnutls_handshake() , was interrupted and returned GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN . After such an interrupt applications may call select() or poll() before restoring the interrupted GnuTLS function.

This function’s output is unreliable if you are using the same session in different threads for sending and receiving.

Returns: 0 if interrupted while trying to read data, or 1 while trying to write data.

When calling gnutls_handshake through a multi-plexer, to be able to handle properly the DTLS handshake retransmission timers, the function gnutls_dtls_get_timeout should be used to estimate when to call gnutls_handshake if no data have been received.

Next: , Up: Setting up the transport layer   [Contents][Index]