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