blob: c998238599706d09ce2ff4209a9f4a29c313c8a7 [file] [log] [blame]
James Kuszmaul4a42b182021-01-17 11:32:46 -08001#include "helper/handler.h"
2#include "helper/parameters.h"
3#include "helper/utils.h"
4#include <rawrtc.h>
5#include <rawrtcc.h>
6#include <rawrtcdc.h>
7#include <re.h>
8#include <stdlib.h> // exit
9#include <string.h> // memcpy
10#include <unistd.h> // STDIN_FILENO
11
12#define DEBUG_MODULE "data-channel-sctp-streamed-app"
13#define DEBUG_LEVEL 7
14#include <re_dbg.h>
15
16enum {
17 TRANSPORT_BUFFER_LENGTH = 1048576, // 1 MiB
18 DEFAULT_MESSAGE_LENGTH = 1073741823, // 1 GiB
19};
20
21struct parameters {
22 struct rawrtc_ice_parameters* ice_parameters;
23 struct rawrtc_ice_candidates* ice_candidates;
24 struct rawrtc_dtls_parameters* dtls_parameters;
25 struct sctp_parameters sctp_parameters;
26};
27
28// Note: Shadows struct client
29struct data_channel_sctp_streamed_client {
30 char* name;
31 char** ice_candidate_types;
32 size_t n_ice_candidate_types;
33 struct rawrtc_ice_gather_options* gather_options;
34 enum rawrtc_ice_role role;
35 struct rawrtc_certificate* certificate;
36 struct rawrtc_ice_gatherer* gatherer;
37 struct rawrtc_ice_transport* ice_transport;
38 struct rawrtc_dtls_transport* dtls_transport;
39 struct rawrtc_sctp_transport* sctp_transport;
40 struct rawrtc_data_transport* data_transport;
41 struct data_channel_helper* data_channel_negotiated;
42 struct data_channel_helper* data_channel;
43 struct list other_data_channels;
44 struct parameters local_parameters;
45 struct parameters remote_parameters;
46};
47
48static void print_local_parameters(struct data_channel_sctp_streamed_client* client);
49
50static struct tmr timer = {0};
51
52static void timer_handler(void* arg) {
53 struct data_channel_helper* const channel = arg;
54 struct data_channel_sctp_streamed_client* const client =
55 (struct data_channel_sctp_streamed_client*) channel->client;
56 uint64_t max_message_size = DEFAULT_MESSAGE_LENGTH; // Default to 1 GiB
57 struct mbuf* buffer;
58 enum rawrtc_code error;
59 enum rawrtc_dtls_role role;
60
61 // Get the remote peer's maximum message size
62 EOE(rawrtc_sctp_capabilities_get_max_message_size(
63 &max_message_size, client->remote_parameters.sctp_parameters.capabilities));
64 if (max_message_size > 0) {
65 max_message_size = min(DEFAULT_MESSAGE_LENGTH, max_message_size);
66 } else {
67 max_message_size = DEFAULT_MESSAGE_LENGTH;
68 }
69
70 // Compose message
71 buffer = mbuf_alloc(max_message_size);
72 EOE(buffer ? RAWRTC_CODE_SUCCESS : RAWRTC_CODE_NO_MEMORY);
73 EOR(mbuf_fill(buffer, 'M', mbuf_get_space(buffer)));
74 mbuf_set_pos(buffer, 0);
75
76 // Send message
77 // TODO: Send streamed once this is implemented
78 DEBUG_PRINTF("(%s) Sending %zu bytes\n", client->name, mbuf_get_left(buffer));
79 error = rawrtc_data_channel_send(channel->channel, buffer, true);
80 if (error) {
81 DEBUG_WARNING("Could not send, reason: %s\n", rawrtc_code_to_str(error));
82 }
83 mem_deref(buffer);
84
85 // Get DTLS role
86 EOE(rawrtc_dtls_parameters_get_role(&role, client->local_parameters.dtls_parameters));
87 if (role == RAWRTC_DTLS_ROLE_CLIENT) {
88 // Close bear-noises
89 DEBUG_PRINTF("(%s) Closing channel\n", client->name, channel->label);
90 EOR(rawrtc_data_channel_close(client->data_channel->channel));
91 }
92}
93
94static void data_channel_open_handler(void* const arg) {
95 struct data_channel_helper* const channel = arg;
96 struct data_channel_sctp_streamed_client* const client =
97 (struct data_channel_sctp_streamed_client*) channel->client;
98 struct mbuf* buffer;
99 enum rawrtc_code error;
100
101 // Print open event
102 default_data_channel_open_handler(arg);
103
104 // Send data delayed on bear-noises
105 if (str_cmp(channel->label, "bear-noises") == 0) {
106 tmr_start(&timer, 30000, timer_handler, channel);
107 return;
108 }
109
110 // Compose message (8 KiB)
111 buffer = mbuf_alloc(1 << 13);
112 EOE(buffer ? RAWRTC_CODE_SUCCESS : RAWRTC_CODE_NO_MEMORY);
113 EOR(mbuf_fill(buffer, 'M', mbuf_get_space(buffer)));
114 mbuf_set_pos(buffer, 0);
115
116 // Send message
117 // TODO: Send streamed once this is implemented
118 DEBUG_PRINTF("(%s) Sending %zu bytes\n", client->name, mbuf_get_left(buffer));
119 error = rawrtc_data_channel_send(channel->channel, buffer, true);
120 if (error) {
121 DEBUG_WARNING("Could not send, reason: %s\n", rawrtc_code_to_str(error));
122 }
123 mem_deref(buffer);
124}
125
126static void data_channel_handler(
127 struct rawrtc_data_channel* const channel, // read-only, MUST be referenced when used
128 void* const arg) {
129 struct data_channel_sctp_streamed_client* const client = arg;
130 struct data_channel_helper* channel_helper;
131
132 // Print data channel event
133 default_data_channel_handler(channel, arg);
134
135 // Create data channel helper instance & add to list
136 // Note: In this case we need to reference the channel because we have not created it
137 data_channel_helper_create_from_channel(&channel_helper, mem_ref(channel), arg, NULL);
138 list_append(&client->other_data_channels, &channel_helper->le, channel_helper);
139
140 // Set handler argument & handlers
141 EOE(rawrtc_data_channel_set_arg(channel, channel_helper));
142 EOE(rawrtc_data_channel_set_open_handler(channel, data_channel_open_handler));
143 EOE(rawrtc_data_channel_set_buffered_amount_low_handler(
144 channel, default_data_channel_buffered_amount_low_handler));
145 EOE(rawrtc_data_channel_set_error_handler(channel, default_data_channel_error_handler));
146 EOE(rawrtc_data_channel_set_close_handler(channel, default_data_channel_close_handler));
147 EOE(rawrtc_data_channel_set_message_handler(channel, default_data_channel_message_handler));
148
149 // Enable streaming mode
150 EOE(rawrtc_data_channel_set_streaming(channel, true));
151}
152
153static void ice_gatherer_local_candidate_handler(
154 struct rawrtc_ice_candidate* const candidate,
155 char const* const url, // read-only
156 void* const arg) {
157 struct data_channel_sctp_streamed_client* const client = arg;
158
159 // Print local candidate
160 default_ice_gatherer_local_candidate_handler(candidate, url, arg);
161
162 // Print local parameters (if last candidate)
163 if (!candidate) {
164 print_local_parameters(client);
165 }
166}
167
168static void dtls_transport_state_change_handler(
169 enum rawrtc_dtls_transport_state const state, // read-only
170 void* const arg) {
171 struct data_channel_sctp_streamed_client* const client = arg;
172
173 // Print state
174 default_dtls_transport_state_change_handler(state, arg);
175
176 // Open? Create new data channel
177 // TODO: Move this once we can create data channels earlier
178 if (state == RAWRTC_DTLS_TRANSPORT_STATE_CONNECTED) {
179 enum rawrtc_dtls_role role;
180
181 // Renew DTLS parameters
182 mem_deref(client->local_parameters.dtls_parameters);
183 EOE(rawrtc_dtls_transport_get_local_parameters(
184 &client->local_parameters.dtls_parameters, client->dtls_transport));
185
186 // Get DTLS role
187 EOE(rawrtc_dtls_parameters_get_role(&role, client->local_parameters.dtls_parameters));
188 DEBUG_PRINTF("(%s) DTLS role: %s\n", client->name, rawrtc_dtls_role_to_str(role));
189
190 // Client? Create data channel
191 if (role == RAWRTC_DTLS_ROLE_CLIENT) {
192 struct rawrtc_data_channel_parameters* channel_parameters;
193
194 // Create data channel helper
195 data_channel_helper_create(
196 &client->data_channel, (struct client*) client, "bear-noises");
197
198 // Create data channel parameters
199 EOE(rawrtc_data_channel_parameters_create(
200 &channel_parameters, client->data_channel->label,
201 RAWRTC_DATA_CHANNEL_TYPE_RELIABLE_UNORDERED, 0, NULL, false, 0));
202
203 // Create data channel
204 EOE(rawrtc_data_channel_create(
205 &client->data_channel->channel, client->data_transport, channel_parameters,
206 data_channel_open_handler, default_data_channel_buffered_amount_low_handler,
207 default_data_channel_error_handler, default_data_channel_close_handler,
208 default_data_channel_message_handler, client->data_channel));
209
210 // Enable streaming mode
211 EOE(rawrtc_data_channel_set_streaming(client->data_channel->channel, true));
212
213 // Un-reference
214 mem_deref(channel_parameters);
215 }
216 }
217}
218
219static void client_init(struct data_channel_sctp_streamed_client* const client) {
220 struct rawrtc_certificate* certificates[1];
221 struct rawrtc_data_channel_parameters* channel_parameters;
222
223 // Generate certificates
224 EOE(rawrtc_certificate_generate(&client->certificate, NULL));
225 certificates[0] = client->certificate;
226
227 // Create ICE gatherer
228 EOE(rawrtc_ice_gatherer_create(
229 &client->gatherer, client->gather_options, default_ice_gatherer_state_change_handler,
230 default_ice_gatherer_error_handler, ice_gatherer_local_candidate_handler, client));
231
232 // Create ICE transport
233 EOE(rawrtc_ice_transport_create(
234 &client->ice_transport, client->gatherer, default_ice_transport_state_change_handler,
235 default_ice_transport_candidate_pair_change_handler, client));
236
237 // Create DTLS transport
238 EOE(rawrtc_dtls_transport_create(
239 &client->dtls_transport, client->ice_transport, certificates, ARRAY_SIZE(certificates),
240 dtls_transport_state_change_handler, default_dtls_transport_error_handler, client));
241
242 // Create SCTP transport
243 EOE(rawrtc_sctp_transport_create(
244 &client->sctp_transport, client->dtls_transport,
245 client->local_parameters.sctp_parameters.port, data_channel_handler,
246 default_sctp_transport_state_change_handler, client));
247 EOE(rawrtc_sctp_transport_set_buffer_length(
248 client->sctp_transport, TRANSPORT_BUFFER_LENGTH, TRANSPORT_BUFFER_LENGTH));
249
250 // Get data transport
251 EOE(rawrtc_sctp_transport_get_data_transport(&client->data_transport, client->sctp_transport));
252
253 // Create data channel helper
254 data_channel_helper_create(
255 &client->data_channel_negotiated, (struct client*) client, "cat-noises");
256
257 // Create data channel parameters
258 EOE(rawrtc_data_channel_parameters_create(
259 &channel_parameters, client->data_channel_negotiated->label,
260 RAWRTC_DATA_CHANNEL_TYPE_RELIABLE_ORDERED, 0, NULL, true, 0));
261
262 // Create pre-negotiated data channel
263 EOE(rawrtc_data_channel_create(
264 &client->data_channel_negotiated->channel, client->data_transport, channel_parameters,
265 data_channel_open_handler, default_data_channel_buffered_amount_low_handler,
266 default_data_channel_error_handler, default_data_channel_close_handler,
267 default_data_channel_message_handler, client->data_channel_negotiated));
268
269 // Enable streaming mode
270 EOE(rawrtc_data_channel_set_streaming(client->data_channel_negotiated->channel, true));
271
272 // Un-reference
273 mem_deref(channel_parameters);
274}
275
276static void client_start_gathering(struct data_channel_sctp_streamed_client* const client) {
277 // Start gathering
278 EOE(rawrtc_ice_gatherer_gather(client->gatherer, NULL));
279}
280
281static void client_start_transports(struct data_channel_sctp_streamed_client* const client) {
282 struct parameters* const remote_parameters = &client->remote_parameters;
283
284 // Start ICE transport
285 EOE(rawrtc_ice_transport_start(
286 client->ice_transport, client->gatherer, remote_parameters->ice_parameters, client->role));
287
288 // Start DTLS transport
289 EOE(rawrtc_dtls_transport_start(client->dtls_transport, remote_parameters->dtls_parameters));
290
291 // Start SCTP transport
292 EOE(rawrtc_sctp_transport_start(
293 client->sctp_transport, remote_parameters->sctp_parameters.capabilities,
294 remote_parameters->sctp_parameters.port));
295}
296
297static void parameters_destroy(struct parameters* const parameters) {
298 // Un-reference
299 parameters->ice_parameters = mem_deref(parameters->ice_parameters);
300 parameters->ice_candidates = mem_deref(parameters->ice_candidates);
301 parameters->dtls_parameters = mem_deref(parameters->dtls_parameters);
302 if (parameters->sctp_parameters.capabilities) {
303 parameters->sctp_parameters.capabilities =
304 mem_deref(parameters->sctp_parameters.capabilities);
305 }
306}
307
308static void client_stop(struct data_channel_sctp_streamed_client* const client) {
309 // Clear other data channels
310 list_flush(&client->other_data_channels);
311
312 if (client->sctp_transport) {
313 EOE(rawrtc_sctp_transport_stop(client->sctp_transport));
314 }
315 if (client->dtls_transport) {
316 EOE(rawrtc_dtls_transport_stop(client->dtls_transport));
317 }
318 if (client->ice_transport) {
319 EOE(rawrtc_ice_transport_stop(client->ice_transport));
320 }
321 if (client->gatherer) {
322 EOE(rawrtc_ice_gatherer_close(client->gatherer));
323 }
324
325 // Un-reference & close
326 parameters_destroy(&client->remote_parameters);
327 parameters_destroy(&client->local_parameters);
328 client->data_channel = mem_deref(client->data_channel);
329 client->data_channel_negotiated = mem_deref(client->data_channel_negotiated);
330 client->data_transport = mem_deref(client->data_transport);
331 client->sctp_transport = mem_deref(client->sctp_transport);
332 client->dtls_transport = mem_deref(client->dtls_transport);
333 client->ice_transport = mem_deref(client->ice_transport);
334 client->gatherer = mem_deref(client->gatherer);
335 client->certificate = mem_deref(client->certificate);
336 client->gather_options = mem_deref(client->gather_options);
337
338 // Stop listening on STDIN
339 fd_close(STDIN_FILENO);
340}
341
342static void client_set_parameters(struct data_channel_sctp_streamed_client* const client) {
343 struct parameters* const remote_parameters = &client->remote_parameters;
344
345 // Set remote ICE candidates
346 EOE(rawrtc_ice_transport_set_remote_candidates(
347 client->ice_transport, remote_parameters->ice_candidates->candidates,
348 remote_parameters->ice_candidates->n_candidates));
349}
350
351static void parse_remote_parameters(int flags, void* arg) {
352 struct data_channel_sctp_streamed_client* const client = arg;
353 enum rawrtc_code error;
354 struct odict* dict = NULL;
355 struct odict* node = NULL;
356 struct rawrtc_ice_parameters* ice_parameters = NULL;
357 struct rawrtc_ice_candidates* ice_candidates = NULL;
358 struct rawrtc_dtls_parameters* dtls_parameters = NULL;
359 struct sctp_parameters sctp_parameters = {0};
360 (void) flags;
361
362 // Get dict from JSON
363 error = get_json_stdin(&dict);
364 if (error) {
365 goto out;
366 }
367
368 // Decode JSON
369 error |= dict_get_entry(&node, dict, "iceParameters", ODICT_OBJECT, true);
370 error |= get_ice_parameters(&ice_parameters, node);
371 error |= dict_get_entry(&node, dict, "iceCandidates", ODICT_ARRAY, true);
372 error |= get_ice_candidates(&ice_candidates, node, arg);
373 error |= dict_get_entry(&node, dict, "dtlsParameters", ODICT_OBJECT, true);
374 error |= get_dtls_parameters(&dtls_parameters, node);
375 error |= dict_get_entry(&node, dict, "sctpParameters", ODICT_OBJECT, true);
376 error |= get_sctp_parameters(&sctp_parameters, node);
377
378 // Ok?
379 if (error) {
380 DEBUG_WARNING("Invalid remote parameters\n");
381 if (sctp_parameters.capabilities) {
382 mem_deref(sctp_parameters.capabilities);
383 }
384 goto out;
385 }
386
387 // Set parameters & start transports
388 client->remote_parameters.ice_parameters = mem_ref(ice_parameters);
389 client->remote_parameters.ice_candidates = mem_ref(ice_candidates);
390 client->remote_parameters.dtls_parameters = mem_ref(dtls_parameters);
391 memcpy(&client->remote_parameters.sctp_parameters, &sctp_parameters, sizeof(sctp_parameters));
392 DEBUG_INFO("Applying remote parameters\n");
393 client_set_parameters(client);
394 client_start_transports(client);
395
396out:
397 // Un-reference
398 mem_deref(dtls_parameters);
399 mem_deref(ice_candidates);
400 mem_deref(ice_parameters);
401 mem_deref(dict);
402
403 // Exit?
404 if (error == RAWRTC_CODE_NO_VALUE) {
405 DEBUG_NOTICE("Exiting\n");
406
407 // Stop client & bye
408 client_stop(client);
409 tmr_cancel(&timer);
410 re_cancel();
411 }
412}
413
414static void client_get_parameters(struct data_channel_sctp_streamed_client* const client) {
415 struct parameters* const local_parameters = &client->local_parameters;
416
417 // Get local ICE parameters
418 EOE(rawrtc_ice_gatherer_get_local_parameters(
419 &local_parameters->ice_parameters, client->gatherer));
420
421 // Get local ICE candidates
422 EOE(rawrtc_ice_gatherer_get_local_candidates(
423 &local_parameters->ice_candidates, client->gatherer));
424
425 // Get local DTLS parameters
426 EOE(rawrtc_dtls_transport_get_local_parameters(
427 &local_parameters->dtls_parameters, client->dtls_transport));
428
429 // Get local SCTP parameters
430 EOE(rawrtc_sctp_transport_get_capabilities(&local_parameters->sctp_parameters.capabilities));
431 EOE(rawrtc_sctp_transport_get_port(
432 &local_parameters->sctp_parameters.port, client->sctp_transport));
433}
434
435static void print_local_parameters(struct data_channel_sctp_streamed_client* client) {
436 struct odict* dict;
437 struct odict* node;
438
439 // Get local parameters
440 client_get_parameters(client);
441
442 // Create dict
443 EOR(odict_alloc(&dict, 16));
444
445 // Create nodes
446 EOR(odict_alloc(&node, 16));
447 set_ice_parameters(client->local_parameters.ice_parameters, node);
448 EOR(odict_entry_add(dict, "iceParameters", ODICT_OBJECT, node));
449 mem_deref(node);
450 EOR(odict_alloc(&node, 16));
451 set_ice_candidates(client->local_parameters.ice_candidates, node);
452 EOR(odict_entry_add(dict, "iceCandidates", ODICT_ARRAY, node));
453 mem_deref(node);
454 EOR(odict_alloc(&node, 16));
455 set_dtls_parameters(client->local_parameters.dtls_parameters, node);
456 EOR(odict_entry_add(dict, "dtlsParameters", ODICT_OBJECT, node));
457 mem_deref(node);
458 EOR(odict_alloc(&node, 16));
459 set_sctp_parameters(client->sctp_transport, &client->local_parameters.sctp_parameters, node);
460 EOR(odict_entry_add(dict, "sctpParameters", ODICT_OBJECT, node));
461 mem_deref(node);
462
463 // Print JSON
464 DEBUG_INFO("Local Parameters:\n%H\n", json_encode_odict, dict);
465
466 // Un-reference
467 mem_deref(dict);
468}
469
470static void exit_with_usage(char* program) {
471 DEBUG_WARNING("Usage: %s <0|1 (ice-role)> [<sctp-port>] [<ice-candidate-type> ...]", program);
472 exit(1);
473}
474
475int main(int argc, char* argv[argc + 1]) {
476 char** ice_candidate_types = NULL;
477 size_t n_ice_candidate_types = 0;
478 enum rawrtc_ice_role role;
479 struct rawrtc_ice_gather_options* gather_options;
480 char* const turn_zwuenf_org_urls[] = {"stun:turn.zwuenf.org"};
481 struct data_channel_sctp_streamed_client client = {0};
482 (void) client.ice_candidate_types;
483 (void) client.n_ice_candidate_types;
484
485 // Debug
486 dbg_init(DBG_DEBUG, DBG_ALL);
487 DEBUG_PRINTF("Init\n");
488
489 // Initialise
490 EOE(rawrtc_init(true));
491
492 // Check arguments length
493 if (argc < 2) {
494 exit_with_usage(argv[0]);
495 }
496
497 // Get ICE role
498 if (get_ice_role(&role, argv[1])) {
499 exit_with_usage(argv[0]);
500 }
501
502 // Get SCTP port (optional)
503 if (argc >= 3 && !str_to_uint16(&client.local_parameters.sctp_parameters.port, argv[2])) {
504 exit_with_usage(argv[0]);
505 }
506
507 // Get enabled ICE candidate types to be added (optional)
508 if (argc >= 4) {
509 ice_candidate_types = &argv[3];
510 n_ice_candidate_types = (size_t) argc - 3;
511 }
512
513 // Create ICE gather options
514 EOE(rawrtc_ice_gather_options_create(&gather_options, RAWRTC_ICE_GATHER_POLICY_ALL));
515
516 // Add ICE servers to ICE gather options
517 EOE(rawrtc_ice_gather_options_add_server(
518 gather_options, turn_zwuenf_org_urls, ARRAY_SIZE(turn_zwuenf_org_urls), NULL, NULL,
519 RAWRTC_ICE_CREDENTIAL_TYPE_NONE));
520
521 // Set client fields
522 client.name = "A";
523 client.ice_candidate_types = ice_candidate_types;
524 client.n_ice_candidate_types = n_ice_candidate_types;
525 client.gather_options = gather_options;
526 client.role = role;
527 list_init(&client.other_data_channels);
528
529 // Setup client
530 client_init(&client);
531
532 // Start gathering
533 client_start_gathering(&client);
534
535 // Listen on stdin
536 EOR(fd_listen(STDIN_FILENO, FD_READ, parse_remote_parameters, &client));
537
538 // Start main loop
539 EOR(re_main(default_signal_handler));
540
541 // Stop client & bye
542 client_stop(&client);
543 before_exit();
544 return 0;
545}