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 */