mirror of
https://github.com/apache/httpd.git
synced 2025-08-10 02:56:11 +00:00
Reinstate r1897458 accidentally reverted in r1897760.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1897861 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
5
changes-entries/ab-ssl-sense-fix.txt
Normal file
5
changes-entries/ab-ssl-sense-fix.txt
Normal file
@ -0,0 +1,5 @@
|
||||
*) ab: Respond appropriately to SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE.
|
||||
Previously the correct event was polled for, but the response to the poll
|
||||
would call write instead of read, and read instead of write. PR 55952
|
||||
[Graham Leggett]
|
||||
|
123
support/ab.c
123
support/ab.c
@ -237,7 +237,11 @@ typedef enum {
|
||||
* know if it worked yet
|
||||
*/
|
||||
STATE_CONNECTED, /* we know TCP connect completed */
|
||||
STATE_READ
|
||||
#ifdef USE_SSL
|
||||
STATE_HANDSHAKE, /* in the handshake phase */
|
||||
#endif
|
||||
STATE_WRITE, /* in the write phase */
|
||||
STATE_READ /* in the read phase */
|
||||
} connect_state_e;
|
||||
|
||||
#define CBUFFSIZE (8192)
|
||||
@ -520,21 +524,13 @@ static void set_polled_events(struct connection *c, apr_int16_t new_reqevents)
|
||||
}
|
||||
}
|
||||
|
||||
static void set_conn_state(struct connection *c, connect_state_e new_state)
|
||||
static void set_conn_state(struct connection *c, connect_state_e new_state,
|
||||
apr_int16_t events)
|
||||
{
|
||||
apr_int16_t events_by_state[] = {
|
||||
0, /* for STATE_UNCONNECTED */
|
||||
APR_POLLOUT, /* for STATE_CONNECTING */
|
||||
APR_POLLIN, /* for STATE_CONNECTED; we don't poll in this state,
|
||||
* so prepare for polling in the following state --
|
||||
* STATE_READ
|
||||
*/
|
||||
APR_POLLIN /* for STATE_READ */
|
||||
};
|
||||
|
||||
c->state = new_state;
|
||||
|
||||
set_polled_events(c, events_by_state[new_state]);
|
||||
set_polled_events(c, events);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------- */
|
||||
@ -707,7 +703,7 @@ static void ssl_print_info(struct connection *c)
|
||||
}
|
||||
ssl_print_connection_info(bio_err,c->ssl);
|
||||
SSL_SESSION_print(bio_err, SSL_get_session(c->ssl));
|
||||
}
|
||||
}
|
||||
|
||||
static void ssl_proceed_handshake(struct connection *c)
|
||||
{
|
||||
@ -783,14 +779,19 @@ static void ssl_proceed_handshake(struct connection *c)
|
||||
}
|
||||
#endif
|
||||
write_request(c);
|
||||
|
||||
do_next = 0;
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
set_polled_events(c, APR_POLLIN);
|
||||
|
||||
set_conn_state(c, STATE_HANDSHAKE, APR_POLLIN);
|
||||
|
||||
do_next = 0;
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
set_polled_events(c, APR_POLLOUT);
|
||||
|
||||
set_conn_state(c, STATE_HANDSHAKE, APR_POLLOUT);
|
||||
|
||||
do_next = 0;
|
||||
break;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
@ -810,9 +811,6 @@ static void ssl_proceed_handshake(struct connection *c)
|
||||
|
||||
static void write_request(struct connection * c)
|
||||
{
|
||||
if (started >= requests) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
apr_time_t tnow;
|
||||
@ -845,10 +843,14 @@ static void write_request(struct connection * c)
|
||||
if (e <= 0) {
|
||||
switch (SSL_get_error(c->ssl, e)) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
set_polled_events(c, APR_POLLIN);
|
||||
|
||||
set_conn_state(c, STATE_WRITE, APR_POLLIN);
|
||||
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
set_polled_events(c, APR_POLLOUT);
|
||||
|
||||
set_conn_state(c, STATE_WRITE, APR_POLLOUT);
|
||||
|
||||
break;
|
||||
default:
|
||||
BIO_printf(bio_err, "SSL write failed - closing connection\n");
|
||||
@ -871,7 +873,7 @@ static void write_request(struct connection * c)
|
||||
close_connection(c);
|
||||
}
|
||||
else {
|
||||
set_polled_events(c, APR_POLLOUT);
|
||||
set_conn_state(c, STATE_WRITE, APR_POLLOUT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -883,7 +885,8 @@ static void write_request(struct connection * c)
|
||||
|
||||
c->endwrite = lasttime = apr_time_now();
|
||||
started++;
|
||||
set_conn_state(c, STATE_READ);
|
||||
|
||||
set_conn_state(c, STATE_READ, APR_POLLIN);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------- */
|
||||
@ -1355,8 +1358,9 @@ static void start_connect(struct connection * c)
|
||||
{
|
||||
apr_status_t rv;
|
||||
|
||||
if (!(started < requests))
|
||||
if (!(started < requests)) {
|
||||
return;
|
||||
}
|
||||
|
||||
c->read = 0;
|
||||
c->bread = 0;
|
||||
@ -1439,12 +1443,12 @@ static void start_connect(struct connection * c)
|
||||
#endif
|
||||
if ((rv = apr_socket_connect(c->aprsock, destsa)) != APR_SUCCESS) {
|
||||
if (APR_STATUS_IS_EINPROGRESS(rv)) {
|
||||
set_conn_state(c, STATE_CONNECTING);
|
||||
set_conn_state(c, STATE_CONNECTING, APR_POLLOUT);
|
||||
c->rwrite = 0;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
set_conn_state(c, STATE_UNCONNECTED);
|
||||
set_conn_state(c, STATE_UNCONNECTED, 0);
|
||||
apr_socket_close(c->aprsock);
|
||||
if (good == 0 && destsa->next) {
|
||||
destsa = destsa->next;
|
||||
@ -1465,7 +1469,6 @@ static void start_connect(struct connection * c)
|
||||
}
|
||||
|
||||
/* connected first time */
|
||||
set_conn_state(c, STATE_CONNECTED);
|
||||
#ifdef USE_SSL
|
||||
if (c->ssl) {
|
||||
ssl_proceed_handshake(c);
|
||||
@ -1513,7 +1516,7 @@ static void close_connection(struct connection * c)
|
||||
}
|
||||
}
|
||||
|
||||
set_conn_state(c, STATE_UNCONNECTED);
|
||||
set_conn_state(c, STATE_UNCONNECTED, 0);
|
||||
#ifdef USE_SSL
|
||||
if (c->ssl) {
|
||||
SSL_shutdown(c->ssl);
|
||||
@ -1571,10 +1574,14 @@ read_more:
|
||||
return;
|
||||
}
|
||||
else if (scode == SSL_ERROR_WANT_READ) {
|
||||
set_polled_events(c, APR_POLLIN);
|
||||
|
||||
set_conn_state(c, STATE_READ, APR_POLLIN);
|
||||
|
||||
}
|
||||
else if (scode == SSL_ERROR_WANT_WRITE) {
|
||||
set_polled_events(c, APR_POLLOUT);
|
||||
|
||||
set_conn_state(c, STATE_READ, APR_POLLOUT);
|
||||
|
||||
}
|
||||
else {
|
||||
/* some fatal error: */
|
||||
@ -1668,7 +1675,7 @@ read_more:
|
||||
}
|
||||
else {
|
||||
/* header is in invalid or too big - close connection */
|
||||
set_conn_state(c, STATE_UNCONNECTED);
|
||||
set_conn_state(c, STATE_UNCONNECTED, 0);
|
||||
apr_socket_close(c->aprsock);
|
||||
err_response++;
|
||||
if (bad++ > 10) {
|
||||
@ -1758,7 +1765,13 @@ read_more:
|
||||
goto read_more;
|
||||
}
|
||||
|
||||
if (c->keepalive && (c->bread >= c->length)) {
|
||||
/* are we done? */
|
||||
if (started >= requests && (c->bread >= c->length)) {
|
||||
close_connection(c);
|
||||
}
|
||||
|
||||
/* are we keepalive? if so, reuse existing connection */
|
||||
else if (c->keepalive && (c->bread >= c->length)) {
|
||||
/* finished a keep-alive connection */
|
||||
good++;
|
||||
/* save out time */
|
||||
@ -1790,7 +1803,7 @@ read_more:
|
||||
c->read = c->bread = 0;
|
||||
/* zero connect time with keep-alive */
|
||||
c->start = c->connect = lasttime = apr_time_now();
|
||||
set_conn_state(c, STATE_CONNECTED);
|
||||
|
||||
write_request(c);
|
||||
}
|
||||
}
|
||||
@ -1980,6 +1993,7 @@ static void test(void)
|
||||
do {
|
||||
status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults);
|
||||
} while (APR_STATUS_IS_EINTR(status));
|
||||
|
||||
if (status != APR_SUCCESS)
|
||||
apr_err("apr_pollset_poll", status);
|
||||
|
||||
@ -2015,8 +2029,23 @@ static void test(void)
|
||||
* connection is done and we loop here endlessly calling
|
||||
* apr_poll().
|
||||
*/
|
||||
if ((rtnev & APR_POLLIN) || (rtnev & APR_POLLPRI) || (rtnev & APR_POLLHUP))
|
||||
read_connection(c);
|
||||
if ((rtnev & APR_POLLIN) || (rtnev & APR_POLLPRI) || (rtnev & APR_POLLHUP)) {
|
||||
|
||||
switch (c->state) {
|
||||
#ifdef USE_SSL
|
||||
case STATE_HANDSHAKE:
|
||||
ssl_proceed_handshake(c);
|
||||
break;
|
||||
#endif
|
||||
case STATE_WRITE:
|
||||
write_request(c);
|
||||
break;
|
||||
case STATE_READ:
|
||||
read_connection(c);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if ((rtnev & APR_POLLERR) || (rtnev & APR_POLLNVAL)) {
|
||||
if (destsa->next && c->state == STATE_CONNECTING && good == 0) {
|
||||
destsa = destsa->next;
|
||||
@ -2040,7 +2069,7 @@ static void test(void)
|
||||
/* call connect() again to detect errors */
|
||||
rv = apr_socket_connect(c->aprsock, destsa);
|
||||
if (rv != APR_SUCCESS) {
|
||||
set_conn_state(c, STATE_UNCONNECTED);
|
||||
set_conn_state(c, STATE_UNCONNECTED, 0);
|
||||
apr_socket_close(c->aprsock);
|
||||
err_conn++;
|
||||
if (bad++ > 10) {
|
||||
@ -2052,7 +2081,7 @@ static void test(void)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
set_conn_state(c, STATE_CONNECTED);
|
||||
|
||||
#ifdef USE_SSL
|
||||
if (c->ssl)
|
||||
ssl_proceed_handshake(c);
|
||||
@ -2060,16 +2089,24 @@ static void test(void)
|
||||
#endif
|
||||
write_request(c);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
/* POLLOUT is one shot */
|
||||
set_polled_events(c, APR_POLLIN);
|
||||
if (c->state == STATE_READ) {
|
||||
read_connection(c);
|
||||
}
|
||||
else {
|
||||
|
||||
switch (c->state) {
|
||||
#ifdef USE_SSL
|
||||
case STATE_HANDSHAKE:
|
||||
ssl_proceed_handshake(c);
|
||||
break;
|
||||
#endif
|
||||
case STATE_WRITE:
|
||||
write_request(c);
|
||||
break;
|
||||
case STATE_READ:
|
||||
read_connection(c);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2692,7 +2729,7 @@ int main(int argc, const char * const argv[])
|
||||
if (ssl_cert != NULL) {
|
||||
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, ssl_cert) <= 0) {
|
||||
BIO_printf(bio_err, "unable to get certificate from '%s'\n",
|
||||
ssl_cert);
|
||||
ssl_cert);
|
||||
ERR_print_errors(bio_err);
|
||||
exit(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user