]> git.meshlink.io Git - utcp/blob - utcp.c
Do port numbers properly.
[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 int utcp_recv(struct utcp *utcp, void *data, size_t len) {
374         if(!utcp) {
375                 errno = EFAULT;
376                 return -1;
377         }
378
379         if(!len)
380                 return 0;
381
382         if(!data) {
383                 errno = EFAULT;
384                 return -1;
385         }
386
387         fprintf(stderr, "%p got: ", utcp);
388         print_packet(data, len);
389
390         struct hdr hdr;
391         if(len < sizeof hdr) {
392                 errno = EBADMSG;
393                 return -1;
394         }
395
396         memcpy(&hdr, data, sizeof hdr);
397         data += sizeof hdr;
398         len -= sizeof hdr;
399
400         if(hdr.ctl & ~(SYN | ACK | RST | FIN)) {
401                 errno = EBADMSG;
402                 return -1;
403         }
404
405         //list_connections(utcp);
406
407         struct utcp_connection *c = find_connection(utcp, hdr.dst, hdr.src);
408
409         // Is it for a new connection?
410
411         if(!c) {
412                 if(hdr.ctl & RST)
413                         return 0;
414
415                 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
416                         // Return SYN+ACK
417                         c->snd.wnd = hdr.wnd;
418                         c->rcv.irs = hdr.seq;
419                         c->rcv.nxt = c->rcv.irs + 1;
420                         set_state(c, SYN_RECEIVED);
421
422                         hdr.dst = c->dst;
423                         hdr.src = c->src;
424                         hdr.ack = c->rcv.irs + 1;
425                         hdr.seq = c->snd.iss;
426                         hdr.ctl = SYN | ACK;
427                         utcp->send(utcp, &hdr, sizeof hdr);
428                         return 0;
429                 } else { // CLOSED
430                         len = 1;
431                         goto reset;
432                 }
433         }
434
435         fprintf(stderr, "%p state %s\n", c->utcp, strstate[c->state]);
436
437         if(c->state == CLOSED) {
438                 fprintf(stderr, "Error: packet recv()d on closed connection %p\n", c);
439                 errno = EBADF;
440                 return -1;
441         }
442
443         // It is for an existing connection.
444         
445         if(c->state == SYN_SENT) {
446                 if(hdr.ctl & ACK) {
447                         if(hdr.ack <= c->snd.iss || hdr.ack > c->snd.nxt) {
448                                 fprintf(stderr, "Invalid ACK, %u %u %u\n", hdr.ack, c->snd.iss, c->snd.nxt);
449                                 goto reset;
450                         }
451                 }
452                 if(hdr.ctl & RST) {
453                         if(!(hdr.ctl & ACK))
454                                 return 0;
455                         set_state(c, CLOSED);
456                         errno = ECONNREFUSED;
457                         c->recv(c, NULL, 0);
458                         return 0;
459                 }
460                 if(hdr.ctl & SYN) {
461                         c->dst = hdr.src;
462                         c->rcv.nxt = hdr.seq + 1;
463                         c->rcv.irs = hdr.seq;
464                         c->snd.wnd = hdr.wnd;
465
466                         if(hdr.ctl & ACK)
467                                 c->snd.una = hdr.ack;
468                         if(c->snd.una > c->snd.iss) {
469                                 set_state(c, ESTABLISHED);
470                                 // TODO: signal app?
471                                 swap_ports(&hdr);
472                                 hdr.seq = c->snd.nxt;
473                                 hdr.ack = c->rcv.nxt;
474                                 hdr.ctl = ACK;
475                         } else {
476                                 set_state(c, SYN_RECEIVED);
477                                 swap_ports(&hdr);
478                                 hdr.seq = c->snd.iss;
479                                 hdr.ack = c->rcv.nxt;
480                                 hdr.ctl = SYN | ACK;
481                         }
482                         utcp->send(utcp, &hdr, sizeof hdr);
483                         // TODO: queue any data?
484                 }
485
486                 return 0;
487         }
488
489         bool acceptable;
490
491         if(len == 0)
492                 if(c->rcv.wnd == 0)
493                         acceptable = hdr.seq == c->rcv.nxt;
494                 else
495                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd);
496         else
497                 if(c->rcv.wnd == 0)
498                         acceptable = false;
499                 else
500                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd)
501                                 || (hdr.seq + len - 1 >= c->rcv.nxt && hdr.seq + len - 1 < c->rcv.nxt + c->rcv.wnd);
502
503         if(!acceptable) {
504                 fprintf(stderr, "Packet not acceptable, %u %u %u %zu\n", hdr.seq, c->rcv.nxt, c->rcv.wnd, len);
505                 if(hdr.ctl & RST)
506                         return 0;
507                 goto ack_and_drop;
508         }
509
510         c->snd.wnd = hdr.wnd;
511
512         // TODO: check whether segment really starts at rcv.nxt, otherwise trim it.
513         
514         if(hdr.ctl & RST) {
515                 switch(c->state) {
516                 case SYN_RECEIVED:
517                         // TODO: delete connection?
518                         break;
519                 case ESTABLISHED:
520                 case FIN_WAIT_1:
521                 case FIN_WAIT_2:
522                 case CLOSE_WAIT:
523                         set_state(c, CLOSED);
524                         errno = ECONNRESET;
525                         c->recv(c, NULL, 0);
526                         break;
527                 case CLOSING:
528                 case LAST_ACK:
529                 case TIME_WAIT:
530                         // TODO: delete connection?
531                         break;
532                 default:
533                         // TODO: wtf?
534                         return 0;
535                 }
536                 set_state(c, CLOSED);
537                 return 0;
538         }
539
540         if(hdr.ctl & SYN) {
541                 switch(c->state) {
542                 case SYN_RECEIVED:
543                 case ESTABLISHED:
544                 case FIN_WAIT_1:
545                 case FIN_WAIT_2:
546                 case CLOSE_WAIT:
547                 case CLOSING:
548                 case LAST_ACK:
549                 case TIME_WAIT:
550                         set_state(c, CLOSED);
551                         errno = ECONNRESET;
552                         c->recv(c, NULL, 0);
553                         goto reset;
554                         break;
555                 default:
556                         // TODO: wtf?
557                         return 0;
558                 }
559         }
560
561         if(!(hdr.ctl & ACK))
562                 return 0;
563
564         switch(c->state) {
565         case SYN_RECEIVED:
566                 if(hdr.ack >= c->snd.una && hdr.ack <= c->snd.nxt)
567                         c->utcp->accept(c, hdr.dst);
568                 
569                 if(c->state != ESTABLISHED)
570                         goto reset;
571                 break;
572         case ESTABLISHED:
573         case CLOSE_WAIT:
574                 if(hdr.ack < c->snd.una)
575                         return 0;
576                 if(hdr.ack > c->snd.nxt)
577                         goto ack_and_drop;
578                 if(hdr.ack > c->snd.una && hdr.ack <= c->snd.nxt) {
579                         c->snd.una = hdr.ack;
580                         if(c->snd.wl1 < hdr.seq || (c->snd.wl1 == hdr.seq && c->snd.wl2 <= hdr.ack)) {
581                                 c->snd.wnd = hdr.wnd;
582                                 c->snd.wl1 = hdr.seq;
583                                 c->snd.wl2 = hdr.ack;
584                         }
585                 }
586                 break;
587         case FIN_WAIT_1:
588                 if(hdr.ack == c->snd.nxt)
589                         set_state(c, FIN_WAIT_2);
590                 break;
591         case FIN_WAIT_2:
592                 // TODO: If nothing left to send, close.
593                 break;
594         case CLOSING:
595                 if(hdr.ack == c->snd.nxt) {
596                         set_state(c, TIME_WAIT);
597                 }
598                 break;
599         case LAST_ACK:
600                 if(hdr.ack == c->snd.nxt) {
601                         set_state(c, CLOSED);
602                 }
603                 return 0;
604         case TIME_WAIT:
605                 // TODO: retransmission of remote FIN, ACK and restart 2 MSL timeout
606                 break;
607         default:
608                 goto reset;
609         }
610
611         // Process data
612
613         switch(c->state) {
614         case ESTABLISHED:
615         case FIN_WAIT_1:
616         case FIN_WAIT_2:
617                 // TODO: process the data, see page 74
618                 break;
619         case CLOSE_WAIT:
620         case CLOSING:
621         case LAST_ACK:
622         case TIME_WAIT:
623                 break;
624         default:
625                 abort();
626         }
627
628         if(hdr.ctl & FIN) {
629                 switch(c->state) {
630                 case CLOSED:
631                 case LISTEN:
632                 case SYN_SENT:
633                         return 0;
634                 case SYN_RECEIVED:
635                 case ESTABLISHED:
636                         set_state(c, CLOSE_WAIT);
637                         c->rcv.nxt++;
638                         goto ack_and_drop;
639                 case FIN_WAIT_1:
640                         set_state(c, CLOSING);
641                         c->rcv.nxt++;
642                         goto ack_and_drop;
643                 case FIN_WAIT_2:
644                         set_state(c, TIME_WAIT);
645                         c->rcv.nxt++;
646                         goto ack_and_drop;
647                 case CLOSE_WAIT:
648                 case CLOSING:
649                 case LAST_ACK:
650                 case TIME_WAIT:
651                         break;
652                 default:
653                         abort();
654                 }
655         }
656
657         // Process the data
658         
659         if(len && c->recv) {
660                 c->recv(c, data, len);
661                 c->rcv.nxt += len;
662                 goto ack_and_drop;
663         }
664
665         return 0;
666
667 reset:
668         swap_ports(&hdr);
669         hdr.wnd = 0;
670         if(hdr.ctl & ACK) {
671                 hdr.seq = hdr.ack;
672                 hdr.ctl = RST;
673         } else {
674                 hdr.ack = hdr.seq + len;
675                 hdr.seq = 0;
676                 hdr.ctl = RST | ACK;
677         }
678         utcp->send(utcp, &hdr, sizeof hdr);
679         return 0;
680
681 ack_and_drop:
682         swap_ports(&hdr);
683         hdr.seq = c->snd.nxt;
684         hdr.ack = c->rcv.nxt;
685         hdr.ctl = ACK;
686         utcp->send(utcp, &hdr, sizeof hdr);
687         if(c->state == CLOSE_WAIT || c->state == TIME_WAIT) {
688                 errno = 0;
689                 c->recv(c, NULL, 0);
690         }
691         return 0;
692 }
693
694 int utcp_shutdown(struct utcp_connection *c, int dir) {
695         if(!c) {
696                 errno = EFAULT;
697                 return -1;
698         }
699
700         if(c->reapable) {
701                 fprintf(stderr, "Error: shutdown() called on closed connection %p\n", c);
702                 errno = EBADF;
703                 return -1;
704         }
705
706         // TODO: handle dir
707
708         switch(c->state) {
709         case CLOSED:
710                 return 0;
711         case LISTEN:
712         case SYN_SENT:
713                 set_state(c, CLOSED);
714                 return 0;
715
716         case SYN_RECEIVED:
717         case ESTABLISHED:
718                 set_state(c, FIN_WAIT_1);
719                 break;
720         case FIN_WAIT_1:
721         case FIN_WAIT_2:
722                 return 0;
723         case CLOSE_WAIT:
724                 set_state(c, LAST_ACK);
725                 break;
726
727         case CLOSING:
728         case LAST_ACK:
729         case TIME_WAIT:
730                 return 0;
731         }
732
733         // Send FIN
734
735         struct hdr hdr;
736
737         hdr.src = c->src;
738         hdr.dst = c->dst;
739         hdr.seq = c->snd.nxt;
740         hdr.ack = c->rcv.nxt;
741         hdr.wnd = c->snd.wnd;
742         hdr.ctl = FIN | ACK;
743
744         c->snd.nxt += 1;
745
746         c->utcp->send(c->utcp, &hdr, sizeof hdr);
747         return 0;
748 }
749
750 int utcp_close(struct utcp_connection *c) {
751         if(utcp_shutdown(c, SHUT_RDWR))
752                 return -1;
753         c->reapable = true;
754         return 0;
755 }
756
757 int utcp_abort(struct utcp_connection *c) {
758         if(!c) {
759                 errno = EFAULT;
760                 return -1;
761         }
762
763         if(c->reapable) {
764                 fprintf(stderr, "Error: abort() called on closed connection %p\n", c);
765                 errno = EBADF;
766                 return -1;
767         }
768
769         c->reapable = true;
770
771         switch(c->state) {
772         case CLOSED:
773                 return 0;
774         case LISTEN:
775         case SYN_SENT:
776         case CLOSING:
777         case LAST_ACK:
778         case TIME_WAIT:
779                 set_state(c, CLOSED);
780                 return 0;
781
782         case SYN_RECEIVED:
783         case ESTABLISHED:
784         case FIN_WAIT_1:
785         case FIN_WAIT_2:
786         case CLOSE_WAIT:
787                 set_state(c, CLOSED);
788                 break;
789         }
790
791         // Send RST
792
793         struct hdr hdr;
794
795         hdr.src = c->src;
796         hdr.dst = c->dst;
797         hdr.seq = c->snd.nxt;
798         hdr.ack = 0;
799         hdr.wnd = 0;
800         hdr.ctl = RST;
801
802         c->utcp->send(c->utcp, &hdr, sizeof hdr);
803         return 0;
804 }
805
806 void utcp_timeout(struct utcp *utcp) {
807         struct timeval now;
808         gettimeofday(&now, NULL);
809
810         for(int i = 0; i < utcp->nconnections; i++) {
811                 struct utcp_connection *c = utcp->connections[i];
812                 if(!c)
813                         continue;
814
815                 if(c->reapable) {
816                         fprintf(stderr, "Reaping %p\n", c);
817                         free_connection(c);
818                         continue;
819                 }
820
821                 if(c->state == CLOSED)
822                         return;
823
824                 if(c->conn_timeout.tv_sec && timercmp(&c->conn_timeout, &now, <)) {
825                         if(!c->reapable) {
826                                 errno = ETIMEDOUT;
827                                 c->recv(c, NULL, 0);
828                         }
829                         c->state = CLOSED;
830                         return;
831                 }
832
833                 if(c->rtrx_timeout.tv_sec && timercmp(&c->rtrx_timeout, &now, <)) {
834                         // TODO: retransmit stuff;
835                 }
836         }
837 }
838
839 struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv) {
840         struct utcp *utcp = calloc(1, sizeof *utcp);
841         if(!utcp)
842                 return NULL;
843
844         utcp->accept = accept;
845         utcp->pre_accept = pre_accept;
846         utcp->send = send;
847         utcp->priv = priv;
848         utcp->gap = -1;
849         utcp->mtu = 1000;
850
851         return utcp;
852 }
853
854 void utcp_exit(struct utcp *utcp) {
855         if(!utcp)
856                 return;
857         for(int i = 0; i < utcp->nconnections; i++)
858                 free_connection(utcp->connections[i]);
859         free(utcp);
860 }