See below for explanation of change; attached diff now correct. -Norman Tuttle, OpenDemand Systems Developer [EMAIL PROTECTED]
On Mon, 13 Oct 2003, Norman Tuttle wrote: > To Apache Flood development team: > > 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.
--- \flood-1.1\flood_net_ssl.c 2003-10-08 19:25:02.000000000 -0400 +++ flood_net_ssl.c 2003-11-04 12:06:16.000000000 -0500 @@ -281,37 +281,41 @@ int sslError; apr_int32_t socketsRead; - /* Wait until there is something to read. */ - if (SSL_pending(s->ssl_connection) < *buflen) { + do + { + + /* 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); + 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: - 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) + 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: + 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. */ - default: - ERR_print_errors_fp(stderr); - return APR_EGENERAL; - } + /* else Continue through with the error case. */ + default: + ERR_print_errors_fp(stderr); + return APR_EGENERAL; + } + } while (sslError != SSL_ERROR_NONE); /* to exit loop: need no error */ return APR_SUCCESS; } @@ -334,24 +338,27 @@ 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: - 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; - } + 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); + 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; }