]> git.meshlink.io Git - utcp/blob - utcp.c
f5875e2f58943523bc9853c68d191267e45d2d11
[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         int timeout;
126
127         struct utcp_connection **connections;
128         int nconnections;
129         int nallocated;
130 };
131
132 static void set_state(struct utcp_connection *c, enum state state) {
133         c->state = state;
134         if(state == ESTABLISHED)
135                 timerclear(&c->conn_timeout);
136         fprintf(stderr, "%p new state: %s\n", c->utcp, strstate[state]);
137 }
138
139 static void print_packet(struct utcp *utcp, const char *dir, const void *pkt, size_t len) {
140         struct hdr hdr;
141         if(len < sizeof hdr) {
142                 fprintf(stderr, "%p %s: short packet (%zu bytes)\n", utcp, dir, len);
143                 return;
144         }
145
146         memcpy(&hdr, pkt, sizeof hdr);
147         fprintf (stderr, "%p %s: src=%u dst=%u seq=%u ack=%u wnd=%u ctl=", utcp, dir, hdr.src, hdr.dst, hdr.seq, hdr.ack, hdr.wnd);
148         if(hdr.ctl & SYN)
149                 fprintf(stderr, "SYN");
150         if(hdr.ctl & RST)
151                 fprintf(stderr, "RST");
152         if(hdr.ctl & FIN)
153                 fprintf(stderr, "FIN");
154         if(hdr.ctl & ACK)
155                 fprintf(stderr, "ACK");
156
157         if(len > sizeof hdr) {
158                 fprintf(stderr, " data=");
159                 for(int i = sizeof hdr; i < len; i++) {
160                         const char *data = pkt;
161                         fprintf(stderr, "%c", data[i] >= 32 ? data[i] : '.');
162                 }
163         }
164
165         fprintf(stderr, "\n");
166 }
167
168 static inline void list_connections(struct utcp *utcp) {
169         fprintf(stderr, "%p has %d connections:\n", utcp, utcp->nconnections);
170         for(int i = 0; i < utcp->nconnections; i++)
171                 fprintf(stderr, "  %u -> %u state %s\n", utcp->connections[i]->src, utcp->connections[i]->dst, strstate[utcp->connections[i]->state]);
172 }
173
174 // Connections are stored in a sorted list.
175 // This gives O(log(N)) lookup time, O(N log(N)) insertion time and O(N) deletion time.
176
177 static int compare(const void *va, const void *vb) {
178         const struct utcp_connection *a = *(struct utcp_connection **)va;
179         const struct utcp_connection *b = *(struct utcp_connection **)vb;
180         if(!a->src || !b->src)
181                 abort();
182         int c = (int)a->src - (int)b->src;
183         if(c)
184                 return c;
185         c = (int)a->dst - (int)b->dst;
186         return c;
187 }
188
189 static struct utcp_connection *find_connection(const struct utcp *utcp, uint16_t src, uint16_t dst) {
190         if(!utcp->nconnections)
191                 return NULL;
192         struct utcp_connection key = {
193                 .src = src,
194                 .dst = dst,
195         }, *keyp = &key;
196         struct utcp_connection **match = bsearch(&keyp, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
197         return match ? *match : NULL;
198 }
199
200 static void free_connection(struct utcp_connection *c) {
201         struct utcp *utcp = c->utcp;
202         struct utcp_connection **cp = bsearch(&c, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
203         if(!cp)
204                 abort();
205
206         int i = cp - utcp->connections;
207         memmove(cp + i, cp + i + 1, (utcp->nconnections - i - 1) * sizeof *cp);
208         utcp->nconnections--;
209
210         free(c);
211 }
212
213 static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t src, uint16_t dst) {
214         // Check whether this combination of src and dst is free
215
216         if(src) {
217                 if(find_connection(utcp, src, dst)) {
218                         errno = EADDRINUSE;
219                         return NULL;
220                 }
221         } else { // If src == 0, generate a random port number with the high bit set
222                 if(utcp->nconnections >= 32767) {
223                         errno = ENOMEM;
224                         return NULL;
225                 }
226                 src = rand() | 0x8000;
227                 while(find_connection(utcp, src, dst))
228                         src++;
229         }
230
231         // Allocate memory for the new connection
232
233         if(utcp->nconnections >= utcp->nallocated) {
234                 if(!utcp->nallocated)
235                         utcp->nallocated = 4;
236                 else
237                         utcp->nallocated *= 2;
238                 struct utcp_connection **new_array = realloc(utcp->connections, utcp->nallocated * sizeof *utcp->connections);
239                 if(!new_array) {
240                         errno = ENOMEM;
241                         return NULL;
242                 }
243                 utcp->connections = new_array;
244         }
245
246         struct utcp_connection *c = calloc(1, sizeof *c);
247         if(!c) {
248                 errno = ENOMEM;
249                 return NULL;
250         }
251
252         // Fill in the details
253
254         c->src = src;
255         c->dst = dst;
256         c->snd.iss = rand();
257         c->snd.una = c->snd.iss;
258         c->snd.nxt = c->snd.iss + 1;
259         c->rcv.wnd = utcp->mtu;
260         c->utcp = utcp;
261         c->sndbufsize = 65536;
262         c->sndbuf = malloc(c->sndbufsize);
263         if(!c->sndbuf)
264                 c->sndbufsize = 0;
265
266         // Add it to the sorted list of connections
267
268         utcp->connections[utcp->nconnections++] = c;
269         qsort(utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
270
271         return c;
272 }
273
274 struct utcp_connection *utcp_connect(struct utcp *utcp, uint16_t dst, utcp_recv_t recv, void *priv) {
275         struct utcp_connection *c = allocate_connection(utcp, 0, dst);
276         if(!c)
277                 return NULL;
278
279         c->recv = recv;
280
281         struct hdr hdr;
282
283         hdr.src = c->src;
284         hdr.dst = c->dst;
285         hdr.seq = c->snd.iss;
286         hdr.ack = 0;
287         hdr.ctl = SYN;
288         hdr.wnd = c->rcv.wnd;
289
290         set_state(c, SYN_SENT);
291
292         print_packet(utcp, "send", &hdr, sizeof hdr);
293         utcp->send(utcp, &hdr, sizeof hdr);
294
295         gettimeofday(&c->conn_timeout, NULL);
296         c->conn_timeout.tv_sec += utcp->timeout;
297
298         return c;
299 }
300
301 void utcp_accept(struct utcp_connection *c, utcp_recv_t recv, void *priv) {
302         if(c->reapable || c->state != SYN_RECEIVED) {
303                 fprintf(stderr, "Error: accept() called on invalid connection %p in state %s\n", c, strstate[c->state]);
304                 return;
305         }
306
307         fprintf(stderr, "%p accepted, %p %p\n", c, recv, priv);
308         c->recv = recv;
309         c->priv = priv;
310         set_state(c, ESTABLISHED);
311 }
312
313 ssize_t utcp_send(struct utcp_connection *c, const void *data, size_t len) {
314         if(c->reapable) {
315                 fprintf(stderr, "Error: send() called on closed connection %p\n", c);
316                 errno = EBADF;
317                 return -1;
318         }
319
320         switch(c->state) {
321         case CLOSED:
322         case LISTEN:
323         case SYN_SENT:
324         case SYN_RECEIVED:
325                 fprintf(stderr, "Error: send() called on unconnected connection %p\n", c);
326                 errno = ENOTCONN;
327                 return -1;
328         case ESTABLISHED:
329         case CLOSE_WAIT:
330                 break;
331         case FIN_WAIT_1:
332         case FIN_WAIT_2:
333         case CLOSING:
334         case LAST_ACK:
335         case TIME_WAIT:
336                 fprintf(stderr, "Error: send() called on closing connection %p\n", c);
337                 errno = EPIPE;
338                 return -1;
339         }
340
341         // Add data to send buffer
342
343         if(!len)
344                 return 0;
345
346         if(!data) {
347                 errno = EFAULT;
348                 return -1;
349         }
350
351         uint32_t bufused = c->snd.nxt - c->snd.una;
352
353         if(len > c->sndbufsize - bufused)
354                 len = c->sndbufsize - bufused;
355
356         memcpy(c->sndbuf + (c->snd.nxt - c->snd.una), data, len);
357
358         // Send segments
359
360         struct {
361                 struct hdr hdr;
362                 char data[c->utcp->mtu];
363         } pkt;
364
365         pkt.hdr.src = c->src;
366         pkt.hdr.dst = c->dst;
367         pkt.hdr.ack = c->rcv.nxt;
368         pkt.hdr.wnd = c->snd.wnd;
369         pkt.hdr.ctl = ACK;
370
371         uint32_t left = len;
372
373         while(left) {
374                 uint32_t seglen = left > c->utcp->mtu ? c->utcp->mtu : left;
375                 pkt.hdr.seq = c->snd.nxt;
376
377                 memcpy(pkt.data, data, seglen);
378
379                 c->snd.nxt += seglen;
380                 data += seglen;
381                 left -= seglen;
382
383                 print_packet(c->utcp, "send", &pkt, sizeof pkt.hdr + seglen);
384                 c->utcp->send(c->utcp, &pkt, sizeof pkt.hdr + seglen);
385         }
386
387         fprintf(stderr, "len=%zu\n", len);
388         return len;
389 }
390
391 static void swap_ports(struct hdr *hdr) {
392         uint16_t tmp = hdr->src;
393         hdr->src = hdr->dst;
394         hdr->dst = tmp;
395 }
396
397 static int32_t seqdiff(uint32_t a, uint32_t b) {
398         return a - b;
399 }
400
401 int utcp_recv(struct utcp *utcp, const void *data, size_t len) {
402         if(!utcp) {
403                 errno = EFAULT;
404                 return -1;
405         }
406
407         if(!len)
408                 return 0;
409
410         if(!data) {
411                 errno = EFAULT;
412                 return -1;
413         }
414
415         print_packet(utcp, "recv", data, len);
416
417         struct hdr hdr;
418         if(len < sizeof hdr) {
419                 errno = EBADMSG;
420                 return -1;
421         }
422
423         memcpy(&hdr, data, sizeof hdr);
424         data += sizeof hdr;
425         len -= sizeof hdr;
426
427         if(hdr.ctl & ~(SYN | ACK | RST | FIN)) {
428                 errno = EBADMSG;
429                 return -1;
430         }
431
432         //list_connections(utcp);
433
434         struct utcp_connection *c = find_connection(utcp, hdr.dst, hdr.src);
435
436         // Is it for a new connection?
437
438         if(!c) {
439                 if(hdr.ctl & RST)
440                         return 0;
441
442                 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
443                         // Return SYN+ACK
444                         c->snd.wnd = hdr.wnd;
445                         c->rcv.irs = hdr.seq;
446                         c->rcv.nxt = c->rcv.irs + 1;
447                         set_state(c, SYN_RECEIVED);
448
449                         hdr.dst = c->dst;
450                         hdr.src = c->src;
451                         hdr.ack = c->rcv.irs + 1;
452                         hdr.seq = c->snd.iss;
453                         hdr.ctl = SYN | ACK;
454                         print_packet(c->utcp, "send", &hdr, sizeof hdr);
455                         utcp->send(utcp, &hdr, sizeof hdr);
456                         return 0;
457                 } else { // CLOSED
458                         len = 1;
459                         goto reset;
460                 }
461         }
462
463         fprintf(stderr, "%p state %s\n", c->utcp, strstate[c->state]);
464
465         if(c->state == CLOSED) {
466                 fprintf(stderr, "Error: packet recv()d on closed connection %p\n", c);
467                 errno = EBADF;
468                 return -1;
469         }
470
471         // It is for an existing connection.
472
473         if(c->state == SYN_SENT) {
474                 if(hdr.ctl & ACK) {
475                         if(seqdiff(hdr.ack, c->snd.iss) <= 0 || seqdiff(hdr.ack, c->snd.nxt) > 0) {
476                                 fprintf(stderr, "Invalid ACK, %u %u %u\n", hdr.ack, c->snd.iss, c->snd.nxt);
477                                 goto reset;
478                         }
479                 }
480                 if(hdr.ctl & RST) {
481                         if(!(hdr.ctl & ACK))
482                                 return 0;
483                         set_state(c, CLOSED);
484                         errno = ECONNREFUSED;
485                         if(c->recv)
486                                 c->recv(c, NULL, 0);
487                         return 0;
488                 }
489                 if(hdr.ctl & SYN) {
490                         c->dst = hdr.src;
491                         c->rcv.nxt = hdr.seq + 1;
492                         c->rcv.irs = hdr.seq;
493                         c->snd.wnd = hdr.wnd;
494
495                         if(hdr.ctl & ACK)
496                                 c->snd.una = hdr.ack;
497                         if(seqdiff(c->snd.una, c->snd.iss) > 0) {
498                                 set_state(c, ESTABLISHED);
499                                 // TODO: signal app?
500                                 swap_ports(&hdr);
501                                 hdr.seq = c->snd.nxt;
502                                 hdr.ack = c->rcv.nxt;
503                                 hdr.ctl = ACK;
504                         } else {
505                                 set_state(c, SYN_RECEIVED);
506                                 swap_ports(&hdr);
507                                 hdr.seq = c->snd.iss;
508                                 hdr.ack = c->rcv.nxt;
509                                 hdr.ctl = SYN | ACK;
510                         }
511                         print_packet(c->utcp, "send", &hdr, sizeof hdr);
512                         utcp->send(utcp, &hdr, sizeof hdr);
513                         // TODO: queue any data?
514                 }
515
516                 return 0;
517         }
518
519         bool acceptable;
520
521         if(len == 0)
522                 if(c->rcv.wnd == 0)
523                         acceptable = hdr.seq == c->rcv.nxt;
524                 else
525                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd);
526         else
527                 if(c->rcv.wnd == 0)
528                         acceptable = false;
529                 else
530                         acceptable = (hdr.seq >= c->rcv.nxt && hdr.seq < c->rcv.nxt + c->rcv.wnd)
531                                 || (hdr.seq + len - 1 >= c->rcv.nxt && hdr.seq + len - 1 < c->rcv.nxt + c->rcv.wnd);
532
533         if(!acceptable) {
534                 fprintf(stderr, "Packet not acceptable, %u %u %u %zu\n", hdr.seq, c->rcv.nxt, c->rcv.wnd, len);
535                 if(hdr.ctl & RST)
536                         return 0;
537                 goto ack_and_drop;
538         }
539
540         c->snd.wnd = hdr.wnd;
541
542         // TODO: check whether segment really starts at rcv.nxt, otherwise trim it.
543
544         if(hdr.ctl & RST) {
545                 switch(c->state) {
546                 case SYN_RECEIVED:
547                         // TODO: delete connection?
548                         break;
549                 case ESTABLISHED:
550                 case FIN_WAIT_1:
551                 case FIN_WAIT_2:
552                 case CLOSE_WAIT:
553                         set_state(c, CLOSED);
554                         errno = ECONNRESET;
555                         if(c->recv)
556                                 c->recv(c, NULL, 0);
557                         break;
558                 case CLOSING:
559                 case LAST_ACK:
560                 case TIME_WAIT:
561                         // TODO: delete connection?
562                         break;
563                 default:
564                         // TODO: wtf?
565                         return 0;
566                 }
567                 set_state(c, CLOSED);
568                 return 0;
569         }
570
571         if(hdr.ctl & SYN) {
572                 switch(c->state) {
573                 case SYN_RECEIVED:
574                 case ESTABLISHED:
575                 case FIN_WAIT_1:
576                 case FIN_WAIT_2:
577                 case CLOSE_WAIT:
578                 case CLOSING:
579                 case LAST_ACK:
580                 case TIME_WAIT:
581                         set_state(c, CLOSED);
582                         errno = ECONNRESET;
583                         if(c->recv)
584                                 c->recv(c, NULL, 0);
585                         goto reset;
586                         break;
587                 default:
588                         // TODO: wtf?
589                         return 0;
590                 }
591         }
592
593         if(!(hdr.ctl & ACK))
594                 return 0;
595
596         switch(c->state) {
597         case SYN_RECEIVED:
598                 if(seqdiff(hdr.ack, c->snd.una) >= 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0)
599                         c->utcp->accept(c, hdr.dst);
600                 
601                 if(c->state != ESTABLISHED)
602                         goto reset;
603
604                 c->snd.una = hdr.ack;
605                 break;
606         case ESTABLISHED:
607         case CLOSE_WAIT:
608                 if(seqdiff(hdr.ack, c->snd.una) < 0)
609                         return 0;
610                 if(seqdiff(hdr.ack, c->snd.nxt) > 0)
611                         goto ack_and_drop;
612                 if(seqdiff(hdr.ack, c->snd.una) > 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0) {
613                         c->snd.una = hdr.ack;
614                         if(seqdiff(c->snd.wl1, hdr.seq) < 0 || (c->snd.wl1 == hdr.seq && seqdiff(c->snd.wl2, hdr.ack) <= 0)) {
615                                 c->snd.wnd = hdr.wnd;
616                                 c->snd.wl1 = hdr.seq;
617                                 c->snd.wl2 = hdr.ack;
618                         }
619                 }
620                 break;
621         case FIN_WAIT_1:
622                 if(hdr.ack == c->snd.nxt)
623                         set_state(c, FIN_WAIT_2);
624                 break;
625         case FIN_WAIT_2:
626                 // TODO: If nothing left to send, close.
627                 break;
628         case CLOSING:
629                 if(hdr.ack == c->snd.nxt) {
630                         set_state(c, TIME_WAIT);
631                 }
632                 break;
633         case LAST_ACK:
634                 if(hdr.ack == c->snd.nxt) {
635                         set_state(c, CLOSED);
636                 }
637                 return 0;
638         case TIME_WAIT:
639                 // TODO: retransmission of remote FIN, ACK and restart 2 MSL timeout
640                 break;
641         default:
642                 goto reset;
643         }
644
645         // Process data
646
647         switch(c->state) {
648         case ESTABLISHED:
649         case FIN_WAIT_1:
650         case FIN_WAIT_2:
651                 // TODO: process the data, see page 74
652                 break;
653         case CLOSE_WAIT:
654         case CLOSING:
655         case LAST_ACK:
656         case TIME_WAIT:
657                 break;
658         default:
659                 abort();
660         }
661
662         if(hdr.ctl & FIN) {
663                 switch(c->state) {
664                 case CLOSED:
665                 case LISTEN:
666                 case SYN_SENT:
667                         return 0;
668                 case SYN_RECEIVED:
669                 case ESTABLISHED:
670                         set_state(c, CLOSE_WAIT);
671                         c->rcv.nxt++;
672                         goto ack_and_drop;
673                 case FIN_WAIT_1:
674                         set_state(c, CLOSING);
675                         c->rcv.nxt++;
676                         goto ack_and_drop;
677                 case FIN_WAIT_2:
678                         set_state(c, TIME_WAIT);
679                         c->rcv.nxt++;
680                         goto ack_and_drop;
681                 case CLOSE_WAIT:
682                 case CLOSING:
683                 case LAST_ACK:
684                 case TIME_WAIT:
685                         break;
686                 default:
687                         abort();
688                 }
689         }
690
691         // Process the data
692
693         if(len && c->recv) {
694                 c->recv(c, data, len);
695                 c->rcv.nxt += len;
696                 goto ack_and_drop;
697         }
698
699         return 0;
700
701 reset:
702         swap_ports(&hdr);
703         hdr.wnd = 0;
704         if(hdr.ctl & ACK) {
705                 hdr.seq = hdr.ack;
706                 hdr.ctl = RST;
707         } else {
708                 hdr.ack = hdr.seq + len;
709                 hdr.seq = 0;
710                 hdr.ctl = RST | ACK;
711         }
712         print_packet(c->utcp, "send", &hdr, sizeof hdr);
713         utcp->send(utcp, &hdr, sizeof hdr);
714         return 0;
715
716 ack_and_drop:
717         swap_ports(&hdr);
718         hdr.seq = c->snd.nxt;
719         hdr.ack = c->rcv.nxt;
720         hdr.ctl = ACK;
721         print_packet(c->utcp, "send", &hdr, sizeof hdr);
722         utcp->send(utcp, &hdr, sizeof hdr);
723         if(c->state == CLOSE_WAIT || c->state == TIME_WAIT) {
724                 errno = 0;
725                 if(c->recv)
726                         c->recv(c, NULL, 0);
727         }
728         return 0;
729 }
730
731 int utcp_shutdown(struct utcp_connection *c, int dir) {
732         if(!c) {
733                 errno = EFAULT;
734                 return -1;
735         }
736
737         if(c->reapable) {
738                 fprintf(stderr, "Error: shutdown() called on closed connection %p\n", c);
739                 errno = EBADF;
740                 return -1;
741         }
742
743         // TODO: handle dir
744
745         switch(c->state) {
746         case CLOSED:
747                 return 0;
748         case LISTEN:
749         case SYN_SENT:
750                 set_state(c, CLOSED);
751                 return 0;
752
753         case SYN_RECEIVED:
754         case ESTABLISHED:
755                 set_state(c, FIN_WAIT_1);
756                 break;
757         case FIN_WAIT_1:
758         case FIN_WAIT_2:
759                 return 0;
760         case CLOSE_WAIT:
761                 set_state(c, LAST_ACK);
762                 break;
763
764         case CLOSING:
765         case LAST_ACK:
766         case TIME_WAIT:
767                 return 0;
768         }
769
770         // Send FIN
771
772         struct hdr hdr;
773
774         hdr.src = c->src;
775         hdr.dst = c->dst;
776         hdr.seq = c->snd.nxt;
777         hdr.ack = c->rcv.nxt;
778         hdr.wnd = c->snd.wnd;
779         hdr.ctl = FIN | ACK;
780
781         c->snd.nxt += 1;
782
783         print_packet(c->utcp, "send", &hdr, sizeof hdr);
784         c->utcp->send(c->utcp, &hdr, sizeof hdr);
785         return 0;
786 }
787
788 int utcp_close(struct utcp_connection *c) {
789         if(utcp_shutdown(c, SHUT_RDWR))
790                 return -1;
791         c->reapable = true;
792         return 0;
793 }
794
795 int utcp_abort(struct utcp_connection *c) {
796         if(!c) {
797                 errno = EFAULT;
798                 return -1;
799         }
800
801         if(c->reapable) {
802                 fprintf(stderr, "Error: abort() called on closed connection %p\n", c);
803                 errno = EBADF;
804                 return -1;
805         }
806
807         c->reapable = true;
808
809         switch(c->state) {
810         case CLOSED:
811                 return 0;
812         case LISTEN:
813         case SYN_SENT:
814         case CLOSING:
815         case LAST_ACK:
816         case TIME_WAIT:
817                 set_state(c, CLOSED);
818                 return 0;
819
820         case SYN_RECEIVED:
821         case ESTABLISHED:
822         case FIN_WAIT_1:
823         case FIN_WAIT_2:
824         case CLOSE_WAIT:
825                 set_state(c, CLOSED);
826                 break;
827         }
828
829         // Send RST
830
831         struct hdr hdr;
832
833         hdr.src = c->src;
834         hdr.dst = c->dst;
835         hdr.seq = c->snd.nxt;
836         hdr.ack = 0;
837         hdr.wnd = 0;
838         hdr.ctl = RST;
839
840         print_packet(c->utcp, "send", &hdr, sizeof hdr);
841         c->utcp->send(c->utcp, &hdr, sizeof hdr);
842         return 0;
843 }
844
845 static void retransmit(struct utcp_connection *c) {
846         if(c->state == CLOSED || c->snd.nxt == c->snd.una)
847                 return;
848
849         struct utcp *utcp = c->utcp;
850
851         struct {
852                 struct hdr hdr;
853                 char data[c->utcp->mtu];
854         } pkt;
855
856         pkt.hdr.src = c->src;
857         pkt.hdr.dst = c->dst;
858
859         switch(c->state) {
860                 case LISTEN:
861                         // TODO: this should not happen
862                         break;
863
864                 case SYN_SENT:
865                         pkt.hdr.seq = c->snd.iss;
866                         pkt.hdr.ack = 0;
867                         pkt.hdr.wnd = c->rcv.wnd;
868                         pkt.hdr.ctl = SYN;
869                         print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr);
870                         utcp->send(utcp, &pkt, sizeof pkt.hdr);
871                         break;
872
873                 case SYN_RECEIVED:
874                         pkt.hdr.seq = c->snd.nxt;
875                         pkt.hdr.ack = c->rcv.nxt;
876                         pkt.hdr.ctl = SYN | ACK;
877                         print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr);
878                         utcp->send(utcp, &pkt, sizeof pkt.hdr);
879                         break;
880
881                 case ESTABLISHED:
882                         pkt.hdr.seq = c->snd.una;
883                         pkt.hdr.ack = c->rcv.nxt;
884                         pkt.hdr.ctl = ACK;
885                         uint32_t len = seqdiff(c->snd.nxt, c->snd.una);
886                         if(len > utcp->mtu)
887                                 len = utcp->mtu;
888                         memcpy(pkt.data, c->sndbuf, len);
889                         print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr + len);
890                         utcp->send(utcp, &pkt, sizeof pkt.hdr + len);
891                         break;
892
893                 default:
894                         // TODO: implement
895                         abort();
896         }
897 }
898
899 /* Handle timeouts.
900  * One call to this function will loop through all connections,
901  * checking if something needs to be resent or not.
902  * The return value is the time to the next timeout in milliseconds,
903  * or maybe a negative value if the timeout is infinite.
904  */
905 int utcp_timeout(struct utcp *utcp) {
906         struct timeval now;
907         gettimeofday(&now, NULL);
908         struct timeval next = {now.tv_sec + 3600, now.tv_usec};
909
910         for(int i = 0; i < utcp->nconnections; i++) {
911                 struct utcp_connection *c = utcp->connections[i];
912                 if(!c)
913                         continue;
914
915                 if(c->state == CLOSED) {
916                         if(c->reapable) {
917                                 fprintf(stderr, "Reaping %p\n", c);
918                                 free_connection(c);
919                                 i--;
920                         }
921                         continue;
922                 }
923
924                 if(timerisset(&c->conn_timeout) && timercmp(&c->conn_timeout, &now, <)) {
925                         errno = ETIMEDOUT;
926                         c->state = CLOSED;
927                         if(c->recv)
928                                 c->recv(c, NULL, 0);
929                         continue;
930                 }
931
932                 if(timerisset(&c->rtrx_timeout) && timercmp(&c->rtrx_timeout, &now, <)) {
933                         retransmit(c);
934                 }
935
936                 if(timerisset(&c->conn_timeout) && timercmp(&c->conn_timeout, &next, <))
937                         next = c->conn_timeout;
938
939                 if(c->snd.nxt != c->snd.una) {
940                         c->rtrx_timeout = now;
941                         c->rtrx_timeout.tv_sec++;
942                 } else {
943                         timerclear(&c->rtrx_timeout);
944                 }
945
946                 if(timerisset(&c->rtrx_timeout) && timercmp(&c->rtrx_timeout, &next, <))
947                         next = c->rtrx_timeout;
948         }
949
950         struct timeval diff;
951         timersub(&next, &now, &diff);
952         if(diff.tv_sec < 0)
953                 return 0;
954         return diff.tv_sec * 1000 + diff.tv_usec / 1000;
955 }
956
957 struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv) {
958         struct utcp *utcp = calloc(1, sizeof *utcp);
959         if(!utcp)
960                 return NULL;
961
962         if(!send) {
963                 errno = EFAULT;
964                 return NULL;
965         }
966
967         utcp->accept = accept;
968         utcp->pre_accept = pre_accept;
969         utcp->send = send;
970         utcp->priv = priv;
971         utcp->mtu = 1000;
972         utcp->timeout = 60;
973
974         return utcp;
975 }
976
977 void utcp_exit(struct utcp *utcp) {
978         if(!utcp)
979                 return;
980         for(int i = 0; i < utcp->nconnections; i++)
981                 free_connection(utcp->connections[i]);
982         free(utcp);
983 }
984
985 int utcp_set_connection_timeout(struct utcp *u, int timeout) {
986         int prev = u->timeout;
987         u->timeout = timeout;
988         return prev;
989 }