-Subproject commit eb0a013a9b6c957aee0aecebc7d451dfd6851661
+Subproject commit 7baf55a28cf48163c007ee2ff56678371d78c990
TESTS = \
- basic.test \
- basicpp.test \
- channels.test \
- channels-aio.test \
- channels-aio-fd.test \
- channels-cornercases.test \
- channels-failure.test \
- channels-fork.test \
- channels-no-partial.test \
- channels-udp.test \
- duplicate.test \
- encrypted.test \
- ephemeral.test \
- import-export.test \
- invite-join.test \
- sign-verify.test \
- trio.test \
- trio2.test
+ basic \
+ basicpp \
+ channels \
+ channels-aio \
+ channels-aio-fd \
+ channels-cornercases \
+ channels-failure \
+ channels-fork \
+ channels-no-partial \
+ channels-udp \
+ duplicate \
+ encrypted \
+ ephemeral \
+ import-export \
+ invite-join \
+ sign-verify \
+ trio \
+ trio2
if BLACKBOX_TESTS
SUBDIRS = blackbox
bin_PROGRAMS = $(check_PROGRAMS)
endif
-basic_SOURCES = basic.c
+basic_SOURCES = basic.c utils.c utils.h
basic_LDADD = ../src/libmeshlink.la
-basicpp_SOURCES = basicpp.cpp
+basicpp_SOURCES = basicpp.cpp utils.c utils.h
basicpp_LDADD = ../src/libmeshlink.la
-channels_SOURCES = channels.c
+channels_SOURCES = channels.c utils.c utils.h
channels_LDADD = ../src/libmeshlink.la
channels_aio_SOURCES = channels-aio.c utils.c utils.h
channels_failure_SOURCES = channels-failure.c utils.c utils.h
channels_failure_LDADD = ../src/libmeshlink.la
-channels_fork_SOURCES = channels-fork.c
+channels_fork_SOURCES = channels-fork.c utils.c utils.h
channels_fork_LDADD = ../src/libmeshlink.la
channels_cornercases_SOURCES = channels-cornercases.c utils.c utils.h
channels_udp_SOURCES = channels-udp.c utils.c utils.h
channels_udp_LDADD = ../src/libmeshlink.la
-duplicate_SOURCES = duplicate.c
+duplicate_SOURCES = duplicate.c utils.c utils.h
duplicate_LDADD = ../src/libmeshlink.la
-echo_fork_SOURCES = echo-fork.c
+echo_fork_SOURCES = echo-fork.c utils.c utils.h
echo_fork_LDADD = ../src/libmeshlink.la
-encrypted_SOURCES = encrypted.c
+encrypted_SOURCES = encrypted.c utils.c utils.h
encrypted_LDADD = ../src/libmeshlink.la
-ephemeral_SOURCES = ephemeral.c
+ephemeral_SOURCES = ephemeral.c utils.c utils.h
ephemeral_LDADD = ../src/libmeshlink.la
-import_export_SOURCES = import-export.c
+import_export_SOURCES = import-export.c utils.c utils.h
import_export_LDADD = ../src/libmeshlink.la
-invite_join_SOURCES = invite-join.c
+invite_join_SOURCES = invite-join.c utils.c utils.h
invite_join_LDADD = ../src/libmeshlink.la
-sign_verify_SOURCES = sign-verify.c
+sign_verify_SOURCES = sign-verify.c utils.c utils.h
sign_verify_LDADD = ../src/libmeshlink.la
-trio_SOURCES = trio.c
+trio_SOURCES = trio.c utils.c utils.h
trio_LDADD = ../src/libmeshlink.la
-trio2_SOURCES = trio2.c
+trio2_SOURCES = trio2.c utils.c utils.h
trio2_LDADD = ../src/libmeshlink.la
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
+#include <assert.h>
#include "meshlink.h"
-
-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);
-}
+#include "utils.h"
int main() {
meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
// Open a new meshlink instance.
+ assert(meshlink_destroy("basic_conf"));
meshlink_handle_t *mesh = meshlink_open("basic_conf", "foo", "basic", DEV_CLASS_BACKBONE);
-
- if(!mesh) {
- fprintf(stderr, "Could not initialize configuration for foo\n");
- return 1;
- }
+ assert(mesh);
meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
// Check that our own node exists.
meshlink_node_t *self = meshlink_get_self(mesh);
-
- if(!self) {
- fprintf(stderr, "Foo does not know about itself\n");
- return 1;
- }
-
- if(strcmp(self->name, "foo")) {
- fprintf(stderr, "Foo thinks its name is %s\n", self->name);
- return 1;
- }
+ assert(self);
+ assert(!strcmp(self->name, "foo"));
// Start and stop the mesh.
- if(!meshlink_start(mesh)) {
- fprintf(stderr, "Foo could not start\n");
- return 1;
- }
-
+ assert(meshlink_start(mesh));
meshlink_stop(mesh);
// Make sure we can start and stop the mesh again.
- if(!meshlink_start(mesh)) {
- fprintf(stderr, "Foo could not start twice\n");
- return 1;
- }
-
+ assert(meshlink_start(mesh));
meshlink_stop(mesh);
// Close the mesh and open it again, now with a different name parameter.
meshlink_close(mesh);
-
- // Check that the name is ignored now, and that we still are "foo".
-
mesh = meshlink_open("basic_conf", "bar", "basic", DEV_CLASS_BACKBONE);
+ assert(mesh);
- if(!mesh) {
- fprintf(stderr, "Could not open configuration for foo a second time\n");
- return 1;
- }
-
- meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
-
- if(meshlink_get_node(mesh, "bar")) {
- fprintf(stderr, "Foo knows about bar, it shouldn't\n");
- return 1;
- }
+ // Check that the name is ignored now, and that we still are "foo".
+ assert(!meshlink_get_node(mesh, "bar"));
self = meshlink_get_self(mesh);
-
- if(!self) {
- fprintf(stderr, "Foo doesn't know about itself the second time\n");
- return 1;
- }
-
- if(strcmp(self->name, "foo")) {
- fprintf(stderr, "Foo thinks its name is %s the second time\n", self->name);
- return 1;
- }
+ assert(self);
+ assert(!strcmp(self->name, "foo"));
// Start and stop the mesh.
- if(!meshlink_start(mesh)) {
- fprintf(stderr, "Foo could not start a third time\n");
- return 1;
- }
-
+ assert(meshlink_start(mesh));
meshlink_stop(mesh);
// That's it.
// Destroy the mesh.
- if(!meshlink_destroy("basic_conf")) {
- fprintf(stderr, "Could not destroy configuration\n");
- return 1;
- }
-
- if(!access("basic_conf", F_OK) || errno != ENOENT) {
- fprintf(stderr, "Configuration not fully destroyed\n");
- return 1;
- }
-
- return 0;
+ assert(meshlink_destroy("basic_conf"));
+ assert(access("basic_conf", F_OK) == -1 && errno == ENOENT);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf basic_conf
-./basic
#include <iostream>
#include <unistd.h>
#include <cerrno>
+#include <cassert>
#include "meshlink++.h"
int main() {
// Open a new meshlink instance.
- meshlink::mesh mesh;
- mesh.open("basicpp_conf", "foo", "basicpp", DEV_CLASS_BACKBONE);
+ assert(meshlink::destroy("basicpp_conf"));
+ meshlink::mesh mesh("basicpp_conf", "foo", "basicpp", DEV_CLASS_BACKBONE);
+ assert(mesh.isOpen());
// Check that our own node exists.
meshlink::node *self = mesh.get_self();
- if(!self) {
- cerr << "Foo does not know about itself\n";
- return 1;
- }
- if(strcmp(self->name, "foo")) {
- cerr << "Foo thinks its name is " << self->name << "\n";
- return 1;
- }
+ assert(self);
+ assert(!strcmp(self->name, "foo"));
// Disable local discovery.
// Start and stop the mesh.
- if(!mesh.start()) {
- cerr << "Foo could not start\n";
- return 1;
- }
+ assert(mesh.start());
mesh.stop();
// Make sure we can start and stop the mesh again.
- if(!mesh.start()) {
- cerr << "Foo could not start twice\n";
- return 1;
- }
+ assert(mesh.start());
mesh.stop();
// Close the mesh and open it again, now with a different name parameter.
mesh.close();
+ assert(mesh.open("basicpp_conf", "bar", "basicpp", DEV_CLASS_BACKBONE));
// Check that the name is ignored now, and that we still are "foo".
- mesh.open("basicpp_conf", "bar", "basicpp", DEV_CLASS_BACKBONE);
-
- if(mesh.get_node("bar")) {
- cerr << "Foo knows about bar, it shouldn't\n";
- return 1;
- }
-
+ assert(!mesh.get_node("bar"));
self = mesh.get_self();
- if(!self) {
- cerr << "Foo doesn't know about itself the second time\n";
- return 1;
- }
- if(strcmp(self->name, "foo")) {
- cerr << "Foo thinks its name is " << self->name << " the second time\n";
- return 1;
- }
+ assert(self);
+ assert(!strcmp(self->name, "foo"));
// Start and stop the mesh.
mesh.enable_discovery(false);
- if(!mesh.start()) {
- cerr << "Foo could not start a third time\n";
- return 1;
- }
-
+ assert(mesh.start());
mesh.stop();
- if(!meshlink::destroy("basicpp_conf")) {
- cerr << "Could not destroy configuration\n";
- return 1;
- }
-
- if(!access("basic.conf", F_OK) || errno != ENOENT) {
- cerr << "Configuration not fully destroyed\n";
- return 1;
- }
+ assert(meshlink::destroy("basicpp_conf"));
+ assert(access("basic.conf", F_OK) == -1 && errno == ENOENT);
return 0;
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf basicpp_conf
-./basicpp
static void test_case_key_rotation_05(void **state);
static bool test_key_rotation_05(void);
-static void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
-
- static const char *levelstr[] = {
- [MESHLINK_DEBUG] = "\x1b[34mDEBUG",
- [MESHLINK_INFO] = "\x1b[32mINFO",
- [MESHLINK_WARNING] = "\x1b[33mWARNING",
- [MESHLINK_ERROR] = "\x1b[31mERROR",
- [MESHLINK_CRITICAL] = "\x1b[31mCRITICAL",
- };
-
- fprintf(stderr, "%s(%s):\x1b[0m %s\n", mesh->name, levelstr[level], text);
-}
-
/* Execute key rotation Test Case # 1 - Sanity test */
static void test_case_key_rotation_01(void **state) {
execute_test(test_key_rotation_01, state);
(void)argc;
(void)argv;
+ meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb);
+
// Prepare file
char *outdata = malloc(size);
-
assert(outdata);
for(size_t i = 0; i < size; i++) {
// Open two new meshlink instance.
- meshlink_destroy("channels_aio_fd_conf.1");
- meshlink_destroy("channels_aio_fd_conf.2");
-
- meshlink_handle_t *mesh1 = meshlink_open("channels_aio_fd_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
- assert(mesh1);
-
- meshlink_handle_t *mesh2 = meshlink_open("channels_aio_fd_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
- assert(mesh2);
-
- mesh2->priv = in_infos;
+ meshlink_handle_t *mesh_a, *mesh_b;
+ open_meshlink_pair(&mesh_a, &mesh_b, "channels_aio_fd");
- meshlink_enable_discovery(mesh1, false);
- meshlink_enable_discovery(mesh2, false);
+ mesh_b->priv = in_infos;
- // Import and export both side's data
-
- meshlink_add_address(mesh1, "localhost");
-
- char *data = meshlink_export(mesh1);
- assert(data);
- assert(meshlink_import(mesh2, data));
- free(data);
-
- data = meshlink_export(mesh2);
- assert(data);
- assert(meshlink_import(mesh1, data));
- free(data);
+ meshlink_enable_discovery(mesh_a, false);
+ meshlink_enable_discovery(mesh_b, false);
// Set the callbacks.
- meshlink_set_channel_accept_cb(mesh1, reject_cb);
- meshlink_set_channel_accept_cb(mesh2, accept_cb);
+ meshlink_set_channel_accept_cb(mesh_a, reject_cb);
+ meshlink_set_channel_accept_cb(mesh_b, accept_cb);
// Start both instances
- assert(meshlink_start(mesh1));
- assert(meshlink_start(mesh2));
+ start_meshlink_pair(mesh_a, mesh_b);
- // Open channels from foo to bar.
+ // Open channels from a to b.
- meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
- assert(bar);
+ meshlink_node_t *b = meshlink_get_node(mesh_a, "b");
+ assert(b);
meshlink_channel_t *channels[nchannels];
for(size_t i = 0; i < nchannels; i++) {
- channels[i] = meshlink_channel_open(mesh1, bar, i + 1, NULL, NULL, 0);
+ channels[i] = meshlink_channel_open(mesh_a, b, i + 1, NULL, NULL, 0);
assert(channels[i]);
}
// Send a large buffer of data on each channel.
for(size_t i = 0; i < nchannels; i++) {
- assert(meshlink_channel_aio_fd_send(mesh1, channels[i], fileno(out_infos[i].file), size / 3, aio_fd_cb, &out_infos[i].aio_infos[0]));
- assert(meshlink_channel_aio_fd_send(mesh1, channels[i], fileno(out_infos[i].file), size - size / 3, aio_fd_cb, &out_infos[i].aio_infos[1]));
+ assert(meshlink_channel_aio_fd_send(mesh_a, channels[i], fileno(out_infos[i].file), size / 3, aio_fd_cb, &out_infos[i].aio_infos[0]));
+ assert(meshlink_channel_aio_fd_send(mesh_a, channels[i], fileno(out_infos[i].file), size - size / 3, aio_fd_cb, &out_infos[i].aio_infos[1]));
}
// Wait for everyone to finish.
// Clean up.
- meshlink_close(mesh2);
- meshlink_close(mesh1);
-
- return 0;
+ close_meshlink_pair(mesh_a, mesh_b);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels_aio_fd_conf.*
-./channels-aio-fd
struct aio_info aio_infos[2];
};
-static size_t bar_received_len;
-static struct timeval bar_received_tv;
-static struct sync_flag bar_received_flag;
+static size_t b_received_len;
+static struct timeval b_received_tv;
+static struct sync_flag b_received_flag;
static void aio_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len, void *priv) {
(void)mesh;
(void)channel;
(void)data;
- bar_received_len += len;
+ b_received_len += len;
- if(bar_received_len >= smallsize) {
- gettimeofday(&bar_received_tv, NULL);
- set_sync_flag(&bar_received_flag, true);
+ if(b_received_len >= smallsize) {
+ gettimeofday(&b_received_tv, NULL);
+ set_sync_flag(&b_received_flag, true);
}
}
(void)argc;
(void)argv;
+ meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb);
+
// Prepare data buffers
char *outdata = malloc(size);
-
assert(outdata);
for(size_t i = 0; i < size; i++) {
// Open two new meshlink instance.
- meshlink_destroy("channels_aio_conf.1");
- meshlink_destroy("channels_aio_conf.2");
-
- meshlink_handle_t *mesh1 = meshlink_open("channels_aio_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
- assert(mesh1);
-
- meshlink_handle_t *mesh2 = meshlink_open("channels_aio_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
- assert(mesh2);
-
- mesh2->priv = in_infos;
-
- meshlink_enable_discovery(mesh1, false);
- meshlink_enable_discovery(mesh2, false);
-
- // Import and export both side's data
-
- meshlink_add_address(mesh1, "localhost");
-
- char *data = meshlink_export(mesh1);
- assert(data);
- assert(meshlink_import(mesh2, data));
- free(data);
-
- data = meshlink_export(mesh2);
- assert(data);
- assert(meshlink_import(mesh1, data));
- free(data);
+ meshlink_handle_t *mesh_a, *mesh_b;
+ open_meshlink_pair(&mesh_a, &mesh_b, "channels_aio");
// Set the callbacks.
- meshlink_set_channel_accept_cb(mesh1, reject_cb);
- meshlink_set_channel_accept_cb(mesh2, accept_cb);
+ mesh_b->priv = in_infos;
+
+ meshlink_set_channel_accept_cb(mesh_a, reject_cb);
+ meshlink_set_channel_accept_cb(mesh_b, accept_cb);
// Start both instances
- assert(meshlink_start(mesh1));
- assert(meshlink_start(mesh2));
+ start_meshlink_pair(mesh_a, mesh_b);
- // Open channels from foo to bar.
+ // Open channels from a to b.
- meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
- assert(bar);
+ meshlink_node_t *b = meshlink_get_node(mesh_a, "b");
+ assert(b);
meshlink_channel_t *channels[nchannels + 1];
for(size_t i = 0; i < nchannels + 1; i++) {
- channels[i] = meshlink_channel_open(mesh1, bar, i + 1, NULL, NULL, 0);
+ channels[i] = meshlink_channel_open(mesh_a, b, i + 1, NULL, NULL, 0);
assert(channels[i]);
}
// Send a large buffer of data on each channel.
for(size_t i = 0; i < nchannels; i++) {
- assert(meshlink_channel_aio_send(mesh1, channels[i], outdata, size / 3, aio_cb, &out_infos[i].aio_infos[0]));
- assert(meshlink_channel_aio_send(mesh1, channels[i], outdata + size / 3, size - size / 3, aio_cb, &out_infos[i].aio_infos[1]));
+ assert(meshlink_channel_aio_send(mesh_a, channels[i], outdata, size / 3, aio_cb, &out_infos[i].aio_infos[0]));
+ assert(meshlink_channel_aio_send(mesh_a, channels[i], outdata + size / 3, size - size / 3, aio_cb, &out_infos[i].aio_infos[1]));
}
// Send a little bit on the last channel using a regular send
- assert(meshlink_channel_send(mesh1, channels[nchannels], outdata, smallsize) == smallsize);
+ assert(meshlink_channel_send(mesh_a, channels[nchannels], outdata, smallsize) == (ssize_t)smallsize);
// Wait for everyone to finish.
- assert(wait_sync_flag(&bar_received_flag, 10));
+ assert(wait_sync_flag(&b_received_flag, 10));
for(size_t i = 0; i < nchannels; i++) {
assert(wait_sync_flag(&out_infos[i].aio_infos[0].flag, 10));
// Check that everything is correct.
- assert(bar_received_len == smallsize);
+ assert(b_received_len == smallsize);
for(size_t i = 0; i < nchannels; i++) {
// Data should be transferred intact.
}
// The non-AIO transfer should have completed before everything else
- assert(timercmp(&out_infos[i].aio_infos[0].tv, &bar_received_tv, >=));
- assert(timercmp(&in_infos[i].aio_infos[0].tv, &bar_received_tv, >=));
+ assert(timercmp(&out_infos[i].aio_infos[0].tv, &b_received_tv, >=));
+ assert(timercmp(&in_infos[i].aio_infos[0].tv, &b_received_tv, >=));
}
// Clean up.
- meshlink_close(mesh2);
- meshlink_close(mesh1);
-
- return 0;
+ close_meshlink_pair(mesh_a, mesh_b);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels_aio_conf.*
-./channels-aio
static volatile bool b_closed = false;
static volatile size_t a_poll_cb_len;
-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 a_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
(void)mesh;
(void)channel;
// Re-initialize everything
meshlink_channel_close(a, channel);
- close_meshlink_pair(a, b, "channels-cornercases");
+ close_meshlink_pair(a, b);
b_responded = false;
b_closed = false;
channel_opened.flag = false;
meshlink_channel_close(a, channel);
meshlink_channel_close(a, channel2);
- close_meshlink_pair(a, b, "channels-cornercases");
-
- return 0;
+ close_meshlink_pair(a, b);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels-cornercases_conf.*
-./channels-cornercases
#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;
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);
+ // Open two meshlink instances.
- 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);
+ meshlink_handle_t *mesh_a, *mesh_b;
+ open_meshlink_pair(&mesh_a, &mesh_b, "channels_failure");
// Set the callbacks.
- meshlink_set_channel_accept_cb(mesh2, accept_cb);
+ meshlink_set_channel_accept_cb(mesh_b, accept_cb);
- // Open a channel from foo to bar
+ // Open a channel from a to b
- meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
- assert(bar);
+ meshlink_node_t *b = meshlink_get_node(mesh_a, "b");
+ assert(b);
- meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, receive_cb, NULL, 0);
+ meshlink_channel_t *channel = meshlink_channel_open(mesh_a, b, 7, receive_cb, NULL, 0);
assert(channel);
- meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+ meshlink_set_channel_poll_cb(mesh_a, channel, poll_cb);
// Start both instances
- assert(meshlink_start(mesh1));
- assert(meshlink_start(mesh2));
+ start_meshlink_pair(mesh_a, mesh_b);
// Wait for the channel to be established
sleep(1);
- // Stop mesh2. We should get a notification that the channel has closed after a while.
+ // Stop mesh_b. We should get a notification that the channel has closed after a while.
- meshlink_stop(mesh2);
+ meshlink_stop(mesh_b);
assert(wait_sync_flag(&receive_flag, 70));
assert(receive_len == 0);
- meshlink_channel_close(mesh1, channel);
+ meshlink_channel_close(mesh_a, channel);
- // Try setting up a new channel while bar is still down.
+ // Try setting up a new channel while b is still down.
poll_flag.flag = false;
receive_flag.flag = false;
- channel = meshlink_channel_open(mesh1, bar, 7, NULL, NULL, 0);
+ channel = meshlink_channel_open(mesh_a, b, 7, NULL, NULL, 0);
assert(channel);
- meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+ meshlink_set_channel_poll_cb(mesh_a, channel, poll_cb);
assert(wait_sync_flag(&poll_flag, 70));
assert(poll_len == 0);
// Clean up.
- meshlink_close(mesh1);
- meshlink_close(mesh2);
-
- return 0;
+ close_meshlink_pair(mesh_a, mesh_b);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels_failure_conf.*
-./channels-failure
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
-#include "../src/meshlink.h"
-
-volatile bool bar_reachable = false;
-volatile bool bar_responded = false;
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
-void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
- if(mesh) {
- fprintf(stderr, "(%s) ", mesh->name);
- }
+#include "utils.h"
+#include "../src/meshlink.h"
- fprintf(stderr, "[%d] %s\n", level, text);
-}
+static struct sync_flag bar_responded;
+static struct sync_flag foo_gone;
-void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+static void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
(void)mesh;
+ (void)channel;
+ (void)len;
- if(!strcmp(node->name, "bar")) {
- bar_reachable = reachable;
+ if(len == 5 && !memcmp(data, "Hello", 5)) {
+ set_sync_flag(&bar_responded, true);
}
}
-void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+static void bar_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
(void)mesh;
- (void)channel;
- (void)len;
- if(len == 5 && !memcmp(data, "Hello", 5)) {
- bar_responded = true;
+ if(!strcmp(node->name, "foo") && !reachable) {
+ set_sync_flag(&foo_gone, true);
}
}
-void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+static void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
// Echo the data back.
- meshlink_channel_send(mesh, channel, data, len);
+ if(len) {
+ meshlink_channel_send(mesh, channel, data, len);
+ } else {
+ meshlink_channel_close(mesh, channel);
+ }
}
-bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+static bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
(void)mesh;
(void)channel;
(void)port;
return false;
}
-bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
if(port != 7) {
return false;
}
+ meshlink_set_node_status_cb(mesh, bar_status_cb);
meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
if(data) {
return true;
}
-void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
(void)len;
meshlink_set_channel_poll_cb(mesh, channel, NULL);
}
}
-int main1(int rfd, int wfd) {
- int ret_val;
- (void)ret_val;
+static int main1(int rfd, int wfd) {
meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
- 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");
- return 1;
- }
-
- meshlink_enable_discovery(mesh1, false);
+ assert(meshlink_destroy("channels_fork_conf.1"));
+ meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
+ assert(mesh);
- meshlink_add_address(mesh1, "localhost");
+ meshlink_enable_discovery(mesh, false);
- char *data = meshlink_export(mesh1);
+ meshlink_add_address(mesh, "localhost");
- if(!data) {
- fprintf(stderr, "Foo could not export its configuration\n");
- return 1;
- }
+ char *data = meshlink_export(mesh);
+ assert(data);
- size_t len = strlen(data);
- ret_val = write(wfd, &len, sizeof(len));
- ret_val = write(wfd, data, len);
+ ssize_t len = strlen(data);
+ assert(write(wfd, &len, sizeof(len)) == sizeof(len));
+ assert(write(wfd, data, len) == len);
free(data);
- ret_val = read(rfd, &len, sizeof(len));
+ assert(read(rfd, &len, sizeof(len)) == sizeof(len));
char indata[len + 1];
- ret_val = read(rfd, indata, len);
+ assert(read(rfd, indata, len) == len);
indata[len] = 0;
- fprintf(stderr, "Foo exchanged data\n");
+ assert(meshlink_import(mesh, indata));
- meshlink_import(mesh1, indata);
+ meshlink_set_channel_accept_cb(mesh, reject_cb);
- meshlink_set_channel_accept_cb(mesh1, reject_cb);
- meshlink_set_node_status_cb(mesh1, status_cb);
-
- if(!meshlink_start(mesh1)) {
- fprintf(stderr, "Foo could not start\n");
- return 1;
- }
-
- for(int i = 0; i < 20; i++) {
- sleep(1);
-
- if(bar_reachable) {
- break;
- }
- }
-
- if(!bar_reachable) {
- fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
- return 1;
- }
+ assert(meshlink_start(mesh));
// Open a channel from foo to bar.
- meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
-
- if(!bar) {
- fprintf(stderr, "Foo could not find bar\n");
- return 1;
- }
-
- meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, foo_receive_cb, NULL, 0);
- meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+ meshlink_node_t *bar = meshlink_get_node(mesh, "bar");
+ assert(bar);
- for(int i = 0; i < 5; i++) {
- sleep(1);
+ meshlink_channel_t *channel = meshlink_channel_open(mesh, bar, 7, foo_receive_cb, NULL, 0);
+ assert(channel);
- if(bar_responded) {
- break;
- }
- }
+ meshlink_set_channel_poll_cb(mesh, channel, poll_cb);
- if(!bar_responded) {
- fprintf(stderr, "Bar did not respond to foo's channel message\n");
- return 1;
- }
+ assert(wait_sync_flag(&bar_responded, 20));
- meshlink_channel_close(mesh1, channel);
+ meshlink_channel_close(mesh, channel);
// Clean up.
- meshlink_close(mesh1);
+ meshlink_close(mesh);
return 0;
}
-int main2(int rfd, int wfd) {
- int ret_val;
- (void)ret_val;
- sleep(1);
+static int main2(int rfd, int wfd) {
+#ifdef __linux__
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+#endif
meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
- 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");
- return 1;
- }
-
- meshlink_enable_discovery(mesh2, false);
-
- char *data = meshlink_export(mesh2);
-
- if(!data) {
- fprintf(stderr, "Bar could not export its configuration\n");
- return 1;
- }
+ assert(meshlink_destroy("channels_fork_conf.2"));
+ meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
+ assert(mesh);
- size_t len = strlen(data);
+ meshlink_enable_discovery(mesh, false);
- if(write(wfd, &len, sizeof(len)) <= 0) {
- abort();
- }
+ meshlink_add_address(mesh, "localhost");
- if(write(wfd, data, len) <= 0) {
- abort();
- }
+ char *data = meshlink_export(mesh);
+ assert(data);
+ ssize_t len = strlen(data);
+ assert(write(wfd, &len, sizeof(len)) == sizeof(len));
+ assert(write(wfd, data, len) == len);
free(data);
- ret_val = read(rfd, &len, sizeof(len));
+ assert(read(rfd, &len, sizeof(len)) == sizeof(len));
char indata[len + 1];
- ret_val = read(rfd, indata, len);
+ assert(read(rfd, indata, len) == len);
indata[len] = 0;
- fprintf(stderr, "Bar exchanged data\n");
+ assert(meshlink_import(mesh, indata));
- meshlink_import(mesh2, indata);
+ meshlink_set_channel_accept_cb(mesh, accept_cb);
- meshlink_set_channel_accept_cb(mesh2, accept_cb);
+ assert(meshlink_start(mesh));
- if(!meshlink_start(mesh2)) {
- fprintf(stderr, "Bar could not start\n");
- return 1;
- }
-
- sleep(20);
+ assert(wait_sync_flag(&foo_gone, 20));
- // Clean up.
-
- meshlink_close(mesh2);
+ meshlink_close(mesh);
return 0;
}
+static void alarm_handler(int sig) {
+ (void)sig;
+ assert(0);
+}
int main() {
- int ret_val;
- (void)ret_val;
int fda[2], fdb[2];
- ret_val = pipe2(fda, 0);
- ret_val = pipe2(fdb, 0);
+ assert(pipe2(fda, 0) != -1);
+ assert(pipe2(fdb, 0) != -1);
- if(fork()) {
- return main1(fda[0], fdb[1]);
- } else {
+ if(!fork()) {
return main2(fdb[0], fda[1]);
}
+
+ signal(SIGALRM, alarm_handler);
+ alarm(30);
+ assert(main1(fda[0], fdb[1]) == 0);
+
+ int wstatus;
+ assert(wait(&wstatus) != -1 || errno == ECHILD);
+ assert(WIFEXITED(wstatus));
+ assert(WEXITSTATUS(wstatus) == 0);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels_fork_conf.*
-./channels-fork
(void)argc;
(void)argv;
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
// Start two new meshlink instance.
meshlink_handle_t *mesh_a;
// Clean up.
- close_meshlink_pair(mesh_a, mesh_b, "channels_no_partial");
-
- return 0;
+ close_meshlink_pair(mesh_a, mesh_b);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels_no_partial_conf.*
-./channels-no-partial
size_t received;
};
-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;
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);
}
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);
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) {
}
int main() {
- //meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+ meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb);
- // Open two new meshlink instance.
+ // 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);
for(int i = 0; i < 3; i++) {
char dir[100];
snprintf(dir, sizeof(dir), "channels_udp_conf.%d", i + 1);
+ assert(meshlink_destroy(dir));
clients[i].mesh = meshlink_open(dir, names[i], "channels-udp", DEV_CLASS_STATIONARY);
assert(clients[i].mesh);
clients[i].mesh->priv = &clients[i];
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels_udp_conf.*
-./channels-udp
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
+#include <assert.h>
+#include "utils.h"
#include "../src/meshlink.h"
-volatile bool bar_reachable = false;
-volatile bool bar_responded = false;
+static struct sync_flag b_responded;
-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);
-}
-
-void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
- (void)mesh;
-
- printf("status_cb: %s %sreachable\n", node->name, reachable ? "" : "un");
-
- if(!strcmp(node->name, "bar")) {
- bar_reachable = reachable;
- }
-}
-
-void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+static void a_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
(void)mesh;
(void)channel;
- printf("foo_receive_cb %zu: ", len);
+ printf("a_receive_cb %zu: ", len);
fwrite(data, 1, len, stdout);
printf("\n");
if(len == 5 && !memcmp(data, "Hello", 5)) {
- bar_responded = true;
+ set_sync_flag(&b_responded, true);
}
}
-void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
- printf("bar_receive_cb %zu: ", len);
+static void b_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+ printf("b_receive_cb %zu: ", len);
fwrite(data, 1, len, stdout);
printf("\n");
// Echo the data back.
meshlink_channel_send(mesh, channel, data, len);
}
-bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+static bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
(void)mesh;
(void)channel;
(void)port;
return false;
}
-bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
printf("accept_cb: (from %s on port %u) ", channel->node->name, (unsigned int)port);
if(data) {
return false;
}
- meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
+ meshlink_set_channel_receive_cb(mesh, channel, b_receive_cb);
if(data) {
- bar_receive_cb(mesh, channel, data, len);
+ b_receive_cb(mesh, channel, data, len);
}
return true;
}
-void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
(void)len;
meshlink_set_channel_poll_cb(mesh, channel, NULL);
- if(meshlink_channel_send(mesh, channel, "Hello", 5) != 5) {
- fprintf(stderr, "Could not send whole message\n");
- }
+ assert(meshlink_channel_send(mesh, channel, "Hello", 5) == 5);
}
int main() {
// Open two new meshlink instance.
- meshlink_handle_t *mesh1 = meshlink_open("channels_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
-
- if(!mesh1) {
- fprintf(stderr, "Could not initialize configuration for foo\n");
- return 1;
- }
-
- meshlink_handle_t *mesh2 = meshlink_open("channels_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
-
- if(!mesh2) {
- fprintf(stderr, "Could not initialize configuration for bar\n");
- return 1;
- }
-
- 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");
-
- char *data = meshlink_export(mesh1);
-
- if(!data) {
- fprintf(stderr, "Foo could not export its configuration\n");
- return 1;
- }
-
- if(!meshlink_import(mesh2, data)) {
- fprintf(stderr, "Bar could not import foo's configuration\n");
- return 1;
- }
-
- free(data);
-
- data = meshlink_export(mesh2);
-
- if(!data) {
- fprintf(stderr, "Bar could not export its configuration\n");
- return 1;
- }
-
- if(!meshlink_import(mesh1, data)) {
- fprintf(stderr, "Foo could not import bar's configuration\n");
- return 1;
- }
-
- free(data);
+ meshlink_handle_t *mesh_a, *mesh_b;
+ open_meshlink_pair(&mesh_a, &mesh_b, "channels");
// Set the callbacks.
- meshlink_set_channel_accept_cb(mesh1, reject_cb);
- meshlink_set_channel_accept_cb(mesh2, accept_cb);
-
- meshlink_set_node_status_cb(mesh1, status_cb);
+ meshlink_set_channel_accept_cb(mesh_a, reject_cb);
+ meshlink_set_channel_accept_cb(mesh_b, accept_cb);
// Start both instances
- if(!meshlink_start(mesh1)) {
- fprintf(stderr, "Foo could not start\n");
- return 1;
- }
-
- if(!meshlink_start(mesh2)) {
- fprintf(stderr, "Bar could not start\n");
- return 1;
- }
-
- // Wait for the two to connect.
-
- for(int i = 0; i < 20; i++) {
- sleep(1);
+ start_meshlink_pair(mesh_a, mesh_b);
- if(bar_reachable) {
- break;
- }
- }
+ // Open a channel from a to b.
- if(!bar_reachable) {
- fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
- return 1;
- }
+ meshlink_node_t *b = meshlink_get_node(mesh_a, "b");
+ assert(b);
- // Open a channel from foo to bar.
-
- meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
-
- if(!bar) {
- fprintf(stderr, "Foo could not find bar\n");
- return 1;
- }
+ meshlink_channel_t *channel = meshlink_channel_open(mesh_a, b, 7, a_receive_cb, NULL, 0);
+ assert(channel);
- meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, foo_receive_cb, NULL, 0);
- meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+ meshlink_set_channel_poll_cb(mesh_a, channel, poll_cb);
+ assert(wait_sync_flag(&b_responded, 20));
- for(int i = 0; i < 20; i++) {
- sleep(1);
-
- if(bar_responded) {
- break;
- }
- }
-
- if(!bar_responded) {
- fprintf(stderr, "Bar did not respond to foo's channel message\n");
- return 1;
- }
-
- meshlink_channel_close(mesh1, channel);
+ meshlink_channel_close(mesh_a, channel);
// Clean up.
- meshlink_stop(mesh2);
- meshlink_stop(mesh1);
- meshlink_close(mesh2);
- meshlink_close(mesh1);
-
- return 0;
+ close_meshlink_pair(mesh_a, mesh_b);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf channels_conf.*
-./channels
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
-#include <errno.h>
+#include <assert.h>
#include "meshlink.h"
+#include "utils.h"
-static volatile bool duplicate_detected;
+static struct sync_flag duplicate_detected;
static void handle_duplicate(meshlink_handle_t *mesh, meshlink_node_t *node) {
- meshlink_node_t *self = meshlink_get_self(mesh);
- fprintf(stderr, "%s: detected duplicate node %s\n", self->name, node->name);
- duplicate_detected = true;
+ set_sync_flag(&duplicate_detected, true);
meshlink_blacklist(mesh, node);
}
int main() {
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
// Open meshlink instances
static const char *name[4] = {"foo", "bar", "baz", "foo"};
char dirname[100];
snprintf(dirname, sizeof dirname, "duplicate_conf.%d", i);
+ assert(meshlink_destroy(dirname));
mesh[i] = meshlink_open(dirname, name[i], "duplicate", DEV_CLASS_BACKBONE);
-
- if(!mesh[i]) {
- fprintf(stderr, "Could not initialize configuration for node %d\n", i);
- return 1;
- }
+ assert(mesh[i]);
meshlink_add_address(mesh[i], "localhost");
meshlink_enable_discovery(mesh[i], false);
for(int i = 0; i < 4; i++) {
data[i] = meshlink_export(mesh[i]);
+ assert(data[i]);
}
for(int i = 0; i < 3; i++) {
- meshlink_import(mesh[i], data[i + 1]);
- meshlink_import(mesh[i + 1], data[i]);
+ assert(meshlink_import(mesh[i], data[i + 1]));
+ assert(meshlink_import(mesh[i + 1], data[i]));
}
for(int i = 0; i < 4; i++) {
// Start the meshes
for(int i = 0; i < 4; i++) {
- if(!meshlink_start(mesh[i])) {
- fprintf(stderr, "Could not start mesh %d\n", i);
- return 1;
- }
+ assert(meshlink_start(mesh[i]));
}
// Wait for the duplicate node to be detected
- for(int i = 0; i < 20; i++) {
- sleep(1);
-
- if(duplicate_detected) {
- break;
- }
- }
-
- if(!duplicate_detected) {
- fprintf(stderr, "Failed to detect duplicate node after 20 seconds\n");
- return 1;
- }
+ assert(wait_sync_flag(&duplicate_detected, 20));
// Clean up
for(int i = 0; i < 4; i++) {
meshlink_close(mesh[i]);
}
-
- return 0;
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf duplicate_conf*
-./duplicate
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/wait.h>
-#include "../src/meshlink.h"
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
+#include "meshlink.h"
+#include "utils.h"
/*
* To run this test case, direct a large file to strd
*/
-volatile bool bar_reachable = false;
-volatile bool bar_responded = false;
-volatile bool foo_closed = false;
-int debug_level;
-
-void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
- if(mesh) {
- fprintf(stderr, "(%s) ", mesh->name);
- }
-
- fprintf(stderr, "[%d] %s\n", level, text);
-}
-
-void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
- (void)mesh;
-
- if(!strcmp(node->name, "bar")) {
- bar_reachable = reachable;
- } else if(!strcmp(node->name, "foo"))
- if(!reachable) {
- foo_closed = true;
- }
-}
+static struct sync_flag a_started;
+static struct sync_flag a_stopped;
+static struct sync_flag b_responded;
-void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+static void a_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
(void)mesh;
(void)channel;
(void)data;
// One way only.
}
-void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+static void b_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
(void)mesh;
(void)channel;
if(!len) {
- fprintf(stderr, "Connection closed by foo\n");
- foo_closed = true;
+ set_sync_flag(&a_stopped, true);
+ meshlink_channel_close(mesh, channel);
return;
}
- int ret_val;
- (void)ret_val;
- // Write data to stdout.
- ret_val = write(1, data, len);
+ assert(write(1, data, len) == (ssize_t)len);
}
-bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+static bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
(void)mesh;
(void)channel;
(void)port;
return false;
}
-bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
if(port != 7) {
return false;
}
- meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
+ set_sync_flag(&a_started, true);
+
+ meshlink_set_channel_receive_cb(mesh, channel, b_receive_cb);
if(data) {
- bar_receive_cb(mesh, channel, data, len);
+ b_receive_cb(mesh, channel, data, len);
}
return true;
}
-void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
(void)len;
meshlink_set_channel_poll_cb(mesh, channel, NULL);
- bar_responded = true;
+ set_sync_flag(&b_responded, true);
}
-int main1(void) {
+static int main1(void) {
close(1);
- meshlink_set_log_cb(NULL, debug_level, log_cb);
-
- meshlink_handle_t *mesh1 = meshlink_open("echo-fork_conf.1", "foo", "echo-fork", DEV_CLASS_BACKBONE);
-
- if(!mesh1) {
- fprintf(stderr, "Could not initialize configuration for foo\n");
- return 1;
- }
-
- meshlink_set_log_cb(mesh1, debug_level, log_cb);
- meshlink_set_channel_accept_cb(mesh1, reject_cb);
- meshlink_set_node_status_cb(mesh1, status_cb);
+ meshlink_handle_t *mesh = meshlink_open("echo-fork_conf.1", "a", "echo-fork", DEV_CLASS_BACKBONE);
+ assert(mesh);
- if(!meshlink_start(mesh1)) {
- fprintf(stderr, "Foo could not start\n");
- return 1;
- }
+ meshlink_set_channel_accept_cb(mesh, reject_cb);
- for(int i = 0; i < 20; i++) {
- sleep(1);
+ assert(meshlink_start(mesh));
- if(bar_reachable) {
- break;
- }
- }
+ // Open a channel.
- if(!bar_reachable) {
- fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
- return 1;
- }
+ meshlink_node_t *b = meshlink_get_node(mesh, "b");
+ assert(b);
- // Open a channel from foo to bar.
+ meshlink_channel_t *channel = meshlink_channel_open(mesh, b, 7, a_receive_cb, NULL, 0);
+ assert(channel);
- meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
-
- if(!bar) {
- fprintf(stderr, "Foo could not find bar\n");
- return 1;
- }
-
- meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, foo_receive_cb, NULL, 0);
- meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+ meshlink_set_channel_poll_cb(mesh, channel, poll_cb);
// read and buffer stdin
int BUF_SIZE = 1024 * 1024;
char buffer[BUF_SIZE];
- for(int i = 0; i < 5; i++) {
- sleep(1);
-
- if(bar_responded) {
- break;
- }
- }
-
- if(!bar_responded) {
- fprintf(stderr, "Bar did not respond to foo's channel message\n");
- return 1;
- }
+ assert(wait_sync_flag(&b_responded, 20));
do {
- //fprintf(stderr, ":");
ssize_t len = read(0, buffer, BUF_SIZE);
if(len <= 0) {
char *p = buffer;
while(len > 0) {
- ssize_t sent = meshlink_channel_send(mesh1, channel, p, len);
+ ssize_t sent = meshlink_channel_send(mesh, channel, p, len);
if(sent < 0) {
fprintf(stderr, "Sending message failed\n");
}
} while(true);
- fprintf(stderr, "Foo finished sending\n");
-
- meshlink_channel_close(mesh1, channel);
- sleep(1);
+ meshlink_channel_close(mesh, channel);
// Clean up.
- meshlink_close(mesh1);
+ meshlink_close(mesh);
return 0;
}
-int main2(void) {
+static int main2(void) {
+#ifdef __linux__
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+#endif
+
close(0);
- sleep(1);
+ // Start mesh and wait for incoming channels.
- meshlink_set_log_cb(NULL, debug_level, log_cb);
+ meshlink_handle_t *mesh = meshlink_open("echo-fork_conf.2", "b", "echo-fork", DEV_CLASS_BACKBONE);
+ assert(mesh);
- meshlink_handle_t *mesh2 = meshlink_open("echo-fork_conf.2", "bar", "echo-fork", DEV_CLASS_BACKBONE);
+ meshlink_set_channel_accept_cb(mesh, accept_cb);
- if(!mesh2) {
- fprintf(stderr, "Could not initialize configuration for bar\n");
- return 1;
- }
+ assert(meshlink_start(mesh));
- meshlink_set_log_cb(mesh2, debug_level, log_cb);
- meshlink_set_channel_accept_cb(mesh2, accept_cb);
- meshlink_set_node_status_cb(mesh2, status_cb);
+ // Let it run until a disappears.
- if(!meshlink_start(mesh2)) {
- fprintf(stderr, "Bar could not start\n");
- return 1;
- }
-
- while(!foo_closed) {
- sleep(1);
- }
+ assert(wait_sync_flag(&a_started, 20));
+ assert(wait_sync_flag(&a_stopped, 1000000));
// Clean up.
- meshlink_close(mesh2);
+ meshlink_close(mesh);
return 0;
}
int main() {
- debug_level = getenv("DEBUG") ? MESHLINK_DEBUG : MESHLINK_ERROR;
+ meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb);
// Initialize and exchange configuration.
- meshlink_handle_t *foo = meshlink_open("echo-fork_conf.1", "foo", "echo-fork", DEV_CLASS_BACKBONE);
- meshlink_handle_t *bar = meshlink_open("echo-fork_conf.2", "bar", "echo-fork", DEV_CLASS_BACKBONE);
- meshlink_add_address(foo, "localhost");
- meshlink_import(bar, meshlink_export(foo));
- meshlink_import(foo, meshlink_export(bar));
- meshlink_close(foo);
- meshlink_close(bar);
-
- if(fork()) {
- return main1();
- } else {
+ meshlink_handle_t *mesh_a, *mesh_b;
+
+ open_meshlink_pair(&mesh_a, &mesh_b, "echo-fork");
+ close_meshlink_pair(mesh_a, mesh_b);
+
+ if(!fork()) {
return main2();
}
+
+ assert(main1() == 0);
+
+ int wstatus = 0;
+ assert(wait(&wstatus) != -1);
+ assert(WIFEXITED(wstatus));
+ assert(WEXITSTATUS(wstatus) == 0);
}
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
+#include <assert.h>
#include "meshlink.h"
-
-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);
-}
+#include "utils.h"
int main() {
meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
// Open a new meshlink instance.
+ assert(meshlink_destroy("encrypted_conf"));
meshlink_handle_t *mesh = meshlink_open_encrypted("encrypted_conf", "foo", "encrypted", DEV_CLASS_BACKBONE, "right", 5);
-
- if(!mesh) {
- fprintf(stderr, "Could not initialize configuration for foo\n");
- return 1;
- }
+ assert(mesh);
// Close the mesh and open it again, now with a different key.
meshlink_close(mesh);
mesh = meshlink_open_encrypted("encrypted_conf", "foo", "encrypted", DEV_CLASS_BACKBONE, "wrong", 5);
-
- if(mesh) {
- fprintf(stderr, "Could open mesh with the wrong key\n");
- return 1;
- }
+ assert(!mesh);
// Open it again, now with the right key.
mesh = meshlink_open_encrypted("encrypted_conf", "foo", "encrypted", DEV_CLASS_BACKBONE, "right", 5);
-
- if(!mesh) {
- fprintf(stderr, "Could not open mesh with the right key\n");
- return 1;
- }
+ assert(mesh);
// That's it.
// Destroy the mesh.
- if(!meshlink_destroy("encrypted_conf")) {
- fprintf(stderr, "Could not destroy configuration\n");
- return 1;
- }
-
- if(!access("encrypted_conf", F_OK) || errno != ENOENT) {
- fprintf(stderr, "Configuration not fully destroyed\n");
- return 1;
- }
-
- return 0;
+ assert(meshlink_destroy("encrypted_conf"));
+ assert(access("encrypted_conf", F_OK) == -1 && errno == ENOENT);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf encrypted_conf
-./encrypted
#include <stdio.h>
+#include <stdlib.h>
#include <sys/time.h>
#include <assert.h>
#include "meshlink.h"
-
-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);
-}
+#include "utils.h"
int main() {
meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
meshlink_close(mesh1);
meshlink_close(mesh2);
-
- return 0;
}
+++ /dev/null
-#!/bin/sh
-
-./ephemeral
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
+#include <assert.h>
#include "meshlink.h"
+#include "utils.h"
-volatile bool bar_reachable = false;
-
-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);
-}
+struct sync_flag bar_reachable;
void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
(void)mesh;
- if(!strcmp(node->name, "bar")) {
- bar_reachable = reachable;
+ if(reachable && !strcmp(node->name, "bar")) {
+ set_sync_flag(&bar_reachable, true);
}
}
// Open two new meshlink instance.
- meshlink_handle_t *mesh1 = meshlink_open("import_export_conf.1", "foo", "import-export", DEV_CLASS_BACKBONE);
+ assert(meshlink_destroy("import_export_conf.1"));
+ assert(meshlink_destroy("import_export_conf.2"));
- if(!mesh1) {
- fprintf(stderr, "Could not initialize configuration for foo: %s\n", meshlink_strerror(meshlink_errno));
- return 1;
- }
+ meshlink_handle_t *mesh1 = meshlink_open("import_export_conf.1", "foo", "import-export", DEV_CLASS_BACKBONE);
+ assert(mesh1);
meshlink_handle_t *mesh2 = meshlink_open("import_export_conf.2", "bar", "import-export", DEV_CLASS_BACKBONE);
-
- if(!mesh2) {
- fprintf(stderr, "Could not initialize configuration for bar\n");
- return 1;
- }
-
- meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, log_cb);
- meshlink_set_log_cb(mesh2, MESHLINK_DEBUG, log_cb);
+ assert(mesh2);
// Disable local discovery
meshlink_add_address(mesh2, "localhost");
char *data = meshlink_export(mesh1);
+ assert(data);
- if(!data) {
- fprintf(stderr, "Foo could not export its configuration\n");
- return 1;
- }
-
- fprintf(stderr, "Foo export data:\n%s\n", data);
-
- if(!meshlink_import(mesh2, data)) {
- fprintf(stderr, "Bar could not import foo's configuration\n");
- return 1;
- }
-
+ assert(meshlink_import(mesh2, data));
free(data);
data = meshlink_export(mesh2);
+ assert(data);
- if(!data) {
- fprintf(stderr, "Bar could not export its configuration\n");
- return 1;
- }
-
-
- if(!meshlink_import(mesh1, data)) {
- fprintf(stderr, "Foo could not import bar's configuration\n");
- return 1;
- }
-
+ assert(meshlink_import(mesh1, data));
free(data);
// Start both instances
meshlink_set_node_status_cb(mesh1, status_cb);
- if(!meshlink_start(mesh1)) {
- fprintf(stderr, "Foo could not start\n");
- return 1;
- }
-
- if(!meshlink_start(mesh2)) {
- fprintf(stderr, "Bar could not start\n");
- return 1;
- }
+ assert(meshlink_start(mesh1));
+ assert(meshlink_start(mesh2));
// Wait for the two to connect.
- for(int i = 0; i < 20; i++) {
- sleep(1);
-
- if(bar_reachable) {
- break;
- }
- }
+ assert(wait_sync_flag(&bar_reachable, 20));
- if(!bar_reachable) {
- fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
- return 1;
- }
+ // Wait for UDP communication to become possible.
int pmtu = meshlink_get_pmtu(mesh2, meshlink_get_node(mesh2, "bar"));
pmtu = meshlink_get_pmtu(mesh2, meshlink_get_node(mesh2, "bar"));
}
- if(!pmtu) {
- fprintf(stderr, "UDP communication with bar not possible after 10 seconds\n");
- return 1;
- }
+ assert(pmtu);
// Clean up.
- meshlink_stop(mesh2);
- meshlink_stop(mesh1);
meshlink_close(mesh2);
meshlink_close(mesh1);
-
- return 0;
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf import_export_conf*
-./import-export
#include <assert.h>
#include "meshlink.h"
+#include "utils.h"
-volatile bool baz_reachable = false;
+static struct sync_flag baz_reachable;
-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);
-}
-
-void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
(void)mesh;
- if(!strcmp(node->name, "baz")) {
- baz_reachable = reachable;
+ if(reachable && !strcmp(node->name, "baz")) {
+ set_sync_flag(&baz_reachable, true);
}
}
int main() {
meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+ assert(meshlink_destroy("invite_join_conf.1"));
+ assert(meshlink_destroy("invite_join_conf.2"));
+ assert(meshlink_destroy("invite_join_conf.3"));
+
// Open thee new meshlink instance.
meshlink_handle_t *mesh1 = meshlink_open("invite_join_conf.1", "foo", "invite-join", DEV_CLASS_BACKBONE);
-
- if(!mesh1) {
- fprintf(stderr, "Could not initialize configuration for foo\n");
- return 1;
- }
-
- meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, log_cb);
+ assert(mesh1);
meshlink_handle_t *mesh2 = meshlink_open("invite_join_conf.2", "bar", "invite-join", DEV_CLASS_BACKBONE);
-
- if(!mesh2) {
- fprintf(stderr, "Could not initialize configuration for bar\n");
- return 1;
- }
-
- meshlink_set_log_cb(mesh2, MESHLINK_DEBUG, log_cb);
+ assert(mesh2);
meshlink_handle_t *mesh3 = meshlink_open("invite_join_conf.3", "quux", "invite-join", DEV_CLASS_BACKBONE);
-
- if(!mesh3) {
- fprintf(stderr, "Could not initialize configuration for quux\n");
- return 1;
- }
-
- meshlink_set_log_cb(mesh3, MESHLINK_DEBUG, log_cb);
+ assert(mesh3);
// Disable local discovery.
meshlink_enable_discovery(mesh2, false);
meshlink_enable_discovery(mesh3, false);
- // Start the first instance and have it generate invitations.
+ // Have the first instance generate invitations.
meshlink_set_node_status_cb(mesh1, status_cb);
- if(!meshlink_start(mesh1)) {
- fprintf(stderr, "Foo could not start\n");
- return 1;
- }
-
meshlink_add_address(mesh1, "localhost");
char *baz_url = meshlink_invite(mesh1, NULL, "baz");
-
- if(!baz_url) {
- fprintf(stderr, "Foo could not generate an invitation for baz\n");
- return 1;
- }
+ assert(baz_url);
char *quux_url = meshlink_invite(mesh1, NULL, "quux");
-
- if(!quux_url) {
- fprintf(stderr, "Foo could not generate an invitation for quux\n");
- return 1;
- }
-
- fprintf(stderr, "Invitation URL for baz: %s\n", baz_url);
- fprintf(stderr, "Invitation URL for quux: %s\n", quux_url);
+ assert(quux_url);
// Have the second instance join the first.
- if(!meshlink_join(mesh2, baz_url)) {
- fprintf(stderr, "Baz could not join foo's mesh\n");
- return 1;
- }
+ assert(meshlink_start(mesh1));
- if(!meshlink_start(mesh2)) {
- fprintf(stderr, "Baz could not start\n");
- return 1;
- }
+ assert(meshlink_join(mesh2, baz_url));
+ assert(meshlink_start(mesh2));
// Wait for the two to connect.
- for(int i = 0; i < 60; i++) {
- sleep(1);
+ assert(wait_sync_flag(&baz_reachable, 20));
- if(baz_reachable) {
- break;
- }
- }
-
- if(!baz_reachable) {
- fprintf(stderr, "Baz not reachable for foo after 20 seconds\n");
- return 1;
- }
+ // Wait for UDP communication to become possible.
int pmtu = meshlink_get_pmtu(mesh1, meshlink_get_node(mesh1, "baz"));
pmtu = meshlink_get_pmtu(mesh1, meshlink_get_node(mesh1, "baz"));
}
- if(!pmtu) {
- fprintf(stderr, "UDP communication with baz not possible after 10 seconds\n");
- return 1;
- }
+ assert(pmtu);
// Check that an invitation cannot be used twice
- if(meshlink_join(mesh3, baz_url)) {
- fprintf(stderr, "Quux could join foo's mesh using an already used invitation\n");
- return 1;
- }
-
+ assert(!meshlink_join(mesh3, baz_url));
free(baz_url);
// Check that nodes cannot join with expired invitations
meshlink_set_invitation_timeout(mesh1, 0);
- if(meshlink_join(mesh3, quux_url)) {
- fprintf(stderr, "Quux could join foo's mesh using an outdated invitation\n");
- return 1;
- }
-
+ assert(!meshlink_join(mesh3, quux_url));
free(quux_url);
// Check that existing nodes cannot join another mesh
char *corge_url = meshlink_invite(mesh3, NULL, "corge");
+ assert(corge_url);
- if(!corge_url) {
- fprintf(stderr, "Quux could not generate an invitation for corge\n");
- return 1;
- }
-
- fprintf(stderr, "Invitation URL for corge: %s\n", corge_url);
-
- if(!meshlink_start(mesh3)) {
- fprintf(stderr, "Quux could not start\n");
- return 1;
- }
+ assert(meshlink_start(mesh3));
meshlink_stop(mesh2);
- if(meshlink_join(mesh2, corge_url)) {
- fprintf(stderr, "Bar could join twice\n");
- return 1;
- }
-
+ assert(!meshlink_join(mesh2, corge_url));
free(corge_url);
// Check that invitations work correctly after changing ports
meshlink_stop(mesh3);
int oldport = meshlink_get_port(mesh1);
- bool success;
+ bool success = false;
- for(int i = 0; i < 100; i++) {
+ for(int i = 0; !success && i < 100; i++) {
success = meshlink_set_port(mesh1, 0x9000 + rand() % 0x1000);
}
assert(meshlink_start(mesh1));
quux_url = meshlink_invite(mesh1, NULL, "quux");
- fprintf(stderr, "Invitation URL for quux: %s\n", quux_url);
+ assert(quux_url);
// The old port should not be in the invitation URL
meshlink_close(mesh3);
meshlink_close(mesh2);
meshlink_close(mesh1);
-
- return 0;
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf invite_join_conf*
-./invite-join
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include "meshlink.h"
+#include "utils.h"
int main() {
- // Open two new meshlink instance.
-
- meshlink_handle_t *mesh1 = meshlink_open("sign_verify_conf.1", "foo", "sign-verify", DEV_CLASS_BACKBONE);
-
- if(!mesh1) {
- fprintf(stderr, "Could not initialize configuration for foo\n");
- return 1;
- }
-
- meshlink_handle_t *mesh2 = meshlink_open("sign_verify_conf.2", "bar", "sign-verify", DEV_CLASS_BACKBONE);
-
- if(!mesh2) {
- fprintf(stderr, "Could not initialize configuration for bar\n");
- return 1;
- }
-
- // Import and export both side's data
-
- meshlink_add_address(mesh1, "localhost");
- meshlink_add_address(mesh2, "localhost");
-
- char *data = meshlink_export(mesh1);
-
- if(!meshlink_import(mesh2, data)) {
- fprintf(stderr, "Bar could not import data from foo\n");
- return 1;
- }
-
- free(data);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
- data = meshlink_export(mesh2);
-
- if(!meshlink_import(mesh1, data)) {
- fprintf(stderr, "Foo could not import data from bar\n");
- return 1;
- }
+ // Open two new meshlink instance.
- free(data);
+ meshlink_handle_t *mesh_a, *mesh_b;
+ open_meshlink_pair(&mesh_a, &mesh_b, "sign_verify");
// Verify that a signature made on one node can be verified by its peer.
char sig[MESHLINK_SIGLEN * 2];
size_t siglen = sizeof(sig) * 2;
- if(!meshlink_sign(mesh1, testdata1, sizeof(testdata1), sig, &siglen)) {
- fprintf(stderr, "Signing failed\n");
- return 1;
- }
-
- if(siglen != MESHLINK_SIGLEN) {
- fprintf(stderr, "Signature has unexpected length %zu != %zu\n", siglen, MESHLINK_SIGLEN);
- return 1;
- }
-
- meshlink_node_t *foo = meshlink_get_node(mesh2, "foo");
-
- if(!foo) {
- fprintf(stderr, "Bar did not know about node foo\n");
- return 1;
- }
+ assert(meshlink_sign(mesh_a, testdata1, sizeof(testdata1), sig, &siglen));
+ assert(siglen == MESHLINK_SIGLEN);
- meshlink_node_t *bar = meshlink_get_node(mesh2, "bar");
+ meshlink_node_t *a = meshlink_get_node(mesh_b, "a");
+ assert(a);
- if(!bar) {
- fprintf(stderr, "Bar did not know about node bar\n");
- return 1;
- }
+ meshlink_node_t *b = meshlink_get_node(mesh_b, "b");
+ assert(b);
- if(!meshlink_verify(mesh2, foo, testdata1, sizeof(testdata1), sig, siglen)) {
- fprintf(stderr, "False negative verification\n");
- return 1;
- }
+ assert(meshlink_verify(mesh_b, a, testdata1, sizeof(testdata1), sig, siglen));
// Check that bad signatures are revoked
- if(meshlink_verify(mesh2, foo, testdata1, sizeof(testdata1), sig, siglen / 2)) {
- fprintf(stderr, "False positive verification with half sized signature\n");
- return 1;
- }
-
- if(meshlink_verify(mesh2, foo, testdata1, sizeof(testdata1), sig, siglen * 2)) {
- fprintf(stderr, "False positive verification with double sized signature\n");
- return 1;
- }
-
- if(meshlink_verify(mesh2, foo, testdata2, sizeof(testdata2), sig, siglen)) {
- fprintf(stderr, "False positive verification with wrong data\n");
- return 1;
- }
-
- if(meshlink_verify(mesh2, bar, testdata1, sizeof(testdata1), sig, siglen)) {
- fprintf(stderr, "False positive verification with wrong signer\n");
- return 1;
- }
+ assert(!meshlink_verify(mesh_b, a, testdata1, sizeof(testdata1), sig, siglen / 2));
+ assert(!meshlink_verify(mesh_b, a, testdata1, sizeof(testdata1), sig, siglen * 2));
+ assert(!meshlink_verify(mesh_b, a, testdata2, sizeof(testdata2), sig, siglen));
+ assert(!meshlink_verify(mesh_b, b, testdata1, sizeof(testdata1), sig, siglen));
// Clean up.
- meshlink_close(mesh2);
- meshlink_close(mesh1);
-
- return 0;
+ close_meshlink_pair(mesh_a, mesh_b);
}
+++ /dev/null
-#!/bin/sh
-
-rm -Rf sign_verify_conf*
-./sign-verify
#include "devtools.h"
#include "utils.h"
-static void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
- (void)mesh;
+static struct sync_flag received;
+static struct sync_flag bar_learned_baz;
+static struct sync_flag baz_learned_bar;
- static struct timeval tv0;
- struct timeval tv;
+static void receive_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
+ (void)mesh;
+ (void)source;
- if(tv0.tv_sec == 0) {
- gettimeofday(&tv0, NULL);
+ if(len == 5 && !memcmp(data, "Hello", 5)) {
+ set_sync_flag(&received, true);
}
+}
- gettimeofday(&tv, NULL);
- fprintf(stderr, "%u.%.03u ", (unsigned int)(tv.tv_sec - tv0.tv_sec), (unsigned int)tv.tv_usec / 1000);
+static void bar_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+ (void)mesh;
+ (void)reachable;
- if(mesh) {
- fprintf(stderr, "(%s) ", mesh->name);
+ if(!strcmp(node->name, "baz")) {
+ set_sync_flag(&bar_learned_baz, true);
}
-
- fprintf(stderr, "[%d] %s\n", level, text);
}
-static bool received = false;
-
-static void receive_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
+static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
(void)mesh;
- (void)source;
+ (void)reachable;
- fprintf(stderr, "RECEIVED SOMETHING\n");
-
- if(len == 5 && !memcmp(data, "Hello", 5)) {
- received = true;
+ if(!strcmp(node->name, "bar")) {
+ set_sync_flag(&baz_learned_bar, true);
}
}
int main() {
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
// Create three instances.
const char *name[3] = {"foo", "bar", "baz"};
char *path = NULL;
assert(asprintf(&path, "trio_conf.%d", i) != -1 && path);
+ assert(meshlink_destroy(path));
mesh[i] = meshlink_open(path, name[i], "trio", DEV_CLASS_BACKBONE);
assert(mesh[i]);
free(path);
// start the nodes
+ meshlink_set_node_status_cb(mesh[1], bar_status_cb);
+ meshlink_set_node_status_cb(mesh[2], baz_status_cb);
+
for(int i = 0; i < 3; i++) {
free(data[i]);
assert(meshlink_start(mesh[i]));
// the nodes should now learn about each other
- assert_after(meshlink_get_node(mesh[1], name[2]), 5);
- assert_after(meshlink_get_node(mesh[2], name[1]), 5);
+ assert(wait_sync_flag(&bar_learned_baz, 5));
+ assert(wait_sync_flag(&baz_learned_bar, 5));
// Send a packet, expect it is received
meshlink_set_receive_cb(mesh[1], receive_cb);
- assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 15);
+
+ for(int i = 0; i < 15; i++) {
+ assert(meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5));
+
+ if(wait_sync_flag(&received, 1)) {
+ break;
+ }
+ }
+
+ assert(wait_sync_flag(&received, 15));
// Check that the second and third node have autoconnected to each other
// Communication should still be possible
- assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 15);
+ set_sync_flag(&received, false);
+
+ for(int i = 0; i < 15; i++) {
+ assert(meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5));
+
+ if(wait_sync_flag(&received, 1)) {
+ break;
+ }
+ }
+
+ assert(wait_sync_flag(&received, 15));
// Stop the other nodes
// Start just the other two nodes
- meshlink_set_log_cb(mesh[1], MESHLINK_DEBUG, log_cb);
-
for(int i = 1; i < 3; i++) {
assert(meshlink_start(mesh[i]));
}
// Communication should still be possible
- received = false;
- assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 25);
+ set_sync_flag(&received, false);
+
+ for(int i = 0; i < 15; i++) {
+ assert(meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5));
+
+ if(wait_sync_flag(&received, 1)) {
+ break;
+ }
+ }
+
+ assert(wait_sync_flag(&received, 1));
// Clean up.
+++ /dev/null
-#!/bin/sh
-
-rm -Rf trio_conf.*
-./trio
#include "devtools.h"
#include "utils.h"
-static void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
- (void)mesh;
+static struct sync_flag received;
+static struct sync_flag bar_learned_baz;
+static struct sync_flag baz_learned_bar;
- static struct timeval tv0;
- struct timeval tv;
+static void receive_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
+ (void)mesh;
+ (void)source;
- if(tv0.tv_sec == 0) {
- gettimeofday(&tv0, NULL);
+ if(len == 5 && !memcmp(data, "Hello", 5)) {
+ set_sync_flag(&received, true);
}
+}
- gettimeofday(&tv, NULL);
- fprintf(stderr, "%u.%.03u ", (unsigned int)(tv.tv_sec - tv0.tv_sec), (unsigned int)tv.tv_usec / 1000);
+static void bar_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+ (void)mesh;
+ (void)reachable;
- if(mesh) {
- fprintf(stderr, "(%s) ", mesh->name);
+ if(!strcmp(node->name, "baz")) {
+ set_sync_flag(&bar_learned_baz, true);
}
-
- fprintf(stderr, "[%d] %s\n", level, text);
}
-static bool received = false;
-
-static void receive_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
+static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
(void)mesh;
- (void)source;
+ (void)reachable;
- fprintf(stderr, "RECEIVED SOMETHING\n");
-
- if(len == 5 && !memcmp(data, "Hello", 5)) {
- received = true;
+ if(!strcmp(node->name, "bar")) {
+ set_sync_flag(&baz_learned_bar, true);
}
}
int main() {
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
// Create three instances.
const char *name[3] = {"foo", "bar", "baz"};
char *path = NULL;
assert(asprintf(&path, "trio2_conf.%d", i) != -1 && path);
+ assert(meshlink_destroy(path));
mesh[i] = meshlink_open(path, name[i], "trio2", DEV_CLASS_BACKBONE);
assert(mesh[i]);
free(path);
assert(data[i]);
}
- meshlink_set_log_cb(mesh[1], MESHLINK_DEBUG, log_cb);
-
// first node knows the two other nodes
for(int i = 1; i < 3; i++) {
// start the nodes
+ meshlink_set_node_status_cb(mesh[1], bar_status_cb);
+ meshlink_set_node_status_cb(mesh[2], baz_status_cb);
+
for(int i = 0; i < 3; i++) {
free(data[i]);
assert(meshlink_start(mesh[i]));
// the nodes should now learn about each other
- assert_after(meshlink_get_node(mesh[1], name[2]), 5);
- assert_after(meshlink_get_node(mesh[2], name[1]), 5);
+ assert(wait_sync_flag(&bar_learned_baz, 5));
+ assert(wait_sync_flag(&baz_learned_bar, 5));
// Check that the second and third node autoconnect to each other
// Start just the other two nodes
- meshlink_set_log_cb(mesh[1], MESHLINK_DEBUG, log_cb);
-
for(int i = 1; i < 3; i++) {
assert(meshlink_start(mesh[i]));
}
// Communication should still be possible
- received = false;
meshlink_set_receive_cb(mesh[1], receive_cb);
- assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 25);
+
+ for(int i = 0; i < 25; i++) {
+ assert(meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5));
+
+ if(wait_sync_flag(&received, 1)) {
+ break;
+ }
+ }
+
+ assert(wait_sync_flag(&received, 1));
// Clean up.
+++ /dev/null
-#!/bin/sh
-
-rm -Rf trio2_conf.*
-./trio2
#include <pthread.h>
#include <assert.h>
#include <errno.h>
+#include <time.h>
#include "utils.h"
*pa = *pb = NULL;
char *a_name, *b_name;
- int ret_val;
- (void)ret_val;
- ret_val = asprintf(&a_name, "%s_conf.1", prefix);
+ assert(asprintf(&a_name, "%s_conf.1", prefix) > 0);
assert(a_name);
- ret_val = asprintf(&b_name, "%s_conf.2", prefix);
+ assert(asprintf(&b_name, "%s_conf.2", prefix) > 0);
assert(b_name);
+ assert(meshlink_destroy(a_name));
+ assert(meshlink_destroy(b_name));
+
meshlink_handle_t *a = meshlink_open(a_name, "a", prefix, DEV_CLASS_BACKBONE);
assert(a);
a->priv = &pair_status;
meshlink_set_node_status_cb(a, pair_status_cb);
- meshlink_start(a);
- meshlink_start(b);
+ assert(meshlink_start(a));
+ assert(meshlink_start(b));
assert(wait_sync_flag(&pair_status, 5));
meshlink_stop(b);
}
-void close_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b, const char *prefix) {
- int ret_val;
- (void)ret_val;
+void close_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b) {
meshlink_close(a);
meshlink_close(b);
+}
- if(prefix) {
- char *a_name, *b_name;
+void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
+ static const char *levelstr[] = {
+ [MESHLINK_DEBUG] = "DEBUG",
+ [MESHLINK_INFO] = "INFO",
+ [MESHLINK_WARNING] = "WARNING",
+ [MESHLINK_ERROR] = "ERROR",
+ [MESHLINK_CRITICAL] = "CRITICAL",
+ };
- ret_val = asprintf(&a_name, "%s_conf.1", prefix);
- assert(a_name);
- assert(meshlink_destroy(a_name));
+ static struct timespec ts0;
+ struct timespec ts;
- ret_val = asprintf(&b_name, "%s_conf.2", prefix);
- assert(b_name);
- assert(meshlink_destroy(b_name));
+ clock_gettime(CLOCK_MONOTONIC, &ts);
- free(a_name);
- free(b_name);
+ if(ts0.tv_sec == 0) {
+ ts0 = ts;
}
+
+ float diff = (ts.tv_sec - ts0.tv_sec) + (ts.tv_nsec - ts0.tv_nsec) * 1e-9;
+
+ fprintf(stderr, "%7.3f (%s) [%s] %s\n",
+ diff,
+ mesh ? mesh->name : "",
+ levelstr[level],
+ text);
}
extern void stop_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b);
/// Stop and cleanup a pair of meshlink instances.
-extern void close_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b, const char *prefix);
+extern void close_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b);
/// Link two meshlink instances.
extern void link_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b);
+/// Default log callback
+extern void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text);
+
#define assert_after(cond, timeout)\
do {\
for(int i = 0; i++ <= timeout;) {\
sleep(1);\
}\
} while(0)
+
#endif