]> git.meshlink.io Git - meshlink/blobdiff - src/utcp.c
Fix reception of a trailing, zero-length frame.
[meshlink] / src / utcp.c
index 2a1ac5b86f370ec319b833445a24c918f3bc4402..00e02f6eb7244578d8a9d5c04b342ede293e3913 100644 (file)
@@ -677,6 +677,7 @@ void utcp_accept(struct utcp_connection *c, utcp_recv_t recv, void *priv) {
        debug(c, "accepted %p %p\n", c, recv, priv);
        c->recv = recv;
        c->priv = priv;
+       c->do_poll = true;
        set_state(c, ESTABLISHED);
 }
 
@@ -879,6 +880,9 @@ static void ack_unreliable_framed(struct utcp_connection *c) {
                        // There is no partial data in the send buffer, so stop the flush timer
                        stop_retransmit_timer(c);
                }
+       } else if(left && !timespec_isset(&c->rtrx_timeout)) {
+               // We have partial data and we didn't start the flush timer yet
+               start_flush_timer(c);
        }
 }
 
@@ -1440,11 +1444,11 @@ static void handle_unreliable_framed(struct utcp_connection *c, const struct hdr
        buffer_clear(&c->rcvbuf);
 
        // Handle whole frames
-       while(left > 2) {
+       while(left >= 2) {
                uint16_t framelen;
                memcpy(&framelen, ptr, sizeof(framelen));
 
-               if(left <= (size_t)framelen + 2) {
+               if(left < (size_t)framelen + 2) {
                        break;
                }
 
@@ -2025,6 +2029,7 @@ skip_ack:
                                c->snd.last++;
                                set_state(c, FIN_WAIT_1);
                        } else {
+                               c->do_poll = true;
                                set_state(c, ESTABLISHED);
                        }
 
@@ -2431,7 +2436,7 @@ struct timespec utcp_timeout(struct utcp *utcp) {
                if(c->poll) {
                        if((c->state == ESTABLISHED || c->state == CLOSE_WAIT) && c->do_poll) {
                                c->do_poll = false;
-                               uint32_t len = buffer_free(&c->sndbuf);
+                               uint32_t len = is_framed(c) ? min(buffer_free(&c->sndbuf), MAX_UNRELIABLE_SIZE) : buffer_free(&c->sndbuf);
 
                                if(len) {
                                        c->poll(c, len);