Nikos Balkanas wrote:

> >> To make it clearer. Select or poll will return as soon as the socket is
> >> writable. However, SSL still needs to negotiate keys and
> >> encryption with the
> >> peer before you can exchange any data. This is handled
> >> transparently for you
> >> in each SSL_write call. Therefore SSL replies to you "Yes the socket is
> >> writeable, but I am not done yet with the handshake".

> > That would be SSL_ERROR_WANT_READ. If you get SSL_ERROR_WANT_WRITE, that
> > means OpenSSL found that the socket was not wriable.

> No. SSL doesn't decide that. It is done at a lower level. It is
> decided by
> poll or select.

Huh? SSL knows whether it was trying to read from the socket or write to the
socket when it encountered a 'WOULDBLOCK' error. If nothing changes (and
nothing can change unless you call into OpenSSL) it will repeat that same
operation the next time you call. So it is OpenSSL that will tell you which
direction it needs. It will not return a 'WANT_WRITE' error unless a write
returned a 'WOULDBLOCK' error.

> The socket is writable the minute it unblocks (without
> errors other than SSL_*). And can be either SSL_WRITE or
> SSL_read. Read the
> manual.

Huh? I've read this about five times and I can't figure out what you're
trying to say.

> >> When you get SSL_ERROR_WANT_WRITE  none of your data is written to the
> >> socket.

> > There is no such guarantee. OpenSSL may have written some, all,
> > or none of
> > your data to the socket. All that you know is:

> Yes, there is. By poll. If you get an error, your data is not written.

Again, huh? The 'poll' function will tell you if the socket is writable or
not, but if you call SSL_write and get a 'WANT_WRITE' return value, you have
no way of knowing what OpenSSL may or may not have sent over the socket. The
API is specifically designed so that you don't need to know.

For example, suppose you go to send 148 bytes with a call to SSL_write. This
forms an encrypted block of, say, 256 bytes. OpenSSL calls SSL_write and
sends 180 of those bytes. This may or may not allow the other end to decrypt
any of them (and it probably won't allow it to checksum any of them). What
should SSL_write return? (It cannot return 148, because if it does, you
won't call SSL_write again even if the socket becomes writable). So it
*must* return WANT_WRITE even though it sort of wrote some of the data.

> > 1) OpenSSL needs the socket to be writable to make further progress in
> > this
> > direction.
> >
> > 2) You must provide the same data to OpenSSL the next time you call
> > SSL_write.

> Not necessarily, if you are using moving_buffers.

You are mistaken. Moving buffers is about the buffers moving. It does not
change the requirements about the contents of the buffers. If you call
SSL_write to send 148 bytes of data and it winds up sending, say, 128 of the
256 bytes this encrypt to, OpenSSL will have to return WANT_WRITE. If you
try to send anything other than those same 148 bytes of data (and possibly
some after it), things will break. This is fundamental to the way the API is
designed. UNIX does not provide an 'all or nothing' write function so
OpenSSL can't either.


> >> You need to put it in a loop and call select or poll
> >> again. If you
> >> want to be efficient and not do many loops, put a sched_yield();
> >> inside your
> >> loop.

> > That would be pointless. The 'select' or 'poll' function
> > permits efficient
> > blocking and beneficial context switches. Adding a sched_yield only adds
> > context switches where they are not necessary and blows out the caches.

> Not in the case of SSL. Once poll unblocks SSL still needs the
> socket to do
> its stuff. If you try to write or read, the minute poll unblocks
> you, will
> be in trouble. You have to wait, in a loop, sometimes 50 loops.
> To be more
> CPU efficient, you can use sched_yield(), but it is up to you.

I have no idea what you're talking about, but this makes *NO* sense. You
most certainly should try to write or read the instant poll unblocks. There
is no sense in waiting for anything else to happen.

> It's all in the manual. Read it.

The manual tells you to call sched_yield? I'd love to see a citation. The
'sched_yield' function has almost no legitimate uses and is a known
performance killer. The functions may (or may not) yield the CPU even though
the scheduler (which knows what it's doing) decided to run your thread and
even though you could make forward progress. It also doesn't inform the
scheduler of what you're waiting for, so the scheduler cannot do an
intelligent job of deciding when to reschedule you. You have the 'select'
and 'poll' functions which also yield the CPU but unblock you at precisely
the right time -- when the socket is ready for I/O.

http://kerneltrap.org/Linux/Using_sched_yield_Improperly

Bluntly, nothing you are saying makes any sense.

DS


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [email protected]
Automated List Manager                           [email protected]

Reply via email to