From a18da7ad8a0d9f28dabf97d15407ece748538888 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 13 Aug 2019 21:03:42 +0200 Subject: [PATCH] Allow the channel send and receive buffer size to be changed. This also adds a test to see if this works in combination with MESHLINK_CHANNEL_NO_PARTIAL. --- src/meshlink++.h | 24 +++++++++++++ src/meshlink.c | 26 ++++++++++++++ src/meshlink.h | 22 ++++++++++++ src/meshlink.sym | 2 ++ src/utcp | 2 +- test/Makefile.am | 9 +++-- test/channels-no-partial.c | 67 +++++++++++++++++++++++++++++++++++ test/channels-no-partial.test | 4 +++ 8 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 test/channels-no-partial.c create mode 100755 test/channels-no-partial.test diff --git a/src/meshlink++.h b/src/meshlink++.h index 3666f67d..dee2c706 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -650,6 +650,30 @@ public: meshlink_set_channel_poll_cb(handle, channel, (meshlink_channel_poll_cb_t)cb); } + /// Set the send buffer size of a channel. + /** This function sets the desired size of the send buffer. + * The default size is 128 kB. + * + * @param channel A handle for the channel. + * @param size The desired size for the send buffer. + * If a NULL pointer is given, the callback will be disabled. + */ + void set_channel_sndbuf(channel *channel, size_t size) { + meshlink_set_channel_sndbuf(handle, channel, size); + } + + /// Set the receive buffer size of a channel. + /** This function sets the desired size of the receive buffer. + * The default size is 128 kB. + * + * @param channel A handle for the channel. + * @param size The desired size for the send buffer. + * If a NULL pointer is given, the callback will be disabled. + */ + void set_channel_rcvbuf(channel *channel, size_t size) { + meshlink_set_channel_rcvbuf(handle, channel, size); + } + /// Open a reliable stream channel to another node. /** This function is called whenever a remote node wants to open a channel to the local node. * The application then has to decide whether to accept or reject this channel. diff --git a/src/meshlink.c b/src/meshlink.c index 1b643503..1d33a589 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -2985,6 +2985,32 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac pthread_mutex_unlock(&mesh->mesh_mutex); } +void meshlink_set_channel_sndbuf(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t size) { + (void)mesh; + + if(!channel) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + + pthread_mutex_lock(&mesh->mesh_mutex); + utcp_set_sndbuf(channel->c, size); + pthread_mutex_unlock(&mesh->mesh_mutex); +} + +void meshlink_set_channel_rcvbuf(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t size) { + (void)mesh; + + if(!channel) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + + pthread_mutex_lock(&mesh->mesh_mutex); + utcp_set_rcvbuf(channel->c, size); + pthread_mutex_unlock(&mesh->mesh_mutex); +} + meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len, uint32_t flags) { if(data || len) { abort(); // TODO: handle non-NULL data diff --git a/src/meshlink.h b/src/meshlink.h index 31583e51..075d5f16 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -1035,6 +1035,28 @@ extern void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_ch */ extern void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_poll_cb_t cb); +/// Set the send buffer size of a channel. +/** This function sets the desired size of the send buffer. + * The default size is 128 kB. + * + * @param mesh A handle which represents an instance of MeshLink. + * @param channel A handle for the channel. + * @param size The desired size for the send buffer. + * If a NULL pointer is given, the callback will be disabled. + */ +extern void meshlink_set_channel_sndbuf(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t size); + +/// Set the receive buffer size of a channel. +/** This function sets the desired size of the receive buffer. + * The default size is 128 kB. + * + * @param mesh A handle which represents an instance of MeshLink. + * @param channel A handle for the channel. + * @param size The desired size for the send buffer. + * If a NULL pointer is given, the callback will be disabled. + */ +extern void meshlink_set_channel_rcvbuf(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t size); + /// Open a reliable stream channel to another node. /** This function is called whenever a remote node wants to open a channel to the local node. * The application then has to decide whether to accept or reject this channel. diff --git a/src/meshlink.sym b/src/meshlink.sym index 33cb5a1c..ed2168da 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -55,7 +55,9 @@ meshlink_send meshlink_set_canonical_address meshlink_set_channel_accept_cb meshlink_set_channel_poll_cb +meshlink_set_channel_rcvbuf meshlink_set_channel_receive_cb +meshlink_set_channel_sndbuf meshlink_set_connection_try_cb meshlink_set_default_blacklist meshlink_set_invitation_timeout diff --git a/src/utcp b/src/utcp index 3bc56405..d394c4f4 160000 --- a/src/utcp +++ b/src/utcp @@ -1 +1 @@ -Subproject commit 3bc564058072a79a22320f8c5bc50e8844896114 +Subproject commit d394c4f4f9b820cb1866046e21b834b67fd18ecb diff --git a/test/Makefile.am b/test/Makefile.am index a3d9e9f9..77cee74a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,9 +3,10 @@ TESTS = \ basicpp.test \ channels.test \ channels-aio.test \ + channels-cornercases.test \ channels-failure.test \ channels-fork.test \ - channels-cornercases.test \ + channels-no-partial.test \ duplicate.test \ encrypted.test \ ephemeral.test \ @@ -29,9 +30,10 @@ check_PROGRAMS = \ basicpp \ channels \ channels-aio \ + channels-cornercases \ channels-failure \ channels-fork \ - channels-cornercases \ + channels-no-partial \ duplicate \ echo-fork \ encrypted \ @@ -58,6 +60,9 @@ channels_LDADD = ../src/libmeshlink.la channels_aio_SOURCES = channels-aio.c utils.c utils.h channels_aio_LDADD = ../src/libmeshlink.la +channels_no_partial_SOURCES = channels-no-partial.c utils.c utils.h +channels_no_partial_LDADD = ../src/libmeshlink.la + channels_failure_SOURCES = channels-failure.c utils.c utils.h channels_failure_LDADD = ../src/libmeshlink.la diff --git a/test/channels-no-partial.c b/test/channels-no-partial.c new file mode 100644 index 00000000..caa308fb --- /dev/null +++ b/test/channels-no-partial.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include + +#include "meshlink.h" +#include "utils.h" + +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; +} + +int main(int argc, char *argv[]) { + (void)argc; + (void)argv; + + // Start two new meshlink instance. + + meshlink_handle_t *mesh_a; + meshlink_handle_t *mesh_b; + + open_meshlink_pair(&mesh_a, &mesh_b, "channels_no_partial"); + meshlink_set_channel_accept_cb(mesh_b, accept_cb); + start_meshlink_pair(mesh_a, mesh_b); + + // Open a channel + + meshlink_node_t *b = meshlink_get_node(mesh_a, "b"); + assert(b); + + meshlink_channel_t *channel = meshlink_channel_open_ex(mesh_a, b, 1, NULL, NULL, 0, MESHLINK_CHANNEL_NO_PARTIAL); + assert(channel); + + // Verify that no partial sends succeed. + // If rejected sends would fit an empty send buffer, 0 should be returned, otherwise -1. + + char buf[256] = ""; + + meshlink_set_channel_sndbuf(mesh_a, channel, 256); + assert(meshlink_channel_send(mesh_a, channel, buf, 257) == -1); + assert(meshlink_channel_send(mesh_a, channel, buf, 256) == 256); + + meshlink_set_channel_sndbuf(mesh_a, channel, 512); + assert(meshlink_channel_send(mesh_a, channel, buf, 257) == 0); + assert(meshlink_channel_send(mesh_a, channel, buf, 128) == 128); + assert(meshlink_channel_send(mesh_a, channel, buf, 129) == 0); + assert(meshlink_channel_send(mesh_a, channel, buf, 100) == 100); + assert(meshlink_channel_send(mesh_a, channel, buf, 29) == 0); + assert(meshlink_channel_send(mesh_a, channel, buf, 513) == -1); + + assert_after(!meshlink_channel_get_sendq(mesh_a, channel), 30); + assert(meshlink_channel_send(mesh_a, channel, buf, 512) == 512); + + // Clean up. + + close_meshlink_pair(mesh_a, mesh_b, "channels_no_partial"); + + return 0; +} diff --git a/test/channels-no-partial.test b/test/channels-no-partial.test new file mode 100755 index 00000000..b70252d7 --- /dev/null +++ b/test/channels-no-partial.test @@ -0,0 +1,4 @@ +#!/bin/sh + +rm -Rf channels_no_partial_conf.* +./channels-no-partial -- 2.39.2