4
votes

I use a non blocking socket. For a normal TCP connect I do as in here: Non blocking socket - how to check if a connection was successful?

But for the SSL_connect call I cannot get it to work.

I understand it as I should: 1. Repeatedly call SSL_connect. 2. Check if SSL_get_error is SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. 3. If so, then I am not 100% sure what to do next. Should I call SSL_connect until I don't get that? Or should I do as with a normal socket, check the socket with select using read_fds or write_fds and check with FD_ISSET and if so check getsockopt with SO_ERROR?

Basically, for SSL_connect and a non-blocking socket, what tells me that the connection has succeeded? I have looked at other examples but none are clear enough.

2
Your guess is right: you should wait for appropriate socket events with poll or select api according to operation result. And repeat operation. - Valeri Atamaniouk
But should I call SSL_connect only once ever? What am I waiting for with select? if read or write is set for my socket, what does it mean? WHat should I do? Do I call getsockopt or not? - Soft Ware
Usually you give a connected socket to SSL_connect. This function is not for lower-level connect operation, but for security protocol setup. - Valeri Atamaniouk
Yes I know. I can do SSL_connect with blocking sockets. But I am unsure about nonblocking ones. Some pseudocode for the whole process is what I need. - Soft Ware

2 Answers

5
votes

Here is an algorithm:

int s = socket(...);
fcntl(s, ...); // make it non-blocking
while (-1 == connect(s,...))
{
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(s, &fds);
   select(s + 1, NULL, &fds, NULL, NULL);
}

... // initialize all SSL stuff
SSL_set_fd(ctx, s);
while (-1 == SSL_connect(ssl))
{
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(s, &fds);

   switch (SSL_get_error())
   {
   case SSL_ERROR_WANT_READ:
       select(s + 1, &fds, NULL, NULL, NULL);
       break;
   case SSL_ERROR_WANT_WRITE:
       select(s + 1, NULL, &fds, NULL, NULL);
       break;
   default: abort();
   }
}
// done...
0
votes

Here's a example of an approach using non-blocking sockets with memory bios. The non blocking IO is used to populate the memory BIO's, and IO calls are only made if the poll loop suggests they won't block.

https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca