X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=utcp.c;h=c93d4bb35bc476717fa9233b7c7a43e73d546a77;hb=40ce4f195beb7a64fd326cda201d4f8a684fa72f;hp=1b498a2897d0c4063b568040c24804c6235f636d;hpb=0c29e6bb0a943f9d06067628f894495dcc01c5ba;p=utcp diff --git a/utcp.c b/utcp.c index 1b498a2..c93d4bb 100644 --- a/utcp.c +++ b/utcp.c @@ -86,11 +86,24 @@ static void print_packet(struct utcp *utcp, const char *dir, const void *pkt, si debug("ACK"); if(len > sizeof hdr) { - debug(" data="); - for(int i = sizeof hdr; i < len; i++) { - const char *data = pkt; - debug("%c", data[i] >= 32 ? data[i] : '.'); + uint32_t datalen = len - sizeof hdr; + uint8_t *str = malloc((datalen << 1) + 7); + memcpy(str, " data=", 6); + uint8_t *strptr = str + 6; + const uint8_t *data = pkt; + const uint8_t *dataend = data + datalen; + + while(data != dataend) { + *strptr = (*data >> 4) > 9? (*data >> 4) + 55 : (*data >> 4) + 48; + ++strptr; + *strptr = (*data & 0xf) > 9? (*data & 0xf) + 55 : (*data & 0xf) + 48; + ++strptr; + ++data; } + *strptr = 0; + + debug(str); + free(str); } debug("\n"); @@ -260,6 +273,7 @@ static void free_connection(struct utcp_connection *c) { memmove(cp, cp + 1, (utcp->nconnections - i - 1) * sizeof *cp); utcp->nconnections--; + buffer_exit(&c->rcvbuf); buffer_exit(&c->sndbuf); free(c); } @@ -305,6 +319,7 @@ static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t s } if(!buffer_init(&c->rcvbuf, DEFAULT_RCVBUFSIZE, DEFAULT_MAXRCVBUFSIZE)) { + buffer_exit(&c->sndbuf); free(c); return NULL; } @@ -548,13 +563,14 @@ static void retransmit(struct utcp_connection *c) { pkt->hdr.src = c->src; pkt->hdr.dst = c->dst; + pkt->hdr.wnd = c->rcv.wnd; + pkt->hdr.aux = 0; switch(c->state) { case SYN_SENT: // Send our SYN again pkt->hdr.seq = c->snd.iss; pkt->hdr.ack = 0; - pkt->hdr.wnd = c->rcv.wnd; pkt->hdr.ctl = SYN; print_packet(c->utcp, "rtrx", pkt, sizeof pkt->hdr); utcp->send(utcp, pkt, sizeof pkt->hdr); @@ -850,18 +866,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 +1037,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 +1185,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 +1342,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 +1361,7 @@ struct timeval utcp_timeout(struct utcp *utcp) { } if(timerisset(&c->rtrx_timeout) && timercmp(&c->rtrx_timeout, &now, <)) { + debug("retransmit()\n"); retransmit(c); } @@ -1396,6 +1418,7 @@ void utcp_exit(struct utcp *utcp) { for(int i = 0; i < utcp->nconnections; i++) { if(!utcp->connections[i]->reapable) debug("Warning, freeing unclosed connection %p\n", utcp->connections[i]); + buffer_exit(&utcp->connections[i]->rcvbuf); buffer_exit(&utcp->connections[i]->sndbuf); free(utcp->connections[i]); }