[openssl-users] BIO_read hangs, how can I know if the server wants to send data?

Matt Caswell matt at openssl.org
Tue Apr 26 14:05:34 UTC 2016


Hi Hanno

On 26/04/16 14:28, Hanno Böck wrote:
> Hi,
> 
> I have a problem here using OpenSSL, maybe I have some fundamental
> misunderstanding of how the api is supposed to be used.
> 
> What I want to do: Send a couple of HTTP requests over one connection
> (with HTTP/1.1, keep-alive enabled).
> Seems simple enough: I send a HTTP request and then read what the
> server sends, then send the next.
> 
> However: How do I know when the server has stopped sending?
> I have attached a code sample (it's missing lots of error checking in
> the initialization phase, but that's just for simplification of the
> code and shouldn't matter for now).

There are a few ways of doing this:

1) Track it at the application protocol layer. For example read the
"Content-Length" HTTP header and wait until you've received that amount
of data. This is probably the best way. The other ways below only tell
you whether the network *currently* has any data to provide to you - not
whether the server has finished sending.

2) Use non-blocking IO

3) Check the underlying file descriptor to see if is readable at the
moment. So for example you can call BIO_get_fd(), and then call
"select", or "poll" or similar on the file descriptor to see if it
readable. You may need to use SSL_pending()/SSL_has_pending() in
combination with this (see below).


> The relevant part is here:
> 	for (i = 0; i < 5; i++) {
> 		printf("calling BIO_write\n");
> 		r = BIO_write(bio, request, strlen(request));
> 		printf("%i bytes written\n", r);
> 		do {
> 			printf("calling BIO_read\n");
> 			r = BIO_read(bio, buf, 1024);
> 			printf("%i bytes read\n", r);
> 		} while (r > 0);
> 	}
> 
> Now when I run this code it sends one write and reads a couple of
> times. However when it's done BIO_read will block the program execution
> and not return until a timeout.
> 
> So I need a way to know that there's nothing to read before calling
> BIO_read. Searching the docs I thought SSL_pending() might be what I
> need. However it always returns zero, no matter if the server has
> something to send or not.

SSL_pending() only tells you whether OpenSSL has read data from the
network and processed it, but has not yet provided it to you. This might
happen, for example if OpenSSL received a record of application data but
you only read part of it in the last SSL_read call. Compare with
SSL_has_pending() (only in 1.1.0).


> 
> Another sidenote: I have set the timeout of the context to 2, but it
> still hangs for much longer, so the timeout value doesn't seem to have
> any effect.

SSL_CTX_set_timeout() sets the timeout of the *session*. It has nothing
to do with the connection.

Matt



More information about the openssl-users mailing list