> 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                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to