You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2022/01/25 15:54:22 UTC

svn commit: r1897458 - in /httpd/httpd/trunk: changes-entries/ab-ssl-sense-fix.txt support/ab.c

Author: minfrin
Date: Tue Jan 25 15:54:22 2022
New Revision: 1897458

URL: http://svn.apache.org/viewvc?rev=1897458&view=rev
Log:
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

Added:
    httpd/httpd/trunk/changes-entries/ab-ssl-sense-fix.txt
Modified:
    httpd/httpd/trunk/support/ab.c

Added: httpd/httpd/trunk/changes-entries/ab-ssl-sense-fix.txt
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/changes-entries/ab-ssl-sense-fix.txt?rev=1897458&view=auto
==============================================================================
--- httpd/httpd/trunk/changes-entries/ab-ssl-sense-fix.txt (added)
+++ httpd/httpd/trunk/changes-entries/ab-ssl-sense-fix.txt Tue Jan 25 15:54:22 2022
@@ -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]
+

Modified: httpd/httpd/trunk/support/ab.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/support/ab.c?rev=1897458&r1=1897457&r2=1897458&view=diff
==============================================================================
--- httpd/httpd/trunk/support/ab.c (original)
+++ httpd/httpd/trunk/support/ab.c Tue Jan 25 15:54:22 2022
@@ -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 con
     }
 }
 
-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 connec
     }
     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
             }
 #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
 
 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 connect
             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 connect
                     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 connect
 
     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 connect
 {
     apr_status_t rv;
 
-    if (!(started < requests))
+    if (!(started < requests)) {
         return;
+    }
 
     c->read = 0;
     c->bread = 0;
@@ -1435,12 +1439,12 @@ static void start_connect(struct connect
 #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;
@@ -1461,7 +1465,6 @@ static void start_connect(struct connect
     }
 
     /* connected first time */
-    set_conn_state(c, STATE_CONNECTED);
 #ifdef USE_SSL
     if (c->ssl) {
         ssl_proceed_handshake(c);
@@ -1509,7 +1512,7 @@ static void close_connection(struct conn
         }
     }
 
-    set_conn_state(c, STATE_UNCONNECTED);
+    set_conn_state(c, STATE_UNCONNECTED, 0);
 #ifdef USE_SSL
     if (c->ssl) {
         SSL_shutdown(c->ssl);
@@ -1567,10 +1570,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: */
@@ -1664,7 +1671,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) {
@@ -1754,7 +1761,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 */
@@ -1786,7 +1799,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);
     }
 }
@@ -1976,6 +1989,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);
 
@@ -2011,8 +2025,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;
@@ -2036,7 +2065,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) {
@@ -2048,7 +2077,7 @@ static void test(void)
                         continue;
                     }
                     else {
-                        set_conn_state(c, STATE_CONNECTED);
+
 #ifdef USE_SSL
                         if (c->ssl)
                             ssl_proceed_handshake(c);
@@ -2056,16 +2085,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;
                     }
+
                 }
             }
         }
@@ -2682,7 +2719,7 @@ int main(int argc, const char * const ar
     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);
         }



Re: svn commit: r1897458 - in /httpd/httpd/trunk: changes-entries/ab-ssl-sense-fix.txt support/ab.c

Posted by Ruediger Pluem <rp...@apache.org>.

On 1/25/22 4:54 PM, minfrin@apache.org wrote:
> Author: minfrin
> Date: Tue Jan 25 15:54:22 2022
> New Revision: 1897458
> 
> URL: http://svn.apache.org/viewvc?rev=1897458&view=rev
> Log:
> 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
> 
> Added:
>     httpd/httpd/trunk/changes-entries/ab-ssl-sense-fix.txt
> Modified:
>     httpd/httpd/trunk/support/ab.c
> 

> Modified: httpd/httpd/trunk/support/ab.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/support/ab.c?rev=1897458&r1=1897457&r2=1897458&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/support/ab.c (original)
> +++ httpd/httpd/trunk/support/ab.c Tue Jan 25 15:54:22 2022

> @@ -810,9 +811,6 @@ static void ssl_proceed_handshake(struct
>  
>  static void write_request(struct connection * c)
>  {
> -    if (started >= requests) {
> -        return;
> -    }

Why is this no longer needed?

>  
>      do {
>          apr_time_t tnow;

> @@ -1461,7 +1465,6 @@ static void start_connect(struct connect
>      }
>  
>      /* connected first time */
> -    set_conn_state(c, STATE_CONNECTED);

Why don't we set the state to connected any longer?

>  #ifdef USE_SSL
>      if (c->ssl) {
>          ssl_proceed_handshake(c);

> @@ -1786,7 +1799,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);

Why don't we set the state to connected any longer?

> +
>          write_request(c);
>      }
>  }

> @@ -2048,7 +2077,7 @@ static void test(void)
>                          continue;
>                      }
>                      else {
> -                        set_conn_state(c, STATE_CONNECTED);

Why don't we set the state to connected any longer?

> +
>  #ifdef USE_SSL
>                          if (c->ssl)
>                              ssl_proceed_handshake(c);


Regards

RĂ¼diger