I'm trying to write a secure HTTP server with pipelining, using OpenSSL.
It uses non-blocking I/O, and I have a few questions.

The behavior I'm seeing is:  I start the server on localhost, then I open a
browser and try to access the server.  The browser hangs with "Waiting for
localhost..."; the full response has been written successfully by
SSL_write() but the browser doesn't show the page.  I then kill the server
process, and the page displays immediately in the browser.  Is this
behavior familiar to anyone?

More details:  It's a master-slave architecture with a pool of slave
processes, with each slave process handling one client connection, and the
master process doing little but multiplexing HTTP messages among the
sockets and pipes to/from the slaves.  The basic structure of the master
code is:

- select() on read and write;
- loop through write-ready file descriptors, and for any client sockets
call one of try_accept(), try_shutdown(), try_SSL_read(), or
try_SSL_write(), depending on flags that have been set for that file
descriptor;
- loop through read-ready file descriptors in a similar manner.

Each of the four try_xxx() routines calls the appropriate OpenSSL library
routine, and on return code <= 0 handles each error code from
SSL_get_error().  For example, the raw socket is selected for reading upon
SSL_ERROR_WANT_READ, or for writing upon SSL_ERROR_WANT_WRITE.  Upon
success of each SSL routine, various flags and other state variables are
set.

Does it sound like this basic architecture can accommodate all the cases
needed for non-blocking I/O and OpenSSL?  Is handling the error codes from
those four routines sufficient, or are there others I need to handle?

Is there a way to check for EOF on the raw socket or SSL structure?

Is there a way to flush output written with SSL_write(), so that the
recipient can read it?  Would a rehandshaking do this, and if so how can
one trigger that?

When SSL_shutdown() returns 0 and SSL_ERROR_SYSCALL, how should one
select() on the underlying socket?  The docs I have found are unclear on
this.

Do I need to delve in to the BIO routines to get what I need?  (I know very
little about BIOs.)

The program is in Perl, but the main Perl API to OpenSSL (the Net::SSLeay
module) is mostly just wrappers, and I'm pretty sure these questions would
still apply if the program were in C.

I'm attaching the extracted code, in case anyone wants to look at it.  It's
500 lines including comments, but you can see e.g. just the error-handling
in try_SSL_read() by searching for "sub try_SSL_read".  The full program is
available upon request.

Thanks a lot for any clues!  I appreciate all help.

Cheers,
James

Attachment: embedded-server.pl
Description: Binary data

Reply via email to