]> git.meshlink.io Git - meshlink/blob - test/echo-fork.c
b1b2bfe3fe3905b8dd23e80831c3b6640b9df5f2
[meshlink] / test / echo-fork.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "../src/meshlink.h"
8
9 /*
10  * To run this test case, direct a large file to strd
11  */
12
13 volatile bool bar_reachable = false;
14 volatile bool bar_responded = false;
15
16 void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
17         if(mesh)
18                 fprintf(stderr, "(%s) ", mesh->name);
19         fprintf(stderr, "[%d] %s\n", level, text);
20 }
21
22 void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
23         if(!strcmp(node->name, "bar"))
24                 bar_reachable = reachable;
25 }
26
27 void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
28         char tmp[len+1];
29         memset( tmp, 0, sizeof tmp );
30         snprintf( tmp, len+1, "%s", (char*)data );
31         fprintf(stderr, "Foo received from Bar:\n%s\n", tmp);
32         fprintf(stderr, "==============================\n");
33         fprintf(stdout, "%s", tmp );
34 }
35
36 void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
37         // Echo the data back.
38         //char tmp[len+1];
39         //memset( tmp, 0, sizeof tmp );
40         //snprintf( tmp, len+1, "%s", (char*)data );
41         //fprintf(stderr, "Bar received:\n%s", tmp);
42         //fprintf(stderr, "==============================\n");
43         meshlink_channel_send(mesh, channel, data, len);
44 }
45
46 bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
47         return false;
48 }
49
50 bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
51         if(port != 7)
52                 return false;
53         meshlink_set_channel_receive_cb(mesh, channel, bar_receive_cb);
54         if(data)
55                 bar_receive_cb(mesh, channel, data, len);
56         return true;
57 }
58
59 void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
60         meshlink_set_channel_poll_cb(mesh, channel, NULL);
61         bar_responded=true;
62 }
63
64 int main1(int rfd, int wfd) {
65         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
66
67         meshlink_handle_t *mesh1 = meshlink_open("channels_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
68         if(!mesh1) {
69                 fprintf(stderr, "Could not initialize configuration for foo\n");
70                 return 1;
71         }
72
73         meshlink_add_address(mesh1, "localhost");
74
75         char *data = meshlink_export(mesh1);
76         if(!data) {
77                 fprintf(stderr, "Foo could not export its configuration\n");
78                 return 1;
79         }
80
81         size_t len = strlen(data);
82         write(wfd, &len, sizeof len);
83         write(wfd, data, len);
84         free(data);
85
86         read(rfd, &len, sizeof len);
87         char indata[len + 1];
88         read(rfd, indata, len);
89         indata[len] = 0;
90
91         fprintf(stderr, "Foo exchanged data\n");
92
93         meshlink_import(mesh1, indata);
94
95         meshlink_set_channel_accept_cb(mesh1, reject_cb);
96         meshlink_set_node_status_cb(mesh1, status_cb);
97
98         if(!meshlink_start(mesh1)) {
99                 fprintf(stderr, "Foo could not start\n");
100                 return 1;
101         }
102
103         for(int i = 0; i < 20; i++) {
104                 sleep(1);
105                 if(bar_reachable)
106                         break;
107         }
108
109         if(!bar_reachable) {
110                 fprintf(stderr, "Bar not reachable for foo after 20 seconds\n");
111                 return 1;
112         }
113
114         // Open a channel from foo to bar.
115         
116         meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
117         if(!bar) {
118                 fprintf(stderr, "Foo could not find bar\n");
119                 return 1;
120         }
121
122         meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, foo_receive_cb, NULL, 0);
123         meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
124
125         // read and buffer stdin
126         int BUF_SIZE = 1024;
127         char buffer[BUF_SIZE];
128         size_t contentSize = 1;
129         char *content = malloc( sizeof(char) * BUF_SIZE );
130         if (!content) {
131                 fprintf(stderr, "Could not allocate buffer\n");
132         }
133
134         fprintf(stderr, "Foo reading from stdin...\n");
135         content[0] = '\0';
136         while(fgets(buffer,BUF_SIZE,stdin)) {
137                 char *old = content;
138                 contentSize += strlen(buffer);
139                 content = realloc(content, contentSize);
140                 strcat(content,buffer);
141         }
142
143         for(int i = 0; i < 5; i++) {
144                 sleep(1);
145                 if(bar_responded)
146                         break;
147         }
148
149         if(!bar_responded) {
150                 fprintf(stderr, "Bar did not respond to foo's channel message\n");
151                 return 1;
152         }
153
154         //fprintf(stderr, "Foo sending:\n%s", content);
155         //fprintf(stderr, "==============================\n");
156
157         size_t total = 0;
158         while ( total != contentSize )
159         {
160                 ssize_t tmp = meshlink_channel_send(mesh1, channel, content + total, contentSize - total);
161                 if (tmp >= 0)
162                         total += tmp;
163         }
164
165         sleep(60);
166
167         free(content);
168
169         meshlink_channel_close(mesh1, channel);
170
171         // Clean up.
172
173         meshlink_close(mesh1);
174
175         return 0;
176 }
177
178
179 int main2(int rfd, int wfd) {
180         sleep(1);
181
182         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
183
184         meshlink_handle_t *mesh2 = meshlink_open("channels_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
185         if(!mesh2) {
186                 fprintf(stderr, "Could not initialize configuration for bar\n");
187                 return 1;
188         }
189
190         char *data = meshlink_export(mesh2);
191         if(!data) {
192                 fprintf(stderr, "Bar could not export its configuration\n");
193                 return 1;
194         }
195
196         size_t len = strlen(data);
197         if(write(wfd, &len, sizeof len) <= 0) abort();
198         if(write(wfd, data, len) <= 0) abort();
199         free(data);
200
201         read(rfd, &len, sizeof len);
202         char indata[len + 1];
203         read(rfd, indata, len);
204         indata[len] = 0;
205
206         fprintf(stderr, "Bar exchanged data\n");
207
208         meshlink_import(mesh2, indata);
209
210         meshlink_set_channel_accept_cb(mesh2, accept_cb);
211
212         if(!meshlink_start(mesh2)) {
213                 fprintf(stderr, "Bar could not start\n");
214                 return 1;
215         }
216
217         sleep(60);
218
219         // Clean up.
220
221         meshlink_close(mesh2);
222
223         return 0;
224 }
225
226
227 int main(int argc, char *argv[]) {
228         int fda[2], fdb[2], result;
229
230         pipe2(fda, 0);
231         pipe2(fdb, 0);
232
233         if(fork())
234                 return main1(fda[0], fdb[1]);
235         else
236                 return main2(fdb[0], fda[1]);
237 }