]> git.meshlink.io Git - meshlink/blob - test/channels-fork.c
ecbc9d5887b67fb0baa58352746bfc127b89d755
[meshlink] / test / channels-fork.c
1 #define _GNU_SOURCE 1
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "../src/meshlink.h"
8
9 volatile bool bar_reachable = false;
10 volatile bool bar_responded = false;
11
12 void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
13         if(mesh) {
14                 fprintf(stderr, "(%s) ", mesh->name);
15         }
16
17         fprintf(stderr, "[%d] %s\n", level, text);
18 }
19
20 void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
21         (void)mesh;
22
23         if(!strcmp(node->name, "bar")) {
24                 bar_reachable = reachable;
25         }
26 }
27
28 void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
29         (void)mesh;
30         (void)channel;
31         (void)len;
32
33         if(len == 5 && !memcmp(data, "Hello", 5)) {
34                 bar_responded = true;
35         }
36 }
37
38 void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
39         // Echo the data back.
40         meshlink_channel_send(mesh, channel, data, len);
41 }
42
43 bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
44         (void)mesh;
45         (void)channel;
46         (void)port;
47         (void)data;
48         (void)len;
49
50         return false;
51 }
52
53 bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
54         if(port != 7) {
55                 return false;
56         }
57
58         meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
59
60         if(data) {
61                 bar_receive_cb(mesh, channel, data, len);
62         }
63
64         return true;
65 }
66
67 void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
68         (void)len;
69
70         meshlink_set_channel_poll_cb(mesh, channel, NULL);
71
72         if(meshlink_channel_send(mesh, channel, "Hello", 5) != 5) {
73                 fprintf(stderr, "Could not send whole message\n");
74         }
75 }
76
77 int main1(int rfd, int wfd) {
78         int ret_val;
79         (void)ret_val;
80         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
81
82         meshlink_handle_t *mesh1 = meshlink_open("channels_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
83
84         if(!mesh1) {
85                 fprintf(stderr, "Could not initialize configuration for foo\n");
86                 return 1;
87         }
88
89         meshlink_enable_discovery(mesh1, false);
90
91         meshlink_add_address(mesh1, "localhost");
92
93         char *data = meshlink_export(mesh1);
94
95         if(!data) {
96                 fprintf(stderr, "Foo could not export its configuration\n");
97                 return 1;
98         }
99
100         size_t len = strlen(data);
101         ret_val = write(wfd, &len, sizeof(len));
102         ret_val = write(wfd, data, len);
103         free(data);
104
105         ret_val = read(rfd, &len, sizeof(len));
106         char indata[len + 1];
107         ret_val = read(rfd, indata, len);
108         indata[len] = 0;
109
110         fprintf(stderr, "Foo exchanged data\n");
111
112         meshlink_import(mesh1, indata);
113
114         meshlink_set_channel_accept_cb(mesh1, reject_cb);
115         meshlink_set_node_status_cb(mesh1, status_cb);
116
117         if(!meshlink_start(mesh1)) {
118                 fprintf(stderr, "Foo could not start\n");
119                 return 1;
120         }
121
122         for(int i = 0; i < 20; i++) {
123                 sleep(1);
124
125                 if(bar_reachable) {
126                         break;
127                 }
128         }
129
130         if(!bar_reachable) {
131                 fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
132                 return 1;
133         }
134
135         // Open a channel from foo to bar.
136
137         meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
138
139         if(!bar) {
140                 fprintf(stderr, "Foo could not find bar\n");
141                 return 1;
142         }
143
144         meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, foo_receive_cb, NULL, 0);
145         meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
146
147         for(int i = 0; i < 5; i++) {
148                 sleep(1);
149
150                 if(bar_responded) {
151                         break;
152                 }
153         }
154
155         if(!bar_responded) {
156                 fprintf(stderr, "Bar did not respond to foo's channel message\n");
157                 return 1;
158         }
159
160         meshlink_channel_close(mesh1, channel);
161
162         // Clean up.
163
164         meshlink_close(mesh1);
165
166         return 0;
167 }
168
169
170 int main2(int rfd, int wfd) {
171         int ret_val;
172         (void)ret_val;
173         sleep(1);
174
175         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
176
177         meshlink_handle_t *mesh2 = meshlink_open("channels_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
178
179         if(!mesh2) {
180                 fprintf(stderr, "Could not initialize configuration for bar\n");
181                 return 1;
182         }
183
184         meshlink_enable_discovery(mesh2, false);
185
186         char *data = meshlink_export(mesh2);
187
188         if(!data) {
189                 fprintf(stderr, "Bar could not export its configuration\n");
190                 return 1;
191         }
192
193         size_t len = strlen(data);
194
195         if(write(wfd, &len, sizeof(len)) <= 0) {
196                 abort();
197         }
198
199         if(write(wfd, data, len) <= 0) {
200                 abort();
201         }
202
203         free(data);
204
205         ret_val = read(rfd, &len, sizeof(len));
206         char indata[len + 1];
207         ret_val = read(rfd, indata, len);
208         indata[len] = 0;
209
210         fprintf(stderr, "Bar exchanged data\n");
211
212         meshlink_import(mesh2, indata);
213
214         meshlink_set_channel_accept_cb(mesh2, accept_cb);
215
216         if(!meshlink_start(mesh2)) {
217                 fprintf(stderr, "Bar could not start\n");
218                 return 1;
219         }
220
221         sleep(20);
222
223         // Clean up.
224
225         meshlink_close(mesh2);
226
227         return 0;
228 }
229
230
231 int main() {
232         int ret_val;
233         (void)ret_val;
234         int fda[2], fdb[2];
235
236         ret_val = pipe2(fda, 0);
237         ret_val = pipe2(fdb, 0);
238
239         if(fork()) {
240                 return main1(fda[0], fdb[1]);
241         } else {
242                 return main2(fdb[0], fda[1]);
243         }
244 }