16 struct sync_flag bar_reachable;
18 void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
21 if(reachable && !strcmp(node->name, "bar")) {
22 set_sync_flag(&bar_reachable, true);
27 struct meshlink_node **nodes = NULL;
30 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
32 // Open new meshlink instances.
34 assert(meshlink_destroy("get_all_nodes_conf.1"));
35 assert(meshlink_destroy("get_all_nodes_conf.2"));
36 assert(meshlink_destroy("get_all_nodes_conf.3"));
38 meshlink_handle_t *mesh[3];
39 mesh[0] = meshlink_open("get_all_nodes_conf.1", "foo", "import-export", DEV_CLASS_BACKBONE);
42 mesh[1] = meshlink_open("get_all_nodes_conf.2", "bar", "import-export", DEV_CLASS_STATIONARY);
45 mesh[2] = meshlink_open("get_all_nodes_conf.3", "baz", "get-all-nodes", DEV_CLASS_STATIONARY);
48 // Check that we only know about ourself.
50 nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes);
52 assert(nodes[0] == meshlink_get_self(mesh[0]));
54 // We should never have been online.
56 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
59 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
61 assert(nodes[0] == meshlink_get_self(mesh[0]));
63 // Let nodes know about each other.
65 for(int i = 0; i < 3; i++) {
66 meshlink_enable_discovery(mesh[i], false);
67 assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL));
68 char *data = meshlink_export(mesh[i]);
71 for(int j = 0; j < 3; j++) {
76 assert(meshlink_import(mesh[j], data));
80 // We should know about all nodes now, and their device class.
82 nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes);
85 nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_BACKBONE, nodes, &nnodes);
87 assert(nodes[0] == meshlink_get_self(mesh[0]));
89 nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_STATIONARY, nodes, &nnodes);
92 // But no node should have been online.
94 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
97 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
102 time_t foo_started = time(NULL);
103 assert(meshlink_start(mesh[0]));
105 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
107 assert(nodes[0] == meshlink_get_self(mesh[0]));
109 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
112 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], foo_started - 1, -1, nodes, &nnodes);
114 assert(nodes[0] == meshlink_get_self(mesh[0]));
116 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started - 1, nodes, &nnodes);
119 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes);
121 assert(nodes[0] == meshlink_get_self(mesh[0]));
123 // Start bar and wait for it to connect.
125 meshlink_set_node_status_cb(mesh[0], status_cb);
128 assert(meshlink_start(mesh[1]));
129 assert(wait_sync_flag(&bar_reachable, 20));
130 time_t bar_started = time(NULL);
132 // Validate time ranges.
134 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
137 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
139 assert(nodes[0] == meshlink_get_node(mesh[0], "baz"));
141 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes);
143 assert(nodes[0] == meshlink_get_self(mesh[0]));
145 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes);
147 assert(nodes[0] == meshlink_get_node(mesh[0], "bar"));
148 assert(nodes[1] == meshlink_get_self(mesh[0]));
152 meshlink_stop(mesh[1]);
154 time_t bar_stopped = time(NULL);
156 // Validate we can see when bar was reachable.
158 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_stopped, bar_stopped, nodes, &nnodes);
160 assert(nodes[0] == meshlink_get_self(mesh[0]));
162 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes);
164 assert(nodes[0] == meshlink_get_node(mesh[0], "bar"));
165 assert(nodes[1] == meshlink_get_self(mesh[0]));
167 // Close and restart foo, check that it remembers correctly.
169 meshlink_close(mesh[0]);
171 time_t foo_stopped = time(NULL);
172 mesh[0] = meshlink_open("get_all_nodes_conf.1", "foo", "import-export", DEV_CLASS_BACKBONE);
175 nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes);
178 nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_BACKBONE, nodes, &nnodes);
180 assert(nodes[0] == meshlink_get_self(mesh[0]));
182 nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_STATIONARY, nodes, &nnodes);
185 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
187 assert(nodes[0] == meshlink_get_node(mesh[0], "baz"));
189 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
192 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started - 1, nodes, &nnodes);
195 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes);
197 assert(nodes[0] == meshlink_get_self(mesh[0]));
199 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes);
201 assert(nodes[0] == meshlink_get_node(mesh[0], "bar"));
202 assert(nodes[1] == meshlink_get_self(mesh[0]));
204 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_stopped, bar_stopped, nodes, &nnodes);
206 assert(nodes[0] == meshlink_get_self(mesh[0]));
208 nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], foo_stopped, -1, nodes, &nnodes);
213 for(int i = 0; i < 3; i++) {
214 meshlink_close(mesh[i]);