Shaw Graham George wrote:
Sure.

1.  The server receives the HTTP request, using SSL_read() and
SSL_pending().  The request contains a Keep-Alive request.
2.  The server writes the data out to another process.
3.  The server then it sits on an event handler that multiplexes a
select() (or Windows equivalent) on sockets it has an interest in, and
other events such as receiving data from other processes.

What is the sleep/wakeup IO mechanism you are employing on windows ? WaitForMultipleObjects() ?

Side track: Is it possible to make the window platform listen on > 31 sockets at once per thread ? (or whatever is small limit was)

 At this time
it actually has no interest in any events at the socket, as it is
waiting for the processing to complete.

I take this to mean you revoke all interest in the socket readability/writability. So the server is no oblivious to what the client is doing.

4.  The SSL client lose patience with a lack of response, and does an
SSL shutdown and socket close.

Okay you closed your ears to the read event ? On Unix the select() has an exceptfds which can be used to pickup a socket error/close (but may not be reliable if there is readable data first, since by convention of TCPs orderly shutdown that has to be eaten before the socket close can be seen).

5.  An event is detected, and the server receives the result from the
background processing.

I take this event to mean a read wakeup on channel facing the request processing process ?

6.  It adds write interest to the socket and goes back to sitting on the
event handler.
7.  An event is detected and the server then performs an SSL_write() to
the (non-existent) client, which is successful.

This write may succeed due to kernel buffering and the unread data still in the read buffer of the kernel until that is read the normal TCP shutdown/close condition may not be seen. Or it may fail SSL_write() == -1 && SSL_get_error() == SSL_ERROR_SYSCALL.

But the problem here is that your application is being single minded, in that it has shut its ears to processing more TCP level data (even tho the SSL protocol handling layer might require some read processing to take place, even during writes, but you cut of the SSL protocol layer's source of data).

I can understand why you do it, since you don't want the application to be holding onto data relating to the next pipelined request just yet as you have no intention on servicing it.

What you really wanted in this scenario is continue to observe read interest in the client TCP socket but use an SSL_peek() call. I have called for this API call before, that is an OpenSSL API function that allows WANT_READ processing to take place but does not destructively return application data.

Since OpenSSL doesn't have a SSL_peek() call and your application could hold onto a small buffer of extraneous application data then it would be possible to over-read by one (before you drop read interest). This would not detect the situation where the client wrote multiple requests to the server, waited a short time, then reverted to sending a SSL shutdown notify and closing the socket.

What you really wanted to know was out-of-band indication from the kernel that the client reset the connection. Knowing that client had TCP send shutdown is not useful, only if a connection reset was known about before, which requires the client to have actually sent a TCP reset packet (which I think occurs in the situation you are in, due to the WSAGetLastError() == WSAECONNABORTED.


8.  It then adds read interest in the socket, as it is a Keep-Alive
socket, so it is waiting for the next HTTP request.  It goes back to
sitting on the event handler.

9.  An event is detected and the server then performs:

9a. SSL_read() which fails (return code is -1).
9b. SSL_get_error() which returns SSL_ERROR_SYSCALL.
9c. ERR_get_error() which returns 0.

In the original code SSL_get_shutdown() would not be called unless
SSL_get_error() returns SSL_ERROR_ZERO_RETURN, but I added an extra
debug call after the call to SSL_get_error(), and it did not show
SSL_RECEIVED_SHUTDOWN.

And I have now added a call to WSAGetLastError() after the call to
ERR_get_error(), and it returns WSAECONNABORTED.

So I do get a read event on the socket.  I do call SSL_read.  It fails.
But the shutdown is apparently not received, as:

a.  SSL_get_error() does not return SSL_ERROR_ZERO_RETURN
b.  SSL_get_shutdown() does not show SSL_RECEIVED_SHUTDOWN

I hope that's clear.

Okay knowing that WSAGetLastError() == WSAECONNABORTED as this time is irrelevant, since any SSL_read() == -1 && SSL_get_error() == SSL_ERROR_SYSCALL would always be a sitution to cleanup and close the socket. Since OpenSSL already processes the Winsock API error returns for WANT_READ and WANT_WRITE on non-blocking sockets itself. Getting a SSL_ERROR_SYSCALL is not a recoverable situation. Work through my code snippet to see exactly this behavior.


So after reading it all it seems you want to detect when a client has gone away before your processing has created a response, maybe so you can cancel the processing and save cycles.

There is no mechanism that will be able to detect this 100% if you include the possibility of HTTP request pipelining and that your application serializes request processing on a per socket basis. If you remove one of these factors then it should be possible to detect impatient clients by continuing to maintain read interest in the socket and if necessary storing the application data over-read for when its needed to process the next request. This may catch most situation you want to catch.

One way of ensuring you never get a pipelined request is to move the object being served to a unique IP address / TCP port combination per object per page load. I'm not sure if the pipelining rules for HTTP would allow differing Host: headers to be pipelined in the same connection (if the DNS resolution and port resolution pointed to a HTTP socket your HTTP client connection pool already had open). If it clearly states you can't then changing the host of the object and setting up an alias the other side maybe another option.


HTH

Darryl


PS: Would appreciate replies / references on any info to allow windows to scale socket handling upto at least 4 figure open sockets.
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to