blob: 46ae22b850423364edc36c8c43301a00a5a97078 [file] [log] [blame]
James Kuszmaul4a42b182021-01-17 11:32:46 -08001#include "parameters.h"
2#include "common.h"
3#include "utils.h"
4#include <rawrtc.h>
5#include <rawrtcc.h>
6#include <rawrtcdc.h>
7#include <re.h>
8
9#define DEBUG_MODULE "helper-parameters"
10#define DEBUG_LEVEL 7
11#include <re_dbg.h>
12
13/*
14 * Set ICE parameters in dictionary.
15 */
16void set_ice_parameters(struct rawrtc_ice_parameters* const parameters, struct odict* const dict) {
17 char* username_fragment;
18 char* password;
19 bool ice_lite;
20
21 // Get values
22 EOE(rawrtc_ice_parameters_get_username_fragment(&username_fragment, parameters));
23 EOE(rawrtc_ice_parameters_get_password(&password, parameters));
24 EOE(rawrtc_ice_parameters_get_ice_lite(&ice_lite, parameters));
25
26 // Set ICE parameters
27 EOR(odict_entry_add(dict, "usernameFragment", ODICT_STRING, username_fragment));
28 EOR(odict_entry_add(dict, "password", ODICT_STRING, password));
29 EOR(odict_entry_add(dict, "iceLite", ODICT_BOOL, ice_lite));
30
31 // Un-reference values
32 mem_deref(password);
33 mem_deref(username_fragment);
34}
35
36/*
37 * Set ICE candidates in dictionary.
38 */
39void set_ice_candidates(struct rawrtc_ice_candidates* const parameters, struct odict* const array) {
40 size_t i;
41 struct odict* node;
42
43 // Set ICE candidates
44 for (i = 0; i < parameters->n_candidates; ++i) {
45 enum rawrtc_code error;
46 struct rawrtc_ice_candidate* const candidate = parameters->candidates[i];
47 char* foundation;
48 uint32_t priority;
49 char* ip;
50 enum rawrtc_ice_protocol protocol;
51 uint16_t port;
52 enum rawrtc_ice_candidate_type type;
53 enum rawrtc_ice_tcp_candidate_type tcp_type = RAWRTC_ICE_TCP_CANDIDATE_TYPE_ACTIVE;
54 char* related_address = NULL;
55 uint16_t related_port = 0;
56 char* key;
57
58 // Create object
59 EOR(odict_alloc(&node, 16));
60
61 // Get values
62 EOE(rawrtc_ice_candidate_get_foundation(&foundation, candidate));
63 EOE(rawrtc_ice_candidate_get_priority(&priority, candidate));
64 EOE(rawrtc_ice_candidate_get_ip(&ip, candidate));
65 EOE(rawrtc_ice_candidate_get_protocol(&protocol, candidate));
66 EOE(rawrtc_ice_candidate_get_port(&port, candidate));
67 EOE(rawrtc_ice_candidate_get_type(&type, candidate));
68 error = rawrtc_ice_candidate_get_tcp_type(&tcp_type, candidate);
69 EOE(error == RAWRTC_CODE_NO_VALUE ? RAWRTC_CODE_SUCCESS : error);
70 error = rawrtc_ice_candidate_get_related_address(&related_address, candidate);
71 EOE(error == RAWRTC_CODE_NO_VALUE ? RAWRTC_CODE_SUCCESS : error);
72 error = rawrtc_ice_candidate_get_related_port(&related_port, candidate);
73 EOE(error == RAWRTC_CODE_NO_VALUE ? RAWRTC_CODE_SUCCESS : error);
74
75 // Set ICE candidate values
76 EOR(odict_entry_add(node, "foundation", ODICT_STRING, foundation));
77 EOR(odict_entry_add(node, "priority", ODICT_INT, (int64_t) priority));
78 EOR(odict_entry_add(node, "ip", ODICT_STRING, ip));
79 EOR(odict_entry_add(node, "protocol", ODICT_STRING, rawrtc_ice_protocol_to_str(protocol)));
80 EOR(odict_entry_add(node, "port", ODICT_INT, (int64_t) port));
81 EOR(odict_entry_add(node, "type", ODICT_STRING, rawrtc_ice_candidate_type_to_str(type)));
82 if (protocol == RAWRTC_ICE_PROTOCOL_TCP) {
83 EOR(odict_entry_add(
84 node, "tcpType", ODICT_STRING, rawrtc_ice_tcp_candidate_type_to_str(tcp_type)));
85 }
86 if (related_address) {
87 EOR(odict_entry_add(node, "relatedAddress", ODICT_STRING, related_address));
88 }
89 if (related_port > 0) {
90 EOR(odict_entry_add(node, "relatedPort", (int64_t) ODICT_INT, related_port));
91 }
92
93 // Add to array
94 EOE(rawrtc_sdprintf(&key, "%zu", i));
95 EOR(odict_entry_add(array, key, ODICT_OBJECT, node));
96
97 // Un-reference values
98 mem_deref(key);
99 mem_deref(related_address);
100 mem_deref(ip);
101 mem_deref(foundation);
102 mem_deref(node);
103 }
104}
105
106/*
107 * Set DTLS parameters in dictionary.
108 */
109void set_dtls_parameters(
110 struct rawrtc_dtls_parameters* const parameters, struct odict* const dict) {
111 enum rawrtc_dtls_role role;
112 struct odict* array;
113 struct odict* node;
114 struct rawrtc_dtls_fingerprints* fingerprints;
115 size_t i;
116
117 // Get and set DTLS role
118 EOE(rawrtc_dtls_parameters_get_role(&role, parameters));
119 EOR(odict_entry_add(dict, "role", ODICT_STRING, rawrtc_dtls_role_to_str(role)));
120
121 // Create array
122 EOR(odict_alloc(&array, 16));
123
124 // Get and set fingerprints
125 EOE(rawrtc_dtls_parameters_get_fingerprints(&fingerprints, parameters));
126 for (i = 0; i < fingerprints->n_fingerprints; ++i) {
127 struct rawrtc_dtls_fingerprint* const fingerprint = fingerprints->fingerprints[i];
128 enum rawrtc_certificate_sign_algorithm sign_algorithm;
129 char* value;
130 char* key;
131
132 // Create object
133 EOR(odict_alloc(&node, 16));
134
135 // Get values
136 EOE(rawrtc_dtls_fingerprint_get_sign_algorithm(&sign_algorithm, fingerprint));
137 EOE(rawrtc_dtls_fingerprint_get_value(&value, fingerprint));
138
139 // Set fingerprint values
140 EOR(odict_entry_add(
141 node, "algorithm", ODICT_STRING,
142 rawrtc_certificate_sign_algorithm_to_str(sign_algorithm)));
143 EOR(odict_entry_add(node, "value", ODICT_STRING, value));
144
145 // Add to array
146 EOE(rawrtc_sdprintf(&key, "%zu", i));
147 EOR(odict_entry_add(array, key, ODICT_OBJECT, node));
148
149 // Un-reference values
150 mem_deref(key);
151 mem_deref(value);
152 mem_deref(node);
153 }
154
155 // Un-reference fingerprints
156 mem_deref(fingerprints);
157
158 // Add array to object
159 EOR(odict_entry_add(dict, "fingerprints", ODICT_ARRAY, array));
160 mem_deref(array);
161}
162
163/*
164 * Set SCTP parameters in dictionary.
165 */
166void set_sctp_parameters(
167 struct rawrtc_sctp_transport* const transport,
168 struct sctp_parameters* const parameters,
169 struct odict* const dict) {
170 uint64_t max_message_size;
171 uint16_t port;
172
173 // Get values
174 EOE(rawrtc_sctp_capabilities_get_max_message_size(&max_message_size, parameters->capabilities));
175 EOE(rawrtc_sctp_transport_get_port(&port, transport));
176
177 // Ensure maximum message size fits into int64
178 if (max_message_size > INT64_MAX) {
179 EOE(RAWRTC_CODE_INSUFFICIENT_SPACE);
180 }
181
182 // Set ICE parameters
183 EOR(odict_entry_add(dict, "maxMessageSize", ODICT_INT, (int64_t) max_message_size));
184 EOR(odict_entry_add(dict, "port", ODICT_INT, (int64_t) port));
185}
186
187#if RAWRTC_HAVE_SCTP_REDIRECT_TRANSPORT
188/*
189 * Set SCTP redirect parameters in dictionary.
190 */
191void set_sctp_redirect_parameters(
192 struct rawrtc_sctp_redirect_transport* const transport,
193 struct sctp_parameters* const parameters,
194 struct odict* const dict) {
195 uint64_t max_message_size;
196 uint16_t port;
197
198 // Get values
199 EOE(rawrtc_sctp_capabilities_get_max_message_size(&max_message_size, parameters->capabilities));
200 EOE(rawrtc_sctp_redirect_transport_get_port(&port, transport));
201
202 // Ensure maximum message size fits into int64
203 if (max_message_size > INT64_MAX) {
204 EOE(RAWRTC_CODE_INSUFFICIENT_SPACE);
205 }
206
207 // Set ICE parameters
208 EOR(odict_entry_add(dict, "maxMessageSize", ODICT_INT, (int64_t) max_message_size));
209 EOR(odict_entry_add(dict, "port", ODICT_INT, (int64_t) port));
210}
211#endif
212
213/*
214 * Get ICE parameters from dictionary.
215 */
216enum rawrtc_code get_ice_parameters(
217 struct rawrtc_ice_parameters** const parametersp, struct odict* const dict) {
218 enum rawrtc_code error = RAWRTC_CODE_SUCCESS;
219 char* username_fragment;
220 char* password;
221 bool ice_lite;
222
223 // Get ICE parameters
224 error |= dict_get_entry(&username_fragment, dict, "usernameFragment", ODICT_STRING, true);
225 error |= dict_get_entry(&password, dict, "password", ODICT_STRING, true);
226 error |= dict_get_entry(&ice_lite, dict, "iceLite", ODICT_BOOL, true);
227 if (error) {
228 return error;
229 }
230
231 // Create ICE parameters instance
232 return rawrtc_ice_parameters_create(parametersp, username_fragment, password, ice_lite);
233}
234
235static void ice_candidates_destroy(void* arg) {
236 struct rawrtc_ice_candidates* const candidates = arg;
237 size_t i;
238
239 // Un-reference each item
240 for (i = 0; i < candidates->n_candidates; ++i) {
241 mem_deref(candidates->candidates[i]);
242 }
243}
244
245/*
246 * Get ICE candidates from dictionary.
247 * Filter by enabled ICE candidate types if `client` argument is set to
248 * non-NULL.
249 */
250enum rawrtc_code get_ice_candidates(
251 struct rawrtc_ice_candidates** const candidatesp,
252 struct odict* const dict,
253 struct client* const client) {
254 size_t n;
255 struct rawrtc_ice_candidates* candidates;
256 enum rawrtc_code error = RAWRTC_CODE_SUCCESS;
257 struct le* le;
258
259 // Get length
260 n = list_count(&dict->lst) + 1;
261
262 // Allocate & set length immediately
263 // Note: We allocate more than we need in case ICE candidate types are being filtered but... meh
264 candidates = mem_zalloc(
265 sizeof(*candidates) + (sizeof(struct rawrtc_ice_candidate*) * n), ice_candidates_destroy);
266 if (!candidates) {
267 EWE("No memory to allocate ICE candidates array");
268 }
269 candidates->n_candidates = 0;
270
271 // Get ICE candidates
272 for (le = list_head(&dict->lst); le != NULL; le = le->next) {
273 struct odict* const node = ((struct odict_entry*) le->data)->u.odict;
274 char const* type_str = NULL;
275 enum rawrtc_ice_candidate_type type;
276 char* foundation;
277 uint32_t priority;
278 char* ip;
279 char const* protocol_str = NULL;
280 enum rawrtc_ice_protocol protocol;
281 uint16_t port;
282 char const* tcp_type_str = NULL;
283 enum rawrtc_ice_tcp_candidate_type tcp_type = RAWRTC_ICE_TCP_CANDIDATE_TYPE_ACTIVE;
284 char* related_address = NULL;
285 uint16_t related_port = 0;
286 struct rawrtc_ice_candidate* candidate;
287
288 // Get ICE candidate
289 error |= dict_get_entry(&type_str, node, "type", ODICT_STRING, true);
290 error |= rawrtc_str_to_ice_candidate_type(&type, type_str);
291 error |= dict_get_entry(&foundation, node, "foundation", ODICT_STRING, true);
292 error |= dict_get_uint32(&priority, node, "priority", true);
293 error |= dict_get_entry(&ip, node, "ip", ODICT_STRING, true);
294 error |= dict_get_entry(&protocol_str, node, "protocol", ODICT_STRING, true);
295 error |= rawrtc_str_to_ice_protocol(&protocol, protocol_str);
296 error |= dict_get_uint16(&port, node, "port", true);
297 if (protocol == RAWRTC_ICE_PROTOCOL_TCP) {
298 error |= dict_get_entry(&tcp_type_str, node, "tcpType", ODICT_STRING, true);
299 error |= rawrtc_str_to_ice_tcp_candidate_type(&tcp_type, tcp_type_str);
300 }
301 dict_get_entry(&related_address, node, "relatedAddress", ODICT_STRING, false);
302 dict_get_uint16(&related_port, node, "relatedPort", false);
303 if (error) {
304 goto out;
305 }
306
307 // Create and add ICE candidate
308 error = rawrtc_ice_candidate_create(
309 &candidate, foundation, priority, ip, protocol, port, type, tcp_type, related_address,
310 related_port);
311 if (error) {
312 goto out;
313 }
314
315 // Print ICE candidate
316 print_ice_candidate(candidate, NULL, NULL, client);
317
318 // Store if ICE candidate type enabled
319 if (ice_candidate_type_enabled(client, type)) {
320 candidates->candidates[candidates->n_candidates++] = candidate;
321 } else {
322 mem_deref(candidate);
323 }
324 }
325
326 // End-of-candidates
327 candidates->candidates[candidates->n_candidates++] = NULL;
328
329out:
330 if (error) {
331 mem_deref(candidates);
332 } else {
333 // Set pointer
334 *candidatesp = candidates;
335 }
336 return error;
337}
338
339static void dtls_fingerprints_destroy(void* arg) {
340 struct rawrtc_dtls_fingerprints* const fingerprints = arg;
341 size_t i;
342
343 // Un-reference each item
344 for (i = 0; i < fingerprints->n_fingerprints; ++i) {
345 mem_deref(fingerprints->fingerprints[i]);
346 }
347}
348
349/*
350 * Get DTLS parameters from dictionary.
351 */
352enum rawrtc_code get_dtls_parameters(
353 struct rawrtc_dtls_parameters** const parametersp, struct odict* const dict) {
354 size_t n;
355 struct rawrtc_dtls_parameters* parameters = NULL;
356 struct rawrtc_dtls_fingerprints* fingerprints;
357 enum rawrtc_code error;
358 char const* role_str = NULL;
359 enum rawrtc_dtls_role role;
360 struct odict* node;
361 struct le* le;
362 size_t i;
363
364 // Get fingerprints array and length
365 error = dict_get_entry(&node, dict, "fingerprints", ODICT_ARRAY, true);
366 if (error) {
367 return error;
368 }
369 n = list_count(&node->lst);
370
371 // Allocate & set length immediately
372 fingerprints = mem_zalloc(
373 sizeof(*fingerprints) + (sizeof(struct rawrtc_dtls_fingerprints*) * n),
374 dtls_fingerprints_destroy);
375 if (!fingerprints) {
376 EWE("No memory to allocate DTLS fingerprint array");
377 }
378 fingerprints->n_fingerprints = n;
379
380 // Get role
381 error |= dict_get_entry(&role_str, dict, "role", ODICT_STRING, true);
382 error |= rawrtc_str_to_dtls_role(&role, role_str);
383 if (error) {
384 role = RAWRTC_DTLS_ROLE_AUTO;
385 }
386
387 // Get fingerprints
388 for (le = list_head(&node->lst), i = 0; le != NULL; le = le->next, ++i) {
389 char* algorithm_str = NULL;
390 enum rawrtc_certificate_sign_algorithm algorithm;
391 char* value;
392 node = ((struct odict_entry*) le->data)->u.odict;
393
394 // Get fingerprint
395 error |= dict_get_entry(&algorithm_str, node, "algorithm", ODICT_STRING, true);
396 error |= rawrtc_str_to_certificate_sign_algorithm(&algorithm, algorithm_str);
397 error |= dict_get_entry(&value, node, "value", ODICT_STRING, true);
398 if (error) {
399 goto out;
400 }
401
402 // Create and add fingerprint
403 error = rawrtc_dtls_fingerprint_create(&fingerprints->fingerprints[i], algorithm, value);
404 if (error) {
405 goto out;
406 }
407 }
408
409 // Create DTLS parameters
410 error = rawrtc_dtls_parameters_create(
411 &parameters, role, fingerprints->fingerprints, fingerprints->n_fingerprints);
412
413out:
414 mem_deref(fingerprints);
415
416 if (error) {
417 mem_deref(parameters);
418 } else {
419 // Set pointer
420 *parametersp = parameters;
421 }
422 return error;
423}
424
425/*
426 * Get SCTP parameters from dictionary.
427 */
428enum rawrtc_code get_sctp_parameters(
429 struct sctp_parameters* const parameters, struct odict* const dict) {
430 enum rawrtc_code error;
431 uint64_t max_message_size;
432
433 // Get maximum message size
434 error = dict_get_entry(&max_message_size, dict, "maxMessageSize", ODICT_INT, true);
435 if (error) {
436 return error;
437 }
438
439 // Get port
440 error = dict_get_uint16(&parameters->port, dict, "port", false);
441 if (error && error != RAWRTC_CODE_NO_VALUE) {
442 // Note: Nothing to do in NO VALUE case as port has been set to 0 by default
443 return error;
444 }
445
446 // Create SCTP capabilities instance
447 return rawrtc_sctp_capabilities_create(&parameters->capabilities, max_message_size);
448}