]> git.meshlink.io Git - utcp/blob - utcp.c
Do proper modulo 2^32 comparisons of sequence numbers.
[utcp] / utcp.c
1 /*
2     utcp.c -- Userspace TCP
3     Copyright (C) 2014 Guus Sliepen <guus@tinc-vpn.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #define _GNU_SOURCE
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/time.h>
30 #include <sys/socket.h>
31
32 #define UTCP_INTERNAL
33 #include "utcp.h"
34
35 #define PREP(l) char pkt[(l) + sizeof struct hdr]; struct hdr *hdr = &pkt;
36
37 #define SYN 1
38 #define ACK 2
39 #define FIN 4
40 #define RST 8
41
42 struct hdr {
43         uint16_t src; // Source port
44         uint16_t dst; // Destination port
45         uint32_t seq; // Sequence number
46         uint32_t ack; // Acknowledgement number
47         uint32_t wnd; // Window size
48         uint16_t ctl; // Flags (SYN, ACK, FIN, RST)
49         uint16_t aux; // other stuff
50 };
51
52 enum state {
53         CLOSED,
54         LISTEN,
55         SYN_SENT,
56         SYN_RECEIVED,
57         ESTABLISHED,
58         FIN_WAIT_1,
59         FIN_WAIT_2,
60         CLOSE_WAIT,
61         CLOSING,
62         LAST_ACK,
63         TIME_WAIT
64 };
65
66 const char *strstate[] = {
67         "CLOSED",
68         "LISTEN",
69         "SYN_SENT",
70         "SYN_RECEIVED",
71         "ESTABLISHED",
72         "FIN_WAIT_1",
73         "FIN_WAIT_2",
74         "CLOSE_WAIT",
75         "CLOSING",
76         "LAST_ACK",
77         "TIME_WAIT"
78 };
79
80 struct utcp_connection {
81         void *priv;
82         struct utcp *utcp;
83         bool reapable;
84
85         uint16_t src;
86         uint16_t dst;
87         enum state state;
88
89         // The following two structures form the TCB
90
91         struct {
92                 uint32_t una;
93                 uint32_t nxt;
94                 uint32_t wnd;
95                 uint32_t up;
96                 uint32_t wl1;
97                 uint32_t wl2;
98                 uint32_t iss;
99         } snd;
100
101         struct {
102                 uint32_t nxt;
103                 uint32_t wnd;
104                 uint32_t up;
105                 uint32_t irs;
106         } rcv;
107
108         utcp_recv_t recv;
109
110         struct timeval conn_timeout;
111         struct timeval rtrx_timeout;
112
113         char *sndbuf;
114         uint32_t sndbufsize;
115 };
116
117 struct utcp {
118         void *priv;
119
120         utcp_accept_t accept;
121         utcp_pre_accept_t pre_accept;
122         utcp_send_t send;
123
124         uint16_t mtu;
125
126         struct utcp_connection **connections;
127         int nconnections;
128         int nallocated;
129         int gap;
130 };
131
132 static void set_state(struct utcp_connection *c, enum state state) {
133         c->state = state;
134         fprintf(stderr, "%p new state: %s\n", c->utcp, strstate[state]);
135 }
136
137 static void print_packet(void *pkt, size_t len) {
138         struct hdr hdr;
139         if(len < sizeof hdr) {
140                 fprintf(stderr, "short packet (%zu bytes)\n", len);
141                 return;
142         }
143
144         memcpy(&hdr, pkt, sizeof hdr);
145         fprintf (stderr, "src=%u dst=%u seq=%u ack=%u wnd=%u ctl=", hdr.src, hdr.dst, hdr.seq, hdr.ack, hdr.wnd);
146         if(hdr.ctl & SYN)
147                 fprintf(stderr, "SYN");
148         if(hdr.ctl & RST)
149                 fprintf(stderr, "RST");
150         if(hdr.ctl & FIN)
151                 fprintf(stderr, "FIN");
152         if(hdr.ctl & ACK)
153                 fprintf(stderr, "ACK");
154
155         if(len > sizeof hdr) {
156                 fprintf(stderr, " data=");
157                 for(int i = sizeof hdr; i < len; i++) {
158                         char *data = pkt;
159                         fprintf(stderr, "%c", data[i] >= 32 ? data[i] : '.');
160                 }
161         }
162
163         fprintf(stderr, "\n");
164 }
165
166 static void list_connections(struct utcp *utcp) {
167         fprintf(stderr, "%p has %d connections:\n", utcp, utcp->nconnections);
168         for(int i = 0; i < utcp->nconnections; i++)
169                 fprintf(stderr, "  %u -> %u state %s\n", utcp->connections[i]->src, utcp->connections[i]->dst, strstate[utcp->connections[i]->state]);
170 }
171
172 // Connections are stored in a sorted list.
173 // This gives O(log(N)) lookup time, O(N log(N)) insertion time and O(N) deletion time.
174
175 static int compare(const void *va, const void *vb) {
176         const struct utcp_connection *a = *(struct utcp_connection **)va;
177         const struct utcp_connection *b = *(struct utcp_connection **)vb;
178         if(!a->src || !b->src)
179                 abort();
180         int c = (int)a->src - (int)b->src;
181         if(c)
182                 return c;
183         c = (int)a->dst - (int)b->dst;
184         return c;
185 }
186
187 static struct utcp_connection *find_connection(const struct utcp *utcp, uint16_t src, uint16_t dst) {
188         if(!utcp->nconnections)
189                 return NULL;
190         struct utcp_connection key = {
191                 .src = src,
192                 .dst = dst,
193         }, *keyp = &key;
194         struct utcp_connection **match = bsearch(&keyp, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
195         return match ? *match : NULL;
196 }
197
198 static void free_connection(struct utcp_connection *c) {
199         struct utcp *utcp = c->utcp;
200         struct utcp_connection **cp = bsearch(&c, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
201         if(!cp)
202                 abort();
203
204         int i = cp - utcp->connections;
205         memmove(cp + i, cp + i + 1, (utcp->nconnections - i - 1) * sizeof *cp);
206         utcp->nconnections--;
207
208         free(c);
209 }
210
211 static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t src, uint16_t dst) {
212         // Check whether this combination of src and dst is free
213         
214         if(src) {
215                 if(find_connection(utcp, src, dst)) {
216                         errno = EADDRINUSE;
217                         return NULL;
218                 }
219         } else { // If src == 0, generate a random port number with the high bit set
220                 if(utcp->nconnections >= 32767) {
221                         errno = ENOMEM;
222                         return NULL;
223                 }
224                 src = rand() | 0x8000;
225                 while(find_connection(utcp, src, dst))
226                         src++;
227         }
228
229         // Allocate memory for the new connection
230
231         if(utcp->nconnections >= utcp->nallocated) {
232                 if(!utcp->nallocated)
233                         utcp->nallocated = 4;
234                 else
235                         utcp->nallocated *= 2;
236                 struct utcp_connection **new_array = realloc(utcp->connections, utcp->nallocated * sizeof *utcp->connections);
237                 if(!new_array) {
238                         errno = ENOMEM;
239                         return NULL;
240                 }
241                 utcp->connections = new_array;
242         }
243
244         struct utcp_connection *c = calloc(1, sizeof *c);
245         if(!c) {
246                 errno = ENOMEM;
247                 return NULL;
248         }
249
250         // Fill in the details
251
252         c->src = src;
253         c->dst = dst;
254         c->snd.iss = rand();
255         c->snd.una = c->snd.iss;
256         c->snd.nxt = c->snd.iss + 1;
257         c->rcv.wnd = utcp->mtu;
258         c->utcp = utcp;
259
260         // Add it to the sorted list of connections
261
262         utcp->connections[utcp->nconnections++] = c;
263         qsort(utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
264
265         return c;
266 }
267
268 struct utcp_connection *utcp_connect(struct utcp *utcp, uint16_t dst, utcp_recv_t recv, void *priv) {
269         struct utcp_connection *c = allocate_connection(utcp, 0, dst);
270         if(!c)
271                 return NULL;
272
273         c->recv = recv;
274
275         struct hdr hdr;
276
277         hdr.src = c->src;
278         hdr.dst = c->dst;
279         hdr.seq = c->snd.iss;
280         hdr.ack = 0;
281         hdr.ctl = SYN;
282         hdr.wnd = c->rcv.wnd;
283
284         set_state(c, SYN_SENT);
285
286         utcp->send(utcp, &hdr, sizeof hdr);
287
288         // Set timeout?
289
290         return c;
291 }
292
293 void utcp_accept(struct utcp_connection *c, utcp_recv_t recv, void *priv) {
294         if(c->reapable || c->state != SYN_RECEIVED) {
295                 fprintf(stderr, "Error: accept() called on invalid connection %p in state %s\n", c, strstate[c->state]);
296                 return;
297         }
298
299         fprintf(stderr, "%p accepted, %p %p\n", c, recv, priv);
300         c->recv = recv;
301         c->priv = priv;
302         set_state(c, ESTABLISHED);
303 }
304
305 int utcp_send(struct utcp_connection *c, void *data, size_t len) {
306         if(c->reapable) {
307                 fprintf(stderr, "Error: send() called on closed connection %p\n", c);
308                 errno = EBADF;
309                 return -1;
310         }
311
312         switch(c->state) {
313         case CLOSED:
314         case LISTEN:
315         case SYN_SENT:
316         case SYN_RECEIVED:
317                 fprintf(stderr, "Error: send() called on unconnected connection %p\n", c);
318                 errno = ENOTCONN;
319                 return -1;
320         case ESTABLISHED:
321         case CLOSE_WAIT:
322                 break;
323         case FIN_WAIT_1:
324         case FIN_WAIT_2:
325         case CLOSING:
326         case LAST_ACK:
327         case TIME_WAIT:
328                 fprintf(stderr, "Error: send() called on closing connection %p\n", c);
329                 errno = EPIPE;
330                 return -1;
331         }
332
333         if(!len)
334                 return 0;
335
336         if(!data) {
337                 errno = EFAULT;
338                 return -1;
339         }
340
341         
342         struct {
343                 struct hdr hdr;
344                 char data[len];
345         } pkt;
346
347         pkt.hdr.src = c->src;
348         pkt.hdr.dst = c->dst;
349         pkt.hdr.seq = c->snd.nxt;
350         pkt.hdr.ack = c->rcv.nxt;
351         pkt.hdr.wnd = c->snd.wnd;
352         pkt.hdr.ctl = ACK;
353
354         memcpy(pkt.data, data, len);
355
356         c->snd.nxt += len;
357
358         c->utcp->send(c->utcp, &pkt, sizeof pkt.hdr + len);
359         //
360         // Can we add it to the send window?
361         
362         // Do we need to kick some timers?
363         
364         return 0;
365 }
366
367 static void swap_ports(struct hdr *hdr) {
368         uint16_t tmp = hdr->src;
369         hdr->src = hdr->dst;
370         hdr->dst = tmp;
371 }
372
373 static int16_t seqdiff(uint16_t a, uint16_t b) {
374         return a -b;
375 }
376
377 int utcp_recv(struct utcp *utcp, void *data, size_t len) {
378         if(!utcp) {
379                 errno = EFAULT;
380                 return -1;
381         }
382
383         if(!len)
384                 return 0;
385
386         if(!data) {
387                 errno = EFAULT;
388                 return -1;
389         }
390
391         fprintf(stderr, "%p got: ", utcp);
392         print_packet(data, len);
393
394         struct hdr hdr;
395         if(len < sizeof hdr) {
396                 errno = EBADMSG;
397                 return -1;
398         }
399
400         memcpy(&hdr, data, sizeof hdr);
401         data += sizeof hdr;
402         len -= sizeof hdr;
403
404         if(hdr.ctl & ~(SYN | ACK | RST | FIN)) {
405                 errno = EBADMSG;
406                 return -1;
407         }
408
409         //list_connections(utcp);
410
411         struct utcp_connection *c = find_connection(utcp, hdr.dst, hdr.src);
412
413         // Is it for a new connection?
414
415         if(!c) {
416                 if(hdr.ctl & RST)
417                         return 0;
418
419                 if(hdr.ctl & SYN && !(hdr.ctl & ACK) && utcp->accept && (!utcp->pre_accept || utcp->pre_accept(utcp, hdr.dst)) && (c = allocate_connection(utcp, hdr.dst, hdr.src))) { // LISTEN
420                         // Return SYN+ACK
421                         c->snd.wnd = hdr.wnd;
422                         c->rcv.irs = hdr.seq;
423                         c->rcv.nxt = c->rcv.irs + 1;
424                         set_state(c, SYN_RECEIVED);
425
426                         hdr.dst = c->dst;
427                         hdr.src = c->src;
428                         hdr.ack = c->rcv.irs + 1;
429                         hdr.seq = c->snd.iss;
430                         hdr.ctl = SYN | ACK;
431                         utcp->send(utcp, &hdr, sizeof hdr);
432                         return 0;
433                 } else { // CLOSED
434                         len = 1;
435                         goto reset;
436                 }
437         }
438
439         fprintf(stderr, "%p state %s\n", c->utcp, strstate[c->state]);
440
441         if(c->state == CLOSED) {
442                 fprintf(stderr, "Error: packet recv()d on closed connection %p\n", c);
443                 errno = EBADF;
444                 return -1;
445         }
446
447         // It is for an existing connection.
448         
449         if(c->state == SYN_SENT) {
450                 if(hdr.ctl & ACK) {
451                         if(seqdiff(hdr.ack, c->snd.iss) <= 0 || seqdiff(hdr.ack, c->snd.nxt) > 0) {
452                                 fprintf(stderr, "Invalid ACK, %u %u %u\n", hdr.ack, c->snd.iss, c->snd.nxt);
453                                 goto reset;
454                         }
455                 }
456                 if(hdr.ctl & RST) {
457                         if(!(hdr.ctl & ACK))
458                                 return 0;
459                         set_state(c, CLOSED);
460                         errno = ECONNREFUSED;
461                         c->recv(c, NULL, 0);
462                         return 0;
463                 }
464                 if(hdr.ctl & SYN) {
465                         c->dst = hdr.src;
466                         c->rcv.nxt = hdr.seq + 1;
467                         c->rcv.irs = hdr.seq;
468                         c->snd.wnd = hdr.wnd;
469
470                         if(hdr.ctl & ACK)
471                                 c->snd.una = hdr.ack;
472                         if(seqdiff(c->snd.una, c->snd.iss) > 0) {
473                                 set_state(c, ESTABLISHED);
474                                 // TODO: signal app?
475                                 swap_ports(&hdr);
476                                 hdr.seq = c->snd.nxt;
477                                 hdr.ack = c->rcv.nxt;
478                                 hdr.ctl = ACK;
479                         } else {
480                                 set_state(c, SYN_RECEIVED);
481                                 swap_ports(&hdr);
482                                 hdr.seq = c->snd.iss;
483                                 hdr.ack = c->rcv.nxt;
484                                 hdr.ctl = SYN | ACK;
485                         }
486                         utcp->send(utcp, &hdr, sizeof hdr);
487                         // TODO: queue any data?
488                 }
489
490                 return 0;
491         }
492
493         bool acceptable;
494
495         if(len == 0)
496                 if(c->rcv.wnd == 0)
497                         acceptable = hdr.seq == c->rcv.nxt;
498                 else
499                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd);
500         else
501                 if(c->rcv.wnd == 0)
502                         acceptable = false;
503                 else
504                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd)
505                                 || (hdr.seq + len - 1 >= c->rcv.nxt && hdr.seq + len - 1 < c->rcv.nxt + c->rcv.wnd);
506
507         if(!acceptable) {
508                 fprintf(stderr, "Packet not acceptable, %u %u %u %zu\n", hdr.seq, c->rcv.nxt, c->rcv.wnd, len);
509                 if(hdr.ctl & RST)
510                         return 0;
511                 goto ack_and_drop;
512         }
513
514         c->snd.wnd = hdr.wnd;
515
516         // TODO: check whether segment really starts at rcv.nxt, otherwise trim it.
517         
518         if(hdr.ctl & RST) {
519                 switch(c->state) {
520                 case SYN_RECEIVED:
521                         // TODO: delete connection?
522                         break;
523                 case ESTABLISHED:
524                 case FIN_WAIT_1:
525                 case FIN_WAIT_2:
526                 case CLOSE_WAIT:
527                         set_state(c, CLOSED);
528                         errno = ECONNRESET;
529                         c->recv(c, NULL, 0);
530                         break;
531                 case CLOSING:
532                 case LAST_ACK:
533                 case TIME_WAIT:
534                         // TODO: delete connection?
535                         break;
536                 default:
537                         // TODO: wtf?
538                         return 0;
539                 }
540                 set_state(c, CLOSED);
541                 return 0;
542         }
543
544         if(hdr.ctl & SYN) {
545                 switch(c->state) {
546                 case SYN_RECEIVED:
547                 case ESTABLISHED:
548                 case FIN_WAIT_1:
549                 case FIN_WAIT_2:
550                 case CLOSE_WAIT:
551                 case CLOSING:
552                 case LAST_ACK:
553                 case TIME_WAIT:
554                         set_state(c, CLOSED);
555                         errno = ECONNRESET;
556                         c->recv(c, NULL, 0);
557                         goto reset;
558                         break;
559                 default:
560                         // TODO: wtf?
561                         return 0;
562                 }
563         }
564
565         if(!(hdr.ctl & ACK))
566                 return 0;
567
568         switch(c->state) {
569         case SYN_RECEIVED:
570                 if(seqdiff(hdr.ack, c->snd.una) >= 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0)
571                         c->utcp->accept(c, hdr.dst);
572                 
573                 if(c->state != ESTABLISHED)
574                         goto reset;
575                 break;
576         case ESTABLISHED:
577         case CLOSE_WAIT:
578                 if(seqdiff(hdr.ack, c->snd.una) < 0)
579                         return 0;
580                 if(seqdiff(hdr.ack, c->snd.nxt) > 0)
581                         goto ack_and_drop;
582                 if(seqdiff(hdr.ack, c->snd.una) > 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0) {
583                         c->snd.una = hdr.ack;
584                         if(seqdiff(c->snd.wl1, hdr.seq) < 0 || (c->snd.wl1 == hdr.seq && seqdiff(c->snd.wl2, hdr.ack) <= 0)) {
585                                 c->snd.wnd = hdr.wnd;
586                                 c->snd.wl1 = hdr.seq;
587                                 c->snd.wl2 = hdr.ack;
588                         }
589                 }
590                 break;
591         case FIN_WAIT_1:
592                 if(hdr.ack == c->snd.nxt)
593                         set_state(c, FIN_WAIT_2);
594                 break;
595         case FIN_WAIT_2:
596                 // TODO: If nothing left to send, close.
597                 break;
598         case CLOSING:
599                 if(hdr.ack == c->snd.nxt) {
600                         set_state(c, TIME_WAIT);
601                 }
602                 break;
603         case LAST_ACK:
604                 if(hdr.ack == c->snd.nxt) {
605                         set_state(c, CLOSED);
606                 }
607                 return 0;
608         case TIME_WAIT:
609                 // TODO: retransmission of remote FIN, ACK and restart 2 MSL timeout
610                 break;
611         default:
612                 goto reset;
613         }
614
615         // Process data
616
617         switch(c->state) {
618         case ESTABLISHED:
619         case FIN_WAIT_1:
620         case FIN_WAIT_2:
621                 // TODO: process the data, see page 74
622                 break;
623         case CLOSE_WAIT:
624         case CLOSING:
625         case LAST_ACK:
626         case TIME_WAIT:
627                 break;
628         default:
629                 abort();
630         }
631
632         if(hdr.ctl & FIN) {
633                 switch(c->state) {
634                 case CLOSED:
635                 case LISTEN:
636                 case SYN_SENT:
637                         return 0;
638                 case SYN_RECEIVED:
639                 case ESTABLISHED:
640                         set_state(c, CLOSE_WAIT);
641                         c->rcv.nxt++;
642                         goto ack_and_drop;
643                 case FIN_WAIT_1:
644                         set_state(c, CLOSING);
645                         c->rcv.nxt++;
646                         goto ack_and_drop;
647                 case FIN_WAIT_2:
648                         set_state(c, TIME_WAIT);
649                         c->rcv.nxt++;
650                         goto ack_and_drop;
651                 case CLOSE_WAIT:
652                 case CLOSING:
653                 case LAST_ACK:
654                 case TIME_WAIT:
655                         break;
656                 default:
657                         abort();
658                 }
659         }
660
661         // Process the data
662         
663         if(len && c->recv) {
664                 c->recv(c, data, len);
665                 c->rcv.nxt += len;
666                 goto ack_and_drop;
667         }
668
669         return 0;
670
671 reset:
672         swap_ports(&hdr);
673         hdr.wnd = 0;
674         if(hdr.ctl & ACK) {
675                 hdr.seq = hdr.ack;
676                 hdr.ctl = RST;
677         } else {
678                 hdr.ack = hdr.seq + len;
679                 hdr.seq = 0;
680                 hdr.ctl = RST | ACK;
681         }
682         utcp->send(utcp, &hdr, sizeof hdr);
683         return 0;
684
685 ack_and_drop:
686         swap_ports(&hdr);
687         hdr.seq = c->snd.nxt;
688         hdr.ack = c->rcv.nxt;
689         hdr.ctl = ACK;
690         utcp->send(utcp, &hdr, sizeof hdr);
691         if(c->state == CLOSE_WAIT || c->state == TIME_WAIT) {
692                 errno = 0;
693                 c->recv(c, NULL, 0);
694         }
695         return 0;
696 }
697
698 int utcp_shutdown(struct utcp_connection *c, int dir) {
699         if(!c) {
700                 errno = EFAULT;
701                 return -1;
702         }
703
704         if(c->reapable) {
705                 fprintf(stderr, "Error: shutdown() called on closed connection %p\n", c);
706                 errno = EBADF;
707                 return -1;
708         }
709
710         // TODO: handle dir
711
712         switch(c->state) {
713         case CLOSED:
714                 return 0;
715         case LISTEN:
716         case SYN_SENT:
717                 set_state(c, CLOSED);
718                 return 0;
719
720         case SYN_RECEIVED:
721         case ESTABLISHED:
722                 set_state(c, FIN_WAIT_1);
723                 break;
724         case FIN_WAIT_1:
725         case FIN_WAIT_2:
726                 return 0;
727         case CLOSE_WAIT:
728                 set_state(c, LAST_ACK);
729                 break;
730
731         case CLOSING:
732         case LAST_ACK:
733         case TIME_WAIT:
734                 return 0;
735         }
736
737         // Send FIN
738
739         struct hdr hdr;
740
741         hdr.src = c->src;
742         hdr.dst = c->dst;
743         hdr.seq = c->snd.nxt;
744         hdr.ack = c->rcv.nxt;
745         hdr.wnd = c->snd.wnd;
746         hdr.ctl = FIN | ACK;
747
748         c->snd.nxt += 1;
749
750         c->utcp->send(c->utcp, &hdr, sizeof hdr);
751         return 0;
752 }
753
754 int utcp_close(struct utcp_connection *c) {
755         if(utcp_shutdown(c, SHUT_RDWR))
756                 return -1;
757         c->reapable = true;
758         return 0;
759 }
760
761 int utcp_abort(struct utcp_connection *c) {
762         if(!c) {
763                 errno = EFAULT;
764                 return -1;
765         }
766
767         if(c->reapable) {
768                 fprintf(stderr, "Error: abort() called on closed connection %p\n", c);
769                 errno = EBADF;
770                 return -1;
771         }
772
773         c->reapable = true;
774
775         switch(c->state) {
776         case CLOSED:
777                 return 0;
778         case LISTEN:
779         case SYN_SENT:
780         case CLOSING:
781         case LAST_ACK:
782         case TIME_WAIT:
783                 set_state(c, CLOSED);
784                 return 0;
785
786         case SYN_RECEIVED:
787         case ESTABLISHED:
788         case FIN_WAIT_1:
789         case FIN_WAIT_2:
790         case CLOSE_WAIT:
791                 set_state(c, CLOSED);
792                 break;
793         }
794
795         // Send RST
796
797         struct hdr hdr;
798
799         hdr.src = c->src;
800         hdr.dst = c->dst;
801         hdr.seq = c->snd.nxt;
802         hdr.ack = 0;
803         hdr.wnd = 0;
804         hdr.ctl = RST;
805
806         c->utcp->send(c->utcp, &hdr, sizeof hdr);
807         return 0;
808 }
809
810 void utcp_timeout(struct utcp *utcp) {
811         struct timeval now;
812         gettimeofday(&now, NULL);
813
814         for(int i = 0; i < utcp->nconnections; i++) {
815                 struct utcp_connection *c = utcp->connections[i];
816                 if(!c)
817                         continue;
818
819                 if(c->reapable) {
820                         fprintf(stderr, "Reaping %p\n", c);
821                         free_connection(c);
822                         continue;
823                 }
824
825                 if(c->state == CLOSED)
826                         return;
827
828                 if(c->conn_timeout.tv_sec && timercmp(&c->conn_timeout, &now, <)) {
829                         if(!c->reapable) {
830                                 errno = ETIMEDOUT;
831                                 c->recv(c, NULL, 0);
832                         }
833                         c->state = CLOSED;
834                         return;
835                 }
836
837                 if(c->rtrx_timeout.tv_sec && timercmp(&c->rtrx_timeout, &now, <)) {
838                         // TODO: retransmit stuff;
839                 }
840         }
841 }
842
843 struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv) {
844         struct utcp *utcp = calloc(1, sizeof *utcp);
845         if(!utcp)
846                 return NULL;
847
848         utcp->accept = accept;
849         utcp->pre_accept = pre_accept;
850         utcp->send = send;
851         utcp->priv = priv;
852         utcp->gap = -1;
853         utcp->mtu = 1000;
854
855         return utcp;
856 }
857
858 void utcp_exit(struct utcp *utcp) {
859         if(!utcp)
860                 return;
861         for(int i = 0; i < utcp->nconnections; i++)
862                 free_connection(utcp->connections[i]);
863         free(utcp);
864 }