]> git.meshlink.io Git - utcp/blobdiff - utcp.c
Add fin_wanted() function that checks whether a FIN bit should be set on a packet.
[utcp] / utcp.c
diff --git a/utcp.c b/utcp.c
index 1d8f4b2a9e3a7865e8813d9032d6510b51cb3a8c..f062319fa33a1daa665faaa96f3c567eb488f245 100644 (file)
--- a/utcp.c
+++ b/utcp.c
@@ -103,6 +103,19 @@ static void set_state(struct utcp_connection *c, enum state state) {
        debug("%p new state: %s\n", c->utcp, strstate[state]);
 }
 
+static bool fin_wanted(struct utcp_connection *c, uint32_t seq) {
+       if(seq != c->snd.last)
+               return false;
+       switch(c->state) {
+       case FIN_WAIT_1:
+       case CLOSING:
+       case LAST_ACK:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static inline void list_connections(struct utcp *utcp) {
        debug("%p has %d connections:\n", utcp, utcp->nconnections);
        for(int i = 0; i < utcp->nconnections; i++)
@@ -366,16 +379,9 @@ static void ack(struct utcp_connection *c, bool sendatleastone) {
                c->snd.nxt += seglen;
                left -= seglen;
 
-               if(c->state != ESTABLISHED && seglen && c->snd.nxt == c->snd.last) {
-                       switch(c->state) {
-                       case FIN_WAIT_1:
-                       case CLOSING:
-                               seglen--;
-                               pkt->hdr.ctl |= FIN;
-                               break;
-                       default:
-                               break;
-                       }
+               if(seglen && fin_wanted(c, c->snd.nxt)) {
+                       seglen--;
+                       pkt->hdr.ctl |= FIN;
                }
 
                print_packet(c->utcp, "send", pkt, sizeof pkt->hdr + seglen);
@@ -501,7 +507,10 @@ static void retransmit(struct utcp_connection *c) {
 
                default:
                        // TODO: implement
+#ifdef UTCP_DEBUG
                        abort();
+#endif
+                       break;
        }
 
        free(pkt);
@@ -623,7 +632,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
        case TIME_WAIT:
                break;
        default:
+#ifdef UTCP_DEBUG
                abort();
+#endif
+               break;
        }
 
        // 1b. Drop packets with a sequence number not in our receive window.
@@ -723,7 +735,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                        set_state(c, CLOSED);
                        return 0;
                default:
+#ifdef UTCP_DEBUG
                        abort();
+#endif
+                       break;
                }
        }
 
@@ -822,7 +837,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                        // Ehm, no. We should never receive a second SYN.
                        goto reset;
                default:
+#ifdef UTCP_DEBUG
                        abort();
+#endif
+                       return 0;
                }
 
                // SYN counts as one sequence number
@@ -852,7 +870,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                case SYN_SENT:
                case SYN_RECEIVED:
                        // This should never happen.
+#ifdef UTCP_DEBUG
                        abort();
+#endif
+                       return 0;
                case ESTABLISHED:
                case FIN_WAIT_1:
                case FIN_WAIT_2:
@@ -864,7 +885,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                        // Ehm no, We should never receive more data after a FIN.
                        goto reset;
                default:
+#ifdef UTCP_DEBUG
                        abort();
+#endif
+                       return 0;
                }
 
                ssize_t rxd;
@@ -893,7 +917,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                case SYN_SENT:
                case SYN_RECEIVED:
                        // This should never happen.
+#ifdef UTCP_DEBUG
                        abort();
+#endif
+                       break;
                case ESTABLISHED:
                        set_state(c, CLOSE_WAIT);
                        break;
@@ -912,7 +939,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) {
                        // Ehm, no. We should never receive a second FIN.
                        goto reset;
                default:
+#ifdef UTCP_DEBUG
                        abort();
+#endif
+                       break;
                }
 
                // FIN counts as one sequence number
@@ -1154,63 +1184,71 @@ void utcp_exit(struct utcp *utcp) {
 }
 
 uint16_t utcp_get_mtu(struct utcp *utcp) {
-       return utcp->mtu;
+       return utcp ? utcp->mtu : 0;
 }
 
 void utcp_set_mtu(struct utcp *utcp, uint16_t mtu) {
        // TODO: handle overhead of the header
-       utcp->mtu = mtu;
+       if(utcp)
+               utcp->mtu = mtu;
 }
 
 int utcp_get_user_timeout(struct utcp *u) {
-       return u->timeout;
+       return u ? u->timeout : 0;
 }
 
 void utcp_set_user_timeout(struct utcp *u, int timeout) {
-       u->timeout = timeout;
+       if(u)
+               u->timeout = timeout;
 }
 
 size_t utcp_get_sndbuf(struct utcp_connection *c) {
-       return c->sndbuf.maxsize;
+       return c ? c->sndbuf.maxsize : 0;
 }
 
 size_t utcp_get_sndbuf_free(struct utcp_connection *c) {
-       if(c->state == ESTABLISHED || c->state == CLOSE_WAIT)
+       if(c && (c->state == ESTABLISHED || c->state == CLOSE_WAIT))
                return buffer_free(&c->sndbuf);
        else
                return 0;
 }
 
 void utcp_set_sndbuf(struct utcp_connection *c, size_t size) {
+       if(!c)
+               return;
        c->sndbuf.maxsize = size;
        if(c->sndbuf.maxsize != size)
                c->sndbuf.maxsize = -1;
 }
 
 bool utcp_get_nodelay(struct utcp_connection *c) {
-       return c->nodelay;
+       return c ? c->nodelay : false;
 }
 
 void utcp_set_nodelay(struct utcp_connection *c, bool nodelay) {
-       c->nodelay = nodelay;
+       if(c)
+               c->nodelay = nodelay;
 }
 
 bool utcp_get_keepalive(struct utcp_connection *c) {
-       return c->keepalive;
+       return c ? c->keepalive : false;
 }
 
 void utcp_set_keepalive(struct utcp_connection *c, bool keepalive) {
-       c->keepalive = keepalive;
+       if(c)
+               c->keepalive = keepalive;
 }
 
 size_t utcp_get_outq(struct utcp_connection *c) {
-       return seqdiff(c->snd.nxt, c->snd.una);
+       return c ? seqdiff(c->snd.nxt, c->snd.una) : 0;
 }
 
 void utcp_set_recv_cb(struct utcp_connection *c, utcp_recv_t recv) {
-       c->recv = recv;
+       if(c)
+               c->recv = recv;
 }
 
 void utcp_set_poll_cb(struct utcp_connection *c, utcp_poll_t poll) {
-       c->poll = poll;
+       if(c)
+               c->poll = poll;
 }