From: Guus Sliepen Date: Sun, 7 Jul 2019 14:52:02 +0000 (+0200) Subject: Update UTCP to correctly handle timeouts sending data. X-Git-Url: http://git.meshlink.io/?p=meshlink;a=commitdiff_plain;h=269c5eaed0f3333f014e04835a304bdfa9275e53 Update UTCP to correctly handle timeouts sending data. Also add a test case that checks whether we get a callback when sent data is not acked in a reasonable amount of time. --- diff --git a/src/utcp b/src/utcp index cb9223d3..6ef1b39d 160000 --- a/src/utcp +++ b/src/utcp @@ -1 +1 @@ -Subproject commit cb9223d3b895f1edb35bf7a6fd3aa9305de3f1db +Subproject commit 6ef1b39de8c0b0537da02b212acaba3242afe142 diff --git a/test/Makefile.am b/test/Makefile.am index edeb1a55..80d404e8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -2,6 +2,7 @@ TESTS = \ basic.test \ basicpp.test \ channels.test \ + channels-failure.test \ channels-fork.test \ channels-cornercases.test \ duplicate.test \ @@ -26,6 +27,7 @@ check_PROGRAMS = \ basic \ basicpp \ channels \ + channels-failure \ channels-fork \ channels-cornercases \ duplicate \ @@ -51,6 +53,9 @@ basicpp_LDADD = ../src/libmeshlink.la channels_SOURCES = channels.c channels_LDADD = ../src/libmeshlink.la +channels_failure_SOURCES = channels-failure.c utils.c utils.h +channels_failure_LDADD = ../src/libmeshlink.la + channels_fork_SOURCES = channels-fork.c channels_fork_LDADD = ../src/libmeshlink.la diff --git a/test/channels-failure.c b/test/channels-failure.c new file mode 100644 index 00000000..db888961 --- /dev/null +++ b/test/channels-failure.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include + +#include "../src/meshlink.h" +#include "utils.h" + +static void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) { + static struct timeval tv0; + struct timeval tv; + + if(tv0.tv_sec == 0) { + gettimeofday(&tv0, NULL); + } + + gettimeofday(&tv, NULL); + fprintf(stderr, "%u.%.03u ", (unsigned int)(tv.tv_sec - tv0.tv_sec), (unsigned int)tv.tv_usec / 1000); + + if(mesh) { + fprintf(stderr, "(%s) ", mesh->name); + } + + fprintf(stderr, "[%d] %s\n", level, text); +} + +static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) { + (void)mesh; + (void)channel; + (void)port; + (void)data; + (void)len; + + return true; +} + +static struct sync_flag poll_flag; +static size_t poll_len; + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + meshlink_set_channel_poll_cb(mesh, channel, NULL); + poll_len = len; + set_sync_flag(&poll_flag, true); +} + +static struct sync_flag receive_flag; +static size_t receive_len; + +static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) { + (void)mesh; + (void)channel; + (void)data; + + receive_len = len; + set_sync_flag(&receive_flag, true); +} + +int main() { + meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb); + + // Open three meshlink instances. + + meshlink_handle_t *mesh1 = meshlink_open("channels_failure_conf.1", "foo", "channels", DEV_CLASS_BACKBONE); + meshlink_handle_t *mesh2 = meshlink_open("channels_failure_conf.2", "bar", "channels", DEV_CLASS_BACKBONE); + + assert(mesh1); + assert(mesh2); + + meshlink_enable_discovery(mesh1, false); + meshlink_enable_discovery(mesh2, false); + + meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, log_cb); + meshlink_set_log_cb(mesh2, MESHLINK_DEBUG, log_cb); + + // Import and export both side's data + + meshlink_add_address(mesh1, "localhost"); + meshlink_add_address(mesh2, "localhost"); + + char *data1 = meshlink_export(mesh1); + char *data2 = meshlink_export(mesh2); + + assert(data1); + assert(data2); + + assert(meshlink_import(mesh1, data2)); + assert(meshlink_import(mesh2, data1)); + + free(data1); + free(data2); + + // Set the callbacks. + + meshlink_set_channel_accept_cb(mesh2, accept_cb); + + // Open a channel from foo to bar + + meshlink_node_t *bar = meshlink_get_node(mesh1, "bar"); + assert(bar); + + meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, receive_cb, NULL, 0); + assert(channel); + + meshlink_set_channel_poll_cb(mesh1, channel, poll_cb); + + // Start both instances + + assert(meshlink_start(mesh1)); + assert(meshlink_start(mesh2)); + + // Wait for the channel to be established + + assert(wait_sync_flag(&poll_flag, 10)); + assert(poll_len != 0); + + sleep(1); + + // Stop mesh2, then try to send data to it. We should get a notification that the channel has closed after a while. + + assert(!check_sync_flag(&receive_flag)); + + meshlink_stop(mesh2); + + assert(meshlink_channel_send(mesh1, channel, "hello", 5) == 5); + + assert(wait_sync_flag(&receive_flag, 70)); + assert(receive_len == 0); + + meshlink_channel_close(mesh1, channel); + + // Try setting up a new channel while bar is still down. + + poll_flag.flag = false; + receive_flag.flag = false; + + channel = meshlink_channel_open(mesh1, bar, 7, NULL, NULL, 0); + assert(channel); + + meshlink_set_channel_poll_cb(mesh1, channel, poll_cb); + + assert(wait_sync_flag(&poll_flag, 70)); + assert(poll_len == 0); + + // Clean up. + + meshlink_close(mesh1); + meshlink_close(mesh2); + + return 0; +} diff --git a/test/channels-failure.test b/test/channels-failure.test new file mode 100755 index 00000000..7a01fa1b --- /dev/null +++ b/test/channels-failure.test @@ -0,0 +1,4 @@ +#!/bin/sh + +rm -Rf channels_failure_conf.* +./channels-failure diff --git a/test/channels-fork.c b/test/channels-fork.c index ecbc9d58..cf916f09 100644 --- a/test/channels-fork.c +++ b/test/channels-fork.c @@ -79,7 +79,7 @@ int main1(int rfd, int wfd) { (void)ret_val; meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb); - meshlink_handle_t *mesh1 = meshlink_open("channels_conf.1", "foo", "channels", DEV_CLASS_BACKBONE); + meshlink_handle_t *mesh1 = meshlink_open("channels_fork_conf.1", "foo", "channels", DEV_CLASS_BACKBONE); if(!mesh1) { fprintf(stderr, "Could not initialize configuration for foo\n"); @@ -174,7 +174,7 @@ int main2(int rfd, int wfd) { meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb); - meshlink_handle_t *mesh2 = meshlink_open("channels_conf.2", "bar", "channels", DEV_CLASS_BACKBONE); + meshlink_handle_t *mesh2 = meshlink_open("channels_fork_conf.2", "bar", "channels", DEV_CLASS_BACKBONE); if(!mesh2) { fprintf(stderr, "Could not initialize configuration for bar\n");