commit d4bc9aa446e9fc562633c41cd91e9c242c4eed67
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2026-06-18T05:05:50Z |
| subject | Fixed long upload session got timed out |
commit d4bc9aa446e9fc562633c41cd91e9c242c4eed67
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2026-06-18T05:05:50Z
Fixed long upload session got timed out
---
src/stream_conn.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++------
src/stream_conn.h | 5 ++++
src/stream_pipe.c | 2 ++
src/stream_route.h | 4 +++
4 files changed, 80 insertions(+), 8 deletions(-)
diff --git a/src/stream_conn.c b/src/stream_conn.c
index 5fe4b6f..ff87b2d 100644
--- a/src/stream_conn.c
+++ b/src/stream_conn.c
@@ -22,6 +22,11 @@ void free_conn(conn_t *conn) {
return;
}
+ if (conn->idle_ev) {
+ event_free(conn->idle_ev);
+ conn->idle_ev = NULL;
+ }
+
if (conn->client != NULL) {
bufferevent_free(conn->client);
}
@@ -43,15 +48,67 @@ static void set_connect_timeout(conn_t *conn, const struct route *r)
bufferevent_set_timeouts(conn->upstream, NULL, &connect_timeout);
}
-static void set_idle_timeouts(conn_t *conn, const struct route *r)
+static void clear_idle_timeout(conn_t *conn)
{
- struct timeval idle_timeout = {
- .tv_sec = r->opts.idle_timeout_sec,
+ bufferevent_set_timeouts(conn->client, NULL, NULL);
+ bufferevent_set_timeouts(conn->upstream, NULL, NULL);
+}
+
+static void schedule_conn_idle_timer(conn_t *conn)
+{
+ if (!conn->idle_ev)
+ return;
+
+ if (conn->route->opts.idle_timeout_sec <= 0)
+ return;
+
+ struct timeval tv = {
+ .tv_sec = conn->route->opts.idle_timeout_sec,
.tv_usec = 0,
};
- bufferevent_set_timeouts(conn->client, &idle_timeout, &idle_timeout);
- bufferevent_set_timeouts(conn->upstream, &idle_timeout, &idle_timeout);
+ evtimer_add(conn->idle_ev, &tv);
+}
+
+static void conn_idle_timeout_cb(evutil_socket_t fd, short events, void *arg)
+{
+ (void)events;
+ (void)fd;
+
+ conn_t *conn = arg;
+
+ if (!conn) {
+ return;
+ }
+
+ if (conn->activity_seq != conn->idle_check_seq) {
+ conn->idle_check_seq = conn->activity_seq;
+ schedule_conn_idle_timer(conn);
+ return;
+ }
+
+ LOG_WARN("stream connection idle timed out",
+ "listen", _LOGV_ENDPOINT(&conn->route->listen),
+ "upstream", _LOGV_ENDPOINT(&conn->route->upstream)
+ );
+
+ free_conn(conn);
+}
+
+static int start_conn_idle_timer(conn_t *conn)
+{
+ if (conn->route->opts.idle_timeout_sec <= 0)
+ return 0;
+
+ conn->activity_seq = 1;
+ conn->idle_check_seq = conn->activity_seq;
+
+ conn->idle_ev = evtimer_new(conn->owner->base, conn_idle_timeout_cb, conn);
+ if (!conn->idle_ev)
+ return -1;
+
+ schedule_conn_idle_timer(conn);
+ return 0;
}
void set_client_idle_timeout(conn_t *conn, const struct route *r)
@@ -229,7 +286,8 @@ void stream_upstream_event_cb(struct bufferevent *bev, short events, void *arg)
if (events & BEV_EVENT_CONNECTED) {
conn->upstream_connected = true;
- set_idle_timeouts(conn, conn->route);
+ clear_idle_timeout(conn);
+ start_conn_idle_timer(conn);
bufferevent_enable(conn->client, EV_READ | EV_WRITE);
return;
@@ -409,6 +467,9 @@ void worker_adopt_client_fd(struct worker *w, struct worker_stream_client_msg *a
const struct route *r = ac->route;
+ conn->activity_seq = 1;
+ conn->idle_check_seq = 1;
+
conn->owner = w;
conn->route = r;
@@ -582,8 +643,8 @@ int stream_route_adopt_client_for_fuzz(
ac.route = r;
if (peer_addr != NULL &&
- peer_addr_len > 0 &&
- peer_addr_len <= sizeof(ac.peer_addr)) {
+ peer_addr_len > 0 &&
+ peer_addr_len <= sizeof(ac.peer_addr)) {
memcpy(&ac.peer_addr, peer_addr, peer_addr_len);
ac.peer_addr_len = peer_addr_len;
}
diff --git a/src/stream_conn.h b/src/stream_conn.h
index 320e2ef..6033344 100644
--- a/src/stream_conn.h
+++ b/src/stream_conn.h
@@ -20,6 +20,11 @@ void stream_upstream_event_cb(struct bufferevent *bev, short events, void *arg);
void worker_adopt_client_fd(struct worker *w, struct worker_stream_client_msg *ac);
+static inline void conn_touch(conn_t *conn)
+{
+ conn->activity_seq++;
+}
+
#ifdef FUZZ
int stream_route_adopt_client_for_fuzz(
struct event_base *base,
diff --git a/src/stream_pipe.c b/src/stream_pipe.c
index b511ad1..eddaacd 100644
--- a/src/stream_pipe.c
+++ b/src/stream_pipe.c
@@ -35,6 +35,7 @@ void pipe_client_read_cb(struct bufferevent *client, void *arg)
stream_sniff_peek_client_input(&conn->sniff, src);
}
+ conn_touch(conn);
evbuffer_add_buffer(dst, src);
if (evbuffer_get_length(dst) >= STREAM_READ_HIGH_WATER) {
@@ -72,6 +73,7 @@ void pipe_upstream_read_cb(struct bufferevent *upstream, void *arg)
);
#endif
+ conn_touch(conn);
evbuffer_add_buffer(dst, src);
if (evbuffer_get_length(dst) >= STREAM_READ_HIGH_WATER) {
diff --git a/src/stream_route.h b/src/stream_route.h
index adc08a8..a9e243a 100644
--- a/src/stream_route.h
+++ b/src/stream_route.h
@@ -35,6 +35,10 @@ typedef struct conn_s {
bool upstream_connected;
bool close_after_client_eof;
bool close_client_after_drain;
+
+ uint64_t activity_seq;
+ uint64_t idle_check_seq;
+ struct event *idle_ev;
} conn_t;
int start_stream_route(