dear ressl fellows, when trying to properly reimplement a curses client (i.e. handling stdin with select) with a tls connection using ressl (i.e. handling a server socket with select), I stumbled upon conflicting recommendations in man pages regarding whether to use blocking sockets in BIOs.
The BIO_read(3) tells me to use non blocking sockets and select() to figure out if there's work for me to do on the writing side and vice versa: > One technique sometimes used with blocking sockets is to use a system > call (such as select(), poll() or equivalent) to determine when data > is available and then call read() to read the data. The > equivalent with BIOs (that is call select() on the underlying I/O > structure and then call BIO_read()to read the data) should not be > used because a single call to BIO_read() can cause several reads > (and writes in the case of SSL BIOs) on the underlying I/O structure > and may block as a result. > Instead select() (or equivalent) should be combined with non blocking > I/O so successive reads will request a retry instead of blocking. However the BIO_should_retry(3) man page then warns me, that the ASN.1 parser does not really work with non blocking reads from BIOs: > The OpenSSL ASN1 functions cannot gracefully deal with non blocking > I/O: that is they cannot retry after a partial read or write. This is > usually worked around by only passing the relevant data to ASN1 > functions when the entire structure can be read or written. Now I could make the app multi threaded and use a blocking tls_read in one thread, while handling user interactions in another. But this leaves no way to abort pending read/write actions in the tls thread. So far so bad. Looks like with the ressl BIO API, I can not reliably use either socket. Now I noticed that libtls's tls_client.c only allows for tls_connect which creates blocking sockets only or tls_connect_socket which appears to use the underlying socket's blocking state. The socket itself is opaque to me, so that I can not call select() to see if data is pending there which is a surprisingly missing feature, considering tls_read blocking non-abort-ably in SSL_read. tls_read can also return a surprising TLS_WRITE_AGAIN on non-blocking sockets, where I think it should handle this condition for the caller. Maybe my use case just is not very common, but maybe someone can help me out with a proper way to use the API with a client waiting for input on multiple fds. On a related note I wonder what the correct way is to cancel a blocking tls operation from another thread. TIA, erdgeist