]> git.meshlink.io Git - utcp/blobdiff - utcp.c
handle overlapping packets
[utcp] / utcp.c
diff --git a/utcp.c b/utcp.c
index 1b498a2897d0c4063b568040c24804c6235f636d..c125ce0a04d50414b69f22a9cae4abbf62f5f25a 100644 (file)
--- a/utcp.c
+++ b/utcp.c
@@ -850,18 +850,22 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
 
        if(c->state == SYN_SENT)
                acceptable = true;
-
-       // TODO: handle packets overlapping c->rcv.nxt.
-#if 1
-       // Only use this when accepting out-of-order packets.
        else if(len == 0)
                acceptable = seqdiff(hdr.seq, c->rcv.nxt) >= 0;
-       else
+       else {
+               int32_t rcv_offset = seqdiff(hdr.seq, c->rcv.nxt);
+
+               // cut already accepted front overlapping
+               if(rcv_offset < 0) {
+                       acceptable = rcv_offset + len >= 0;
+                       if(acceptable) {
+                               data -= rcv_offset;
+                               len += rcv_offset;
+                       }
+               }
+
                acceptable = seqdiff(hdr.seq, c->rcv.nxt) >= 0 && seqdiff(hdr.seq, c->rcv.nxt) + len <= c->rcvbuf.maxsize;
-#else
-       if(c->state != SYN_SENT)
-               acceptable = hdr.seq == c->rcv.nxt;
-#endif
+       }
 
        if(!acceptable) {
                debug("Packet not acceptable, %u <= %u + %zu < %u\n", c->rcv.nxt, hdr.seq, len, c->rcv.nxt + c->rcvbuf.maxsize);
@@ -1017,6 +1021,7 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                                //Reset the congestion window so we wait for ACKs.
                                c->snd.nxt = c->snd.una;
                                c->snd.cwnd = utcp->mtu;
+                               start_retransmit_timer(c);
                        }
                }
        }
@@ -1164,8 +1169,7 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
        // - or we got an ack, so we should maybe send a bit more data
        //   -> sendatleastone = false
 
-ack:
-       ack(c, prevrcvnxt != c->rcv.nxt);
+       ack(c, len || prevrcvnxt != c->rcv.nxt);
        return 0;
 
 reset:
@@ -1322,6 +1326,7 @@ struct timeval utcp_timeout(struct utcp *utcp) {
                if(!c)
                        continue;
 
+               // delete connections that have been utcp_close()d.
                if(c->state == CLOSED) {
                        if(c->reapable) {
                                debug("Reaping %p\n", c);
@@ -1340,6 +1345,7 @@ struct timeval utcp_timeout(struct utcp *utcp) {
                }
 
                if(timerisset(&c->rtrx_timeout) && timercmp(&c->rtrx_timeout, &now, <)) {
+                       debug("retransmit()\n");
                        retransmit(c);
                }