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