[gnutls-help] Truly non-blocking example of gnutls usage

Alex Bligh alex at alex.org.uk
Fri Apr 8 18:16:06 CEST 2016


Thanks for your reply.

On 8 Apr 2016, at 14:35, Nikos Mavrogiannopoulos <nmav at gnutls.org> wrote:

> On Fri, Apr 8, 2016 at 10:36 AM, Alex Bligh <alex at alex.org.uk> wrote:
>> Is there a simple, easy to reuse, example of gnu-tls acting like a
>> proxy which is truly non-blocking? By truly non-blocking I mean using
>> non-blocking writes as well as non-blocking reads. The danger I
>> am concerned about is receiving a large amount of plain-text,
>> gnutls converting that to cypher-text, attempting to write it
>> but blocking because the remote side is not ready to receive it.
>> The remote side is not ready to receive it because it has its
>> own output blocked as gnutls is not polling for reads as
>> it's blocked above, meaning deadlock.
> Blocking is a matter of the underlying socket functions.

Perhaps I should have used the word 'asynchronous'

> If you set
> the sockets to non blocking mode gnutls operates in a non-blocking way
> almost identically to berkeley sockets. Have you checked the manual?
> https://www.gnutls.org/manual/html_node/Asynchronous-operation.html

I had done, but it was not fantastically helpful.

The manual says "GnuTLS does not keep a write buffer, thus when writing
no additional actions are required." which I took to mean it was writing
synchronously (but reading async).

> The simplest example is mini-eagain.c from the test suite which
> verifies the asynchronous operation of gnutls_record_send and recv.

Thanks - that was helpful. But it doesn't do a select loop
as far as I can tell.

The examples there set their own push/pull functions, which I understand
to be to read/write the crypted traffic.

I was planning if possible to use straight sockets. Does a select
loop now look something like the code below? (pseudo-code, error checking omitted)
I'm guessing here, and an example would be really helpful.

Also do I need to manually verify certificates after a handshake?
src/cli.c seems to do this with its own callback functions, but I
don't know whether that's for debugging purposes only?

int tls_wr_interrupted = 0;
while (1)
    size_t buffered = gnutls_record_check_pending ();
    if (buffered)
      timeout = 0; // don't wait on select if we have buffered data
      timeout = infinite;

    if (!bufIsEmpty (plainToCrypt) || tls_wr_interrupted)
      FD_SET (crypt, write_fd_set);
    if (!bufIsEmpty (cryptToPlain))
      FD_SET (plain, write_fd_set);

    if (!bufIsFull (plainToCrypt))
      FD_SET (plain, read_fd_set);
    if (!bufIsFull (cryptToPlain))
      FD_SET (crypt, read_fd_set);

    select (read_fd_set, write_fd_set, 0, timeout);

    if (FD_IS_SET (crypt, read_fd_set) || buffered)
      buffer (cryptToPlain, gnutls_record_recv ( ...));

    if (FD_IS_SET (crypt, write_fd_set))
	if tls_wr_interrupted
	    err = gnutls_record_send (NULL);
	    err = gnutls_record_send (unbuffer (plainToCrypt), ...);
	tls_wr_interrupted = (err == GNUTLS_E_INTERRUPTED);

    if (FD_IS_SET (plain, read_fd_set))
      buffer (plainToCrypt, read (plain, ...));

    if (FD_IS_SET (plain, write_fd_set))
      write (plain, unbuffer (cryptToPlain) ...);


Alex Bligh

More information about the Gnutls-help mailing list