12 #include <sys/prctl.h>
16 #include "../src/meshlink.h"
18 static struct sync_flag bar_responded;
19 static struct sync_flag foo_connected;
20 static struct sync_flag foo_gone;
22 static void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
27 if(len == 5 && !memcmp(data, "Hello", 5)) {
28 set_sync_flag(&bar_responded, true);
32 static void bar_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
35 if(!strcmp(node->name, "foo") && !reachable) {
36 set_sync_flag(&foo_gone, true);
40 static void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
41 // Echo the data back.
43 meshlink_channel_send(mesh, channel, data, len);
45 meshlink_channel_close(mesh, channel);
49 static bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
59 static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
64 meshlink_set_node_status_cb(mesh, bar_status_cb);
65 meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
66 set_sync_flag(&foo_connected, true);
69 bar_receive_cb(mesh, channel, data, len);
75 static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
78 meshlink_set_channel_poll_cb(mesh, channel, NULL);
80 if(meshlink_channel_send(mesh, channel, "Hello", 5) != 5) {
81 fprintf(stderr, "Could not send whole message\n");
85 static int main1(int rfd, int wfd) {
86 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
88 assert(meshlink_destroy("channels_fork_conf.1"));
89 meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
92 meshlink_enable_discovery(mesh, false);
94 meshlink_add_address(mesh, "localhost");
96 char *data = meshlink_export(mesh);
99 ssize_t len = strlen(data);
100 assert(write(wfd, &len, sizeof(len)) == sizeof(len));
101 assert(write(wfd, data, len) == len);
104 assert(read(rfd, &len, sizeof(len)) == sizeof(len));
105 char indata[len + 1];
106 assert(read(rfd, indata, len) == len);
109 assert(meshlink_import(mesh, indata));
111 meshlink_set_channel_accept_cb(mesh, reject_cb);
113 assert(meshlink_start(mesh));
115 // Open a channel from foo to bar.
117 meshlink_node_t *bar = meshlink_get_node(mesh, "bar");
120 meshlink_channel_t *channel = meshlink_channel_open(mesh, bar, 7, foo_receive_cb, NULL, 0);
123 meshlink_set_channel_poll_cb(mesh, channel, poll_cb);
125 assert(wait_sync_flag(&bar_responded, 20));
127 meshlink_channel_close(mesh, channel);
131 meshlink_close(mesh);
137 static int main2(int rfd, int wfd) {
139 prctl(PR_SET_PDEATHSIG, SIGTERM);
142 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
144 assert(meshlink_destroy("channels_fork_conf.2"));
145 meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
148 meshlink_enable_discovery(mesh, false);
150 meshlink_add_address(mesh, "localhost");
152 char *data = meshlink_export(mesh);
155 ssize_t len = strlen(data);
156 assert(write(wfd, &len, sizeof(len)) == sizeof(len));
157 assert(write(wfd, data, len) == len);
160 assert(read(rfd, &len, sizeof(len)) == sizeof(len));
161 char indata[len + 1];
162 assert(read(rfd, indata, len) == len);
165 assert(meshlink_import(mesh, indata));
167 meshlink_set_channel_accept_cb(mesh, accept_cb);
169 assert(meshlink_start(mesh));
171 assert(wait_sync_flag(&foo_connected, 20));
172 assert(wait_sync_flag(&foo_gone, 20));
174 meshlink_close(mesh);
179 static void alarm_handler(int sig) {
187 assert(pipe2(fda, 0) != -1);
188 assert(pipe2(fdb, 0) != -1);
191 return main2(fdb[0], fda[1]);
194 signal(SIGALRM, alarm_handler);
196 assert(main1(fda[0], fdb[1]) == 0);
199 assert(wait(&wstatus) != -1 || errno == ECHILD);
200 assert(WIFEXITED(wstatus));
201 assert(WEXITSTATUS(wstatus) == 0);