]> git.meshlink.io Git - meshlink/blob - test/channels.c
Never automatically try to bind to ports >= 32768.
[meshlink] / test / channels.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/time.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         static struct timeval tv0;
14         struct timeval tv;
15
16         if(tv0.tv_sec == 0) {
17                 gettimeofday(&tv0, NULL);
18         }
19
20         gettimeofday(&tv, NULL);
21         fprintf(stderr, "%u.%.03u ", (unsigned int)(tv.tv_sec - tv0.tv_sec), (unsigned int)tv.tv_usec / 1000);
22
23         if(mesh) {
24                 fprintf(stderr, "(%s) ", mesh->name);
25         }
26
27         fprintf(stderr, "[%d] %s\n", level, text);
28 }
29
30 void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
31         (void)mesh;
32
33         printf("status_cb: %s %sreachable\n", node->name, reachable ? "" : "un");
34
35         if(!strcmp(node->name, "bar")) {
36                 bar_reachable = reachable;
37         }
38 }
39
40 void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
41         (void)mesh;
42         (void)channel;
43
44         printf("foo_receive_cb %zu: ", len);
45         fwrite(data, 1, len, stdout);
46         printf("\n");
47
48         if(len == 5 && !memcmp(data, "Hello", 5)) {
49                 bar_responded = true;
50         }
51 }
52
53 void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
54         printf("bar_receive_cb %zu: ", len);
55         fwrite(data, 1, len, stdout);
56         printf("\n");
57         // Echo the data back.
58         meshlink_channel_send(mesh, channel, data, len);
59 }
60
61 bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
62         (void)mesh;
63         (void)channel;
64         (void)port;
65         (void)data;
66         (void)len;
67
68         return false;
69 }
70
71 bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
72         printf("accept_cb: (from %s on port %u) ", channel->node->name, (unsigned int)port);
73
74         if(data) {
75                 fwrite(data, 1, len, stdout);
76         }
77
78         printf("\n");
79
80         if(port != 7) {
81                 return false;
82         }
83
84         meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
85
86         if(data) {
87                 bar_receive_cb(mesh, channel, data, len);
88         }
89
90         return true;
91 }
92
93 void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
94         (void)len;
95
96         meshlink_set_channel_poll_cb(mesh, channel, NULL);
97
98         if(meshlink_channel_send(mesh, channel, "Hello", 5) != 5) {
99                 fprintf(stderr, "Could not send whole message\n");
100         }
101 }
102
103 int main() {
104         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
105
106         // Open two new meshlink instance.
107
108         meshlink_handle_t *mesh1 = meshlink_open("channels_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
109
110         if(!mesh1) {
111                 fprintf(stderr, "Could not initialize configuration for foo\n");
112                 return 1;
113         }
114
115         meshlink_handle_t *mesh2 = meshlink_open("channels_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
116
117         if(!mesh2) {
118                 fprintf(stderr, "Could not initialize configuration for bar\n");
119                 return 1;
120         }
121
122         meshlink_enable_discovery(mesh1, false);
123         meshlink_enable_discovery(mesh2, false);
124         meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, log_cb);
125         meshlink_set_log_cb(mesh2, MESHLINK_DEBUG, log_cb);
126
127         // Import and export both side's data
128
129         meshlink_add_address(mesh1, "localhost");
130
131         char *data = meshlink_export(mesh1);
132
133         if(!data) {
134                 fprintf(stderr, "Foo could not export its configuration\n");
135                 return 1;
136         }
137
138         if(!meshlink_import(mesh2, data)) {
139                 fprintf(stderr, "Bar could not import foo's configuration\n");
140                 return 1;
141         }
142
143         free(data);
144
145         data = meshlink_export(mesh2);
146
147         if(!data) {
148                 fprintf(stderr, "Bar could not export its configuration\n");
149                 return 1;
150         }
151
152         if(!meshlink_import(mesh1, data)) {
153                 fprintf(stderr, "Foo could not import bar's configuration\n");
154                 return 1;
155         }
156
157         free(data);
158
159         // Set the callbacks.
160
161         meshlink_set_channel_accept_cb(mesh1, reject_cb);
162         meshlink_set_channel_accept_cb(mesh2, accept_cb);
163
164         meshlink_set_node_status_cb(mesh1, status_cb);
165
166         // Start both instances
167
168         if(!meshlink_start(mesh1)) {
169                 fprintf(stderr, "Foo could not start\n");
170                 return 1;
171         }
172
173         if(!meshlink_start(mesh2)) {
174                 fprintf(stderr, "Bar could not start\n");
175                 return 1;
176         }
177
178         // Wait for the two to connect.
179
180         for(int i = 0; i < 20; i++) {
181                 sleep(1);
182
183                 if(bar_reachable) {
184                         break;
185                 }
186         }
187
188         if(!bar_reachable) {
189                 fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
190                 return 1;
191         }
192
193         // Open a channel from foo to bar.
194
195         meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
196
197         if(!bar) {
198                 fprintf(stderr, "Foo could not find bar\n");
199                 return 1;
200         }
201
202         meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, foo_receive_cb, NULL, 0);
203         meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
204
205         for(int i = 0; i < 20; i++) {
206                 sleep(1);
207
208                 if(bar_responded) {
209                         break;
210                 }
211         }
212
213         if(!bar_responded) {
214                 fprintf(stderr, "Bar did not respond to foo's channel message\n");
215                 return 1;
216         }
217
218         meshlink_channel_close(mesh1, channel);
219
220         // Clean up.
221
222         meshlink_stop(mesh2);
223         meshlink_stop(mesh1);
224         meshlink_close(mesh2);
225         meshlink_close(mesh1);
226
227         return 0;
228 }