+ free(pkt);
+}
+
+static void retransmit(struct utcp_connection *c) {
+ if(c->state == CLOSED || c->snd.last == c->snd.una) {
+ debug(c, "retransmit() called but nothing to retransmit!\n");
+ stop_retransmit_timer(c);
+ return;
+ }
+
+ struct utcp *utcp = c->utcp;
+
+ struct {
+ struct hdr hdr;
+ uint8_t data[];
+ } *pkt = c->utcp->pkt;
+
+ pkt->hdr.src = c->src;
+ pkt->hdr.dst = c->dst;
+ pkt->hdr.wnd = c->rcvbuf.maxsize;
+ 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.ctl = SYN;
+ pkt->hdr.aux = 0x0101;
+ pkt->data[0] = 1;
+ pkt->data[1] = 0;
+ pkt->data[2] = 0;
+ pkt->data[3] = c->flags & 0x7;
+ print_packet(c, "rtrx", pkt, sizeof(pkt->hdr) + 4);
+ utcp->send(utcp, pkt, sizeof(pkt->hdr) + 4);
+ break;
+
+ case SYN_RECEIVED:
+ // Send SYNACK again
+ pkt->hdr.seq = c->snd.nxt;
+ pkt->hdr.ack = c->rcv.nxt;
+ pkt->hdr.ctl = SYN | ACK;
+ print_packet(c, "rtrx", pkt, sizeof(pkt->hdr));
+ utcp->send(utcp, pkt, sizeof(pkt->hdr));
+ break;
+
+ case ESTABLISHED:
+ case FIN_WAIT_1:
+ case CLOSE_WAIT:
+ case CLOSING:
+ case LAST_ACK:
+ // Send unacked data again.
+ pkt->hdr.seq = c->snd.una;
+ pkt->hdr.ack = c->rcv.nxt;
+ pkt->hdr.ctl = ACK;
+ uint32_t len = min(seqdiff(c->snd.last, c->snd.una), utcp->mss);
+
+ if(fin_wanted(c, c->snd.una + len)) {
+ len--;
+ pkt->hdr.ctl |= FIN;
+ }
+
+ // RFC 5681 slow start after timeout
+ uint32_t flightsize = seqdiff(c->snd.nxt, c->snd.una);
+ c->snd.ssthresh = max(flightsize / 2, utcp->mss * 2); // eq. 4
+ c->snd.cwnd = utcp->mss;
+ 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:
+ case LISTEN:
+ case TIME_WAIT:
+ case FIN_WAIT_2:
+ // We shouldn't need to retransmit anything in this state.