memmove(cp, cp + 1, (utcp->nconnections - i - 1) * sizeof *cp);
utcp->nconnections--;
+ buffer_exit(&c->rcvbuf);
buffer_exit(&c->sndbuf);
free(c);
}
}
if(!buffer_init(&c->rcvbuf, DEFAULT_RCVBUFSIZE, DEFAULT_MAXRCVBUFSIZE)) {
+ buffer_exit(&c->sndbuf);
free(c);
return NULL;
}
}
static void retransmit(struct utcp_connection *c) {
- if(c->state == CLOSED || c->snd.nxt == c->snd.una)
+ if(c->state == CLOSED || c->snd.last == c->snd.una) {
+ debug("Retransmit() called but nothing to retransmit!\n");
+ stop_retransmit_timer(c);
return;
+ }
struct utcp *utcp = c->utcp;
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);
c->snd.last++;
ack(c, false);
+ if(!timerisset(&c->rtrx_timeout))
+ start_retransmit_timer(c);
return 0;
}
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]);
}