]> git.meshlink.io Git - meshlink/blob - test/channels-fork.c
Fix all compiler warnings found using -Wall -W -pedantic.
[meshlink] / test / channels-fork.c
1 #define _GNU_SOURCE
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         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
79
80         meshlink_handle_t *mesh1 = meshlink_open("channels_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
81
82         if(!mesh1) {
83                 fprintf(stderr, "Could not initialize configuration for foo\n");
84                 return 1;
85         }
86
87         meshlink_enable_discovery(mesh1, false);
88
89         meshlink_add_address(mesh1, "localhost");
90
91         char *data = meshlink_export(mesh1);
92
93         if(!data) {
94                 fprintf(stderr, "Foo could not export its configuration\n");
95                 return 1;
96         }
97
98         size_t len = strlen(data);
99         write(wfd, &len, sizeof(len));
100         write(wfd, data, len);
101         free(data);
102
103         read(rfd, &len, sizeof(len));
104         char indata[len + 1];
105         read(rfd, indata, len);
106         indata[len] = 0;
107
108         fprintf(stderr, "Foo exchanged data\n");
109
110         meshlink_import(mesh1, indata);
111
112         meshlink_set_channel_accept_cb(mesh1, reject_cb);
113         meshlink_set_node_status_cb(mesh1, status_cb);
114
115         if(!meshlink_start(mesh1)) {
116                 fprintf(stderr, "Foo could not start\n");
117                 return 1;
118         }
119
120         for(int i = 0; i < 20; i++) {
121                 sleep(1);
122
123                 if(bar_reachable) {
124                         break;
125                 }
126         }
127
128         if(!bar_reachable) {
129                 fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
130                 return 1;
131         }
132
133         // Open a channel from foo to bar.
134
135         meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
136
137         if(!bar) {
138                 fprintf(stderr, "Foo could not find bar\n");
139                 return 1;
140         }
141
142         meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, foo_receive_cb, NULL, 0);
143         meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
144
145         for(int i = 0; i < 5; i++) {
146                 sleep(1);
147
148                 if(bar_responded) {
149                         break;
150                 }
151         }
152
153         if(!bar_responded) {
154                 fprintf(stderr, "Bar did not respond to foo's channel message\n");
155                 return 1;
156         }
157
158         meshlink_channel_close(mesh1, channel);
159
160         // Clean up.
161
162         meshlink_close(mesh1);
163
164         return 0;
165 }
166
167
168 int main2(int rfd, int wfd) {
169         sleep(1);
170
171         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
172
173         meshlink_handle_t *mesh2 = meshlink_open("channels_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
174
175         if(!mesh2) {
176                 fprintf(stderr, "Could not initialize configuration for bar\n");
177                 return 1;
178         }
179
180         meshlink_enable_discovery(mesh2, false);
181
182         char *data = meshlink_export(mesh2);
183
184         if(!data) {
185                 fprintf(stderr, "Bar could not export its configuration\n");
186                 return 1;
187         }
188
189         size_t len = strlen(data);
190
191         if(write(wfd, &len, sizeof(len)) <= 0) {
192                 abort();
193         }
194
195         if(write(wfd, data, len) <= 0) {
196                 abort();
197         }
198
199         free(data);
200
201         read(rfd, &len, sizeof(len));
202         char indata[len + 1];
203         read(rfd, indata, len);
204         indata[len] = 0;
205
206         fprintf(stderr, "Bar exchanged data\n");
207
208         meshlink_import(mesh2, indata);
209
210         meshlink_set_channel_accept_cb(mesh2, accept_cb);
211
212         if(!meshlink_start(mesh2)) {
213                 fprintf(stderr, "Bar could not start\n");
214                 return 1;
215         }
216
217         sleep(20);
218
219         // Clean up.
220
221         meshlink_close(mesh2);
222
223         return 0;
224 }
225
226
227 int main() {
228         int fda[2], fdb[2];
229
230         pipe2(fda, 0);
231         pipe2(fdb, 0);
232
233         if(fork()) {
234                 return main1(fda[0], fdb[1]);
235         } else {
236                 return main2(fdb[0], fda[1]);
237         }
238 }