]> git.meshlink.io Git - meshlink/blob - test/blacklist.c
4be4cbd0d45f1fad9c283d9f5d4290f2f8f78493
[meshlink] / 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
15 #include "meshlink.h"
16 #include "devtools.h"
17 #include "utils.h"
18
19 static struct sync_flag bar_connected;
20 static struct sync_flag bar_disconnected;
21 static struct sync_flag baz_connected;
22
23 static void foo_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
24         (void)mesh;
25         (void)reachable;
26
27         if(!strcmp(node->name, "bar")) {
28                 if(reachable) {
29                         set_sync_flag(&bar_connected, true);
30                 } else {
31                         set_sync_flag(&bar_disconnected, true);
32                 }
33         }
34 }
35
36 static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
37         (void)mesh;
38         (void)reachable;
39
40         if(!strcmp(node->name, "bar")) {
41                 if(reachable) {
42                         set_sync_flag(&baz_connected, true);
43                 }
44         }
45 }
46
47 int main() {
48         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
49
50         // Create three instances.
51
52         const char *name[3] = {"foo", "bar", "baz"};
53         meshlink_handle_t *mesh[3];
54         char *data[3];
55
56         for(int i = 0; i < 3; i++) {
57                 char *path = NULL;
58                 assert(asprintf(&path, "blacklist_conf.%d", i) != -1 && path);
59
60                 assert(meshlink_destroy(path));
61                 mesh[i] = meshlink_open(path, name[i], "blacklist", DEV_CLASS_BACKBONE);
62                 assert(mesh[i]);
63                 free(path);
64
65                 assert(meshlink_add_address(mesh[i], "localhost"));
66
67                 data[i] = meshlink_export(mesh[i]);
68                 assert(data[i]);
69
70                 // Enable default blacklist on all nodes.
71                 meshlink_set_default_blacklist(mesh[i], true);
72         }
73
74         // The first node knows the two other nodes.
75
76         for(int i = 1; i < 3; i++) {
77                 assert(meshlink_import(mesh[i], data[0]));
78                 assert(meshlink_import(mesh[0], data[i]));
79
80                 assert(meshlink_get_node(mesh[i], name[0]));
81                 assert(meshlink_get_node(mesh[0], name[i]));
82
83         }
84
85         for(int i = 0; i < 3; i++) {
86                 free(data[i]);
87         }
88
89         // Second and third node should not know each other yet.
90
91         assert(!meshlink_get_node(mesh[1], name[2]));
92         assert(!meshlink_get_node(mesh[2], name[1]));
93
94         // Whitelisting and blacklisting by name should work.
95
96         assert(meshlink_whitelist_by_name(mesh[0], "quux"));
97         assert(meshlink_blacklist_by_name(mesh[0], "xyzzy"));
98
99         // Since these nodes now exist we should be able to forget them.
100
101         assert(meshlink_forget_node(mesh[0], meshlink_get_node(mesh[0], "quux")));
102
103         // Start the nodes.
104
105         meshlink_set_node_status_cb(mesh[0], foo_status_cb);
106         meshlink_set_node_status_cb(mesh[2], baz_status_cb);
107
108         for(int i = 0; i < 3; i++) {
109                 assert(meshlink_start(mesh[i]));
110         }
111
112         // Wait for them to connect.
113
114         assert(wait_sync_flag(&bar_connected, 5));
115
116         // Blacklist bar
117
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));
121
122         // Whitelist bar
123
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));
127
128         // Bar should not connect to baz
129
130         assert(wait_sync_flag(&baz_connected, 5) == false);
131
132         // But it should know about baz by now
133
134         meshlink_node_t *bar = meshlink_get_node(mesh[2], "bar");
135         meshlink_node_t *baz = meshlink_get_node(mesh[1], "baz");
136         assert(bar);
137         assert(baz);
138
139         // Have bar and baz whitelist each other
140
141         assert(meshlink_whitelist(mesh[1], baz));
142         assert(meshlink_whitelist(mesh[2], bar));
143
144         // They should connect to each other
145
146         assert(wait_sync_flag(&baz_connected, 15));
147
148         // Trying to forget an active node should fail.
149
150         assert(!meshlink_forget_node(mesh[1], baz));
151
152         // We need to re-acquire the handle to baz
153
154         baz = meshlink_get_node(mesh[1], "baz");
155         assert(baz);
156
157         // Stop the mesh.
158
159         for(int i = 0; i < 3; i++) {
160                 meshlink_stop(mesh[i]);
161         }
162
163         // Forgetting a node should work now.
164
165         assert(meshlink_forget_node(mesh[1], baz));
166
167         // Clean up.
168
169         for(int i = 0; i < 3; i++) {
170                 meshlink_close(mesh[i]);
171         }
172
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);
176
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);
180
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);
183         assert(mesh[0]);
184         assert(meshlink_get_node(mesh[0], "xyzzy"));
185         assert(!meshlink_get_node(mesh[0], "quux"));
186
187         meshlink_close(mesh[0]);
188 }