From: Guus Sliepen Date: Thu, 28 May 2020 19:02:32 +0000 (+0200) Subject: Wake up the MeshLink thread if framed channel data is pending to be flushed. X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=refs%2Fheads%2Ffeature%2Fchannel-message-framing;p=meshlink Wake up the MeshLink thread if framed channel data is pending to be flushed. 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. --- diff --git a/src/meshlink.c b/src/meshlink.c index 89680ef7..b309d219 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -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; } diff --git a/src/utcp.c b/src/utcp.c index 00e02f6e..d6b0a590 100644 --- a/src/utcp.c +++ b/src/utcp.c @@ -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; +} diff --git a/src/utcp.h b/src/utcp.h index 60ecdd34..c5481499 100644 --- a/src/utcp.h +++ b/src/utcp.h @@ -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); diff --git a/src/utcp_priv.h b/src/utcp_priv.h index 8713d2d4..8702e30f 100644 --- a/src/utcp_priv.h +++ b/src/utcp_priv.h @@ -109,6 +109,7 @@ struct utcp_connection { bool reapable; bool do_poll; + bool flush_needed; // Callbacks