To Apache Flood development team: As part of our work on the Flood code (in our usage of it as par of an enterprise product), I have been instructed to contribute back our changes on a daily basis so we can both contribute them back to the product and get back inportant feedback on these changes.
Other than some small touch-ups, these changes to flood_net_ssl.c involve 1) taking recursive function code out of socket read/write functions, (replacing with do .. while loop) resulting in a) more robust code, with less possibility of stack-related issues. b) errors returned in recursively-called code were not being propagated. c) with iterative code it is easier to set limits on the amount of iteration, if necessary. I have not changed the logic here (yet). and 2) the addition of certain cases which should cause a continuation of reading. The -u3 diff is taken from the current directory holding the modified file and the \flood-1.1 directory holding the original from Apache project, and is attached here as fns.diff since as inline the mailer would modify the text. -Norman Tuttle, OpenDemand Systems Developer [EMAIL PROTECTED]
--- flood_net_ssl.c 2003-10-13 09:30:48.000000000 -0400 +++ \flood-1.1\flood_net_ssl.c 2003-10-08 19:25:02.000000000 -0400 @@ -84,8 +84,8 @@ #if APR_HAS_THREADS apr_thread_mutex_t **ssl_locks; -typedef struct CRYPTO_dynlock_value { - apr_thread_mutex_t *lock; +typedef struct CRYPTO_dynlock_value { + apr_thread_mutex_t *lock; } CRYPTO_dynlock_value; static CRYPTO_dynlock_value *ssl_dyn_create(const char* file, int line) @@ -101,7 +101,7 @@ return l; } -static void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file, +static void ssl_dyn_lock(int mode, CRYPTO_dynlock_value *l, const char *file, int line) { if (mode & CRYPTO_LOCK) { @@ -131,7 +131,7 @@ static unsigned long ssl_id(void) { /* FIXME: This is lame and not portable. -aaron */ - return (unsigned long) apr_os_thread_current(); + return (unsigned long) apr_os_thread_current(); } #endif @@ -213,7 +213,7 @@ void ssl_read_socket_handshake(ssl_socket_t *s); ssl_socket_t* ssl_open_socket(apr_pool_t *pool, request_t *r, - apr_status_t *status) + apr_status_t *status) { apr_os_sock_t ossock; int e, sslError; @@ -222,7 +222,7 @@ /* Open our TCP-based connection */ ssl_socket->socket = open_socket(pool, r, status); - + if (!ssl_socket->socket) return NULL; @@ -260,7 +260,7 @@ break; default: ERR_print_errors_fp(stderr); - return NULL; + return NULL; } } @@ -281,52 +281,45 @@ int sslError; apr_int32_t socketsRead; - do - { - - /* Wait until there is something to read. */ - if (SSL_pending(s->ssl_connection) < *buflen) { + /* Wait until there is something to read. */ + if (SSL_pending(s->ssl_connection) < *buflen) { e = apr_poll(&s->socket->read_pollset, 1, &socketsRead, LOCAL_SOCKET_TIMEOUT); if (socketsRead != 1) return APR_TIMEUP; - } + } - e = SSL_read(s->ssl_connection, buf, *buflen); - sslError = SSL_get_error(s->ssl_connection, e); - if (sslError!=SSL_ERROR_WANT_READ) *buflen = 0; + e = SSL_read(s->ssl_connection, buf, *buflen); + sslError = SSL_get_error(s->ssl_connection, e); - switch (sslError) - { - case SSL_ERROR_NONE: - *buflen = e; - break; - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_WANT_X509_LOOKUP: -// ssl_read_socket(s, buf, buflen); // Now uses do-while loop to do this properly! - break; - case SSL_ERROR_ZERO_RETURN: /* Peer closed connection. */ - return APR_EOF; - case SSL_ERROR_SYSCALL: /* Look at errno. */ - if (errno == 0) + switch (sslError) + { + case SSL_ERROR_NONE: + *buflen = e; + break; + case SSL_ERROR_WANT_READ: + ssl_read_socket(s, buf, buflen); + break; + case SSL_ERROR_ZERO_RETURN: /* Peer closed connection. */ + return APR_EOF; + case SSL_ERROR_SYSCALL: /* Look at errno. */ + if (errno == 0) return APR_EOF; - /* Continue through with the error case. */ -// case SSL_ERROR_WANT_WRITE: /* Technically, not an error. */ // (this is also in default) // Moved up now! - default: - ERR_print_errors_fp(stderr); - return APR_EGENERAL; - } + /* Continue through with the error case. */ + case SSL_ERROR_WANT_WRITE: /* Technically, not an error. */ + default: + ERR_print_errors_fp(stderr); + return APR_EGENERAL; } - while (sslError != SSL_ERROR_NONE); // to get out of this loop, need no errors! + return APR_SUCCESS; } void ssl_read_socket_handshake(ssl_socket_t *s) { char buf[1]; - int buflen = 1; + int buflen = 1; /* Wait until there is something to read. */ apr_int32_t socketsRead; apr_status_t e; @@ -341,28 +334,26 @@ apr_status_t e; int sslError; - do - { /* Returns an error. */ - e = SSL_write(s->ssl_connection, r->rbuf, r->rbufsize); + e = SSL_write(s->ssl_connection, r->rbuf, r->rbufsize); - sslError = SSL_get_error(s->ssl_connection, e); - switch (sslError) - { - case SSL_ERROR_NONE: - case SSL_ERROR_WANT_WRITE: - break; - case SSL_ERROR_WANT_READ: - ssl_read_socket_handshake(s); -// ssl_write_socket(s, r); // handled by while-do loop - break; - default: - ERR_print_errors_fp(stderr); - return APR_EGENERAL; - } + sslError = SSL_get_error(s->ssl_connection, e); + switch (sslError) + { + case SSL_ERROR_NONE: + break; + case SSL_ERROR_WANT_READ: + ssl_read_socket_handshake(s); + ssl_write_socket(s, r); + break; + case SSL_ERROR_WANT_WRITE: + break; + default: + ERR_print_errors_fp(stderr); + return APR_EGENERAL; } - while (sslError == SSL_ERROR_WANT_READ); // to get out of this loop, need no errors! (WANT_WRITE not considered error) - return APR_SUCCESS; + + return APR_SUCCESS; } #else /* FLOOD_HAS_OPENSSL */