]> git.meshlink.io Git - utcp/blob - utcp.c
Move private struct declarations e.a. to utcp_priv.h.
[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 #include "utcp_priv.h"
33
34 static void set_state(struct utcp_connection *c, enum state state) {
35         c->state = state;
36         if(state == ESTABLISHED)
37                 timerclear(&c->conn_timeout);
38         fprintf(stderr, "%p new state: %s\n", c->utcp, strstate[state]);
39 }
40
41 static void print_packet(struct utcp *utcp, const char *dir, const void *pkt, size_t len) {
42         struct hdr hdr;
43         if(len < sizeof hdr) {
44                 fprintf(stderr, "%p %s: short packet (%zu bytes)\n", utcp, dir, len);
45                 return;
46         }
47
48         memcpy(&hdr, pkt, sizeof hdr);
49         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);
50         if(hdr.ctl & SYN)
51                 fprintf(stderr, "SYN");
52         if(hdr.ctl & RST)
53                 fprintf(stderr, "RST");
54         if(hdr.ctl & FIN)
55                 fprintf(stderr, "FIN");
56         if(hdr.ctl & ACK)
57                 fprintf(stderr, "ACK");
58
59         if(len > sizeof hdr) {
60                 fprintf(stderr, " data=");
61                 for(int i = sizeof hdr; i < len; i++) {
62                         const char *data = pkt;
63                         fprintf(stderr, "%c", data[i] >= 32 ? data[i] : '.');
64                 }
65         }
66
67         fprintf(stderr, "\n");
68 }
69
70 static inline void list_connections(struct utcp *utcp) {
71         fprintf(stderr, "%p has %d connections:\n", utcp, utcp->nconnections);
72         for(int i = 0; i < utcp->nconnections; i++)
73                 fprintf(stderr, "  %u -> %u state %s\n", utcp->connections[i]->src, utcp->connections[i]->dst, strstate[utcp->connections[i]->state]);
74 }
75
76 // Connections are stored in a sorted list.
77 // This gives O(log(N)) lookup time, O(N log(N)) insertion time and O(N) deletion time.
78
79 static int compare(const void *va, const void *vb) {
80         const struct utcp_connection *a = *(struct utcp_connection **)va;
81         const struct utcp_connection *b = *(struct utcp_connection **)vb;
82         if(!a->src || !b->src)
83                 abort();
84         int c = (int)a->src - (int)b->src;
85         if(c)
86                 return c;
87         c = (int)a->dst - (int)b->dst;
88         return c;
89 }
90
91 static struct utcp_connection *find_connection(const struct utcp *utcp, uint16_t src, uint16_t dst) {
92         if(!utcp->nconnections)
93                 return NULL;
94         struct utcp_connection key = {
95                 .src = src,
96                 .dst = dst,
97         }, *keyp = &key;
98         struct utcp_connection **match = bsearch(&keyp, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
99         return match ? *match : NULL;
100 }
101
102 static void free_connection(struct utcp_connection *c) {
103         struct utcp *utcp = c->utcp;
104         struct utcp_connection **cp = bsearch(&c, utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
105         if(!cp)
106                 abort();
107
108         int i = cp - utcp->connections;
109         memmove(cp + i, cp + i + 1, (utcp->nconnections - i - 1) * sizeof *cp);
110         utcp->nconnections--;
111
112         free(c);
113 }
114
115 static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t src, uint16_t dst) {
116         // Check whether this combination of src and dst is free
117
118         if(src) {
119                 if(find_connection(utcp, src, dst)) {
120                         errno = EADDRINUSE;
121                         return NULL;
122                 }
123         } else { // If src == 0, generate a random port number with the high bit set
124                 if(utcp->nconnections >= 32767) {
125                         errno = ENOMEM;
126                         return NULL;
127                 }
128                 src = rand() | 0x8000;
129                 while(find_connection(utcp, src, dst))
130                         src++;
131         }
132
133         // Allocate memory for the new connection
134
135         if(utcp->nconnections >= utcp->nallocated) {
136                 if(!utcp->nallocated)
137                         utcp->nallocated = 4;
138                 else
139                         utcp->nallocated *= 2;
140                 struct utcp_connection **new_array = realloc(utcp->connections, utcp->nallocated * sizeof *utcp->connections);
141                 if(!new_array) {
142                         errno = ENOMEM;
143                         return NULL;
144                 }
145                 utcp->connections = new_array;
146         }
147
148         struct utcp_connection *c = calloc(1, sizeof *c);
149         if(!c) {
150                 errno = ENOMEM;
151                 return NULL;
152         }
153
154         // Fill in the details
155
156         c->src = src;
157         c->dst = dst;
158         c->snd.iss = rand();
159         c->snd.una = c->snd.iss;
160         c->snd.nxt = c->snd.iss + 1;
161         c->rcv.wnd = utcp->mtu;
162         c->utcp = utcp;
163         c->sndbufsize = 65536;
164         c->sndbuf = malloc(c->sndbufsize);
165         if(!c->sndbuf)
166                 c->sndbufsize = 0;
167
168         // Add it to the sorted list of connections
169
170         utcp->connections[utcp->nconnections++] = c;
171         qsort(utcp->connections, utcp->nconnections, sizeof *utcp->connections, compare);
172
173         return c;
174 }
175
176 struct utcp_connection *utcp_connect(struct utcp *utcp, uint16_t dst, utcp_recv_t recv, void *priv) {
177         struct utcp_connection *c = allocate_connection(utcp, 0, dst);
178         if(!c)
179                 return NULL;
180
181         c->recv = recv;
182
183         struct hdr hdr;
184
185         hdr.src = c->src;
186         hdr.dst = c->dst;
187         hdr.seq = c->snd.iss;
188         hdr.ack = 0;
189         hdr.ctl = SYN;
190         hdr.wnd = c->rcv.wnd;
191
192         set_state(c, SYN_SENT);
193
194         print_packet(utcp, "send", &hdr, sizeof hdr);
195         utcp->send(utcp, &hdr, sizeof hdr);
196
197         gettimeofday(&c->conn_timeout, NULL);
198         c->conn_timeout.tv_sec += utcp->timeout;
199
200         return c;
201 }
202
203 void utcp_accept(struct utcp_connection *c, utcp_recv_t recv, void *priv) {
204         if(c->reapable || c->state != SYN_RECEIVED) {
205                 fprintf(stderr, "Error: accept() called on invalid connection %p in state %s\n", c, strstate[c->state]);
206                 return;
207         }
208
209         fprintf(stderr, "%p accepted, %p %p\n", c, recv, priv);
210         c->recv = recv;
211         c->priv = priv;
212         set_state(c, ESTABLISHED);
213 }
214
215 ssize_t utcp_send(struct utcp_connection *c, const void *data, size_t len) {
216         if(c->reapable) {
217                 fprintf(stderr, "Error: send() called on closed connection %p\n", c);
218                 errno = EBADF;
219                 return -1;
220         }
221
222         switch(c->state) {
223         case CLOSED:
224         case LISTEN:
225         case SYN_SENT:
226         case SYN_RECEIVED:
227                 fprintf(stderr, "Error: send() called on unconnected connection %p\n", c);
228                 errno = ENOTCONN;
229                 return -1;
230         case ESTABLISHED:
231         case CLOSE_WAIT:
232                 break;
233         case FIN_WAIT_1:
234         case FIN_WAIT_2:
235         case CLOSING:
236         case LAST_ACK:
237         case TIME_WAIT:
238                 fprintf(stderr, "Error: send() called on closing connection %p\n", c);
239                 errno = EPIPE;
240                 return -1;
241         }
242
243         // Add data to send buffer
244
245         if(!len)
246                 return 0;
247
248         if(!data) {
249                 errno = EFAULT;
250                 return -1;
251         }
252
253         uint32_t bufused = c->snd.nxt - c->snd.una;
254
255         /* Check our send buffer.
256          * - If it's big enough, just put the data in there.
257          * - If not, decide whether to enlarge. (TODO, now we just always enlarge)
258          * - Cap len so it doesn't overflow our buffer.
259          */
260
261         if(len > c->sndbufsize - bufused) {
262                 c->sndbufsize *= 2;
263                 c->sndbuf = realloc(c->sndbuf, c->sndbufsize);
264         }
265
266         if(len > c->sndbufsize - bufused)
267                 len = c->sndbufsize - bufused;
268
269         if(!len) {
270                 errno == EWOULDBLOCK;
271                 return 0;
272         }
273
274         memcpy(c->sndbuf + bufused, data, len);
275
276         // Send segments
277
278         struct {
279                 struct hdr hdr;
280                 char data[c->utcp->mtu];
281         } pkt;
282
283         pkt.hdr.src = c->src;
284         pkt.hdr.dst = c->dst;
285         pkt.hdr.ack = c->rcv.nxt;
286         pkt.hdr.wnd = c->snd.wnd;
287         pkt.hdr.ctl = ACK;
288
289         uint32_t left = len;
290
291         while(left) {
292                 uint32_t seglen = left > c->utcp->mtu ? c->utcp->mtu : left;
293                 pkt.hdr.seq = c->snd.nxt;
294
295                 memcpy(pkt.data, data, seglen);
296
297                 c->snd.nxt += seglen;
298                 data += seglen;
299                 left -= seglen;
300
301                 print_packet(c->utcp, "send", &pkt, sizeof pkt.hdr + seglen);
302                 c->utcp->send(c->utcp, &pkt, sizeof pkt.hdr + seglen);
303         }
304
305         fprintf(stderr, "len=%zu\n", len);
306         return len;
307 }
308
309 static void swap_ports(struct hdr *hdr) {
310         uint16_t tmp = hdr->src;
311         hdr->src = hdr->dst;
312         hdr->dst = tmp;
313 }
314
315 static int32_t seqdiff(uint32_t a, uint32_t b) {
316         return a - b;
317 }
318
319 int utcp_recv(struct utcp *utcp, const void *data, size_t len) {
320         if(!utcp) {
321                 errno = EFAULT;
322                 return -1;
323         }
324
325         if(!len)
326                 return 0;
327
328         if(!data) {
329                 errno = EFAULT;
330                 return -1;
331         }
332
333         print_packet(utcp, "recv", data, len);
334
335         // Drop packets smaller than the header
336
337         struct hdr hdr;
338         if(len < sizeof hdr) {
339                 errno = EBADMSG;
340                 return -1;
341         }
342
343         // Make a copy from the potentially unaligned data to a struct hdr
344
345         memcpy(&hdr, data, sizeof hdr);
346         data += sizeof hdr;
347         len -= sizeof hdr;
348
349         // Drop packets with an unknown CTL flag
350
351         if(hdr.ctl & ~(SYN | ACK | RST | FIN)) {
352                 errno = EBADMSG;
353                 return -1;
354         }
355
356         // Try to match the packet to an existing connection
357
358         struct utcp_connection *c = find_connection(utcp, hdr.dst, hdr.src);
359
360         // Is it for a new connection?
361
362         if(!c) {
363                 // Ignore RST packets
364
365                 if(hdr.ctl & RST)
366                         return 0;
367
368                 // Is it a SYN packet and are we LISTENing?
369
370                 if(hdr.ctl & SYN && !(hdr.ctl & ACK) && utcp->accept) {
371                         // If we don't want to accept it, send a RST back
372                         if((utcp->pre_accept && !utcp->pre_accept(utcp, hdr.dst))) {
373                                 len = 1;
374                                 goto reset;
375                         }
376
377                         // Try to allocate memory, otherwise send a RST back
378                         c = allocate_connection(utcp, hdr.dst, hdr.src);
379                         if(!c) {
380                                 len = 1;
381                                 goto reset;
382                         }
383
384                         // Return SYN+ACK, go to SYN_RECEIVED state
385                         c->snd.wnd = hdr.wnd;
386                         c->rcv.irs = hdr.seq;
387                         c->rcv.nxt = c->rcv.irs + 1;
388                         set_state(c, SYN_RECEIVED);
389
390                         hdr.dst = c->dst;
391                         hdr.src = c->src;
392                         hdr.ack = c->rcv.irs + 1;
393                         hdr.seq = c->snd.iss;
394                         hdr.ctl = SYN | ACK;
395                         print_packet(c->utcp, "send", &hdr, sizeof hdr);
396                         utcp->send(utcp, &hdr, sizeof hdr);
397                 } else {
398                         // No, we don't want your packets, send a RST back
399                         len = 1;
400                         goto reset;
401                 }
402
403                 return 0;
404         }
405
406         fprintf(stderr, "%p state %s\n", c->utcp, strstate[c->state]);
407
408         // In case this is for a CLOSED connection, ignore the packet.
409         // TODO: make it so incoming packets can never match a CLOSED connection.
410
411         if(c->state == CLOSED)
412                 return 0;
413
414         // It is for an existing connection.
415
416         // 1. Drop invalid packets.
417
418         // 1a. Drop packets that should not happen in our current state.
419
420         switch(c->state) {
421         case SYN_SENT:
422         case SYN_RECEIVED:
423         case ESTABLISHED:
424         case FIN_WAIT_1:
425         case FIN_WAIT_2:
426         case CLOSE_WAIT:
427         case CLOSING:
428         case LAST_ACK:
429         case TIME_WAIT:
430                 break;
431         default:
432                 abort();
433         }
434
435         // 1b. Drop packets with a sequence number not in our receive window.
436
437         bool acceptable;
438
439         if(c->state == SYN_SENT)
440                 acceptable = true;
441
442         // TODO: handle packets overlapping c->rcv.nxt.
443 #if 0
444         // Only use this when accepting out-of-order packets.
445         else if(len == 0)
446                 if(c->rcv.wnd == 0)
447                         acceptable = hdr.seq == c->rcv.nxt;
448                 else
449                         acceptable = (seqdiff(hdr.seq, c->rcv.nxt) >= 0 && seqdiff(hdr.seq, c->rcv.nxt + c->rcv.wnd) < 0);
450         else
451                 if(c->rcv.wnd == 0)
452                         // We don't accept data when the receive window is zero.
453                         acceptable = false;
454                 else
455                         // Both start and end of packet must be within the receive window
456                         acceptable = (seqdiff(hdr.seq, c->rcv.nxt) >= 0 && seqdiff(hdr.seq, c->rcv.nxt + c->rcv.wnd) < 0)
457                                 || (seqdiff(hdr.seq + len + 1, c->rcv.nxt) >= 0 && seqdiff(hdr.seq + len - 1, c->rcv.nxt + c->rcv.wnd) < 0);
458 #else
459         if(c->state != SYN_SENT)
460                 acceptable = hdr.seq == c->rcv.nxt;
461 #endif
462
463         if(!acceptable) {
464                 fprintf(stderr, "Packet not acceptable, %u  <= %u + %zu < %u\n", c->rcv.nxt, hdr.seq, len, c->rcv.nxt + c->rcv.wnd);
465                 // Ignore unacceptable RST packets.
466                 if(hdr.ctl & RST)
467                         return 0;
468                 // Otherwise, send an ACK back in the hope things improve.
469                 goto ack;
470         }
471
472         c->snd.wnd = hdr.wnd; // TODO: move below
473
474         // 1c. Drop packets with an invalid ACK.
475         // ackno should not roll back, and it should also not be bigger than snd.nxt.
476
477         if(hdr.ctl & ACK && (seqdiff(hdr.ack, c->snd.nxt) > 0 || seqdiff(hdr.ack, c->snd.una) < 0)) {
478                 fprintf(stderr, "Packet ack seqno out of range, %u %u %u\n", hdr.ack, c->snd.una, c->snd.nxt);
479                 // Ignore unacceptable RST packets.
480                 if(hdr.ctl & RST)
481                         return 0;
482                 goto reset;
483         }
484
485         // 2. Handle RST packets
486
487         if(hdr.ctl & RST) {
488                 switch(c->state) {
489                 case SYN_SENT:
490                         if(!(hdr.ctl & ACK))
491                                 return 0;
492                         // The peer has refused our connection.
493                         set_state(c, CLOSED);
494                         errno = ECONNREFUSED;
495                         if(c->recv)
496                                 c->recv(c, NULL, 0);
497                         return 0;
498                 case SYN_RECEIVED:
499                         if(hdr.ctl & ACK)
500                                 return 0;
501                         // We haven't told the application about this connection yet. Silently delete.
502                         free_connection(c);
503                         return 0;
504                 case ESTABLISHED:
505                 case FIN_WAIT_1:
506                 case FIN_WAIT_2:
507                 case CLOSE_WAIT:
508                         if(hdr.ctl & ACK)
509                                 return 0;
510                         // The peer has aborted our connection.
511                         set_state(c, CLOSED);
512                         errno = ECONNRESET;
513                         if(c->recv)
514                                 c->recv(c, NULL, 0);
515                         return 0;
516                 case CLOSING:
517                 case LAST_ACK:
518                 case TIME_WAIT:
519                         if(hdr.ctl & ACK)
520                                 return 0;
521                         // As far as the application is concerned, the connection has already been closed.
522                         // If it has called utcp_close() already, we can immediately free this connection.
523                         if(c->reapable) {
524                                 free_connection(c);
525                                 return 0;
526                         }
527                         // Otherwise, immediately move to the CLOSED state.
528                         set_state(c, CLOSED);
529                         return 0;
530                 default:
531                         abort();
532                 }
533         }
534
535         // 3. Advance snd.una
536
537         uint32_t advanced = seqdiff(hdr.ack, c->snd.una);
538         c->snd.una = hdr.ack;
539
540         if(advanced) {
541                 fprintf(stderr, "%p advanced %u\n", utcp, advanced);
542                 // Make room in the send buffer.
543                 // TODO: try to avoid memmoving too much. Circular buffer?
544                 uint32_t left = seqdiff(c->snd.nxt, hdr.ack);
545                 if(left)
546                         memmove(c->sndbuf, c->sndbuf + advanced, left);
547         }
548
549         // 4. Update timers
550
551         if(advanced) {
552                 timerclear(&c->conn_timeout); // It should be set anew in utcp_timeout() if c->snd.una != c->snd.nxt.
553                 if(c->snd.una == c->snd.nxt)
554                         timerclear(&c->rtrx_timeout);
555         }
556
557         // 5. Process SYN stuff
558
559         if(hdr.ctl & SYN) {
560                 switch(c->state) {
561                 case SYN_SENT:
562                         // This is a SYNACK. It should always have ACKed the SYN.
563                         if(!advanced)
564                                 goto reset;
565                         c->rcv.irs = hdr.seq;
566                         c->rcv.nxt = hdr.seq;
567                         set_state(c, ESTABLISHED);
568                         // TODO: notify application of this somehow.
569                         break;
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                         // Ehm, no. We should never receive a second SYN.
579                         goto reset;
580                 default:
581                         abort();
582                 }
583
584                 // SYN counts as one sequence number
585                 c->rcv.nxt++;
586         }
587
588         // 6. Process new data
589
590         if(c->state == SYN_RECEIVED) {
591                 // This is the ACK after the SYNACK. It should always have ACKed the SYNACK.
592                 if(!advanced)
593                         goto reset;
594
595                 // Are we still LISTENing?
596                 if(utcp->accept)
597                         utcp->accept(c, c->src);
598
599                 if(c->state != ESTABLISHED) {
600                         set_state(c, CLOSED);
601                         c->reapable = true;
602                         goto reset;
603                 }
604         }
605
606         if(len) {
607                 switch(c->state) {
608                 case SYN_SENT:
609                 case SYN_RECEIVED:
610                         // This should never happen.
611                         abort();
612                 case ESTABLISHED:
613                 case FIN_WAIT_1:
614                 case FIN_WAIT_2:
615                         break;
616                 case CLOSE_WAIT:
617                 case CLOSING:
618                 case LAST_ACK:
619                 case TIME_WAIT:
620                         // Ehm no, We should never receive more data after a FIN.
621                         goto reset;
622                 default:
623                         abort();
624                 }
625
626                 int rxd;
627
628                 if(c->recv) {
629                         rxd = c->recv(c, data, len);
630                         if(rxd < 0)
631                                 rxd = 0;
632                         else if(rxd > len)
633                                 rxd = len; // Bad application, bad!
634                 } else {
635                         rxd = len;
636                 }
637
638                 c->rcv.nxt += len;
639         }
640
641         // 7. Process FIN stuff
642
643         if(hdr.ctl & FIN) {
644                 switch(c->state) {
645                 case SYN_SENT:
646                 case SYN_RECEIVED:
647                         // This should never happen.
648                         abort();
649                 case ESTABLISHED:
650                         set_state(c, CLOSE_WAIT);
651                         break;
652                 case FIN_WAIT_1:
653                         set_state(c, CLOSING);
654                         break;
655                 case FIN_WAIT_2:
656                         set_state(c, TIME_WAIT);
657                         break;
658                 case CLOSE_WAIT:
659                 case CLOSING:
660                 case LAST_ACK:
661                 case TIME_WAIT:
662                         // Ehm, no. We should never receive a second FIN.
663                         goto reset;
664                 default:
665                         abort();
666                 }
667
668                 // FIN counts as one sequence number
669                 c->rcv.nxt++;
670
671                 // Inform the application that the peer closed the connection.
672                 if(c->recv) {
673                         errno = 0;
674                         c->recv(c, NULL, 0);
675                 }
676         }
677
678         if(!len && !advanced)
679                 return 0;
680
681         if(!len && !(hdr.ctl & SYN) && !(hdr.ctl & FIN))
682                 return 0;
683
684 ack:
685         hdr.src = c->src;
686         hdr.dst = c->dst;
687         hdr.seq = c->snd.nxt;
688         hdr.ack = c->rcv.nxt;
689         hdr.ctl = ACK;
690         print_packet(c->utcp, "send", &hdr, sizeof hdr);
691         utcp->send(utcp, &hdr, sizeof hdr);
692         return 0;
693
694 reset:
695         swap_ports(&hdr);
696         hdr.wnd = 0;
697         if(hdr.ctl & ACK) {
698                 hdr.seq = hdr.ack;
699                 hdr.ctl = RST;
700         } else {
701                 hdr.ack = hdr.seq + len;
702                 hdr.seq = 0;
703                 hdr.ctl = RST | ACK;
704         }
705         print_packet(utcp, "send", &hdr, sizeof hdr);
706         utcp->send(utcp, &hdr, sizeof hdr);
707         return 0;
708
709 }
710
711 int utcp_shutdown(struct utcp_connection *c, int dir) {
712         fprintf(stderr, "%p shutdown %d\n", c->utcp, dir);
713         if(!c) {
714                 errno = EFAULT;
715                 return -1;
716         }
717
718         if(c->reapable) {
719                 fprintf(stderr, "Error: shutdown() called on closed connection %p\n", c);
720                 errno = EBADF;
721                 return -1;
722         }
723
724         // TODO: handle dir
725
726         switch(c->state) {
727         case CLOSED:
728                 return 0;
729         case LISTEN:
730         case SYN_SENT:
731                 set_state(c, CLOSED);
732                 return 0;
733
734         case SYN_RECEIVED:
735         case ESTABLISHED:
736                 set_state(c, FIN_WAIT_1);
737                 break;
738         case FIN_WAIT_1:
739         case FIN_WAIT_2:
740                 return 0;
741         case CLOSE_WAIT:
742                 set_state(c, CLOSING);
743                 break;
744
745         case CLOSING:
746         case LAST_ACK:
747         case TIME_WAIT:
748                 return 0;
749         }
750
751         // Send FIN
752
753         struct hdr hdr;
754
755         hdr.src = c->src;
756         hdr.dst = c->dst;
757         hdr.seq = c->snd.nxt;
758         hdr.ack = c->rcv.nxt;
759         hdr.wnd = c->snd.wnd;
760         hdr.ctl = FIN | ACK;
761
762         c->snd.nxt += 1;
763
764         print_packet(c->utcp, "send", &hdr, sizeof hdr);
765         c->utcp->send(c->utcp, &hdr, sizeof hdr);
766         return 0;
767 }
768
769 int utcp_close(struct utcp_connection *c) {
770         if(utcp_shutdown(c, SHUT_RDWR))
771                 return -1;
772         c->reapable = true;
773         return 0;
774 }
775
776 int utcp_abort(struct utcp_connection *c) {
777         if(!c) {
778                 errno = EFAULT;
779                 return -1;
780         }
781
782         if(c->reapable) {
783                 fprintf(stderr, "Error: abort() called on closed connection %p\n", c);
784                 errno = EBADF;
785                 return -1;
786         }
787
788         c->reapable = true;
789
790         switch(c->state) {
791         case CLOSED:
792                 return 0;
793         case LISTEN:
794         case SYN_SENT:
795         case CLOSING:
796         case LAST_ACK:
797         case TIME_WAIT:
798                 set_state(c, CLOSED);
799                 return 0;
800
801         case SYN_RECEIVED:
802         case ESTABLISHED:
803         case FIN_WAIT_1:
804         case FIN_WAIT_2:
805         case CLOSE_WAIT:
806                 set_state(c, CLOSED);
807                 break;
808         }
809
810         // Send RST
811
812         struct hdr hdr;
813
814         hdr.src = c->src;
815         hdr.dst = c->dst;
816         hdr.seq = c->snd.nxt;
817         hdr.ack = 0;
818         hdr.wnd = 0;
819         hdr.ctl = RST;
820
821         print_packet(c->utcp, "send", &hdr, sizeof hdr);
822         c->utcp->send(c->utcp, &hdr, sizeof hdr);
823         return 0;
824 }
825
826 static void retransmit(struct utcp_connection *c) {
827         if(c->state == CLOSED || c->snd.nxt == c->snd.una)
828                 return;
829
830         struct utcp *utcp = c->utcp;
831
832         struct {
833                 struct hdr hdr;
834                 char data[c->utcp->mtu];
835         } pkt;
836
837         pkt.hdr.src = c->src;
838         pkt.hdr.dst = c->dst;
839
840         switch(c->state) {
841                 case LISTEN:
842                         // TODO: this should not happen
843                         break;
844
845                 case SYN_SENT:
846                         pkt.hdr.seq = c->snd.iss;
847                         pkt.hdr.ack = 0;
848                         pkt.hdr.wnd = c->rcv.wnd;
849                         pkt.hdr.ctl = SYN;
850                         print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr);
851                         utcp->send(utcp, &pkt, sizeof pkt.hdr);
852                         break;
853
854                 case SYN_RECEIVED:
855                         pkt.hdr.seq = c->snd.nxt;
856                         pkt.hdr.ack = c->rcv.nxt;
857                         pkt.hdr.ctl = SYN | ACK;
858                         print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr);
859                         utcp->send(utcp, &pkt, sizeof pkt.hdr);
860                         break;
861
862                 case ESTABLISHED:
863                 case FIN_WAIT_1:
864                         pkt.hdr.seq = c->snd.una;
865                         pkt.hdr.ack = c->rcv.nxt;
866                         pkt.hdr.ctl = ACK;
867                         uint32_t len = seqdiff(c->snd.nxt, c->snd.una);
868                         if(c->state == FIN_WAIT_1)
869                                 len--;
870                         if(len > utcp->mtu)
871                                 len = utcp->mtu;
872                         else {
873                                 if(c->state == FIN_WAIT_1)
874                                         pkt.hdr.ctl |= FIN;
875                         }
876                         memcpy(pkt.data, c->sndbuf, len);
877                         print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr + 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 void utcp_set_mtu(struct utcp *utcp, uint16_t mtu) {
974         // TODO: handle overhead of the header
975         utcp->mtu = mtu;
976 }
977
978 int utcp_set_connection_timeout(struct utcp *u, int timeout) {
979         int prev = u->timeout;
980         u->timeout = timeout;
981         return prev;
982 }