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