]> git.meshlink.io Git - meshlink/blob - test/channels-buffer-storage.c
Allow the application to provide channel send/receive buffers.
[meshlink] / test / channels-buffer-storage.c
1 #ifdef NDEBUG
2 #undef NDEBUG
3 #endif
4
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/time.h>
10 #include <assert.h>
11
12 #include "utils.h"
13 #include "../src/meshlink.h"
14
15 static struct sync_flag b_responded;
16 static struct sync_flag aio_finished;
17
18 static const size_t size = 25000000; // size of data to transfer
19
20 static void a_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
21         (void)mesh;
22         (void)channel;
23
24         if(len == 5 && !memcmp(data, "Hello", 5)) {
25                 set_sync_flag(&b_responded, true);
26         }
27 }
28
29 static void b_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
30         assert(meshlink_channel_send(mesh, channel, data, len) == (ssize_t)len);
31 }
32
33 static bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
34         (void)mesh;
35         (void)channel;
36         (void)port;
37         (void)data;
38         (void)len;
39
40         return false;
41 }
42
43 static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
44         printf("accept_cb: (from %s on port %u) ", channel->node->name, (unsigned int)port);
45
46         if(data) {
47                 fwrite(data, 1, len, stdout);
48         }
49
50         printf("\n");
51
52         if(port != 7) {
53                 return false;
54         }
55
56         meshlink_set_channel_receive_cb(mesh, channel, b_receive_cb);
57         meshlink_set_channel_sndbuf(mesh, channel, size);
58
59         if(data) {
60                 b_receive_cb(mesh, channel, data, len);
61         }
62
63         return true;
64 }
65
66 static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
67         (void)len;
68
69         meshlink_set_channel_poll_cb(mesh, channel, NULL);
70
71         assert(meshlink_channel_send(mesh, channel, "Hello", 5) == 5);
72 }
73
74 static void aio_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len, void *priv) {
75         (void)mesh;
76         (void)channel;
77         (void)data;
78         (void)len;
79         (void)priv;
80
81         set_sync_flag(&aio_finished, true);
82 }
83
84 int main(void) {
85         init_sync_flag(&b_responded);
86         init_sync_flag(&aio_finished);
87
88         meshlink_set_log_cb(NULL, MESHLINK_INFO, log_cb);
89
90         // Open two new meshlink instance.
91
92         meshlink_handle_t *mesh_a, *mesh_b;
93         open_meshlink_pair(&mesh_a, &mesh_b, "channels-buffer-storage");
94
95         // Set the callbacks.
96
97         meshlink_set_channel_accept_cb(mesh_a, reject_cb);
98         meshlink_set_channel_accept_cb(mesh_b, accept_cb);
99
100         // Start both instances
101
102         start_meshlink_pair(mesh_a, mesh_b);
103
104         // Open a channel from a to b.
105
106         meshlink_node_t *b = meshlink_get_node(mesh_a, "b");
107         assert(b);
108
109         meshlink_channel_t *channel = meshlink_channel_open(mesh_a, b, 7, a_receive_cb, NULL, 0);
110         assert(channel);
111
112         size_t buf_size = 1024 * 1024;
113         char *sndbuf = malloc(1024 * 1024);
114         assert(sndbuf);
115         char *rcvbuf = malloc(1024 * 1024);
116         assert(rcvbuf);
117
118         // Set external buffers
119
120         meshlink_set_channel_sndbuf_storage(mesh_a, channel, sndbuf, buf_size);
121         meshlink_set_channel_rcvbuf_storage(mesh_a, channel, rcvbuf, buf_size);
122
123         // Check that we can transition back and forth to external buffers
124
125         meshlink_set_channel_sndbuf_storage(mesh_a, channel, NULL, 4096);
126         meshlink_set_channel_rcvbuf(mesh_a, channel, 4096);
127
128         meshlink_set_channel_sndbuf_storage(mesh_a, channel, sndbuf, buf_size);
129         meshlink_set_channel_rcvbuf_storage(mesh_a, channel, rcvbuf, buf_size);
130
131         // Wait for the channel to finish connecting
132
133         meshlink_set_channel_poll_cb(mesh_a, channel, poll_cb);
134         assert(wait_sync_flag(&b_responded, 20));
135
136         // Send a lot of data
137
138         char *outdata = malloc(size);
139         assert(outdata);
140
141         for(size_t i = 0; i < size; i++) {
142                 outdata[i] = i;
143         }
144
145         char *indata = malloc(size);
146         assert(indata);
147
148         assert(meshlink_channel_aio_receive(mesh_a, channel, indata, size, aio_cb, NULL));
149         assert(meshlink_channel_aio_send(mesh_a, channel, outdata, size, NULL, NULL));
150         assert(wait_sync_flag(&aio_finished, 20));
151         assert(!memcmp(indata, outdata, size));
152
153         // Done
154
155         meshlink_channel_close(mesh_a, channel);
156
157         // Clean up.
158
159         free(indata);
160         free(outdata);
161         free(rcvbuf);
162         free(sndbuf);
163
164         close_meshlink_pair(mesh_a, mesh_b);
165 }