Hi! On Wed, 2017-12-13 at 07:42 +0100, Claudio Jeker wrote: > I have seen something similar and came to the conclusion that the > timeout > handling of relayd is not correct. As long as traffic is flowing the > timeout should be reset (at least that is what every other > implementation > does). This is not really happening in relayd. I have seen this on > GET > requests that are huge (timeout hits in the middle of the transimit > and > kills the session). > > Because of this I think the diff is a workaround and does not solve > the > real underlying problem.
My next try. It schedules a timer event to bump bufferevent timeouts. One of the possibilities is to schedule it eg once every second, but I choose to schedule the event at half of the remaining bufferevent timeout. Rivo Index: usr.sbin/relayd/relay.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relay.c,v retrieving revision 1.236 diff -u -p -r1.236 relay.c --- usr.sbin/relayd/relay.c 28 Nov 2017 01:51:47 -0000 1.236 +++ usr.sbin/relayd/relay.c 16 Dec 2017 00:36:31 -0000 @@ -69,6 +69,7 @@ int relay_socket_connect(struct sockad void relay_accept(int, short, void *); void relay_input(struct rsession *); +void relay_timeout(int, short, void *); void relay_hash_addr(SIPHASH_CTX *, struct sockaddr_storage *, int); @@ -662,6 +663,7 @@ relay_connected(int fd, short sig, void struct bufferevent *bev; struct ctl_relay_event *out = &con->se_out; socklen_t len; + struct timeval tv; int error; if (sig == EV_TIMEOUT) { @@ -724,6 +726,14 @@ relay_connected(int fd, short sig, void bufferevent_settimeout(bev, rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec); + + evtimer_set(&con->se_ev, relay_timeout, con); + timerclear(&tv); + tv.tv_sec = rlay->rl_conf.timeout.tv_sec / 2; + if (tv.tv_sec == 0) + tv.tv_usec = 500000; + evtimer_add(&con->se_ev, &tv); + bufferevent_setwatermark(bev, EV_WRITE, RELAY_MIN_PREFETCHED * proto->tcpbufsiz, 0); bufferevent_enable(bev, EV_READ|EV_WRITE); @@ -955,6 +965,38 @@ relay_spliceadjust(struct ctl_relay_even cre->splicelen = -1; return (0); +} + +void +relay_timeout(int fd, short event, void *arg) +{ + struct rsession *con = arg; + struct ctl_relay_event *cre = &con->se_out; + struct relay *rlay = con->se_relay; + struct timeval tv, tv_now; + time_t timeout; + + timerclear(&tv); + getmonotime(&tv_now); + timersub(&tv_now, &con->se_tv_last, &tv); + timeout = rlay->rl_conf.timeout.tv_sec - tv.tv_sec; + + DPRINTF("%s: session %d: last %llds ago, timeout %llds", __func__, + con->se_id, tv.tv_sec, timeout); + + if (timeout > 0){ + bufferevent_settimeout(cre->bev, timeout, timeout); + bufferevent_settimeout(con->se_in.bev, timeout, timeout); + } + + evtimer_set(&con->se_ev, relay_timeout, con); + tv.tv_sec = (rlay->rl_conf.timeout.tv_sec - tv.tv_sec) / 2; + if (tv.tv_sec == 0) + tv.tv_usec = 500000; + evtimer_add(&con->se_ev, &tv); + + DPRINTF("%s: session %d: next after %llds", __func__, con->se_id, + tv.tv_sec); } void