Reputation: 8160
I have a TCP networking library which implements a bunch of protocol (redis, http etc), and they are implemented using BSD sockets.
A lot of the code uses select() and other functions that are meant for BSD sockets. Am I right in assuming that this won't work on the SSL sockets? Or will they work as is?
I'm just wondering if SSL and BSD sockets are so different that they require a completely different approach to implementation.
Upvotes: 7
Views: 3623
Reputation: 2736
This may be late, but may serve a good reference to future users. There is a good thread on using select() function on url http://developerweb.net/viewtopic.php?id=6824 . One example cited is as follows
int sslsock_handle_nbio (ssl, ret, totv)
void *ssl; /* -> the SSL info */
int ret; /* the SSL I/O function return value */
struct timeval *totv; /* -> timeout info, or NULL */
{
int sfd, i;
fd_set rset, wset;
sfd = SSL_get_fd (ssl);
i = SSL_get_error (ssl, ret);
if (i == SSL_ERROR_WANT_READ) {
do {
FD_ZERO (&rset);
FD_SET (sfd, &rset);
i = select (sfd + 1, &rset, NULL, NULL, totv);
} while ((i < 0) && (errno == EINTR));
if (i == 0) {
/* the select() timed out */
ret = -2;
errno = ETIMEDOUT;
} else {
/* either an error, or it's readable */
ret = i;
}
} else if (i == SSL_ERROR_WANT_WRITE) {
do {
FD_ZERO (&wset);
FD_SET (sfd, &wset);
i = select (sfd + 1, NULL, &wset, NULL, totv);
} while ((i < 0) && (errno == EINTR));
if (i == 0) {
/* the select() timed out */
ret = -2;
errno = ETIMEDOUT;
} else {
/* either an error, or it's writable */
ret = i;
}
}
/* else, leave "ret" alone, and return it as-is */
return (ret);
}
This is only after performing SSL_read()
or SSL_write()
.
Upvotes: 0
Reputation: 597081
Assuming you are referring to OpenSSL, it sits on top of the socket, it does not replace it. So all direct-socket operations, like select()
, still work. The difference, however, is that OpenSSL handles reading and writing for you so you would replace recv()
with ssl_read()
and send()
with ssl_write()
, but you can (and in some cases need to) still use select()
directly. However, you can't just call it whenever you want, you have to wait until OpenSSL tells you to call it. So, for example, if you have a reading loop that calls select()
first and then calls recv()
only when select()
reports readability, you would have to swap that logic around. Call ssl_read()
first, and then call select
() only if ssl_read()
returns either SSL_ERROR_WANT_READ
or SSL_ERROR_WANT_WRITE
(note that ssl_read()
can perform writing operations internally, and ssl_write()
can perform reading operations internally).
Upvotes: 7
Reputation: 534
One thing that comes to mind is that you should not do a select on the fd via which the ssl connection runs. That is because it might for example say you can read from it while the ssl_read will block. That is then caused for example by SSL doing a key renegotiating and not application data to become available. That's one of the pitfals.
Upvotes: 2