> > 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? There are two things going on here. One is a low memory condition. An attempt to write may fail even though there's data to be read. So you want to call SSL_read before SSL_write in a condition where you're going to call both. However, this can cause a nasty race condition. You select for writability because you're writing a lot. You get a hit, you call SSL_write. While SSL_write is running it has to read some data from the socket. This turns out to be application data. If you don't call SSL_read (even though you never got a readability hit from 'select'), you can deadlock. (The data is not on the socket anymore, the SSL engine has it.) So you should only 'select' when SSL tells you to. Otherwise, assume the operation might complete without blocking, because it in fact might. Do not 'select' for readability just because you want to read *unencrypted* data. Only 'select' for readability if the SSL engine tells you that it needs to read data to make forward progress. (In fact, there's no harm in doing the 'select', but there is harm in refusing to call SSL_read until you get a hit from 'select'.) > 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). Correct. And you do not wait for 'select' to give you a read hit to call SSL_read -- the SSL engine might have already read the data from the socket during a call to SSL_write! > 2) You check for socket writability if you get WANT_WRITE for > the last operation, and on hit you retry that operation. Yes. > Is this understanding correct? You got it. Basically, you do not assume any connection between the motion of encrypted data and the motion of unencrypted data. > 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? Yes, this seems to be pseudo-code for a correct way to get blocking behavior with non-blocking sockets. Of course, it's not really blocking behavior because the calls to 'select' allow you to get other work done. I believe that's what you want, so this should give it to you. DS ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]