Hi! I'm resending my previous proposal.
Bump client<>relay, relay<>server bufferevent timeouts as long there is some traffic flowing. Current code doesn't handle long unidirectional flows correctly. Simplest route would be to check presence of traffic every second, but I choose to schedule the task at half of the remainig 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 28 Dec 2017 16:28:03 -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,37 @@ 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 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(con->se_out.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