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

Reply via email to