]> git.meshlink.io Git - meshlink/commitdiff
Wake up the MeshLink thread if framed channel data is pending to be flushed. feature/channel-message-framing
authorGuus Sliepen <guus@meshlink.io>
Thu, 28 May 2020 19:02:32 +0000 (21:02 +0200)
committerGuus Sliepen <guus@meshlink.io>
Thu, 28 May 2020 19:02:32 +0000 (21:02 +0200)
When sending data on framed UDP channels, if there is a partial frame in
the send buffer waiting to be flushed after the flush timer expires, this
data was added by the application thread. The MeshLink thread does not know
that a timer was updated, and might use an old timeout value and not
respond in time. So if we detect that this might happen, we signal the
MeshLink thread so it can calculate a new timeout and call select() again.

src/meshlink.c
src/utcp.c
src/utcp.h
src/utcp_priv.h

index 89680ef79a9cedc3e1f5be062050d6b47f8bfd6c..b309d2190eb9b41e1c21d8976193468291cade50 100644 (file)
@@ -3933,6 +3933,10 @@ ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *chann
                meshlink_errno = MESHLINK_ENETWORK;
        }
 
+       if(utcp_get_flush_needed(channel->c)) {
+               signal_trigger(&mesh->loop, &mesh->datafromapp);
+       }
+
        return retval;
 }
 
index 00e02f6eb7244578d8a9d5c04b342ede293e3913..d6b0a590fed3670615a687ef9c01e44dab2454f1 100644 (file)
@@ -875,6 +875,10 @@ static void ack_unreliable_framed(struct utcp_connection *c) {
        if(sent_packet) {
                if(left) {
                        // We sent one packet but we have partial data left, (re)start the flush timer
+                       if(!timespec_isset(&c->rtrx_timeout)) {
+                               c->flush_needed = true;
+                       }
+
                        start_flush_timer(c);
                } else {
                        // There is no partial data in the send buffer, so stop the flush timer
@@ -882,6 +886,7 @@ static void ack_unreliable_framed(struct utcp_connection *c) {
                }
        } else if(left && !timespec_isset(&c->rtrx_timeout)) {
                // We have partial data and we didn't start the flush timer yet
+               c->flush_needed = true;
                start_flush_timer(c);
        }
 }
@@ -2790,3 +2795,9 @@ int utcp_get_flush_timeout(struct utcp *utcp) {
 void utcp_set_flush_timeout(struct utcp *utcp, int milliseconds) {
        utcp->flush_timeout = milliseconds;
 }
+
+bool utcp_get_flush_needed(struct utcp_connection *c) {
+       bool value = c->flush_needed;
+       c->flush_needed = false;
+       return value;
+}
index 60ecdd34d24e12418b8910ef0cd9faa62e6e7aec..c54814991ed23d7f43e44334c0691639447e5e79 100644 (file)
@@ -88,6 +88,7 @@ void utcp_set_user_timeout(struct utcp *utcp, int seconds);
 
 int utcp_get_flush_timeout(struct utcp *utcp);
 void utcp_set_flush_timeout(struct utcp *utcp, int milliseconds);
+bool utcp_get_flush_needed(struct utcp_connection *connection);
 
 uint16_t utcp_get_mtu(struct utcp *utcp);
 uint16_t utcp_get_mss(struct utcp *utcp);
index 8713d2d4e0554017b270338b406e502398a478e8..8702e30f8de37496f4f7b5714c2d6d5d857a7da2 100644 (file)
@@ -109,6 +109,7 @@ struct utcp_connection {
 
        bool reapable;
        bool do_poll;
+       bool flush_needed;
 
        // Callbacks