]> git.meshlink.io Git - meshlink/commitdiff
Allow the channel send and receive buffer size to be changed.
authorGuus Sliepen <guus@meshlink.io>
Tue, 13 Aug 2019 19:03:42 +0000 (21:03 +0200)
committerGuus Sliepen <guus@meshlink.io>
Tue, 13 Aug 2019 19:03:42 +0000 (21:03 +0200)
This also adds a test to see if this works in combination with
MESHLINK_CHANNEL_NO_PARTIAL.

src/meshlink++.h
src/meshlink.c
src/meshlink.h
src/meshlink.sym
src/utcp
test/Makefile.am
test/channels-no-partial.c [new file with mode: 0644]
test/channels-no-partial.test [new file with mode: 0755]

index 3666f67d827e789d724b431b4c76960ef24bda6a..dee2c7060d04bc352b59901f911fc7d8a78a7009 100644 (file)
@@ -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.
index 1b643503f6a9416d72528571697d93a0213e33dd..1d33a5897ad07155c8413794a7cbc3f77373d4c4 100644 (file)
@@ -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
index 31583e510050589506e493a6afff798aa3eda015..075d5f16fee33618fbfa130f3862841f826605fd 100644 (file)
@@ -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.
index 33cb5a1c96ef00862aa3ef208531669bf18186e4..ed2168da4e1a024ffb96f94e6b0dd8dead73c2cb 100644 (file)
@@ -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
index 3bc564058072a79a22320f8c5bc50e8844896114..d394c4f4f9b820cb1866046e21b834b67fd18ecb 160000 (submodule)
--- a/src/utcp
+++ b/src/utcp
@@ -1 +1 @@
-Subproject commit 3bc564058072a79a22320f8c5bc50e8844896114
+Subproject commit d394c4f4f9b820cb1866046e21b834b67fd18ecb
index a3d9e9f936d479f26e2fd66242dc70827f8df529..77cee74a7c72ef1261e784cd115b1c4c51de79cc 100644 (file)
@@ -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 (file)
index 0000000..caa308f
--- /dev/null
@@ -0,0 +1,67 @@
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#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 (executable)
index 0000000..b70252d
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+rm -Rf channels_no_partial_conf.*
+./channels-no-partial