> Yes, the protocol is asynchronous exactly, not "query/response" sequence,
> and could not re-design it now.
Many protocols are that way and should be that way. I wouldn't redesign the
protocol unless it was badly designed in the first place.
> I could not find sufficient documents or examples about
> non-blocking I/O for
> newbie like me. By way of experiment, I tried to re-write the code again
> with BIO and non-blocking I/O.
> The read() wrapping function I made newlly is below;
> ------- snip -------
> BIO_set_nbio( cbio, 1 ) ;
> BIO_do_connect( cbio ) ;
> BIO_do_handshake( cbio ) ;
>
> int read_ssl( ... ) {
> while ( 1 ) {
> pthread_mutex_lock( &rw_lock ) ;
> int ret = BIO_read( cbio ... ) ;
> pthread_mutex_unlock( &rw_lock ) ;
> if ( ret > 0 ) {
> break ;
> } else if ( ! BIO_should_retry( cbio ) ) {
> do_something_ERROR() ;
> break ;
> }
> usleep( a_little ) ; // to prevent wasting CPU
> }
> }
> ------- snip -------
>
> Will this work correctly with multithreaded asynchronous I/O?
> But I think, this way is not better than simple blocking I/O like the
> original code. It wastes CPU by the loop and gets poor response
> time by the
> sleep. Is there any way better than it?
That's correct, but very poor for precisely the reasons you explain. You
should take a look at the include s_client example. The basic idea is this:
Reading:
1) Acquire the mutex.
2) Call SSL_pending. If any bytes are already available, call SSL_read,
release the lock, and return. (Note that calls to SSL_write might wind up
reading from the socket, so data might already be waiting.)
3) Call SSL_read. If it returns a positive number, release the lock and
return the data. If zero, release the lock and return EOF.
4) Pass the return value of SSL_read to SSL_get_error.
5) If the error was not WANT_READ or WANT_WRITE, handle it as appropriate.
You can assume it's fatal.
6) If the error was WANT_READ or WANT_WRITE, release the lock, select for
read or write as asked, re-acquire the lock, and go back to step 2.
Writing:
1) Acquire the mutex.
2) Call SSL_write. If we have sent all of the data, release the lock and
returen.
3) If we sent any data, re-adjust to only send the data that remains and go
to step 2.
4) If we got a zero, release the lock and return the number of bytes
successfully sent.
5) If we got an error, pass the return value to SSL_get_error.
6) If the error is fatal error, release the lock and return.
7) Obey the WANT_READ or WANT_WRITE by releasing the lock, calling 'select',
and re-acquiring the lock. Go back to step 2.
Note that SSL_read can return WANT_WRITE and SSL_write can return WANT_READ.
DS
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List [email protected]
Automated List Manager [EMAIL PROTECTED]