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 assert(meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), "localhost", NULL));
89 char *data = meshlink_export(mesh);
92 ssize_t len = strlen(data);
93 assert(write(wfd, &len, sizeof(len)) == sizeof(len));
94 assert(write(wfd, data, len) == len);
97 assert(read(rfd, &len, sizeof(len)) == sizeof(len));
99 assert(read(rfd, indata, len) == len);
102 assert(meshlink_import(mesh, indata));
104 assert(meshlink_start(mesh));
106 // Open a channel from foo to bar.
108 meshlink_node_t *bar = meshlink_get_node(mesh, "bar");
111 meshlink_channel_t *channel = meshlink_channel_open(mesh, bar, 7, foo_receive_cb, NULL, 0);
114 meshlink_set_channel_poll_cb(mesh, channel, poll_cb);
116 assert(wait_sync_flag(&bar_responded, 20));
118 meshlink_channel_close(mesh, channel);
122 meshlink_close(mesh);
128 static int main2(int rfd, int wfd) {
130 prctl(PR_SET_PDEATHSIG, SIGTERM);
133 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
135 assert(meshlink_destroy("channels_fork_conf.2"));
136 meshlink_handle_t *mesh = meshlink_open("channels_fork_conf.2", "bar", "channels-fork", DEV_CLASS_BACKBONE);
139 assert(meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), "localhost", NULL));
141 char *data = meshlink_export(mesh);
144 ssize_t len = strlen(data);
145 assert(write(wfd, &len, sizeof(len)) == sizeof(len));
146 assert(write(wfd, data, len) == len);
149 assert(read(rfd, &len, sizeof(len)) == sizeof(len));
150 char indata[len + 1];
151 assert(read(rfd, indata, len) == len);
154 assert(meshlink_import(mesh, indata));
156 meshlink_set_channel_accept_cb(mesh, accept_cb);
158 assert(meshlink_start(mesh));
160 assert(wait_sync_flag(&foo_connected, 20));
161 assert(wait_sync_flag(&foo_gone, 20));
163 meshlink_close(mesh);
168 static void alarm_handler(int sig) {
174 init_sync_flag(&bar_responded);
175 init_sync_flag(&foo_connected);
176 init_sync_flag(&foo_gone);
180 assert(pipe(fda) != -1);
181 assert(pipe(fdb) != -1);
184 return main2(fdb[0], fda[1]);
187 signal(SIGALRM, alarm_handler);
189 assert(main1(fda[0], fdb[1]) == 0);
192 assert(wait(&wstatus) != -1 || errno == ECHILD);
193 assert(WIFEXITED(wstatus));
194 assert(WEXITSTATUS(wstatus) == 0);