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 init_sync_flag(&bar_connected);
49 init_sync_flag(&bar_disconnected);
50 init_sync_flag(&baz_connected);
52 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
54 // Create three instances.
56 const char *name[3] = {"foo", "bar", "baz"};
57 meshlink_handle_t *mesh[3];
60 for(int i = 0; i < 3; i++) {
62 assert(asprintf(&path, "blacklist_conf.%d", i) != -1 && path);
64 assert(meshlink_destroy(path));
65 mesh[i] = meshlink_open(path, name[i], "blacklist", DEV_CLASS_BACKBONE);
69 assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL));
71 data[i] = meshlink_export(mesh[i]);
74 // Enable default blacklist on all nodes.
75 meshlink_set_default_blacklist(mesh[i], true);
78 // The first node knows the two other nodes.
80 for(int i = 1; i < 3; i++) {
81 assert(meshlink_import(mesh[i], data[0]));
82 assert(meshlink_import(mesh[0], data[i]));
84 assert(meshlink_get_node(mesh[i], name[0]));
85 assert(meshlink_get_node(mesh[0], name[i]));
89 for(int i = 0; i < 3; i++) {
93 // Second and third node should not know each other yet.
95 assert(!meshlink_get_node(mesh[1], name[2]));
96 assert(!meshlink_get_node(mesh[2], name[1]));
98 // Whitelisting and blacklisting by name should work.
100 assert(meshlink_whitelist_by_name(mesh[0], "quux"));
101 assert(meshlink_blacklist_by_name(mesh[0], "xyzzy"));
103 // Since these nodes now exist we should be able to forget them.
105 assert(meshlink_forget_node(mesh[0], meshlink_get_node(mesh[0], "quux")));
109 meshlink_set_node_status_cb(mesh[0], foo_status_cb);
110 meshlink_set_node_status_cb(mesh[2], baz_status_cb);
112 for(int i = 0; i < 3; i++) {
113 assert(meshlink_start(mesh[i]));
116 // Wait for them to connect.
118 assert(wait_sync_flag(&bar_connected, 5));
122 set_sync_flag(&bar_disconnected, false);
123 assert(meshlink_blacklist(mesh[0], meshlink_get_node(mesh[0], name[1])));
124 assert(wait_sync_flag(&bar_disconnected, 5));
128 set_sync_flag(&bar_connected, false);
129 assert(meshlink_whitelist(mesh[0], meshlink_get_node(mesh[0], name[1])));
130 assert(wait_sync_flag(&bar_connected, 15));
132 // Bar should not connect to baz
134 assert(wait_sync_flag(&baz_connected, 5) == false);
136 // But it should know about baz by now
138 meshlink_node_t *bar = meshlink_get_node(mesh[2], "bar");
139 meshlink_node_t *baz = meshlink_get_node(mesh[1], "baz");
143 // Have bar and baz whitelist each other
145 assert(meshlink_whitelist(mesh[1], baz));
146 assert(meshlink_whitelist(mesh[2], bar));
148 // They should connect to each other
150 assert(wait_sync_flag(&baz_connected, 15));
152 // Trying to forget an active node should fail.
154 assert(!meshlink_forget_node(mesh[1], baz));
156 // We need to re-acquire the handle to baz
158 baz = meshlink_get_node(mesh[1], "baz");
163 for(int i = 0; i < 3; i++) {
164 meshlink_stop(mesh[i]);
167 // Forgetting a node should work now.
169 assert(meshlink_forget_node(mesh[1], baz));
173 for(int i = 0; i < 3; i++) {
174 meshlink_close(mesh[i]);
177 // Check that foo has a config file for xyzzy but not quux
178 assert(access("blacklist_conf.0/current/hosts/xyzzy", F_OK) == 0);
179 assert(access("blacklist_conf.0/current/hosts/quux", F_OK) != 0 && errno == ENOENT);
181 // Check that bar has no config file for baz
182 assert(access("blacklist_conf.2/current/hosts/bar", F_OK) == 0);
183 assert(access("blacklist_conf.1/current/hosts/baz", F_OK) != 0 && errno == ENOENT);
185 // Check that we remember xyzzy but not quux after reopening the mesh
186 mesh[0] = meshlink_open("blacklist_conf.0", "foo", "blacklist", DEV_CLASS_BACKBONE);
188 assert(meshlink_get_node(mesh[0], "xyzzy"));
189 assert(!meshlink_get_node(mesh[0], "quux"));
191 meshlink_close(mesh[0]);