]> git.meshlink.io Git - utcp/commitdiff
Add a function to manually start the connection timeout timers.
authorGuus Sliepen <guus@sliepen.org>
Sun, 7 Jul 2019 16:00:06 +0000 (18:00 +0200)
committerGuus Sliepen <guus@sliepen.org>
Sun, 7 Jul 2019 16:00:06 +0000 (18:00 +0200)
If the application knows the peer is offline, it can call utcp_offline().
This will start the connection timers on all connections to that peer.
This can be undone by marking the peer online again. This will also reset
the retransmission timers.

utcp.c
utcp.h

diff --git a/utcp.c b/utcp.c
index f4bd7cf718c19197c00ad14efb1b322275a21739..d837d27a1b96fe05b860ce8fcf692bbda115f092 100644 (file)
--- a/utcp.c
+++ b/utcp.c
@@ -1863,9 +1863,15 @@ void utcp_reset_timers(struct utcp *utcp) {
        then.tv_sec += utcp->timeout;
 
        for(int i = 0; i < utcp->nconnections; i++) {
-               utcp->connections[i]->rtrx_timeout = now;
-               utcp->connections[i]->conn_timeout = then;
-               utcp->connections[i]->rtt_start.tv_sec = 0;
+               struct utcp_connection *c = utcp->connections[i];
+
+               if(c->reapable) {
+                       continue;
+               }
+
+               c->rtrx_timeout = now;
+               c->conn_timeout = then;
+               c->rtt_start.tv_sec = 0;
        }
 
        if(utcp->rto > START_RTO) {
@@ -1990,3 +1996,48 @@ void utcp_set_accept_cb(struct utcp *utcp, utcp_accept_t accept, utcp_pre_accept
                utcp->pre_accept = pre_accept;
        }
 }
+
+void utcp_expect_data(struct utcp_connection *c, bool expect) {
+       if(!c || c->reapable) {
+               return;
+       }
+
+       if(!(c->state == ESTABLISHED || c->state == FIN_WAIT_1 || c->state == FIN_WAIT_2)) {
+               return;
+       }
+
+       if(expect) {
+               // If we expect data, start the connection timer.
+               if(!timerisset(&c->conn_timeout)) {
+                       gettimeofday(&c->conn_timeout, NULL);
+                       c->conn_timeout.tv_sec += c->utcp->timeout;
+               }
+       } else {
+               // If we want to cancel expecting data, only clear the timer when there is no unACKed data.
+               if(c->snd.una == c->snd.last) {
+                       timerclear(&c->conn_timeout);
+               }
+       }
+}
+
+void utcp_offline(struct utcp *utcp, bool offline) {
+       for(int i = 0; i < utcp->nconnections; i++) {
+               struct utcp_connection *c = utcp->connections[i];
+
+               if(!c->reapable) {
+                       utcp_expect_data(c, offline);
+
+                       // If we are online again, reset the retransmission timers, but keep the connection timeout as it is,
+                       // to prevent peers toggling online/offline state frequently from keeping connections alive
+                       // if there is no progress in sending actual data.
+                       if(!offline) {
+                               gettimeofday(&utcp->connections[i]->rtrx_timeout, NULL);
+                               utcp->connections[i]->rtt_start.tv_sec = 0;
+                       }
+               }
+       }
+
+       if(!offline && utcp->rto > START_RTO) {
+               utcp->rto = START_RTO;
+       }
+}
diff --git a/utcp.h b/utcp.h
index 5d646762437cafe093796d787d78ee45bd0e5532..4b7075b56520eb79e4c3600ed7ca6427d0421b56 100644 (file)
--- a/utcp.h
+++ b/utcp.h
@@ -89,6 +89,8 @@ extern void utcp_set_mtu(struct utcp *utcp, uint16_t mtu);
 
 extern void utcp_reset_timers(struct utcp *utcp);
 
+extern void utcp_offline(struct utcp *utcp, bool offline);
+
 // Per-socket options
 
 extern size_t utcp_get_sndbuf(struct utcp_connection *connection);
@@ -110,4 +112,6 @@ extern void utcp_set_keepalive(struct utcp_connection *connection, bool keepaliv
 
 extern size_t utcp_get_outq(struct utcp_connection *connection);
 
+extern void utcp_expect_data(struct utcp_connection *connection, bool expect);
+
 #endif