From 27a8e60e9ad3687fc0fe53505d3569a5fd2f99be Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Thu, 12 Jan 2023 15:58:25 -0300 Subject: [PATCH] TCP keepalives --- mip/mip.c | 43 ++++++++++++++++++++++--------------------- mongoose.c | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 48 insertions(+), 42 deletions(-) diff --git a/mip/mip.c b/mip/mip.c index 402fd2d9..a551eed0 100644 --- a/mip/mip.c +++ b/mip/mip.c @@ -541,12 +541,21 @@ static size_t tx_tcp_pkt(struct mip_if *ifp, struct pkt *pkt, uint8_t flags, mg_htonl(mg_ntohl(pkt->tcp->seq) + delta), buf, len); } +static void settmout(struct mg_connection *c, uint8_t type) { + struct mip_if *ifp = (struct mip_if *) c->mgr->priv; + struct connstate *s = (struct connstate *) (c + 1); + unsigned n = type == MIP_TTYPE_ACK ? MIP_TCP_ACK_MS : MIP_TCP_KEEPALIVE_MS; + s->timer = ifp->now + n; + s->ttype = type; + MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer)); +} + static struct mg_connection *accept_conn(struct mg_connection *lsn, struct pkt *pkt) { struct mg_connection *c = mg_alloc_conn(lsn->mgr); struct connstate *s = (struct connstate *) (c + 1); s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq); - s->timer = ((struct mip_if *) c->mgr->priv)->now + MIP_TCP_KEEPALIVE_MS; + settmout(c, MIP_TTYPE_KEEPALIVE); c->rem.ip = pkt->ip->src; c->rem.port = pkt->tcp->sport; MG_DEBUG( @@ -564,15 +573,6 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, return c; } -static void settmout(struct mg_connection *c, uint8_t type) { - struct mip_if *ifp = (struct mip_if *) c->mgr->priv; - struct connstate *s = (struct connstate *) (c + 1); - unsigned n = type == MIP_TTYPE_ACK ? MIP_TCP_ACK_MS : MIP_TCP_KEEPALIVE_MS; - s->timer = ifp->now + n; - s->ttype = type; - MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer)); -} - long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { struct mip_if *ifp = (struct mip_if *) c->mgr->priv; struct connstate *s = (struct connstate *) (c + 1); @@ -581,7 +581,7 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { if (tx_tcp(ifp, c->rem.ip, TH_PUSH | TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) { s->seq += (uint32_t) len; - settmout(c, MIP_TTYPE_KEEPALIVE); + if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE); } else { return MG_IO_ERR; } @@ -663,11 +663,6 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { static void rx_tcp(struct mip_if *ifp, struct pkt *pkt) { struct mg_connection *c = getpeer(ifp->mgr, pkt, false); struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1); - - if (c != NULL && s->ttype == MIP_TTYPE_KEEPALIVE) { - s->tmiss = 0; // Reset missed keep-alive counter - settmout(c, MIP_TTYPE_KEEPALIVE); // Advance keep-alive timer - } #if 0 MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len)); #endif @@ -675,6 +670,7 @@ static void rx_tcp(struct mip_if *ifp, struct pkt *pkt) { s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1; tx_tcp_pkt(ifp, pkt, TH_ACK, pkt->tcp->ack, NULL, 0); c->is_connecting = 0; // Client connected + settmout(c, MIP_TTYPE_KEEPALIVE); mg_call(c, MG_EV_CONNECT, NULL); // Let user know } else if (c != NULL && c->is_connecting) { tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0); @@ -685,7 +681,9 @@ static void rx_tcp(struct mip_if *ifp, struct pkt *pkt) { 4, &pkt->ip->dst, mg_ntohs(pkt->tcp->dport))); mg_hexdump(pkt->pay.buf, pkt->pay.len); #endif - read_conn(c, pkt); + s->tmiss = 0; // Reset missed keep-alive counter + settmout(c, MIP_TTYPE_KEEPALIVE); // Advance keep-alive timer + read_conn(c, pkt); // Override timer with ACK timeout if needed } else if ((c = getpeer(ifp->mgr, pkt, true)) == NULL) { tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0); } else if (pkt->tcp->flags & TH_SYN) { @@ -830,10 +828,13 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) { tx_tcp(ifp, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), "", 0); } else { - MG_DEBUG(("%lu keepalive", c->id)); - tx_tcp(ifp, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, - mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0); - if (s->tmiss++ > 2) mg_error(c, "keepalive"); + if (s->tmiss++ > 2) { + mg_error(c, "keepalive"); + } else { + MG_DEBUG(("%lu keepalive", c->id)); + tx_tcp(ifp, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, + mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0); + } } settmout(c, MIP_TTYPE_KEEPALIVE); } diff --git a/mongoose.c b/mongoose.c index 01cefc68..b8c2af28 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7012,12 +7012,21 @@ static size_t tx_tcp_pkt(struct mip_if *ifp, struct pkt *pkt, uint8_t flags, mg_htonl(mg_ntohl(pkt->tcp->seq) + delta), buf, len); } +static void settmout(struct mg_connection *c, uint8_t type) { + struct mip_if *ifp = (struct mip_if *) c->mgr->priv; + struct connstate *s = (struct connstate *) (c + 1); + unsigned n = type == MIP_TTYPE_ACK ? MIP_TCP_ACK_MS : MIP_TCP_KEEPALIVE_MS; + s->timer = ifp->now + n; + s->ttype = type; + MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer)); +} + static struct mg_connection *accept_conn(struct mg_connection *lsn, struct pkt *pkt) { struct mg_connection *c = mg_alloc_conn(lsn->mgr); struct connstate *s = (struct connstate *) (c + 1); s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq); - s->timer = ((struct mip_if *) c->mgr->priv)->now + MIP_TCP_KEEPALIVE_MS; + settmout(c, MIP_TTYPE_KEEPALIVE); c->rem.ip = pkt->ip->src; c->rem.port = pkt->tcp->sport; MG_DEBUG( @@ -7035,15 +7044,6 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, return c; } -static void settmout(struct mg_connection *c, uint8_t type) { - struct mip_if *ifp = (struct mip_if *) c->mgr->priv; - struct connstate *s = (struct connstate *) (c + 1); - unsigned n = type == MIP_TTYPE_ACK ? MIP_TCP_ACK_MS : MIP_TCP_KEEPALIVE_MS; - s->timer = ifp->now + n; - s->ttype = type; - MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer)); -} - long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { struct mip_if *ifp = (struct mip_if *) c->mgr->priv; struct connstate *s = (struct connstate *) (c + 1); @@ -7052,7 +7052,10 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { if (tx_tcp(ifp, c->rem.ip, TH_PUSH | TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) { s->seq += (uint32_t) len; - settmout(c, MIP_TTYPE_KEEPALIVE); + if (s->ttype == MIP_TTYPE_ACK) { + settmout(c, MIP_TTYPE_KEEPALIVE); + MG_INFO(("Sent piggybacked ack, restarted keepalive timer")); + } } else { return MG_IO_ERR; } @@ -7134,11 +7137,6 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { static void rx_tcp(struct mip_if *ifp, struct pkt *pkt) { struct mg_connection *c = getpeer(ifp->mgr, pkt, false); struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1); - - if (c != NULL && s->ttype == MIP_TTYPE_KEEPALIVE) { - s->tmiss = 0; // Reset missed keep-alive counter - settmout(c, MIP_TTYPE_KEEPALIVE); // Advance keep-alive timer - } #if 0 MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len)); #endif @@ -7146,6 +7144,7 @@ static void rx_tcp(struct mip_if *ifp, struct pkt *pkt) { s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1; tx_tcp_pkt(ifp, pkt, TH_ACK, pkt->tcp->ack, NULL, 0); c->is_connecting = 0; // Client connected + settmout(c, MIP_TTYPE_KEEPALIVE); mg_call(c, MG_EV_CONNECT, NULL); // Let user know } else if (c != NULL && c->is_connecting) { tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0); @@ -7156,7 +7155,10 @@ static void rx_tcp(struct mip_if *ifp, struct pkt *pkt) { 4, &pkt->ip->dst, mg_ntohs(pkt->tcp->dport))); mg_hexdump(pkt->pay.buf, pkt->pay.len); #endif - read_conn(c, pkt); + s->tmiss = 0; // Reset missed keep-alive counter + settmout(c, MIP_TTYPE_KEEPALIVE); // Advance keep-alive timer + MG_INFO(("Restart keepalive count")); + read_conn(c, pkt); // Override timer with ACK timeout if needed } else if ((c = getpeer(ifp->mgr, pkt, true)) == NULL) { tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0); } else if (pkt->tcp->flags & TH_SYN) { @@ -7301,10 +7303,13 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) { tx_tcp(ifp, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), "", 0); } else { - MG_DEBUG(("%lu keepalive", c->id)); - tx_tcp(ifp, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, - mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0); - if (s->tmiss++ > 2) mg_error(c, "keepalive"); + if (s->tmiss++ > 2) { + mg_error(c, "keepalive"); + } else { + MG_DEBUG(("%lu keepalive", c->id)); + tx_tcp(ifp, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, + mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0); + } } settmout(c, MIP_TTYPE_KEEPALIVE); }