Hi!

relay_error() sets se_done even if write buffer is not drained and
relay_write() will close the connection if se_done is set

I have a case with 76k json payload where relay_error() detects EOF
on read socket, sets so_done but write socket is not drained yet
and socket is closed before all the content is transfered.

debug output:
version: HTTP/1.1 rescode: 200 resmsg: OK
relay_writeheader_kv: Connection: close
relay_writeheader_kv: Content-Length: 76854
relay_writeheader_kv: Content-Type: application/json;charset=utf-8
relay_read_httpcontent: session 1: size 3752, to read 76854
relay_read_httpcontent: done, size 3752, to read 73102
relay_read_httpcontent: session 1: size 16384, to read 73102
relay_read_httpcontent: done, size 16384, to read 56718
relay_write buffer len 4081 se_done 0
relay_read_httpcontent: session 1: size 56718, to read 56718
relay_read_httpcontent: done, size 56718, to read 0
relay_read_http: session 1: size 0, to read -2
relay_write buffer len 44415 se_done 0
relay_write buffer len 28031 se_done 1
relay test, session 1 (1 active), 0, 1.2.3.4 -> 5.5.66.66:9999, last write 
(done), GET

fix:
Index: usr.sbin/relayd/relay.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.225
diff -u -p -r1.225 relay.c
--- usr.sbin/relayd/relay.c     9 Aug 2017 21:29:17 -0000       1.225
+++ usr.sbin/relayd/relay.c     22 Aug 2017 17:07:33 -0000
@@ -788,9 +788,12 @@ relay_write(struct bufferevent *bev, voi
 {
        struct ctl_relay_event  *cre = arg;
        struct rsession         *con = cre->con;
+       struct evbuffer         *dst = EVBUFFER_OUTPUT(bev);
 
        getmonotime(&con->se_tv_last);
 
+       if (EVBUFFER_LENGTH(dst))
+               return;
        if (con->se_done)
                goto done;
        if (relay_splice(cre->dst) == -1)
@@ -962,7 +965,6 @@ relay_error(struct bufferevent *bev, sho
 {
        struct ctl_relay_event  *cre = arg;
        struct rsession         *con = cre->con;
-       struct evbuffer         *dst;
 
        if (error & EVBUFFER_TIMEOUT) {
                if (cre->splicelen >= 0) {
@@ -1017,9 +1019,7 @@ relay_error(struct bufferevent *bev, sho
 
                con->se_done = 1;
                if (cre->dst->bev != NULL) {
-                       dst = EVBUFFER_OUTPUT(cre->dst->bev);
-                       if (EVBUFFER_LENGTH(dst))
-                               return;
+                       return;
                } else if (cre->toread == TOREAD_UNLIMITED || cre->toread == 0)
                        return;
 


Rivo

Reply via email to