]> git.meshlink.io Git - meshlink/blobdiff - test/channels-udp.c
Never automatically try to bind to ports >= 32768.
[meshlink] / test / channels-udp.c
index 8b9e163fe2ab7ddf016e75e613a312c8b1bb9115..6b71ebdde8e923450bf84a0bfbe92c5f77ecce38 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
 #include <assert.h>
 #include <stdio.h>
 #include <unistd.h>
 #include "../src/meshlink.h"
 #include "utils.h"
 
+#define SMALL_SIZE 512
+#define SMALL_COUNT 2500
+#define LARGE_SIZE 131072
+
 static struct sync_flag accept_flag;
-static struct sync_flag close_flag;
 
 struct client {
        meshlink_handle_t *mesh;
        meshlink_channel_t *channel;
        size_t received;
+       bool got_large_packet;
+       struct sync_flag close_flag;
 };
 
-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 void server_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
-       (void)data;
-
-       // We expect no data from clients, apart from disconnections.
-       assert(len == 0);
-
-       meshlink_channel_t **c = mesh->priv;
-       int count = 0;
-
-       for(int i = 0; i < 3; i++) {
-               if(c[i] == channel) {
-                       c[i] = NULL;
-                       fprintf(stderr, "server received channel %d closure from %s\n", i, channel->node->name);
-
-                       meshlink_channel_close(mesh, channel);
-               }
-
-               if(c[i]) {
-                       count++;
-               }
-       }
+static void client_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+       assert(mesh->priv);
+       struct client *client = mesh->priv;
 
-       if(!count) {
-               set_sync_flag(&close_flag, true);
+       if(!data && !len) {
+               set_sync_flag(&client->close_flag, true);
+               meshlink_channel_close(mesh, channel);
+               return;
        }
-}
-
-static void client_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
-       (void)channel;
-       (void)data;
 
        // We expect always the same amount of data from the server.
-       assert(len == 1000);
-       assert(mesh->priv);
-       struct client *client = mesh->priv;
+       assert(len == 512 || len == LARGE_SIZE);
        client->received += len;
+
+       if(len == LARGE_SIZE) {
+               client->got_large_packet = true;
+       }
 }
 
 static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
        assert(mesh->priv);
        struct client *client = mesh->priv;
 
-       assert(reachable);
-
-       if(!strcmp(node->name, "server")) {
+       if(reachable && !strcmp(node->name, "server")) {
                assert(!client->channel);
                client->channel = meshlink_channel_open_ex(mesh, node, 1, client_receive_cb, NULL, 0, MESHLINK_CHANNEL_UDP);
                assert(client->channel);
@@ -93,14 +63,12 @@ static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint
 
        assert(port == 1);
        assert(meshlink_channel_get_flags(mesh, channel) == MESHLINK_CHANNEL_UDP);
-       meshlink_set_channel_receive_cb(mesh, channel, server_receive_cb);
 
        assert(mesh->priv);
        meshlink_channel_t **c = mesh->priv;
 
        for(int i = 0; i < 3; i++) {
                if(c[i] == NULL) {
-                       fprintf(stderr, "server accepted channel %d from %s\n", i, channel->node->name);
                        c[i] = channel;
 
                        if(i == 2) {
@@ -114,16 +82,19 @@ static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint
        return false;
 }
 
-int main() {
-       //meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+int main(void) {
+       init_sync_flag(&accept_flag);
 
-       // Open two new meshlink instance.
+       meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb);
+
+       // Open four new meshlink instance, the server and three peers.
 
        const char *names[3] = {"foo", "bar", "baz"};
        struct client clients[3];
        meshlink_channel_t *channels[3] = {NULL, NULL, NULL};
        memset(clients, 0, sizeof(clients));
 
+       assert(meshlink_destroy("channels_udp_conf.0"));
        meshlink_handle_t *server = meshlink_open("channels_udp_conf.0", "server", "channels-udp", DEV_CLASS_BACKBONE);
        assert(server);
        meshlink_enable_discovery(server, false);
@@ -134,6 +105,8 @@ int main() {
        for(int i = 0; i < 3; i++) {
                char dir[100];
                snprintf(dir, sizeof(dir), "channels_udp_conf.%d", i + 1);
+               assert(meshlink_destroy(dir));
+               init_sync_flag(&clients[i].close_flag);
                clients[i].mesh = meshlink_open(dir, names[i], "channels-udp", DEV_CLASS_STATIONARY);
                assert(clients[i].mesh);
                clients[i].mesh->priv = &clients[i];
@@ -152,27 +125,43 @@ int main() {
                assert(clients[i].channel);
        }
 
+       // Check that we can send up to 65535 bytes without errors
+
+       char large_data[LARGE_SIZE] = "";
+
+       for(int i = 0; i < 3; i++) {
+               assert(meshlink_channel_send(server, channels[i], large_data, sizeof(large_data)) == sizeof(large_data));
+       }
+
+       // Assert that packets larger than 16 MiB are not allowed
+
+       assert(meshlink_channel_send(server, channels[0], large_data, 16777216) == -1);
+
        // Stream packets from server to clients for 5 seconds at 40 Mbps (1 kB * 500 Hz)
 
-       char data[1000];
+       char data[SMALL_SIZE];
+       memset(data, 'U', sizeof(data));
+
+       for(int j = 0; j < SMALL_COUNT; j++) {
+               const struct timespec req = {0, 2000000};
+               nanosleep(&req, NULL);
 
-       for(int j = 0; j < 2500; j++) {
                for(int i = 0; i < 3; i++) {
                        assert(meshlink_channel_send(server, channels[i], data, sizeof(data)) == sizeof(data));
                }
-
-               const struct timespec req = {0, 2000000};
-               clock_nanosleep(CLOCK_MONOTONIC, 0, &req, NULL);
        }
 
-       // Let the clients close the channels
+       // Shutdown the write side of the server's channels
 
        for(int i = 0; i < 3; i++) {
-               meshlink_channel_close(clients[i].mesh, clients[i].channel);
-               meshlink_set_node_status_cb(clients[i].mesh, NULL);
+               meshlink_channel_shutdown(server, channels[i], SHUT_WR);
        }
 
-       assert(wait_sync_flag(&close_flag, 10));
+       // Wait for the clients to finish reading all the data
+
+       for(int i = 0; i < 3; i++) {
+               assert(wait_sync_flag(&clients[i].close_flag, 10));
+       }
 
        // Check that the clients have received (most of) the data
 
@@ -181,8 +170,10 @@ int main() {
        }
 
        for(int i = 0; i < 3; i++) {
-               assert(clients[i].received >= 2400000);
-               assert(clients[i].received <= 2500000);
+               size_t max_received = SMALL_SIZE * SMALL_COUNT + LARGE_SIZE;
+               assert(clients[i].received >= max_received / 2);
+               assert(clients[i].received <= max_received);
+               assert(clients[i].got_large_packet);
        }
 
        // Clean up.