]> git.meshlink.io Git - meshlink/commitdiff
Add utility functions to create paired MeshLink instances.
authorGuus Sliepen <guus@meshlink.io>
Sun, 13 Aug 2017 21:07:25 +0000 (23:07 +0200)
committerGuus Sliepen <guus@meshlink.io>
Sun, 13 Aug 2017 21:07:25 +0000 (23:07 +0200)
This also adds a start_meshlink_pair() function which starts the two instances
and waits for them to establish a connection with each other. A condition
variable is used to avoid having to poll.

test/utils.c [new file with mode: 0644]
test/utils.h [new file with mode: 0644]

diff --git a/test/utils.c b/test/utils.c
new file mode 100644 (file)
index 0000000..d7505ce
--- /dev/null
@@ -0,0 +1,114 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "utils.h"
+
+void set_sync_flag(struct sync_flag *s) {
+       pthread_mutex_lock(&s->mutex);
+       s->flag = true;
+       pthread_cond_broadcast(&s->cond);
+       pthread_mutex_unlock(&s->mutex);
+}
+
+bool wait_sync_flag(struct sync_flag *s, int seconds) {
+       struct timespec timeout;
+       clock_gettime(CLOCK_REALTIME, &timeout);
+       timeout.tv_sec += seconds;
+
+       while(!s->flag)
+               if(!pthread_cond_timedwait(&s->cond, &s->mutex, &timeout) || errno != EINTR)
+                       break;
+
+       return s->flag;
+}
+
+void open_meshlink_pair(meshlink_handle_t **pa, meshlink_handle_t **pb, const char *prefix) {
+       // Create two new MeshLink instances
+
+       *pa = *pb = NULL;
+
+       char *a_name, *b_name;
+
+       asprintf(&a_name, "%s_conf.1", prefix);
+       assert(a_name);
+
+       asprintf(&b_name, "%s_conf.2", prefix);
+       assert(b_name);
+
+       meshlink_handle_t *a = meshlink_open(a_name, "a", prefix, DEV_CLASS_BACKBONE);
+       assert(a);
+
+       meshlink_handle_t *b = meshlink_open(b_name, "b", prefix, DEV_CLASS_BACKBONE);
+       assert(b);
+
+       meshlink_enable_discovery(a, false);
+       meshlink_enable_discovery(b, false);
+
+       // Import and export both side's data
+
+       meshlink_add_address(a, "localhost");
+
+       char *data = meshlink_export(a);
+       assert(data);
+       assert(meshlink_import(b, data));
+       free(data);
+
+       data = meshlink_export(b);
+       assert(data);
+       assert(meshlink_import(a, data));
+       free(data);
+
+       *pa = a;
+       *pb = b;
+}
+
+// Don't poll in the application thread, use a condition variable to signal when the peer is online.
+static void pair_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+       set_sync_flag(mesh->priv);
+}
+
+void start_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b) {
+       struct sync_flag pair_status = {};
+
+       a->priv = &pair_status;
+       meshlink_set_node_status_cb(a, pair_status_cb);
+
+       pthread_mutex_lock(&pair_status.mutex);
+
+       meshlink_start(a);
+       meshlink_start(b);
+
+       assert(wait_sync_flag(&pair_status, 5));
+
+       pthread_mutex_unlock(&pair_status.mutex);
+
+       meshlink_set_node_status_cb(a, NULL);
+       a->priv = NULL;
+}
+
+void stop_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b) {
+       meshlink_stop(a);
+       meshlink_stop(b);
+}
+
+void close_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b, const char *prefix) {
+       meshlink_close(a);
+       meshlink_close(b);
+
+       if(prefix) {
+               char *a_name, *b_name;
+
+               asprintf(&a_name, "%s_conf.1", prefix);
+               assert(a_name);
+               assert(meshlink_destroy(a_name));
+
+               asprintf(&b_name, "%s_conf.2", prefix);
+               assert(b_name);
+               assert(meshlink_destroy(b_name));
+       }
+}
diff --git a/test/utils.h b/test/utils.h
new file mode 100644 (file)
index 0000000..e1073df
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef MESHLINK_TEST_UTILS_H
+#define MESHLINK_TEST_UTILS_H
+
+#include "../src/meshlink.h"
+
+// Simple synchronisation between threads
+struct sync_flag {
+       pthread_mutex_t mutex;
+       pthread_cond_t cond;
+       bool flag;
+};
+
+extern void set_sync_flag(struct sync_flag *s);
+extern bool wait_sync_flag(struct sync_flag *s, int seconds);
+
+/// Create a pair of meshlink instances that are already joined together.
+extern void open_meshlink_pair(meshlink_handle_t **a, meshlink_handle_t **b, const char *prefix);
+
+/// Start a pair of meshlink instances and wait for them to connect together.
+extern void start_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b);
+
+/// Stop a pair of meshlink instances.
+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);
+
+#endif
+