X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=utcp.c;h=ac598ddae28667fd9a40c28ace29255b7dd22f66;hb=83f65f2eee2d5c7d58b27021770926d53f0f193e;hp=b53541d5e3e6bab3400daf70ed8141e9b018b01c;hpb=488a66580c31a873b93ed541505e1525607bbed8;p=utcp diff --git a/utcp.c b/utcp.c index b53541d..ac598dd 100644 --- a/utcp.c +++ b/utcp.c @@ -808,27 +808,24 @@ static void retransmit(struct utcp_connection *c) { pkt->hdr.seq = c->snd.una; pkt->hdr.ack = c->rcv.nxt; pkt->hdr.ctl = ACK; - uint32_t len = seqdiff(c->snd.last, c->snd.una); - - if(len > utcp->mtu) { - len = utcp->mtu; - } + uint32_t len = min(seqdiff(c->snd.last, c->snd.una), utcp->mtu); if(fin_wanted(c, c->snd.una + len)) { len--; pkt->hdr.ctl |= FIN; } - c->snd.nxt = c->snd.una + len; - // RFC 5681 slow start after timeout - c->snd.ssthresh = max(c->snd.cwnd / 2, utcp->mtu * 2); // eq. 4 + uint32_t flightsize = seqdiff(c->snd.nxt, c->snd.una); + c->snd.ssthresh = max(flightsize / 2, utcp->mtu * 2); // eq. 4 c->snd.cwnd = utcp->mtu; debug_cwnd(c); buffer_copy(&c->sndbuf, pkt->data, 0, len); print_packet(c, "rtrx", pkt, sizeof(pkt->hdr) + len); utcp->send(utcp, pkt, sizeof(pkt->hdr) + len); + + c->snd.nxt = c->snd.una + len; break; case CLOSED: @@ -851,6 +848,7 @@ static void retransmit(struct utcp_connection *c) { } c->rtt_start.tv_sec = 0; // invalidate RTT timer + c->dupack = 0; // cancel any ongoing fast recovery cleanup: free(pkt); @@ -1460,14 +1458,15 @@ synack: break; } } else { - if(!len && is_reliable(c)) { + if(!len && is_reliable(c) && c->snd.una != c->snd.last) { c->dupack++; debug(c, "duplicate ACK %d\n", c->dupack); if(c->dupack == 3) { // RFC 5681 fast recovery debug(c, "fast recovery started\n", c->dupack); - c->snd.ssthresh = max(c->snd.cwnd / 2, utcp->mtu * 2); // eq. 4 + uint32_t flightsize = seqdiff(c->snd.nxt, c->snd.una); + c->snd.ssthresh = max(flightsize / 2, utcp->mtu * 2); // eq. 4 c->snd.cwnd = min(c->snd.ssthresh + 3 * utcp->mtu, c->sndbuf.maxsize); if(c->snd.cwnd > c->sndbuf.maxsize) { @@ -1486,6 +1485,11 @@ synack: debug_cwnd(c); } + + // We got an ACK which indicates the other side did get one of our packets. + // Reset the retransmission timer to avoid going to slow start, + // but don't touch the connection timeout. + start_retransmit_timer(c); } }