Hi,

the following diff adds support for HTTP pipelining.

With pipelining, the client sends multiple requests before receiving
the responses in the same order.  It was long dead and disabled in
most browsers before Apple decided to turn it on in iOS Safari.

btw. There is no need to enable EV_READ in server_write() - and it can
cause a problem with pipelining - so I removed this line below.

OK?  Testers?

Reyk

Index: usr.sbin/httpd/httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.127
diff -u -p -u -p -r1.127 httpd.h
--- usr.sbin/httpd/httpd.h      31 Jan 2017 14:39:47 -0000      1.127
+++ usr.sbin/httpd/httpd.h      31 Jan 2017 19:59:11 -0000
@@ -342,6 +342,7 @@ struct client {
        size_t                   clt_headerlen;
        int                      clt_headersdone;
        unsigned int             clt_persist;
+       unsigned int             clt_pipelining;
        int                      clt_line;
        int                      clt_done;
        int                      clt_chunk;
Index: usr.sbin/httpd/server.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server.c,v
retrieving revision 1.104
diff -u -p -u -p -r1.104 server.c
--- usr.sbin/httpd/server.c     31 Jan 2017 17:25:05 -0000      1.104
+++ usr.sbin/httpd/server.c     31 Jan 2017 19:59:11 -0000
@@ -846,8 +846,6 @@ server_write(struct bufferevent *bev, vo
        if (clt->clt_done)
                goto done;
 
-       bufferevent_enable(bev, EV_READ);
-
        if (clt->clt_srvbev && clt->clt_srvbev_throttled) {
                bufferevent_enable(clt->clt_srvbev, EV_READ);
                clt->clt_srvbev_throttled = 0;
Index: usr.sbin/httpd/server_file.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_file.c,v
retrieving revision 1.64
diff -u -p -u -p -r1.64 server_file.c
--- usr.sbin/httpd/server_file.c        31 Jan 2017 14:39:47 -0000      1.64
+++ usr.sbin/httpd/server_file.c        31 Jan 2017 19:59:11 -0000
@@ -589,7 +589,7 @@ void
 server_file_error(struct bufferevent *bev, short error, void *arg)
 {
        struct client           *clt = arg;
-       struct evbuffer         *dst;
+       struct evbuffer         *src, *dst;
 
        if (error & EVBUFFER_TIMEOUT) {
                server_close(clt, "buffer event timeout");
@@ -608,6 +608,12 @@ server_file_error(struct bufferevent *be
 
                clt->clt_done = 1;
 
+               src = EVBUFFER_INPUT(clt->clt_bev);
+
+               /* Close the connection if a previous pipeline is empty */
+               if (clt->clt_pipelining && EVBUFFER_LENGTH(src) == 0)
+                       clt->clt_persist = 0;
+
                if (clt->clt_persist) {
                        /* Close input file and wait for next HTTP request */
                        if (clt->clt_fd != -1)
@@ -616,6 +622,12 @@ server_file_error(struct bufferevent *be
                        clt->clt_toread = TOREAD_HTTP_HEADER;
                        server_reset_http(clt);
                        bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
+
+                       /* Start pipelining if the buffer is not empty */
+                       if (EVBUFFER_LENGTH(src)) {
+                               clt->clt_pipelining++;
+                               server_read_http(clt->clt_bev, arg);
+                       }
                        return;
                }
 
Index: usr.sbin/httpd/server_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.112
diff -u -p -u -p -r1.112 server_http.c
--- usr.sbin/httpd/server_http.c        31 Jan 2017 14:39:47 -0000      1.112
+++ usr.sbin/httpd/server_http.c        31 Jan 2017 19:59:11 -0000
@@ -1186,6 +1186,10 @@ server_response(struct httpd *httpd, str
        if (clt->clt_persist >= srv_conf->maxrequests)
                clt->clt_persist = 0;
 
+       /* pipelining should end after the first "idempotent" method */
+       if (clt->clt_pipelining && clt->clt_toread > 0)
+               clt->clt_persist = 0;
+
        /*
         * Do we have a Host header and matching configuration?
         * XXX the Host can also appear in the URL path.

Reply via email to