At 11:59 17.07.2006 +0100, you wrote:
>Henrik Thuermer wrote:
>> If we receive some data we process it via one BIO_write call followed by
>> SSL_read calls until the call to SSL_read fails with SSL_get_error() ==
>> SSL_ERROR_WANT_READ or SSL_read returns no more data (SSL_ERROR_WANT_WRITE
>> is also handled correctly - I hope). Then we stop reading from the ssl
>> connection until we receive new data.
>
>Just to confirm your understanding on this point, as your description is
>unclear.

Sorry if I was unclear in my email.

>
>You may not necessarily receive new data, as in new
>application level data.
>

I do not understand what you mean here. Maybe the misunderstanding is that
you assume the ssl library handles the tcp socket? But in our case the
socket handling (send/recv) is done by the application not by the ssl library.

If I write "receive some data" I mean our application reads the data from a
TCP socket and transfer it to the ssl connection via BIO_write. Our read
routine looks something like this (The BIO was "connected" to the ssl
object with SSL_set_bio before ssl connection setup):

void ReceiveSomeData(SSL* ssl, SOCKET s, BIO* bioRead)
{

    ....

    int rcvd = recv(s, recvBuffer, 8192, 0);

    int bytesWritten = BIO_write(bioRead, recvBuffer, rcvd);

    if (bytesWritten != rcvd) {
        assert(false);
        // this never happens during our tests
    }

    while (true) {

         char buffer[bufferLength];
        int bytesRead = SSL_read (ssl, buffer, bufferLenght);

        if (bytesRead > 0) 
            DoSomethingWithTheData();
        else if (bytesRead == 0) 
            // nothing more to decrypt -> stop here until we receive more data
            break;
        else if (bytesRead < 0) {
            if (SSL_get_error() == SSL_ERROR_WANT_READ) {
                // nothing more to decrypt -> stop here until we receive
more data
                ERR_clear_error();
                break;
            }
            if (SSL_get_error() == SSL_ERROR_WANT_WRITE) {
                // never happens during our test (initial ssl connection
setup is done
                // at another place)
                ERR_clear_error();
                SendOutStandingSSLData();
            }
        }
    }

    ...
}

>
>It is safe to keep trying SSL_write() after every SSL_read() to see if
>it can do more work, otherwise it will persist with the WANT_READ state.
>

I'm really not familiar with the library sorce code. I only stepped into it
during debugging and found the following:

SSL_read internally calls ssl2_read_internal:

static int ssl2_read_internal(SSL *s, void *buf, int len, int peek)
{

...

    if (s->rstate == SSL_ST_READ_BODY)
        {
        n=s->s2->rlength+2+s->s2->three_byte_header;
        if (n > (int)s->packet_length)
            {
            n-=s->packet_length;
            i=read_n(s,(unsigned int)n,(unsigned int)n,1);
            if (i <= 0) return(i); /* ERROR */
            }

...

}

In our case this returns in the line marked with /* ERROR */ (should this
be /* error or non-blocking */ like at the other call to read_n?). The
internal read state remains SSL_ST_READ_BODY. If SSL_read is called the
next time it immediatly falls into this if statement evaluating

n=s->s2->rlength+2+s->s2->three_byte_header;

But if we have called SSL_write before, it may have changed the value of
s->s2->three_byte_header. 
I did not test wether SSL_write really _changed_  s->s2->three_byte_header
(it certainly will touch it).
But: Our problem disappears if we do not call SSL_write in this situation
but wait until some more data is available and we can call
BIO_write/SSL_read again hoping that this will change the read state to
SSL_ST_READ_HEADER :-). This leads me to the assumption that sometimes you
should not call SSL_write (unlikely?) or that we use the ssl library in the
wrong way (likely, but where is the mistake?).


>
>If you are non-blocking the only special case is to start ignoring the
>select/poll/read/write writability event mechanism to drive your writes
>at the point you get WANT_READ from SSL_write().  But keep watching and
>processing readability events like normal, but while ignoring
>writability events after each call to SSL_read() (successful or not)
>attempt a SSL_write(), if that no longer returns WANT_READ then you can
>stop ignoring and start using your writability event indication to drive
>SSL_write() again.
>

I think we handle WANT_READ/WANT_WRITE correctly (at least the cases which
happens in our test environment) because:
-ssl connection setup is always successful
-after ssl connection setup the only error we get is WANT_READ after
SSL_read returns with -1, which the application interprets as: no more or
not enough encrypted data in internal buffer, wait until new data is received.


>
>
>> This works but it is only a hack, of course (and may deadlock sometimes if
>> ssl->rstate == SSL_ST_READ_HEADER on both sides of the connection at the
>> same time). What we are doing wrong?
>
>I've not taken in the problem completely here.  If this deadlock is
>correct, can you provide a packet/data dump of the session.
>

The deadlock did not happen up to now and it's  an "application level"
deadlock which has nothing to do with the ssl library usage. It's simply a
problem of our ugly hack:

node_A:

Tries to send some data to node_B, but it can't because  ssl->rstate !=
SSL_ST_READ_HEADER. It will only start sending data again after it has
received and decrypted data from node_B which has changed ssl->rstate  to
SSL_ST_READ_HEADER.

node_B:

Reaches the same state as node_A at the same time.

In that case we have a deadlock because node_B is now waiting for data from
node_A and vice versa.


>
>Darryl
>______________________________________________________________________
>OpenSSL Project                                 http://www.openssl.org
>User Support Mailing List                    openssl-users@openssl.org
>Automated List Manager                           [EMAIL PROTECTED]


Henrik

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to