]> git.meshlink.io Git - meshlink/blobdiff - test/blacklist.c
Add support for black/whitelisting by name, and forgetting nodes.
[meshlink] / test / blacklist.c
diff --git a/test/blacklist.c b/test/blacklist.c
new file mode 100644 (file)
index 0000000..d504460
--- /dev/null
@@ -0,0 +1,180 @@
+#define _GNU_SOURCE
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#include "meshlink.h"
+#include "devtools.h"
+#include "utils.h"
+
+static struct sync_flag bar_connected;
+static struct sync_flag bar_disconnected;
+static struct sync_flag baz_connected;
+
+static void foo_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+       (void)mesh;
+       (void)reachable;
+
+       if(!strcmp(node->name, "bar")) {
+               if(reachable) {
+                       set_sync_flag(&bar_connected, true);
+               } else {
+                       set_sync_flag(&bar_disconnected, true);
+               }
+       }
+}
+
+static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+       (void)mesh;
+       (void)reachable;
+
+       if(!strcmp(node->name, "bar")) {
+               if(reachable) {
+                       set_sync_flag(&baz_connected, true);
+               }
+       }
+}
+
+int main() {
+       meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+       // Create three instances.
+
+       const char *name[3] = {"foo", "bar", "baz"};
+       meshlink_handle_t *mesh[3];
+       char *data[3];
+
+       for(int i = 0; i < 3; i++) {
+               char *path = NULL;
+               assert(asprintf(&path, "blacklist_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);
+
+               assert(meshlink_add_address(mesh[i], "localhost"));
+
+               data[i] = meshlink_export(mesh[i]);
+               assert(data[i]);
+
+               // Enable default blacklist on all nodes.
+               meshlink_set_default_blacklist(mesh[i], true);
+       }
+
+       // The first node knows the two other nodes.
+
+       for(int i = 1; i < 3; i++) {
+               assert(meshlink_import(mesh[i], data[0]));
+               assert(meshlink_import(mesh[0], data[i]));
+
+               assert(meshlink_get_node(mesh[i], name[0]));
+               assert(meshlink_get_node(mesh[0], name[i]));
+
+       }
+
+       for(int i = 0; i < 3; i++) {
+               free(data[i]);
+       }
+
+       // Second and third node should not know each other yet.
+
+       assert(!meshlink_get_node(mesh[1], name[2]));
+       assert(!meshlink_get_node(mesh[2], name[1]));
+
+       // Whitelisting and blacklisting by name should work.
+
+       assert(meshlink_whitelist_by_name(mesh[0], "quux"));
+       assert(meshlink_blacklist_by_name(mesh[0], "xyzzy"));
+
+       // Since these nodes now exist we should be able to forget them.
+
+       assert(meshlink_forget_node(mesh[0], meshlink_get_node(mesh[0], "quux")));
+
+       // Start the nodes.
+
+       meshlink_set_node_status_cb(mesh[0], foo_status_cb);
+       meshlink_set_node_status_cb(mesh[2], baz_status_cb);
+
+       for(int i = 0; i < 3; i++) {
+               assert(meshlink_start(mesh[i]));
+       }
+
+       // Wait for them to connect.
+
+       assert(wait_sync_flag(&bar_connected, 5));
+
+       // Blacklist bar
+
+       set_sync_flag(&bar_disconnected, false);
+       assert(meshlink_blacklist(mesh[0], meshlink_get_node(mesh[0], name[1])));
+       assert(wait_sync_flag(&bar_disconnected, 5));
+
+       // Whitelist bar
+
+       set_sync_flag(&bar_connected, false);
+       assert(meshlink_whitelist(mesh[0], meshlink_get_node(mesh[0], name[1])));
+       assert(wait_sync_flag(&bar_connected, 15));
+
+       // Bar should not connect to baz
+
+       assert(wait_sync_flag(&baz_connected, 5) == false);
+
+       // But it should know about baz by now
+
+       meshlink_node_t *bar = meshlink_get_node(mesh[2], "bar");
+       meshlink_node_t *baz = meshlink_get_node(mesh[1], "baz");
+       assert(bar);
+       assert(baz);
+
+       // Have bar and baz whitelist each other
+
+       assert(meshlink_whitelist(mesh[1], baz));
+       assert(meshlink_whitelist(mesh[2], bar));
+
+       // They should connect to each other
+
+       assert(wait_sync_flag(&baz_connected, 15));
+
+       // Trying to forget an active node should fail.
+
+       assert(!meshlink_forget_node(mesh[1], baz));
+
+       // We need to re-acquire the handle to baz
+
+       baz = meshlink_get_node(mesh[1], "baz");
+       assert(baz);
+
+       // Stop the mesh.
+
+       for(int i = 0; i < 3; i++) {
+               meshlink_stop(mesh[i]);
+       }
+
+       // Forgetting a node should work now.
+
+       assert(meshlink_forget_node(mesh[1], baz));
+
+       // Clean up.
+
+       for(int i = 0; i < 3; i++) {
+               meshlink_close(mesh[i]);
+       }
+
+       // Check that foo has a config file for xyzzy but not quux
+       assert(access("blacklist_conf.0/current/hosts/xyzzy", F_OK) == 0);
+       assert(access("blacklist_conf.0/current/hosts/quux", F_OK) != 0 && errno == ENOENT);
+
+       // Check that bar has no config file for baz
+       assert(access("blacklist_conf.2/current/hosts/bar", F_OK) == 0);
+       assert(access("blacklist_conf.1/current/hosts/baz", F_OK) != 0 && errno == ENOENT);
+}