The issue is down to the OpenSSL API thread-safety rules (which are dictated to by the internal design of OpenSSL).

I covered those thread-safety rules in a previous posting.



Yes the common application design pattern for full-duplex SSL streams is to only ever have one thread doing the work on a specific instance of 'SSL *' at any one time.

Given your application design requirements you indicated in your original posting then in order to achieve all your goals you must use the kernel socket in non-blocking mode.

The reasons why were explained in a previous reply of mine.



There is no reason why you should be warned away from using OpenSSL with non-blocking sockets. But you have to understand multi-threaded programming is hard and therefore more programmers will have difficulty previously in simply not understanding the concepts correctly.








Jason Pettiss wrote:
To make sure I'm clear on this: if I myself don't have any data to read and an 
SSL_write returns WANT_READ, that doesn't mean I myself need to call SSL_read-- 
what it means is I need to wait until the socket is readable, and then call 
SSL_write again (with the same args of course).

Okay this is a new question. Yes if you call SSL_write() and get back -1/WANT_READ then yes you do need to call SSL_read() to unstall that situation. In-fact SSL_peek() might be better to use if you have no where to put the application data right now but you want to attempt to see if the condition can be resolved by the next SSL protocol packet to be processed. Obviously if application data exists and is in the way calling SSL_peek() won't clear the SSL_write() stall. You must SSL_read() that data so the OpenSSL library can get to the final part of the renegotiation handshake packet.

I do not believe the SSL_write() call is allowed to access the underlying BIO/kernel-socket to read in more data. I think SSL_write() is allowed to process any data already read into buffer (from kernel to OpenSSL library internal buffer) in an attempt to unstall the situation itself. But it can't invoke read() on the kernel for it.

Due to this you have to call SSL_read()|SSL_peek() at least once, since these calls are allowed to access the underlying BIO/kernel-socket to attempt to read() in more data.


So once you observe an SSL_write() returning -1/WANT_READ you should immediately attempt to SSL_read()|SSL_peek() and if that also returns -1/WANT_READ then you can go to sleep and wait for more data to come in (wait until the socket is readable).

When that data comes in you call SSL_read()|SSL_peek() and if that doesn't return -1/WANT_READ then should give your SSL_write() another try. From memory I think SSL_read()|SSL_peek() return 0 (i.e. no new application data) at least once to eat up the final part of the renegotiation handshake process.

But it doesn't hurt to always call SSL_write() after every SSL_read()|SSL_peek() if you know that you are under this special condition (that SSL_write() previously returned -1/WANT_READ). Once your SSL_write() returns something other than -1/WANT_READ you can clear this special condition.


Now the same is true in reverse. The special condition that is SSL_read() returning -1/WANT_WRITE. I'm sure you can work out the details on this.


Darryl
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to