12 #include <sys/types.h>
17 #include <sys/prctl.h>
21 #include "../src/meshlink-tiny.h"
23 static struct sync_flag bar_responded;
24 static struct sync_flag foo_connected;
25 static struct sync_flag foo_gone;
27 static void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
32 if(len == 5 && !memcmp(data, "Hello", 5)) {
33 set_sync_flag(&bar_responded, true);
37 static void bar_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
40 if(!strcmp(node->name, "foo") && !reachable) {
41 set_sync_flag(&foo_gone, true);
45 static void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
46 // Echo the data back.
48 assert(meshlink_channel_send(mesh, channel, data, len) == (ssize_t)len);
50 meshlink_channel_close(mesh, channel);
54 static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
59 meshlink_set_node_status_cb(mesh, bar_status_cb);
60 meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
61 set_sync_flag(&foo_connected, true);
64 bar_receive_cb(mesh, channel, data, len);
70 static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
73 meshlink_set_channel_poll_cb(mesh, channel, NULL);
75 if(meshlink_channel_send(mesh, channel, "Hello", 5) != 5) {
76 fprintf(stderr, "Could not send whole message\n");
80 static int main1(int rfd, int wfd) {
81 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
83 assert(meshlink_destroy("channels_fork_conf.1"));
84 meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.1", "foo", "channels-fork", DEV_CLASS_BACKBONE);
87 meshlink_enable_discovery(mesh, false);
89 assert(meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), "localhost", NULL));
91 char *data = meshlink_export(mesh);
94 ssize_t len = strlen(data);
95 assert(write(wfd, &len, sizeof(len)) == sizeof(len));
96 assert(write(wfd, data, len) == len);
99 assert(read(rfd, &len, sizeof(len)) == sizeof(len));
100 char indata[len + 1];
101 assert(read(rfd, indata, len) == len);
104 assert(meshlink_import(mesh, indata));
106 assert(meshlink_start(mesh));
108 // Open a channel from foo to bar.
110 meshlink_node_t *bar = meshlink_get_node(mesh, "bar");
113 meshlink_channel_t *channel = meshlink_channel_open(mesh, bar, 7, foo_receive_cb, NULL, 0);
116 meshlink_set_channel_poll_cb(mesh, channel, poll_cb);
118 assert(wait_sync_flag(&bar_responded, 20));
120 meshlink_channel_close(mesh, channel);
124 meshlink_close(mesh);
130 static int main2(int rfd, int wfd) {
132 prctl(PR_SET_PDEATHSIG, SIGTERM);
135 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
137 assert(meshlink_destroy("channels_fork_conf.2"));
138 meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.2", "bar", "channels-fork", DEV_CLASS_BACKBONE);
141 meshlink_enable_discovery(mesh, false);
143 assert(meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), "localhost", NULL));
145 char *data = meshlink_export(mesh);
148 ssize_t len = strlen(data);
149 assert(write(wfd, &len, sizeof(len)) == sizeof(len));
150 assert(write(wfd, data, len) == len);
153 assert(read(rfd, &len, sizeof(len)) == sizeof(len));
154 char indata[len + 1];
155 assert(read(rfd, indata, len) == len);
158 assert(meshlink_import(mesh, indata));
160 meshlink_set_channel_accept_cb(mesh, accept_cb);
162 assert(meshlink_start(mesh));
164 assert(wait_sync_flag(&foo_connected, 20));
165 assert(wait_sync_flag(&foo_gone, 20));
167 meshlink_close(mesh);
172 static void alarm_handler(int sig) {
178 init_sync_flag(&bar_responded);
179 init_sync_flag(&foo_connected);
180 init_sync_flag(&foo_gone);
184 assert(pipe(fda) != -1);
185 assert(pipe(fdb) != -1);
188 return main2(fdb[0], fda[1]);
191 signal(SIGALRM, alarm_handler);
193 assert(main1(fda[0], fdb[1]) == 0);
196 assert(wait(&wstatus) != -1 || errno == ECHILD);
197 assert(WIFEXITED(wstatus));
198 assert(WEXITSTATUS(wstatus) == 0);