19 static struct sync_flag bar_connected;
20 static struct sync_flag bar_disconnected;
21 static struct sync_flag baz_connected;
23 static void foo_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
27 if(!strcmp(node->name, "bar")) {
29 set_sync_flag(&bar_connected, true);
31 set_sync_flag(&bar_disconnected, true);
36 static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
40 if(!strcmp(node->name, "bar")) {
42 set_sync_flag(&baz_connected, true);
48 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
50 // Create three instances.
52 const char *name[3] = {"foo", "bar", "baz"};
53 meshlink_handle_t *mesh[3];
56 for(int i = 0; i < 3; i++) {
58 assert(asprintf(&path, "blacklist_conf.%d", i) != -1 && path);
60 assert(meshlink_destroy(path));
61 mesh[i] = meshlink_open(path, name[i], "blacklist", DEV_CLASS_BACKBONE);
65 assert(meshlink_add_address(mesh[i], "localhost"));
67 data[i] = meshlink_export(mesh[i]);
70 // Enable default blacklist on all nodes.
71 meshlink_set_default_blacklist(mesh[i], true);
74 // The first node knows the two other nodes.
76 for(int i = 1; i < 3; i++) {
77 assert(meshlink_import(mesh[i], data[0]));
78 assert(meshlink_import(mesh[0], data[i]));
80 assert(meshlink_get_node(mesh[i], name[0]));
81 assert(meshlink_get_node(mesh[0], name[i]));
85 for(int i = 0; i < 3; i++) {
89 // Second and third node should not know each other yet.
91 assert(!meshlink_get_node(mesh[1], name[2]));
92 assert(!meshlink_get_node(mesh[2], name[1]));
94 // Whitelisting and blacklisting by name should work.
96 assert(meshlink_whitelist_by_name(mesh[0], "quux"));
97 assert(meshlink_blacklist_by_name(mesh[0], "xyzzy"));
99 // Since these nodes now exist we should be able to forget them.
101 assert(meshlink_forget_node(mesh[0], meshlink_get_node(mesh[0], "quux")));
105 meshlink_set_node_status_cb(mesh[0], foo_status_cb);
106 meshlink_set_node_status_cb(mesh[2], baz_status_cb);
108 for(int i = 0; i < 3; i++) {
109 assert(meshlink_start(mesh[i]));
112 // Wait for them to connect.
114 assert(wait_sync_flag(&bar_connected, 5));
118 set_sync_flag(&bar_disconnected, false);
119 assert(meshlink_blacklist(mesh[0], meshlink_get_node(mesh[0], name[1])));
120 assert(wait_sync_flag(&bar_disconnected, 5));
124 set_sync_flag(&bar_connected, false);
125 assert(meshlink_whitelist(mesh[0], meshlink_get_node(mesh[0], name[1])));
126 assert(wait_sync_flag(&bar_connected, 15));
128 // Bar should not connect to baz
130 assert(wait_sync_flag(&baz_connected, 5) == false);
132 // But it should know about baz by now
134 meshlink_node_t *bar = meshlink_get_node(mesh[2], "bar");
135 meshlink_node_t *baz = meshlink_get_node(mesh[1], "baz");
139 // Have bar and baz whitelist each other
141 assert(meshlink_whitelist(mesh[1], baz));
142 assert(meshlink_whitelist(mesh[2], bar));
144 // They should connect to each other
146 assert(wait_sync_flag(&baz_connected, 15));
148 // Trying to forget an active node should fail.
150 assert(!meshlink_forget_node(mesh[1], baz));
152 // We need to re-acquire the handle to baz
154 baz = meshlink_get_node(mesh[1], "baz");
159 for(int i = 0; i < 3; i++) {
160 meshlink_stop(mesh[i]);
163 // Forgetting a node should work now.
165 assert(meshlink_forget_node(mesh[1], baz));
169 for(int i = 0; i < 3; i++) {
170 meshlink_close(mesh[i]);
173 // Check that foo has a config file for xyzzy but not quux
174 assert(access("blacklist_conf.0/current/hosts/xyzzy", F_OK) == 0);
175 assert(access("blacklist_conf.0/current/hosts/quux", F_OK) != 0 && errno == ENOENT);
177 // Check that bar has no config file for baz
178 assert(access("blacklist_conf.2/current/hosts/bar", F_OK) == 0);
179 assert(access("blacklist_conf.1/current/hosts/baz", F_OK) != 0 && errno == ENOENT);
181 // Check that we remember xyzzy but not quux after reopening the mesh
182 mesh[0] = meshlink_open("blacklist_conf.0", "foo", "blacklist", DEV_CLASS_BACKBONE);
184 assert(meshlink_get_node(mesh[0], "xyzzy"));
185 assert(!meshlink_get_node(mesh[0], "quux"));
187 meshlink_close(mesh[0]);