]> git.meshlink.io Git - utcp/blob - utcp.c
Update snd.una when receiving an ACK in the SYN_RECEIVED state.
[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
601                 c->snd.una = hdr.ack;
602                 break;
603         case ESTABLISHED:
604         case CLOSE_WAIT:
605                 if(seqdiff(hdr.ack, c->snd.una) < 0)
606                         return 0;
607                 if(seqdiff(hdr.ack, c->snd.nxt) > 0)
608                         goto ack_and_drop;
609                 if(seqdiff(hdr.ack, c->snd.una) > 0 && seqdiff(hdr.ack, c->snd.nxt) <= 0) {
610                         c->snd.una = hdr.ack;
611                         if(seqdiff(c->snd.wl1, hdr.seq) < 0 || (c->snd.wl1 == hdr.seq && seqdiff(c->snd.wl2, hdr.ack) <= 0)) {
612                                 c->snd.wnd = hdr.wnd;
613                                 c->snd.wl1 = hdr.seq;
614                                 c->snd.wl2 = hdr.ack;
615                         }
616                 }
617                 break;
618         case FIN_WAIT_1:
619                 if(hdr.ack == c->snd.nxt)
620                         set_state(c, FIN_WAIT_2);
621                 break;
622         case FIN_WAIT_2:
623                 // TODO: If nothing left to send, close.
624                 break;
625         case CLOSING:
626                 if(hdr.ack == c->snd.nxt) {
627                         set_state(c, TIME_WAIT);
628                 }
629                 break;
630         case LAST_ACK:
631                 if(hdr.ack == c->snd.nxt) {
632                         set_state(c, CLOSED);
633                 }
634                 return 0;
635         case TIME_WAIT:
636                 // TODO: retransmission of remote FIN, ACK and restart 2 MSL timeout
637                 break;
638         default:
639                 goto reset;
640         }
641
642         // Process data
643
644         switch(c->state) {
645         case ESTABLISHED:
646         case FIN_WAIT_1:
647         case FIN_WAIT_2:
648                 // TODO: process the data, see page 74
649                 break;
650         case CLOSE_WAIT:
651         case CLOSING:
652         case LAST_ACK:
653         case TIME_WAIT:
654                 break;
655         default:
656                 abort();
657         }
658
659         if(hdr.ctl & FIN) {
660                 switch(c->state) {
661                 case CLOSED:
662                 case LISTEN:
663                 case SYN_SENT:
664                         return 0;
665                 case SYN_RECEIVED:
666                 case ESTABLISHED:
667                         set_state(c, CLOSE_WAIT);
668                         c->rcv.nxt++;
669                         goto ack_and_drop;
670                 case FIN_WAIT_1:
671                         set_state(c, CLOSING);
672                         c->rcv.nxt++;
673                         goto ack_and_drop;
674                 case FIN_WAIT_2:
675                         set_state(c, TIME_WAIT);
676                         c->rcv.nxt++;
677                         goto ack_and_drop;
678                 case CLOSE_WAIT:
679                 case CLOSING:
680                 case LAST_ACK:
681                 case TIME_WAIT:
682                         break;
683                 default:
684                         abort();
685                 }
686         }
687
688         // Process the data
689
690         if(len && c->recv) {
691                 c->recv(c, data, len);
692                 c->rcv.nxt += len;
693                 goto ack_and_drop;
694         }
695
696         return 0;
697
698 reset:
699         swap_ports(&hdr);
700         hdr.wnd = 0;
701         if(hdr.ctl & ACK) {
702                 hdr.seq = hdr.ack;
703                 hdr.ctl = RST;
704         } else {
705                 hdr.ack = hdr.seq + len;
706                 hdr.seq = 0;
707                 hdr.ctl = RST | ACK;
708         }
709         utcp->send(utcp, &hdr, sizeof hdr);
710         return 0;
711
712 ack_and_drop:
713         swap_ports(&hdr);
714         hdr.seq = c->snd.nxt;
715         hdr.ack = c->rcv.nxt;
716         hdr.ctl = ACK;
717         utcp->send(utcp, &hdr, sizeof hdr);
718         if(c->state == CLOSE_WAIT || c->state == TIME_WAIT) {
719                 errno = 0;
720                 if(c->recv)
721                         c->recv(c, NULL, 0);
722         }
723         return 0;
724 }
725
726 int utcp_shutdown(struct utcp_connection *c, int dir) {
727         if(!c) {
728                 errno = EFAULT;
729                 return -1;
730         }
731
732         if(c->reapable) {
733                 fprintf(stderr, "Error: shutdown() called on closed connection %p\n", c);
734                 errno = EBADF;
735                 return -1;
736         }
737
738         // TODO: handle dir
739
740         switch(c->state) {
741         case CLOSED:
742                 return 0;
743         case LISTEN:
744         case SYN_SENT:
745                 set_state(c, CLOSED);
746                 return 0;
747
748         case SYN_RECEIVED:
749         case ESTABLISHED:
750                 set_state(c, FIN_WAIT_1);
751                 break;
752         case FIN_WAIT_1:
753         case FIN_WAIT_2:
754                 return 0;
755         case CLOSE_WAIT:
756                 set_state(c, LAST_ACK);
757                 break;
758
759         case CLOSING:
760         case LAST_ACK:
761         case TIME_WAIT:
762                 return 0;
763         }
764
765         // Send FIN
766
767         struct hdr hdr;
768
769         hdr.src = c->src;
770         hdr.dst = c->dst;
771         hdr.seq = c->snd.nxt;
772         hdr.ack = c->rcv.nxt;
773         hdr.wnd = c->snd.wnd;
774         hdr.ctl = FIN | ACK;
775
776         c->snd.nxt += 1;
777
778         c->utcp->send(c->utcp, &hdr, sizeof hdr);
779         return 0;
780 }
781
782 int utcp_close(struct utcp_connection *c) {
783         if(utcp_shutdown(c, SHUT_RDWR))
784                 return -1;
785         c->reapable = true;
786         return 0;
787 }
788
789 int utcp_abort(struct utcp_connection *c) {
790         if(!c) {
791                 errno = EFAULT;
792                 return -1;
793         }
794
795         if(c->reapable) {
796                 fprintf(stderr, "Error: abort() called on closed connection %p\n", c);
797                 errno = EBADF;
798                 return -1;
799         }
800
801         c->reapable = true;
802
803         switch(c->state) {
804         case CLOSED:
805                 return 0;
806         case LISTEN:
807         case SYN_SENT:
808         case CLOSING:
809         case LAST_ACK:
810         case TIME_WAIT:
811                 set_state(c, CLOSED);
812                 return 0;
813
814         case SYN_RECEIVED:
815         case ESTABLISHED:
816         case FIN_WAIT_1:
817         case FIN_WAIT_2:
818         case CLOSE_WAIT:
819                 set_state(c, CLOSED);
820                 break;
821         }
822
823         // Send RST
824
825         struct hdr hdr;
826
827         hdr.src = c->src;
828         hdr.dst = c->dst;
829         hdr.seq = c->snd.nxt;
830         hdr.ack = 0;
831         hdr.wnd = 0;
832         hdr.ctl = RST;
833
834         c->utcp->send(c->utcp, &hdr, sizeof hdr);
835         return 0;
836 }
837
838 static void retransmit(struct utcp_connection *c) {
839         if(c->state == CLOSED || c->snd.nxt == c->snd.una)
840                 return;
841
842         struct utcp *utcp = c->utcp;
843
844         struct {
845                 struct hdr hdr;
846                 char data[c->utcp->mtu];
847         } pkt;
848
849         pkt.hdr.src = c->src;
850         pkt.hdr.dst = c->dst;
851
852         switch(c->state) {
853                 case LISTEN:
854                         // TODO: this should not happen
855                         break;
856
857                 case SYN_SENT:
858                         pkt.hdr.seq = c->snd.iss;
859                         pkt.hdr.ack = 0;
860                         pkt.hdr.wnd = c->rcv.wnd;
861                         pkt.hdr.ctl = SYN;
862                         utcp->send(utcp, &pkt, sizeof pkt.hdr);
863                         break;
864
865                 case SYN_RECEIVED:
866                         pkt.hdr.seq = c->snd.nxt;
867                         pkt.hdr.ack = c->rcv.nxt;
868                         pkt.hdr.ctl = SYN | ACK;
869                         utcp->send(utcp, &pkt, sizeof pkt.hdr);
870                         break;
871
872                 case ESTABLISHED:
873                         pkt.hdr.seq = c->snd.una;
874                         pkt.hdr.ack = c->rcv.nxt;
875                         pkt.hdr.ctl = ACK;
876                         uint32_t len = seqdiff(c->snd.nxt, c->snd.una);
877                         if(len > utcp->mtu)
878                                 len = utcp->mtu;
879                         memcpy(pkt.data, c->sndbuf, len);
880                         utcp->send(utcp, &pkt, sizeof pkt.hdr + len);
881                         break;
882
883                 default:
884                         // TODO: implement
885                         abort();
886         }
887 }
888
889 /* Handle timeouts.
890  * One call to this function will loop through all connections,
891  * checking if something needs to be resent or not.
892  * The return value is the time to the next timeout in milliseconds,
893  * or maybe a negative value if the timeout is infinite.
894  */
895 int utcp_timeout(struct utcp *utcp) {
896         struct timeval now;
897         gettimeofday(&now, NULL);
898         struct timeval next = {now.tv_sec + 3600, now.tv_usec};
899
900         for(int i = 0; i < utcp->nconnections; i++) {
901                 struct utcp_connection *c = utcp->connections[i];
902                 if(!c)
903                         continue;
904
905                 if(c->state == CLOSED) {
906                         if(c->reapable) {
907                                 fprintf(stderr, "Reaping %p\n", c);
908                                 free_connection(c);
909                                 i--;
910                         }
911                         continue;
912                 }
913
914                 if(timerisset(&c->conn_timeout) && timercmp(&c->conn_timeout, &now, <)) {
915                         errno = ETIMEDOUT;
916                         c->state = CLOSED;
917                         if(c->recv)
918                                 c->recv(c, NULL, 0);
919                         continue;
920                 }
921
922                 if(timerisset(&c->rtrx_timeout) && timercmp(&c->rtrx_timeout, &now, <)) {
923                         retransmit(c);
924                 }
925
926                 if(timerisset(&c->conn_timeout) && timercmp(&c->conn_timeout, &next, <))
927                         next = c->conn_timeout;
928
929                 if(c->snd.nxt != c->snd.una) {
930                         c->rtrx_timeout = now;
931                         c->rtrx_timeout.tv_sec++;
932                 } else {
933                         timerclear(&c->rtrx_timeout);
934                 }
935
936                 if(timerisset(&c->rtrx_timeout) && timercmp(&c->rtrx_timeout, &next, <))
937                         next = c->rtrx_timeout;
938         }
939
940         struct timeval diff;
941         timersub(&next, &now, &diff);
942         if(diff.tv_sec < 0)
943                 return 0;
944         return diff.tv_sec * 1000 + diff.tv_usec / 1000;
945 }
946
947 struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv) {
948         struct utcp *utcp = calloc(1, sizeof *utcp);
949         if(!utcp)
950                 return NULL;
951
952         if(!send) {
953                 errno = EFAULT;
954                 return NULL;
955         }
956
957         utcp->accept = accept;
958         utcp->pre_accept = pre_accept;
959         utcp->send = send;
960         utcp->priv = priv;
961         utcp->mtu = 1000;
962         utcp->timeout = 60;
963
964         return utcp;
965 }
966
967 void utcp_exit(struct utcp *utcp) {
968         if(!utcp)
969                 return;
970         for(int i = 0; i < utcp->nconnections; i++)
971                 free_connection(utcp->connections[i]);
972         free(utcp);
973 }
974
975 int utcp_set_connection_timeout(struct utcp *u, int timeout) {
976         int prev = u->timeout;
977         u->timeout = timeout;
978         return prev;
979 }