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]