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
embedded-server.pl
Description: Binary data