mirror of
https://github.com/apache/httpd.git
synced 2025-08-13 14:40:20 +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]
|
||||||
|
|
119
support/ab.c
119
support/ab.c
@ -237,7 +237,11 @@ typedef enum {
|
|||||||
* know if it worked yet
|
* know if it worked yet
|
||||||
*/
|
*/
|
||||||
STATE_CONNECTED, /* we know TCP connect completed */
|
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;
|
} connect_state_e;
|
||||||
|
|
||||||
#define CBUFFSIZE (8192)
|
#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;
|
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_print_connection_info(bio_err,c->ssl);
|
||||||
SSL_SESSION_print(bio_err, SSL_get_session(c->ssl));
|
SSL_SESSION_print(bio_err, SSL_get_session(c->ssl));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ssl_proceed_handshake(struct connection *c)
|
static void ssl_proceed_handshake(struct connection *c)
|
||||||
{
|
{
|
||||||
@ -783,14 +779,19 @@ static void ssl_proceed_handshake(struct connection *c)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
write_request(c);
|
write_request(c);
|
||||||
|
|
||||||
do_next = 0;
|
do_next = 0;
|
||||||
break;
|
break;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
set_polled_events(c, APR_POLLIN);
|
|
||||||
|
set_conn_state(c, STATE_HANDSHAKE, APR_POLLIN);
|
||||||
|
|
||||||
do_next = 0;
|
do_next = 0;
|
||||||
break;
|
break;
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
set_polled_events(c, APR_POLLOUT);
|
|
||||||
|
set_conn_state(c, STATE_HANDSHAKE, APR_POLLOUT);
|
||||||
|
|
||||||
do_next = 0;
|
do_next = 0;
|
||||||
break;
|
break;
|
||||||
case SSL_ERROR_WANT_CONNECT:
|
case SSL_ERROR_WANT_CONNECT:
|
||||||
@ -810,9 +811,6 @@ static void ssl_proceed_handshake(struct connection *c)
|
|||||||
|
|
||||||
static void write_request(struct connection * c)
|
static void write_request(struct connection * c)
|
||||||
{
|
{
|
||||||
if (started >= requests) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
apr_time_t tnow;
|
apr_time_t tnow;
|
||||||
@ -845,10 +843,14 @@ static void write_request(struct connection * c)
|
|||||||
if (e <= 0) {
|
if (e <= 0) {
|
||||||
switch (SSL_get_error(c->ssl, e)) {
|
switch (SSL_get_error(c->ssl, e)) {
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
set_polled_events(c, APR_POLLIN);
|
|
||||||
|
set_conn_state(c, STATE_WRITE, APR_POLLIN);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
set_polled_events(c, APR_POLLOUT);
|
|
||||||
|
set_conn_state(c, STATE_WRITE, APR_POLLOUT);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BIO_printf(bio_err, "SSL write failed - closing connection\n");
|
BIO_printf(bio_err, "SSL write failed - closing connection\n");
|
||||||
@ -871,7 +873,7 @@ static void write_request(struct connection * c)
|
|||||||
close_connection(c);
|
close_connection(c);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_polled_events(c, APR_POLLOUT);
|
set_conn_state(c, STATE_WRITE, APR_POLLOUT);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -883,7 +885,8 @@ static void write_request(struct connection * c)
|
|||||||
|
|
||||||
c->endwrite = lasttime = apr_time_now();
|
c->endwrite = lasttime = apr_time_now();
|
||||||
started++;
|
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;
|
apr_status_t rv;
|
||||||
|
|
||||||
if (!(started < requests))
|
if (!(started < requests)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
c->read = 0;
|
c->read = 0;
|
||||||
c->bread = 0;
|
c->bread = 0;
|
||||||
@ -1439,12 +1443,12 @@ static void start_connect(struct connection * c)
|
|||||||
#endif
|
#endif
|
||||||
if ((rv = apr_socket_connect(c->aprsock, destsa)) != APR_SUCCESS) {
|
if ((rv = apr_socket_connect(c->aprsock, destsa)) != APR_SUCCESS) {
|
||||||
if (APR_STATUS_IS_EINPROGRESS(rv)) {
|
if (APR_STATUS_IS_EINPROGRESS(rv)) {
|
||||||
set_conn_state(c, STATE_CONNECTING);
|
set_conn_state(c, STATE_CONNECTING, APR_POLLOUT);
|
||||||
c->rwrite = 0;
|
c->rwrite = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_conn_state(c, STATE_UNCONNECTED);
|
set_conn_state(c, STATE_UNCONNECTED, 0);
|
||||||
apr_socket_close(c->aprsock);
|
apr_socket_close(c->aprsock);
|
||||||
if (good == 0 && destsa->next) {
|
if (good == 0 && destsa->next) {
|
||||||
destsa = destsa->next;
|
destsa = destsa->next;
|
||||||
@ -1465,7 +1469,6 @@ static void start_connect(struct connection * c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* connected first time */
|
/* connected first time */
|
||||||
set_conn_state(c, STATE_CONNECTED);
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
if (c->ssl) {
|
if (c->ssl) {
|
||||||
ssl_proceed_handshake(c);
|
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
|
#ifdef USE_SSL
|
||||||
if (c->ssl) {
|
if (c->ssl) {
|
||||||
SSL_shutdown(c->ssl);
|
SSL_shutdown(c->ssl);
|
||||||
@ -1571,10 +1574,14 @@ read_more:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (scode == SSL_ERROR_WANT_READ) {
|
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) {
|
else if (scode == SSL_ERROR_WANT_WRITE) {
|
||||||
set_polled_events(c, APR_POLLOUT);
|
|
||||||
|
set_conn_state(c, STATE_READ, APR_POLLOUT);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* some fatal error: */
|
/* some fatal error: */
|
||||||
@ -1668,7 +1675,7 @@ read_more:
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* header is in invalid or too big - close connection */
|
/* 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);
|
apr_socket_close(c->aprsock);
|
||||||
err_response++;
|
err_response++;
|
||||||
if (bad++ > 10) {
|
if (bad++ > 10) {
|
||||||
@ -1758,7 +1765,13 @@ read_more:
|
|||||||
goto 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 */
|
/* finished a keep-alive connection */
|
||||||
good++;
|
good++;
|
||||||
/* save out time */
|
/* save out time */
|
||||||
@ -1790,7 +1803,7 @@ read_more:
|
|||||||
c->read = c->bread = 0;
|
c->read = c->bread = 0;
|
||||||
/* zero connect time with keep-alive */
|
/* zero connect time with keep-alive */
|
||||||
c->start = c->connect = lasttime = apr_time_now();
|
c->start = c->connect = lasttime = apr_time_now();
|
||||||
set_conn_state(c, STATE_CONNECTED);
|
|
||||||
write_request(c);
|
write_request(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1980,6 +1993,7 @@ static void test(void)
|
|||||||
do {
|
do {
|
||||||
status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults);
|
status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults);
|
||||||
} while (APR_STATUS_IS_EINTR(status));
|
} while (APR_STATUS_IS_EINTR(status));
|
||||||
|
|
||||||
if (status != APR_SUCCESS)
|
if (status != APR_SUCCESS)
|
||||||
apr_err("apr_pollset_poll", status);
|
apr_err("apr_pollset_poll", status);
|
||||||
|
|
||||||
@ -2015,8 +2029,23 @@ static void test(void)
|
|||||||
* connection is done and we loop here endlessly calling
|
* connection is done and we loop here endlessly calling
|
||||||
* apr_poll().
|
* apr_poll().
|
||||||
*/
|
*/
|
||||||
if ((rtnev & APR_POLLIN) || (rtnev & APR_POLLPRI) || (rtnev & APR_POLLHUP))
|
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);
|
read_connection(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if ((rtnev & APR_POLLERR) || (rtnev & APR_POLLNVAL)) {
|
if ((rtnev & APR_POLLERR) || (rtnev & APR_POLLNVAL)) {
|
||||||
if (destsa->next && c->state == STATE_CONNECTING && good == 0) {
|
if (destsa->next && c->state == STATE_CONNECTING && good == 0) {
|
||||||
destsa = destsa->next;
|
destsa = destsa->next;
|
||||||
@ -2040,7 +2069,7 @@ static void test(void)
|
|||||||
/* call connect() again to detect errors */
|
/* call connect() again to detect errors */
|
||||||
rv = apr_socket_connect(c->aprsock, destsa);
|
rv = apr_socket_connect(c->aprsock, destsa);
|
||||||
if (rv != APR_SUCCESS) {
|
if (rv != APR_SUCCESS) {
|
||||||
set_conn_state(c, STATE_UNCONNECTED);
|
set_conn_state(c, STATE_UNCONNECTED, 0);
|
||||||
apr_socket_close(c->aprsock);
|
apr_socket_close(c->aprsock);
|
||||||
err_conn++;
|
err_conn++;
|
||||||
if (bad++ > 10) {
|
if (bad++ > 10) {
|
||||||
@ -2052,7 +2081,7 @@ static void test(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_conn_state(c, STATE_CONNECTED);
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
if (c->ssl)
|
if (c->ssl)
|
||||||
ssl_proceed_handshake(c);
|
ssl_proceed_handshake(c);
|
||||||
@ -2060,16 +2089,24 @@ static void test(void)
|
|||||||
#endif
|
#endif
|
||||||
write_request(c);
|
write_request(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* POLLOUT is one shot */
|
|
||||||
set_polled_events(c, APR_POLLIN);
|
switch (c->state) {
|
||||||
if (c->state == STATE_READ) {
|
#ifdef USE_SSL
|
||||||
read_connection(c);
|
case STATE_HANDSHAKE:
|
||||||
}
|
ssl_proceed_handshake(c);
|
||||||
else {
|
break;
|
||||||
|
#endif
|
||||||
|
case STATE_WRITE:
|
||||||
write_request(c);
|
write_request(c);
|
||||||
|
break;
|
||||||
|
case STATE_READ:
|
||||||
|
read_connection(c);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user