---- Original message ----
>Date: Tue, 22 Aug 2006 12:22:37 -0700
>From: "David Schwartz" <[EMAIL PROTECTED]>  
>Subject: RE: Wrapping SSL_read/SSL_write so they behave like
read/write.]  
>To: <openssl-users@openssl.org>

>       You should 'select' for writability if and only if you get a
WANT_WRITE
>indication, whether it comes from SSL_read or SSL_write. This
is the *only*
>thing that means that you would block while trying to send
encrypted data to
>the socket. (Whether or not you are trying to currently send
any unencrypted
>data has nothing to do with it.)
>
>       If you get a 'select' hit, whether for readability or
writability, you
>should retry *all* operations, whether reads or writes.
(Obviously, don't
>call SSL_write unless you have some data to write!)
>
>       Again, I also recommend trying an SSL_read on any hit,
whether for
>readability or writability, before doing anything else. This
will 100%
>ensure you don't deadlock (as long as you call SSL_read after
each SSL_write
>until it runs out) nd it will give you better behavior under
edge conditions
>like memory pressure.
Sorry, but could you give a little more explaination for this,
probably with an example?

>>Are you suggesting that the write hit from select is an
>>indication that the descriptor is writable and hence the data
>>that SSL required to write before it could serve our read
>>request must have been written. And so we would expect a
>>successful SSL_read after this write hit from select?
>
>       If you got a WANT_WRITE, that means the operation could not
proceed until
>encrypted data could be written. Once the socket is writable,
the operation
>can proceed. So you should retry it. No harm in retrying all
current
>operations (always SSL_read, but SSL_write if there's
unencrypted data to
>send).
>
>Moreover, should we not wait again for a read hit from select
>before we SSL_read()?
>
>       That would be a disaster. The corresponding encrypted data
might have
>already been read. You should *never* assume no inbound data
will be
>available until the socket is readable unless SSL_read just
returned
>WANT_READ and you have no called SSL_write since then.
>
>       The SSL engine may have already read the encrypted data,
during a previous
>call to SSL_read or a previous call to SSL_write! So waiting
for more data
>to be received can deadlock you.
>
>       Do not assume that no unencrypted data can be read until
encrypted data can
>be read unless you know this for a fact. The only way you can
know this for
>a fact is if two things are the case:
>
>       1) Your last SSL_read returned WANT_READ, *and*
>
>       2) You have not called SSL_write since then.
>
>       Otherwise, you should *not* wait for readability before
calling SSL_read.
>The encrypted data may have already been read.
>
>       Note that if an SSL_write returns WANT_READ, you should
'select' for
>readability and then retry the SSL_write. No harm in doing an
SSL_read
>before or after that. In fact, there are good reasons for
doing one both
>before and after, assuming the first SSL_read doesn't return
'WANT_READ'.
>
So in short, 
1) you check for socket readability if you get WANT_READ for
your last operation, and on hit you retry the last operation
(whether SSL_read or SSL_write).
2) You check for socket writability if you get WANT_WRITE for
the last operation, and on hit you retry that operation.

Is this understanding correct?

With this understanding, the following piece of code should
work with an assumption that you beforehand know how much of
application data are you expecting and set the buffer size
appropriately. Buffer full is one condition when you return ....

select(for the socket readability)
socket_ssl_read(fd) /* This is the wrapper */
process_the_data();

socket_ssl_read(fd)
{
    set appropriate buffer size;
    while(1)
    {
        ret = SSL_read();
        if (ret < 1)
        {
           ret1 = SSL_get_error();
           switch(ret1)
           {
           case WANT_READ:   select(for readability);
                             break;
           case WANT_WRITE:  select(for writability);
                             break;
           default:  return error;
           }
        }
        if (buffer full)
           return;
    }
}
Something similar can be done for SSL_write wrapper.

In the current context, these wrappers can be called for each
connectio descriptor. 
But then the wrappers will return only on error or after they
read the full data. So will that actually exibit blocking
behavior? 


~ Urjit

DISCLAIMER
==========
This e-mail may contain privileged and confidential information which is the 
property of Persistent Systems Pvt. Ltd. It is intended only for the use of the 
individual or entity to which it is addressed. If you are not the intended 
recipient, you are not authorized to read, retain, copy, print, distribute or 
use this message. If you have received this communication in error, please 
notify the sender and delete all copies of this message. Persistent Systems 
Pvt. Ltd. does not accept any liability for virus infected mails.
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to