Reputation: 4031
I'm writing a simple http server in C, I added some OpenSSL around it to support secure connections and it works great with blocking sockets.
However if I switch to non-blocking sockets, the SSL_accept(ssl) always returns -1 on the first attempt, even if I add a time delay before it.
I originally assumed it may have something to do with the socket not ready for reads/writes but that doesn't seem to be the case as a delay of even 150ms had the same behavior.
However, if I execute SSL_accept(ssl) then issue a short 50ms delay and retry SSL_accept(ssl), I get a successful SSL connection each time. Sending and receiving encrypted traffic works just as expected.
I'm not using socket select, I'm simply polling sockets for connect/recv/send.
Why is this? Am I missing a required call for non-blocking accepts?
Below is the snippet I've added to my code to mitigate this behavior.
int sslfail = SSL_accept(ssl);
#if NONBLOCKINGIO
// Perculiar issue where non-blocking sockets require 2 accept attempts with a brief delay betweek them to avoid error.
usleep(50 * 1000);
sslfail = SSL_accept(ssl);
#endif
Upvotes: 0
Views: 443
Reputation: 73294
From the ssl_accept man page:
If the underlying BIO is non-blocking, SSL_accept() will also return when the underlying BIO could not satisfy the needs of SSL_accept() to continue the handshake, indicating the problem by the return value -1. In this case a call to SSL_get_error() with the return value of SSL_accept() will yield SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE . The calling process then must repeat the call after taking appropriate action to satisfy the needs of SSL_accept(). The action depends on the underlying BIO . When using a non-blocking socket, nothing is to be done, but select() can be used to check for the required condition. When using a buffering BIO , like a BIO pair, data must be written into or retrieved out of the BIO before being able to continue.
Upvotes: 1