This is a discussion on Re: Asynchronous ENGINE operation? - Openssl ; On Wed, Mar 05, 2008 at 12:10:04PM -0500, Geoff Thorpe wrote: > > I was not involved in the discussion so am not familiar with the > arguments. However I agree that SSL_[poll|select]() would be unwise > because it presumes ...
On Wed, Mar 05, 2008 at 12:10:04PM -0500, Geoff Thorpe wrote:
> I was not involved in the discussion so am not familiar with the
> arguments. However I agree that SSL_[poll|select]() would be unwise
> because it presumes to make the SSL/TLS stack transport-aware, whereas
> the BIO scheme is an honest (if sometimes inelegant) attempt to leave
> the stack transport-agnostic. SSL/TLS can be fed data on all sides
But you can't stay transport-agnostic and actually use the stack in
non-blocking mode now. You *must* extract the underlying file descriptor
and sleep on it with select/poll, which effectively forecloses any option
of using some other asynchronous event mechanism at the same time except
heavyweight signals, under Unix at least (and using signals that way will
butcher performance; I have benchmarked this).
> > This API also *already* requires any operations that would block to be
> > reissued at the SSL layer by retrying exactly the same operation again
> > after the file descriptor for that session comes up ready with select
> > or poll.
> Sure, but that's because you are *not* suspended miles down a code path
> that you need to find your way back to. It means the state-machine has
> advanced as far as it can go and to advance further, you will need the
> presence of either input on your read BIO or some drainage on your write
> BIO. Those events are on the exterior of the SSL/TLS state-machine and
> represent a stable state, the code-paths exit cleanly in that state and
> when progress is possible, we will go down new code paths to do new
> work. This is not the same as trying to pick up where you left off way
> down a code-path that has not been designed with suspend-and-retry
> semantics in mind. Eg. if you were calling SSL_read() when you got a
> WANT_WRITE, but you then called SSL_write() - it should *not* crash.
Should not, or does not? I think you're a bit optimistic about the
current implementation, for what it's worth. Failure to retry the exact
same operation, now, causes chaos, including data corruption.
> What you're describing, about being able to replay your way down a prior
> code-path, would be very hard to make robust in an equivalent way.
For what it's worth, I and my coworkers have done this, to an originally
openssl-derived code base, which still retains BIO, etc., and it was not
too hard to make it work at least as well as the current read/write
> > So, given my "note first" and "note second" I believe I have established
> > that, to do non-blocking I/O in a single-threaded application with OpenSSL,
> > one must already:
> > 1) Dip beneath the SSL abstraction layer to get the file
> > descriptor for each session.
> No, this is one form it must be able to take, but this is not *the*
> general method for OpenSSL to support.
But it is the only way that works now. And that is the problem: the
current API, I think, essentially precludes the simultaneous use of
some other notification mechanism for another type of asynchronous
events, because _while_ you are sleeping for some SSL sessions in
select/poll for I/O ready on their file descriptors, you can not be
doing anything else. It all gets easier with multiple threads, of
course -- but it is precisely single-threaded, "traditional Unix"
event-driven applications that are the consumers of the existing
non-blocking API. I think you're right; we do largely agree on,
given the opportunity to start over from scratch, a new API for this
ought to look. But I am just highly skeptical that it's possible to do
anything cleaner than the (admittedly ugly, but ugly in the same way
the current API is ugly) scheme I've described, and actually keep
existing single-threaded code written to the non-blocking API working
with non-blocking I/O. You have to be able to wait for I/O completion
on some sessions and crypto completion on others (or, ideally, both,
for each direction of one session!) at the same time -- and the
basically mandatory use of select/poll in the existing API precludes
using anything else to wait on the crypto. At least, so it seems to
me (though I am eager to see what you come up with).
OpenSSL Project http://www.openssl.org
Development Mailing List email@example.com
Automated List Manager firstname.lastname@example.org