summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-09-26 18:03:00 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-10-01 06:39:47 -0400
commit39c0c2c3edc27706297d84d118f87d5afefa3341 (patch)
treecc55007374b97f9543548f3aedd56b4e6fd4d39e
parented2c6983007c52cab1d903d29222f27f53eb5d86 (diff)
downloadlighttpd-git-39c0c2c3edc27706297d84d118f87d5afefa3341.tar.gz
[core] cap size of data framed for HTTP/2 response
cap size of data framed for HTTP/2 response until more data sent to client make sure to reschedule connection in job queue if max_bytes reached and then the entire con->write_queue was flushed to network, or else there is a chance the request may not get rescheduled (and then will timeout) if the request is completed from the backend and there is no other traffic or streams to trigger connection processing. (check con->write_queue > 8k rather than empty from last round, since small frames such as connection preface may have been added this round while processing con->read_queue)
-rw-r--r--src/connections.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/connections.c b/src/connections.c
index 5639d3e7..43f8c343 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -1242,6 +1242,10 @@ connection_state_machine_h2 (request_st * const h2r, connection * const con)
? connection_write_throttle(con, MAX_WRITE_LIMIT)
: 0;
const off_t fsize = (off_t)h2c->s_max_frame_size;
+ const off_t cqlen = chunkqueue_length(con->write_queue);
+ if (cqlen > 8192 && max_bytes > 65536) max_bytes = 65536;
+ max_bytes -= cqlen;
+ if (max_bytes < 0) max_bytes = 0;
/* XXX: to avoid buffer bloat due to staging too much data in
* con->write_queue, consider setting limit on how much is staged
@@ -1314,6 +1318,8 @@ connection_state_machine_h2 (request_st * const h2r, connection * const con)
connection_request_end_h2(h2r, con);
}
}
+
+ if (0 == max_bytes) resched |= 2;
}
if (h2c->sent_goaway > 0 && h2c->rused) {
@@ -1339,6 +1345,8 @@ connection_state_machine_h2 (request_st * const h2r, connection * const con)
if (chunkqueue_is_empty(con->write_queue)
&& 0 == h2c->rused && h2c->sent_goaway)
connection_set_state(h2r, CON_STATE_RESPONSE_END);
+ else if (resched & 2)
+ resched = (resched & 1) | (chunkqueue_is_empty(con->write_queue));
}
if (h2r->state == CON_STATE_WRITE) {