[core] refuse excess initial streams only if block (fixes #3100)

refuse excess streams only if would block DATA frames for active streams
(for excess streams received on initial connect, prior to receiving
SETTINGS ACK from client)

(thx flynn)

x-ref:
  "Random TLS errors on established connections"
  https://redmine.lighttpd.net/issues/3100
  "Chrome 92, HTTP/2, fcgi, mutiple puts no response"
  https://redmine.lighttpd.net/issues/3093
master
Glenn Strauss 2 years ago
parent 58b9cca536
commit 3a5704380b

@ -412,22 +412,39 @@ static int
h2_send_refused_stream (uint32_t h2id, connection * const con)
{
h2con * const h2c = con->h2;
if (0 == h2c->sent_settings /*(see h2_recv_settings() comments)*/
|| (h2id < 200 && log_monotonic_secs - con->connection_start < 2)) {
/* too many active streams; refuse new stream */
h2c->h2_cid = h2id;
h2_send_rst_stream_id(h2id, con, H2_E_REFUSED_STREAM);
return 1;
}
else {
/* alternative: stop processing frames and defer processing this
* HEADERS frame until num active streams drops below limit.
if (h2c->sent_settings) { /*(see h2_recv_settings() comments)*/
/* client connected and immediately sent flurry of request streams
* (h2c->sent_settings is non-zero if sent SETTINGS frame to
* client and have not yet received SETTINGS ACK from client)
* lighttpd sends SETTINGS_MAX_CONCURRENT_STREAMS <limit> with
* server Connection Preface, so a well-behaved client will
* adjust after it sends its initial requests.
* (e.g. h2load -n 100 -m 100 sends 100 requests upon connect)*/
return -1;
* (e.g. h2load -n 100 -m 100 sends 100 requests upon connect)
*
* Check if active streams have pending request body. If all active
* streams have pending request body, then must refuse new stream as
* progress might be blocked if active streams all wait for DATA. */
for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
const request_st * const r = h2c->r[i];
if (r->reqbody_length == r->reqbody_queue.bytes_in) {
/* no pending request body; at least this request may proceed,
* though others waiting for request body may block until new
* request streams become active if new request streams precede
* DATA frames for active streams
*
* alternative to sending refused stream:
* stop processing frames and defer processing this HEADERS
* frame until num active streams drops below limit. */
return -1;
}
}
}
/* too many active streams; refuse new stream */
h2c->h2_cid = h2id;
h2_send_rst_stream_id(h2id, con, H2_E_REFUSED_STREAM);
return 1;
}

Loading…
Cancel
Save