gnutls-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gnutls_record_recv timeout with blocking sockets


From: Sam Varshavchik
Subject: Re: gnutls_record_recv timeout with blocking sockets
Date: Mon, 23 May 2011 10:01:41 -0400

Giuseppe Scrivano writes:

Hello,

In wget we are using something like the following pseudo-code to
check if a call to `gnutls_record_recv' will be blocking:

  gnutls_record_check_pending (session) || select_fd (fd, timeout);

You must use non-blocking sockets for this to work.

gnutls just read()s from the socket. If there's nothing to read, read() blocks until there's something to read. gnutls_record_recv() reads from the socket. If it has not received an entire record, it reads again, until it does, then you it returns and tells you what's been read. If the socket is empty before gnutls receives the entire record, gnutls_record_recv keeps reading, and it will block.

gnutls_record_check_pending() is just an indication that there's something still left over from the previous record that your app still hasn't retrieved using gnutls_record_recv(), yet. Your next call to gnutls_record_recv() will get that stuff, instead of reading from the socket.

Only if the socket is non-blocking, read() fails with EAGAIN/EWOULDBLOCK, and gnutls returns accordingly, but the socket must be non-blocking for that to happen.

Note that on Linux, select/poll on blocking sockets is not reliable. See BUGS in select(2) for more info. Neither gnutls, nor anything else, can reliably implement a no-delay read() from a blocking socket. select/poll only works "most" of the time. If "most" of the time is good enough for you, that's one thing, but rarely "most" of the time will be satisfactory.

Is it possible to know in advance if `gnutls_record_recv' will block or
not?  Any suggestion how I could handle properly the --read-timeout in
wget when TLS is used?  Am I missing something?

You must use non-blocking sockets. You do not need to use gnutls_record_check_pending(). You just call gnutls_record_recv() first and foremost. With a non-blocking sockets it never blocks, and always returns without delay. If it gives you back a GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN, you know that the socket must be readable before you have a reasonable expectation that gnutls_record_recv() will give you something when you call it again. It may still return GNUTLS_E_INTERRUPTED/GNUTLS_E_AGAIN the second time too; but you're guaranteed to get that again unless the socket becomes readable first.


Attachment: pgpkYu5_z9pzF.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]