Excuse me if I am saying the obvious.
But did you factor the fact that an SSL renegotiation
or handshake can happen anytime during the
conversation?
Irrespective of whether you are doing SSL_read or
SSL_write... That is why you have to check for pending
write during a SSL_read and vice versa in the non
blocking case.
This is what the manpage says at least. I may be wrong
here.
--- Henrik Thuermer <[EMAIL PROTECTED]> wrote:
> 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"
>
=== message truncated ===
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List [email protected]
Automated List Manager [EMAIL PROTECTED]