]> git.meshlink.io Git - meshlink-tiny/blob - test/blacklist.c
Remove support for meshlink_invite().
[meshlink-tiny] / test / blacklist.c
1 #define _GNU_SOURCE
2
3 #ifdef NDEBUG
4 #undef NDEBUG
5 #endif
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <assert.h>
13 #include <sys/time.h>
14 #include <dirent.h>
15
16 #include "meshlink.h"
17 #include "devtools.h"
18 #include "utils.h"
19
20 static struct sync_flag bar_connected;
21 static struct sync_flag bar_disconnected;
22 static struct sync_flag bar_blacklisted;
23 static struct sync_flag baz_connected;
24
25 static void foo_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
26         (void)mesh;
27         (void)reachable;
28
29         if(!strcmp(node->name, "bar")) {
30                 if(reachable) {
31                         set_sync_flag(&bar_connected, true);
32                 } else {
33                         set_sync_flag(&bar_disconnected, true);
34                 }
35         }
36 }
37
38 static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
39         (void)mesh;
40         (void)reachable;
41
42         if(!strcmp(node->name, "bar")) {
43                 if(reachable) {
44                         set_sync_flag(&baz_connected, true);
45                 }
46         }
47 }
48
49 static void bar_blacklisted_cb(meshlink_handle_t *mesh, meshlink_node_t *node) {
50         (void)mesh;
51
52         if(!strcmp(node->name, "foo")) {
53                 set_sync_flag(&bar_blacklisted, true);
54         }
55 }
56
57 int main(void) {
58         init_sync_flag(&bar_connected);
59         init_sync_flag(&bar_disconnected);
60         init_sync_flag(&bar_blacklisted);
61         init_sync_flag(&baz_connected);
62
63         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
64
65         // Create three instances.
66
67         const char *name[3] = {"foo", "bar", "baz"};
68         meshlink_handle_t *mesh[3];
69         char *data[3];
70
71         for(int i = 0; i < 3; i++) {
72                 char *path = NULL;
73                 assert(asprintf(&path, "blacklist_conf.%d", i) != -1 && path);
74
75                 assert(meshlink_destroy(path));
76                 mesh[i] = meshlink_open(path, name[i], "blacklist", DEV_CLASS_BACKBONE);
77                 assert(mesh[i]);
78                 free(path);
79
80                 assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL));
81
82                 data[i] = meshlink_export(mesh[i]);
83                 assert(data[i]);
84
85                 // Enable default blacklist on all nodes.
86                 meshlink_set_default_blacklist(mesh[i], true);
87         }
88
89         // The first node knows the two other nodes.
90
91         for(int i = 1; i < 3; i++) {
92                 assert(meshlink_import(mesh[i], data[0]));
93                 assert(meshlink_import(mesh[0], data[i]));
94
95                 assert(meshlink_get_node(mesh[i], name[0]));
96                 assert(meshlink_get_node(mesh[0], name[i]));
97
98         }
99
100         for(int i = 0; i < 3; i++) {
101                 free(data[i]);
102         }
103
104         // Second and third node should not know each other yet.
105
106         assert(!meshlink_get_node(mesh[1], name[2]));
107         assert(!meshlink_get_node(mesh[2], name[1]));
108
109         // Check default blacklist status
110
111         assert(!meshlink_get_node_blacklisted(mesh[0], meshlink_get_self(mesh[0])));
112         assert(!meshlink_get_node_blacklisted(mesh[0], meshlink_get_node(mesh[0], name[1])));
113         assert(meshlink_get_node_blacklisted(mesh[1], meshlink_get_node(mesh[1], name[2])));
114         assert(meshlink_get_node_blacklisted(mesh[2], meshlink_get_node(mesh[2], name[1])));
115
116         // Whitelisting and blacklisting by name should work.
117
118         assert(meshlink_whitelist_by_name(mesh[0], "quux"));
119         assert(meshlink_blacklist_by_name(mesh[0], "xyzzy"));
120         assert(meshlink_get_node(mesh[0], "quux"));
121         assert(!meshlink_get_node_blacklisted(mesh[0], meshlink_get_node(mesh[0], "quux")));
122         assert(meshlink_get_node_blacklisted(mesh[0], meshlink_get_node(mesh[0], "xyzzy")));
123
124         meshlink_node_t **nodes = NULL;
125         size_t nnodes = 0;
126         nodes = meshlink_get_all_nodes_by_blacklisted(mesh[0], true, nodes, &nnodes);
127         assert(nnodes == 1);
128         assert(!strcmp(nodes[0]->name, "xyzzy"));
129
130         nodes = meshlink_get_all_nodes_by_blacklisted(mesh[0], false, nodes, &nnodes);
131         assert(nnodes == 4);
132         assert(!strcmp(nodes[0]->name, "bar"));
133         assert(!strcmp(nodes[1]->name, "baz"));
134         assert(!strcmp(nodes[2]->name, "foo"));
135         assert(!strcmp(nodes[3]->name, "quux"));
136
137         free(nodes);
138
139         // Since these nodes now exist we should be able to forget them.
140
141         assert(meshlink_forget_node(mesh[0], meshlink_get_node(mesh[0], "quux")));
142         assert(meshlink_get_node_blacklisted(mesh[0], meshlink_get_node(mesh[0], "quux"))); // default blacklisted again
143
144         // Start the nodes.
145
146         meshlink_set_node_status_cb(mesh[0], foo_status_cb);
147         meshlink_set_node_status_cb(mesh[2], baz_status_cb);
148
149         for(int i = 0; i < 3; i++) {
150                 assert(meshlink_start(mesh[i]));
151         }
152
153         // Wait for them to connect.
154
155         assert(wait_sync_flag(&bar_connected, 5));
156
157         // Blacklist bar
158
159         meshlink_set_blacklisted_cb(mesh[1], bar_blacklisted_cb);
160
161         set_sync_flag(&bar_disconnected, false);
162         assert(meshlink_blacklist(mesh[0], meshlink_get_node(mesh[0], name[1])));
163         assert(wait_sync_flag(&bar_disconnected, 5));
164         assert(meshlink_get_node_blacklisted(mesh[0], meshlink_get_node(mesh[0], name[1])));
165
166         assert(wait_sync_flag(&bar_blacklisted, 10));
167
168         // Whitelist bar
169
170         set_sync_flag(&bar_connected, false);
171         assert(meshlink_whitelist(mesh[0], meshlink_get_node(mesh[0], name[1])));
172         assert(wait_sync_flag(&bar_connected, 15));
173         assert(!meshlink_get_node_blacklisted(mesh[0], meshlink_get_node(mesh[0], name[1])));
174
175         // Bar should not connect to baz
176
177         assert(wait_sync_flag(&baz_connected, 5) == false);
178
179         // But it should know about baz by now
180
181         meshlink_node_t *bar = meshlink_get_node(mesh[2], "bar");
182         meshlink_node_t *baz = meshlink_get_node(mesh[1], "baz");
183         assert(bar);
184         assert(baz);
185
186         // Have bar and baz whitelist each other
187
188         assert(meshlink_whitelist(mesh[1], baz));
189         assert(meshlink_whitelist(mesh[2], bar));
190         assert(!meshlink_get_node_blacklisted(mesh[1], baz));
191         assert(!meshlink_get_node_blacklisted(mesh[2], bar));
192
193         // They should connect to each other
194
195         assert(wait_sync_flag(&baz_connected, 15));
196
197         // Trying to forget an active node should fail.
198
199         assert(!meshlink_forget_node(mesh[1], baz));
200
201         // We need to re-acquire the handle to baz
202
203         baz = meshlink_get_node(mesh[1], "baz");
204         assert(baz);
205
206         // Stop the mesh.
207
208         for(int i = 0; i < 3; i++) {
209                 meshlink_stop(mesh[i]);
210         }
211
212         // Forgetting a node should work now.
213
214         assert(meshlink_forget_node(mesh[1], baz));
215
216         // Clean up.
217
218         for(int i = 0; i < 3; i++) {
219                 meshlink_close(mesh[i]);
220         }
221
222         // Check that foo has a config file for xyzzy but not quux
223         assert(access("blacklist_conf.0/current/hosts/xyzzy", F_OK) == 0);
224         assert(access("blacklist_conf.0/current/hosts/quux", F_OK) != 0 && errno == ENOENT);
225
226         // Check that bar has no config file for baz
227         assert(access("blacklist_conf.2/current/hosts/bar", F_OK) == 0);
228         assert(access("blacklist_conf.1/current/hosts/baz", F_OK) != 0 && errno == ENOENT);
229
230         // Check that we remember xyzzy but not quux after reopening the mesh
231         mesh[0] = meshlink_open("blacklist_conf.0", "foo", "blacklist", DEV_CLASS_BACKBONE);
232         assert(mesh[0]);
233         assert(meshlink_get_node(mesh[0], "xyzzy"));
234         assert(!meshlink_get_node(mesh[0], "quux"));
235
236         meshlink_close(mesh[0]);
237 }