Concurrent gnutls_record_send and gnutls_record_recv
nmav at gnutls.org
Fri Dec 18 11:06:51 CET 2009
Sam Varshavchik wrote:
> I want my application to be able to read/write from a TLS session
> concurrently, which requires non-blocking socket transport, and I am
> trying to figure out how to use the API correctly. I see that the
> documentation indicates the gnutls is thread safe; but does that mean
> that one thread can be using gnutls_record_send() while another thread
> be using gnutls_record_recv() at the same time?
Yes this can be done in a thread safe way without locks. Even fork and
read/write from different processes works. The only issue is on
gnutls_bye(). To terminate the session properly you should call with
SHUT_WR and start reading until EOF (0) is received.
> That's one approach that
> I am considering. If not, and I have to multiplex a single thread
> between reading and writing, I am trying to figure out how to use the
> API correctly. So far, I have:
> * If there's something waiting to be written, call gnutls_record_send.
> If gnutls_record_send returned GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN,
> call gnutls_record_get_direction(), and note its return value. If
> gnutls_record_send wrote something, and there's more left to write, take
> it from the top.
> * Call gnutls_record_recv. If something was read, process the read data,
> and take it from the top again. If gnutls_record_recv came back with
> GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN, call
> gnutls_record_get_direction(), combine its return value with the return
> value after gnutls_record_send() (if applicable), computing the
> corresponding combination of POLLIN and POLLOUT, then call poll() to
> wait for the required I/O state.
> Also, in an established TLS session, after the handshake completes, if
> gnutls_record_recv() or gnutls_record_send() returns
> GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN, will
> gnutls_record_get_direction() always return 0 after gnutls_record_recv
> and 1 after gnutls_record_send(), or are there situations where
> gnutls_record_recv() would need to write to the underlying transport,
> and gnutls_record_send() would need to read from the underlying
> transport, and how would that be squared away with the application's
> simultaneous usage of gnutls_record_send() and gnutls_record_recv()?
No there is no such case. They behave exactly like recv() and send().
More information about the Gnutls-help