summaryrefslogtreecommitdiff
path: root/src/h2.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2023-04-09 00:19:09 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2023-04-29 16:27:58 -0400
commit5c6b81b7e384c40c82304443d3f362b305a6fdfd (patch)
treed3bf8d099d3954d96ff5cdb4a2999e0428455377 /src/h2.c
parent3ec59882a388b8e084695d2ff9917d3acf48d83f (diff)
downloadlighttpd-git-5c6b81b7e384c40c82304443d3f362b305a6fdfd.tar.gz
[core] h2_check_timeout()
Diffstat (limited to 'src/h2.c')
-rw-r--r--src/h2.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/h2.c b/src/h2.c
index be255654..62c06037 100644
--- a/src/h2.c
+++ b/src/h2.c
@@ -3052,3 +3052,82 @@ h2_upgrade_h2c (request_st * const r, connection * const con)
h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
}
}
+
+
+int
+h2_check_timeout (connection * const con, const unix_time64_t cur_ts)
+{
+ h2con * const h2c = con->h2;
+ request_st * const r = &con->request;
+ int changed = (r->state != CON_STATE_WRITE); /*(e.g. CON_STATE_ERROR)*/
+
+ if (!changed) {
+ if (h2c->rused) {
+ for (uint32_t i = 0; i < h2c->rused; ++i) {
+ request_st * const rr = h2c->r[i];
+ if (rr->state == CON_STATE_ERROR) { /*(should not happen)*/
+ changed = 1;
+ continue;
+ }
+ if (rr->reqbody_length != rr->reqbody_queue.bytes_in) {
+ /* XXX: should timeout apply if not trying to read on h2con?
+ * (still applying timeout to catch stuck connections) */
+ /* XXX: con->read_idle_ts is not per-request, so timeout
+ * will not occur if other read activity occurs on h2con
+ * (future: might keep separate timestamp per-request) */
+ if (cur_ts - con->read_idle_ts > rr->conf.max_read_idle) {
+ /* time - out */
+ if (rr->conf.log_request_handling) {
+ log_error(rr->conf.errh, __FILE__, __LINE__,
+ "request aborted - read timeout: %d", con->fd);
+ }
+ connection_set_state_error(r, CON_STATE_ERROR);
+ changed = 1;
+ }
+ }
+
+ if (rr->state != CON_STATE_READ_POST
+ && con->write_request_ts != 0) {
+ /* XXX: con->write_request_ts is not per-request, so timeout
+ * will not occur if other write activity occurs on h2con
+ * (future: might keep separate timestamp per-request) */
+ if (cur_ts - con->write_request_ts
+ > r->conf.max_write_idle) {
+ /*(see comment further down about max_write_idle)*/
+ /* time - out */
+ if (r->conf.log_timeouts) {
+ log_error(r->conf.errh, __FILE__, __LINE__,
+ "NOTE: a request from %s for %.*s timed out "
+ "after writing %lld bytes. We waited %d seconds. "
+ "If this is a problem, increase "
+ "server.max-write-idle",
+ r->dst_addr_buf->ptr,
+ BUFFER_INTLEN_PTR(&r->target),
+ (long long)r->write_queue.bytes_out,
+ (int)r->conf.max_write_idle);
+ }
+ connection_set_state_error(r, CON_STATE_ERROR);
+ changed = 1;
+ }
+ }
+ }
+ }
+ else {
+ if (cur_ts - con->read_idle_ts > con->keep_alive_idle) {
+ /* time - out */
+ if (r->conf.log_request_handling) {
+ log_error(r->conf.errh, __FILE__, __LINE__,
+ "connection closed - keep-alive timeout: %d",
+ con->fd);
+ }
+ connection_set_state(r, CON_STATE_RESPONSE_END);
+ changed = 1;
+ }
+ }
+ /* process changes before optimistic read of additional HTTP/2 frames */
+ if (changed)
+ con->is_readable = 0;
+ }
+
+ return changed;
+}