]> git.meshlink.io Git - utcp/blob - utcp.c
Segmentize outgoing packets.
[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         c->sndbufsize = 65536;
260         c->sndbuf = malloc(c->sndbufsize);
261         if(!c->sndbuf)
262                 c->sndbufsize = 0;
263
264         // Add it to the sorted list of connections
265
266         utcp->connections[utcp->nconnections++] = c;
267         qsort(utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
268
269         return c;
270 }
271
272 struct utcp_connection *utcp_connect(struct utcp *utcp, uint16_t dst, utcp_recv_t recv, void *priv) {
273         struct utcp_connection *c = allocate_connection(utcp, 0, dst);
274         if(!c)
275                 return NULL;
276
277         c->recv = recv;
278
279         struct hdr hdr;
280
281         hdr.src = c->src;
282         hdr.dst = c->dst;
283         hdr.seq = c->snd.iss;
284         hdr.ack = 0;
285         hdr.ctl = SYN;
286         hdr.wnd = c->rcv.wnd;
287
288         set_state(c, SYN_SENT);
289
290         utcp->send(utcp, &hdr, sizeof hdr);
291
292         // Set timeout?
293
294         return c;
295 }
296
297 void utcp_accept(struct utcp_connection *c, utcp_recv_t recv, void *priv) {
298         if(c->reapable || c->state != SYN_RECEIVED) {
299                 fprintf(stderr, "Error: accept() called on invalid connection %p in state %s\n", c, strstate[c->state]);
300                 return;
301         }
302
303         fprintf(stderr, "%p accepted, %p %p\n", c, recv, priv);
304         c->recv = recv;
305         c->priv = priv;
306         set_state(c, ESTABLISHED);
307 }
308
309 ssize_t utcp_send(struct utcp_connection *c, void *data, size_t len) {
310         if(c->reapable) {
311                 fprintf(stderr, "Error: send() called on closed connection %p\n", c);
312                 errno = EBADF;
313                 return -1;
314         }
315
316         switch(c->state) {
317         case CLOSED:
318         case LISTEN:
319         case SYN_SENT:
320         case SYN_RECEIVED:
321                 fprintf(stderr, "Error: send() called on unconnected connection %p\n", c);
322                 errno = ENOTCONN;
323                 return -1;
324         case ESTABLISHED:
325         case CLOSE_WAIT:
326                 break;
327         case FIN_WAIT_1:
328         case FIN_WAIT_2:
329         case CLOSING:
330         case LAST_ACK:
331         case TIME_WAIT:
332                 fprintf(stderr, "Error: send() called on closing connection %p\n", c);
333                 errno = EPIPE;
334                 return -1;
335         }
336
337         // Add data to send buffer
338
339         if(!len)
340                 return 0;
341
342         if(!data) {
343                 errno = EFAULT;
344                 return -1;
345         }
346
347         uint32_t bufused = c->snd.nxt - c->snd.una;
348
349         if(len > c->sndbufsize - bufused)
350                 len = c->sndbufsize - bufused;
351
352         memcpy(c->sndbuf + (c->snd.nxt - c->snd.una), data, len);
353
354         // Send segments
355
356         struct {
357                 struct hdr hdr;
358                 char data[c->utcp->mtu];
359         } pkt;
360
361         pkt.hdr.src = c->src;
362         pkt.hdr.dst = c->dst;
363         pkt.hdr.ack = c->rcv.nxt;
364         pkt.hdr.wnd = c->snd.wnd;
365         pkt.hdr.ctl = ACK;
366
367         uint32_t left = len;
368
369         while(left) {
370                 uint32_t seglen = left > c->utcp->mtu ? c->utcp->mtu : left;
371                 pkt.hdr.seq = c->snd.nxt;
372
373                 memcpy(pkt.data, data, seglen);
374
375                 c->snd.nxt += seglen;
376                 data += seglen;
377                 left -= seglen;
378
379                 c->utcp->send(c->utcp, &pkt, sizeof pkt.hdr + seglen);
380         }
381
382         fprintf(stderr, "len=%u\n", len);
383         return len;
384 }
385
386 static void swap_ports(struct hdr *hdr) {
387         uint16_t tmp = hdr->src;
388         hdr->src = hdr->dst;
389         hdr->dst = tmp;
390 }
391
392 static int16_t seqdiff(uint16_t a, uint16_t b) {
393         return a -b;
394 }
395
396 int utcp_recv(struct utcp *utcp, void *data, size_t len) {
397         if(!utcp) {
398                 errno = EFAULT;
399                 return -1;
400         }
401
402         if(!len)
403                 return 0;
404
405         if(!data) {
406                 errno = EFAULT;
407                 return -1;
408         }
409
410         fprintf(stderr, "%p got: ", utcp);
411         print_packet(data, len);
412
413         struct hdr hdr;
414         if(len < sizeof hdr) {
415                 errno = EBADMSG;
416                 return -1;
417         }
418
419         memcpy(&hdr, data, sizeof hdr);
420         data += sizeof hdr;
421         len -= sizeof hdr;
422
423         if(hdr.ctl & ~(SYN | ACK | RST | FIN)) {
424                 errno = EBADMSG;
425                 return -1;
426         }
427
428         //list_connections(utcp);
429
430         struct utcp_connection *c = find_connection(utcp, hdr.dst, hdr.src);
431
432         // Is it for a new connection?
433
434         if(!c) {
435                 if(hdr.ctl & RST)
436                         return 0;
437
438                 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
439                         // Return SYN+ACK
440                         c->snd.wnd = hdr.wnd;
441                         c->rcv.irs = hdr.seq;
442                         c->rcv.nxt = c->rcv.irs + 1;
443                         set_state(c, SYN_RECEIVED);
444
445                         hdr.dst = c->dst;
446                         hdr.src = c->src;
447                         hdr.ack = c->rcv.irs + 1;
448                         hdr.seq = c->snd.iss;
449                         hdr.ctl = SYN | ACK;
450                         utcp->send(utcp, &hdr, sizeof hdr);
451                         return 0;
452                 } else { // CLOSED
453                         len = 1;
454                         goto reset;
455                 }
456         }
457
458         fprintf(stderr, "%p state %s\n", c->utcp, strstate[c->state]);
459
460         if(c->state == CLOSED) {
461                 fprintf(stderr, "Error: packet recv()d on closed connection %p\n", c);
462                 errno = EBADF;
463                 return -1;
464         }
465
466         // It is for an existing connection.
467
468         if(c->state == SYN_SENT) {
469                 if(hdr.ctl & ACK) {
470                         if(seqdiff(hdr.ack, c->snd.iss) <= 0 || seqdiff(hdr.ack, c->snd.nxt) > 0) {
471                                 fprintf(stderr, "Invalid ACK, %u %u %u\n", hdr.ack, c->snd.iss, c->snd.nxt);
472                                 goto reset;
473                         }
474                 }
475                 if(hdr.ctl & RST) {
476                         if(!(hdr.ctl & ACK))
477                                 return 0;
478                         set_state(c, CLOSED);
479                         errno = ECONNREFUSED;
480                         c->recv(c, NULL, 0);
481                         return 0;
482                 }
483                 if(hdr.ctl & SYN) {
484                         c->dst = hdr.src;
485                         c->rcv.nxt = hdr.seq + 1;
486                         c->rcv.irs = hdr.seq;
487                         c->snd.wnd = hdr.wnd;
488
489                         if(hdr.ctl & ACK)
490                                 c->snd.una = hdr.ack;
491                         if(seqdiff(c->snd.una, c->snd.iss) > 0) {
492                                 set_state(c, ESTABLISHED);
493                                 // TODO: signal app?
494                                 swap_ports(&hdr);
495                                 hdr.seq = c->snd.nxt;
496                                 hdr.ack = c->rcv.nxt;
497                                 hdr.ctl = ACK;
498                         } else {
499                                 set_state(c, SYN_RECEIVED);
500                                 swap_ports(&hdr);
501                                 hdr.seq = c->snd.iss;
502                                 hdr.ack = c->rcv.nxt;
503                                 hdr.ctl = SYN | ACK;
504                         }
505                         utcp->send(utcp, &hdr, sizeof hdr);
506                         // TODO: queue any data?
507                 }
508
509                 return 0;
510         }
511
512         bool acceptable;
513
514         if(len == 0)
515                 if(c->rcv.wnd == 0)
516                         acceptable = hdr.seq == c->rcv.nxt;
517                 else
518                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd);
519         else
520                 if(c->rcv.wnd == 0)
521                         acceptable = false;
522                 else
523                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd)
524                                 || (hdr.seq + len - 1 >= c->rcv.nxt && hdr.seq + len - 1 < c->rcv.nxt + c->rcv.wnd);
525
526         if(!acceptable) {
527                 fprintf(stderr, "Packet not acceptable, %u %u %u %zu\n", hdr.seq, c->rcv.nxt, c->rcv.wnd, len);
528                 if(hdr.ctl & RST)
529                         return 0;
530                 goto ack_and_drop;
531         }
532
533         c->snd.wnd = hdr.wnd;
534
535         // TODO: check whether segment really starts at rcv.nxt, otherwise trim it.
536
537         if(hdr.ctl & RST) {
538                 switch(c->state) {
539                 case SYN_RECEIVED:
540                         // TODO: delete connection?
541                         break;
542                 case ESTABLISHED:
543                 case FIN_WAIT_1:
544                 case FIN_WAIT_2:
545                 case CLOSE_WAIT:
546                         set_state(c, CLOSED);
547                         errno = ECONNRESET;
548                         c->recv(c, NULL, 0);
549                         break;
550                 case CLOSING:
551                 case LAST_ACK:
552                 case TIME_WAIT:
553                         // TODO: delete connection?
554                         break;
555                 default:
556                         // TODO: wtf?
557                         return 0;
558                 }
559                 set_state(c, CLOSED);
560                 return 0;
561         }
562
563         if(hdr.ctl & SYN) {
564                 switch(c->state) {
565                 case SYN_RECEIVED:
566                 case ESTABLISHED:
567                 case FIN_WAIT_1:
568                 case FIN_WAIT_2:
569                 case CLOSE_WAIT:
570                 case CLOSING:
571                 case LAST_ACK:
572                 case TIME_WAIT:
573                         set_state(c, CLOSED);
574                         errno = ECONNRESET;
575                         c->recv(c, NULL, 0);
576                         goto reset;
577                         break;
578                 default:
579                         // TODO: wtf?
580                         return 0;
581                 }
582         }
583
584         if(!(hdr.ctl & ACK))
585                 return 0;
586
587         switch(c->state) {
588         case SYN_RECEIVED:
589                 if(seqdiff(hdr.ack, c->snd.una) >= 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0)
590                         c->utcp->accept(c, hdr.dst);
591                 
592                 if(c->state != ESTABLISHED)
593                         goto reset;
594                 break;
595         case ESTABLISHED:
596         case CLOSE_WAIT:
597                 if(seqdiff(hdr.ack, c->snd.una) < 0)
598                         return 0;
599                 if(seqdiff(hdr.ack, c->snd.nxt) > 0)
600                         goto ack_and_drop;
601                 if(seqdiff(hdr.ack, c->snd.una) > 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0) {
602                         c->snd.una = hdr.ack;
603                         if(seqdiff(c->snd.wl1, hdr.seq) < 0 || (c->snd.wl1 == hdr.seq && seqdiff(c->snd.wl2, hdr.ack) <= 0)) {
604                                 c->snd.wnd = hdr.wnd;
605                                 c->snd.wl1 = hdr.seq;
606                                 c->snd.wl2 = hdr.ack;
607                         }
608                 }
609                 break;
610         case FIN_WAIT_1:
611                 if(hdr.ack == c->snd.nxt)
612                         set_state(c, FIN_WAIT_2);
613                 break;
614         case FIN_WAIT_2:
615                 // TODO: If nothing left to send, close.
616                 break;
617         case CLOSING:
618                 if(hdr.ack == c->snd.nxt) {
619                         set_state(c, TIME_WAIT);
620                 }
621                 break;
622         case LAST_ACK:
623                 if(hdr.ack == c->snd.nxt) {
624                         set_state(c, CLOSED);
625                 }
626                 return 0;
627         case TIME_WAIT:
628                 // TODO: retransmission of remote FIN, ACK and restart 2 MSL timeout
629                 break;
630         default:
631                 goto reset;
632         }
633
634         // Process data
635
636         switch(c->state) {
637         case ESTABLISHED:
638         case FIN_WAIT_1:
639         case FIN_WAIT_2:
640                 // TODO: process the data, see page 74
641                 break;
642         case CLOSE_WAIT:
643         case CLOSING:
644         case LAST_ACK:
645         case TIME_WAIT:
646                 break;
647         default:
648                 abort();
649         }
650
651         if(hdr.ctl & FIN) {
652                 switch(c->state) {
653                 case CLOSED:
654                 case LISTEN:
655                 case SYN_SENT:
656                         return 0;
657                 case SYN_RECEIVED:
658                 case ESTABLISHED:
659                         set_state(c, CLOSE_WAIT);
660                         c->rcv.nxt++;
661                         goto ack_and_drop;
662                 case FIN_WAIT_1:
663                         set_state(c, CLOSING);
664                         c->rcv.nxt++;
665                         goto ack_and_drop;
666                 case FIN_WAIT_2:
667                         set_state(c, TIME_WAIT);
668                         c->rcv.nxt++;
669                         goto ack_and_drop;
670                 case CLOSE_WAIT:
671                 case CLOSING:
672                 case LAST_ACK:
673                 case TIME_WAIT:
674                         break;
675                 default:
676                         abort();
677                 }
678         }
679
680         // Process the data
681
682         if(len && c->recv) {
683                 c->recv(c, data, len);
684                 c->rcv.nxt += len;
685                 goto ack_and_drop;
686         }
687
688         return 0;
689
690 reset:
691         swap_ports(&hdr);
692         hdr.wnd = 0;
693         if(hdr.ctl & ACK) {
694                 hdr.seq = hdr.ack;
695                 hdr.ctl = RST;
696         } else {
697                 hdr.ack = hdr.seq + len;
698                 hdr.seq = 0;
699                 hdr.ctl = RST | ACK;
700         }
701         utcp->send(utcp, &hdr, sizeof hdr);
702         return 0;
703
704 ack_and_drop:
705         swap_ports(&hdr);
706         hdr.seq = c->snd.nxt;
707         hdr.ack = c->rcv.nxt;
708         hdr.ctl = ACK;
709         utcp->send(utcp, &hdr, sizeof hdr);
710         if(c->state == CLOSE_WAIT || c->state == TIME_WAIT) {
711                 errno = 0;
712                 c->recv(c, NULL, 0);
713         }
714         return 0;
715 }
716
717 int utcp_shutdown(struct utcp_connection *c, int dir) {
718         if(!c) {
719                 errno = EFAULT;
720                 return -1;
721         }
722
723         if(c->reapable) {
724                 fprintf(stderr, "Error: shutdown() called on closed connection %p\n", c);
725                 errno = EBADF;
726                 return -1;
727         }
728
729         // TODO: handle dir
730
731         switch(c->state) {
732         case CLOSED:
733                 return 0;
734         case LISTEN:
735         case SYN_SENT:
736                 set_state(c, CLOSED);
737                 return 0;
738
739         case SYN_RECEIVED:
740         case ESTABLISHED:
741                 set_state(c, FIN_WAIT_1);
742                 break;
743         case FIN_WAIT_1:
744         case FIN_WAIT_2:
745                 return 0;
746         case CLOSE_WAIT:
747                 set_state(c, LAST_ACK);
748                 break;
749
750         case CLOSING:
751         case LAST_ACK:
752         case TIME_WAIT:
753                 return 0;
754         }
755
756         // Send FIN
757
758         struct hdr hdr;
759
760         hdr.src = c->src;
761         hdr.dst = c->dst;
762         hdr.seq = c->snd.nxt;
763         hdr.ack = c->rcv.nxt;
764         hdr.wnd = c->snd.wnd;
765         hdr.ctl = FIN | ACK;
766
767         c->snd.nxt += 1;
768
769         c->utcp->send(c->utcp, &hdr, sizeof hdr);
770         return 0;
771 }
772
773 int utcp_close(struct utcp_connection *c) {
774         if(utcp_shutdown(c, SHUT_RDWR))
775                 return -1;
776         c->reapable = true;
777         return 0;
778 }
779
780 int utcp_abort(struct utcp_connection *c) {
781         if(!c) {
782                 errno = EFAULT;
783                 return -1;
784         }
785
786         if(c->reapable) {
787                 fprintf(stderr, "Error: abort() called on closed connection %p\n", c);
788                 errno = EBADF;
789                 return -1;
790         }
791
792         c->reapable = true;
793
794         switch(c->state) {
795         case CLOSED:
796                 return 0;
797         case LISTEN:
798         case SYN_SENT:
799         case CLOSING:
800         case LAST_ACK:
801         case TIME_WAIT:
802                 set_state(c, CLOSED);
803                 return 0;
804
805         case SYN_RECEIVED:
806         case ESTABLISHED:
807         case FIN_WAIT_1:
808         case FIN_WAIT_2:
809         case CLOSE_WAIT:
810                 set_state(c, CLOSED);
811                 break;
812         }
813
814         // Send RST
815
816         struct hdr hdr;
817
818         hdr.src = c->src;
819         hdr.dst = c->dst;
820         hdr.seq = c->snd.nxt;
821         hdr.ack = 0;
822         hdr.wnd = 0;
823         hdr.ctl = RST;
824
825         c->utcp->send(c->utcp, &hdr, sizeof hdr);
826         return 0;
827 }
828
829 void utcp_timeout(struct utcp *utcp) {
830         struct timeval now;
831         gettimeofday(&now, NULL);
832
833         for(int i = 0; i < utcp->nconnections; i++) {
834                 struct utcp_connection *c = utcp->connections[i];
835                 if(!c)
836                         continue;
837
838                 if(c->reapable) {
839                         fprintf(stderr, "Reaping %p\n", c);
840                         free_connection(c);
841                         continue;
842                 }
843
844                 if(c->state == CLOSED)
845                         return;
846
847                 if(c->conn_timeout.tv_sec && timercmp(&c->conn_timeout, &now, <)) {
848                         if(!c->reapable) {
849                                 errno = ETIMEDOUT;
850                                 c->recv(c, NULL, 0);
851                         }
852                         c->state = CLOSED;
853                         return;
854                 }
855
856                 if(c->rtrx_timeout.tv_sec && timercmp(&c->rtrx_timeout, &now, <)) {
857                         // TODO: retransmit stuff;
858                 }
859         }
860 }
861
862 struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv) {
863         struct utcp *utcp = calloc(1, sizeof *utcp);
864         if(!utcp)
865                 return NULL;
866
867         utcp->accept = accept;
868         utcp->pre_accept = pre_accept;
869         utcp->send = send;
870         utcp->priv = priv;
871         utcp->gap = -1;
872         utcp->mtu = 1000;
873
874         return utcp;
875 }
876
877 void utcp_exit(struct utcp *utcp) {
878         if(!utcp)
879                 return;
880         for(int i = 0; i < utcp->nconnections; i++)
881                 free_connection(utcp->connections[i]);
882         free(utcp);
883 }