13 #include "../src/meshlink.h"
16 #define SMALL_SIZE 512
17 #define SMALL_COUNT 2500
18 #define LARGE_SIZE 131072
20 static struct sync_flag accept_flag;
23 meshlink_handle_t *mesh;
24 meshlink_channel_t *channel;
26 bool got_large_packet;
27 struct sync_flag close_flag;
30 static void client_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
32 struct client *client = mesh->priv;
35 set_sync_flag(&client->close_flag, true);
36 meshlink_channel_close(mesh, channel);
40 // We expect always the same amount of data from the server.
41 assert(len == 512 || len == LARGE_SIZE);
42 client->received += len;
44 if(len == LARGE_SIZE) {
45 client->got_large_packet = true;
49 static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
51 struct client *client = mesh->priv;
53 if(reachable && !strcmp(node->name, "server")) {
54 assert(!client->channel);
55 client->channel = meshlink_channel_open_ex(mesh, node, 1, client_receive_cb, NULL, 0, MESHLINK_CHANNEL_UDP);
56 assert(client->channel);
60 static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
65 assert(meshlink_channel_get_flags(mesh, channel) == MESHLINK_CHANNEL_UDP);
68 meshlink_channel_t **c = mesh->priv;
70 for(int i = 0; i < 3; i++) {
75 set_sync_flag(&accept_flag, true);
86 init_sync_flag(&accept_flag);
88 meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb);
90 // Open four new meshlink instance, the server and three peers.
92 const char *names[3] = {"foo", "bar", "baz"};
93 struct client clients[3];
94 meshlink_channel_t *channels[3] = {NULL, NULL, NULL};
95 memset(clients, 0, sizeof(clients));
97 assert(meshlink_destroy("channels_udp_conf.0"));
98 meshlink_handle_t *server = meshlink_open("channels_udp_conf.0", "server", "channels-udp", DEV_CLASS_BACKBONE);
100 meshlink_enable_discovery(server, false);
101 server->priv = channels;
102 meshlink_set_channel_accept_cb(server, accept_cb);
103 assert(meshlink_start(server));
105 for(int i = 0; i < 3; i++) {
107 snprintf(dir, sizeof(dir), "channels_udp_conf.%d", i + 1);
108 assert(meshlink_destroy(dir));
109 init_sync_flag(&clients[i].close_flag);
110 clients[i].mesh = meshlink_open(dir, names[i], "channels-udp", DEV_CLASS_STATIONARY);
111 assert(clients[i].mesh);
112 clients[i].mesh->priv = &clients[i];
113 meshlink_enable_discovery(clients[i].mesh, false);
114 link_meshlink_pair(server, clients[i].mesh);
115 meshlink_set_node_status_cb(clients[i].mesh, status_cb);
116 assert(meshlink_start(clients[i].mesh));
119 // Wait for all three channels to connect
121 assert(wait_sync_flag(&accept_flag, 10));
123 for(int i = 0; i < 3; i++) {
125 assert(clients[i].channel);
128 // Check that we can send up to 65535 bytes without errors
130 char large_data[LARGE_SIZE] = "";
132 for(int i = 0; i < 3; i++) {
133 assert(meshlink_channel_send(server, channels[i], large_data, sizeof(large_data)) == sizeof(large_data));
136 // Assert that packets larger than 16 MiB are not allowed
138 assert(meshlink_channel_send(server, channels[0], large_data, 16777216) == -1);
140 // Stream packets from server to clients for 5 seconds at 40 Mbps (1 kB * 500 Hz)
142 char data[SMALL_SIZE];
143 memset(data, 'U', sizeof(data));
145 for(int j = 0; j < SMALL_COUNT; j++) {
146 const struct timespec req = {0, 2000000};
147 nanosleep(&req, NULL);
149 for(int i = 0; i < 3; i++) {
150 assert(meshlink_channel_send(server, channels[i], data, sizeof(data)) == sizeof(data));
154 // Shutdown the write side of the server's channels
156 for(int i = 0; i < 3; i++) {
157 meshlink_channel_shutdown(server, channels[i], SHUT_WR);
160 // Wait for the clients to finish reading all the data
162 for(int i = 0; i < 3; i++) {
163 assert(wait_sync_flag(&clients[i].close_flag, 10));
166 // Check that the clients have received (most of) the data
168 for(int i = 0; i < 3; i++) {
169 fprintf(stderr, "%s received %zu\n", clients[i].mesh->name, clients[i].received);
172 for(int i = 0; i < 3; i++) {
173 size_t max_received = SMALL_SIZE * SMALL_COUNT + LARGE_SIZE;
174 assert(clients[i].received >= max_received / 2);
175 assert(clients[i].received <= max_received);
176 assert(clients[i].got_large_packet);
181 for(int i = 0; i < 3; i++) {
182 meshlink_close(clients[i].mesh);
185 meshlink_close(server);