]> git.meshlink.io Git - meshlink-tiny/blob - test/trio.c
Rename the library and public header to meshlink-tiny.
[meshlink-tiny] / test / trio.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-tiny.h"
16 #include "devtools.h"
17 #include "utils.h"
18
19 static struct sync_flag received;
20 static struct sync_flag bar_learned_baz;
21 static struct sync_flag baz_learned_bar;
22
23 static void receive_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
24         (void)mesh;
25         (void)source;
26
27         if(len == 5 && !memcmp(data, "Hello", 5)) {
28                 set_sync_flag(&received, true);
29         }
30 }
31
32 static void bar_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
33         (void)mesh;
34         (void)reachable;
35
36         if(!strcmp(node->name, "baz")) {
37                 set_sync_flag(&bar_learned_baz, true);
38         }
39 }
40
41 static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
42         (void)mesh;
43         (void)reachable;
44
45         if(!strcmp(node->name, "bar")) {
46                 set_sync_flag(&baz_learned_bar, true);
47         }
48 }
49
50 int main(void) {
51         init_sync_flag(&received);
52         init_sync_flag(&bar_learned_baz);
53         init_sync_flag(&baz_learned_bar);
54
55         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
56
57         // Create three instances.
58
59         const char *name[3] = {"foo", "bar", "baz"};
60         meshlink_handle_t *mesh[3];
61         char *data[3];
62
63         for(int i = 0; i < 3; i++) {
64                 char *path = NULL;
65                 assert(asprintf(&path, "trio_conf.%d", i) != -1 && path);
66
67                 assert(meshlink_destroy(path));
68                 mesh[i] = meshlink_open(path, name[i], "trio", DEV_CLASS_BACKBONE);
69                 assert(mesh[i]);
70                 free(path);
71
72                 assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL));
73
74                 data[i] = meshlink_export(mesh[i]);
75                 assert(data[i]);
76         }
77
78         // first node knows the two other nodes
79
80         for(int i = 1; i < 3; i++) {
81                 assert(meshlink_import(mesh[i], data[0]));
82                 assert(meshlink_import(mesh[0], data[i]));
83
84                 assert(meshlink_get_node(mesh[i], name[0]));
85                 assert(meshlink_get_node(mesh[0], name[i]));
86         }
87
88         // second and third node should not know each other yet
89
90         assert(!meshlink_get_node(mesh[1], name[2]));
91         assert(!meshlink_get_node(mesh[2], name[1]));
92
93         // start the nodes
94
95         meshlink_set_node_status_cb(mesh[1], bar_status_cb);
96         meshlink_set_node_status_cb(mesh[2], baz_status_cb);
97
98         for(int i = 0; i < 3; i++) {
99                 free(data[i]);
100                 assert(meshlink_start(mesh[i]));
101         }
102
103         // the nodes should now learn about each other
104
105         assert(wait_sync_flag(&bar_learned_baz, 5));
106         assert(wait_sync_flag(&baz_learned_bar, 5));
107
108         // Send a packet, expect it is received
109
110         meshlink_set_receive_cb(mesh[1], receive_cb);
111
112         for(int i = 0; i < 15; i++) {
113                 assert(meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5));
114
115                 if(wait_sync_flag(&received, 1)) {
116                         break;
117                 }
118         }
119
120         assert(wait_sync_flag(&received, 15));
121
122         // Check that the second and third node have autoconnected to each other
123
124         devtool_edge_t *edges = NULL;
125         size_t nedges = 0;
126         assert_after((edges = devtool_get_all_edges(mesh[1], edges, &nedges), nedges == 3), 15);
127         free(edges);
128
129         // Stop the first node
130
131         meshlink_stop(mesh[0]);
132         sleep(1);
133
134         // Communication should still be possible
135
136         set_sync_flag(&received, false);
137
138         for(int i = 0; i < 15; i++) {
139                 assert(meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5));
140
141                 if(wait_sync_flag(&received, 1)) {
142                         break;
143                 }
144         }
145
146         assert(wait_sync_flag(&received, 15));
147
148         // Stop the other nodes
149
150         for(int i = 1; i < 3; i++) {
151                 meshlink_stop(mesh[i]);
152         }
153
154         sleep(1);
155
156         // Start just the other two nodes
157
158         for(int i = 1; i < 3; i++) {
159                 assert(meshlink_start(mesh[i]));
160         }
161
162         assert(meshlink_get_node(mesh[1], name[2]));
163         assert(meshlink_get_node(mesh[2], name[1]));
164
165         // Communication should still be possible
166
167         set_sync_flag(&received, false);
168
169         for(int i = 0; i < 15; i++) {
170                 assert(meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5));
171
172                 if(wait_sync_flag(&received, 1)) {
173                         break;
174                 }
175         }
176
177         assert(wait_sync_flag(&received, 1));
178
179         // Clean up.
180
181         for(int i = 0; i < 3; i++) {
182                 meshlink_close(mesh[i]);
183         }
184 }