blob: c1f2b716d85c9237a8bf396262e322d413aa74c3 [file] [log] [blame]
James Kuszmaul4a42b182021-01-17 11:32:46 -08001#include "configuration.h"
2#include "../certificate/certificate.h"
3#include "../ice_server/server.h"
4#include "../utils/utils.h"
5#include <rawrtc/ice_gather_options.h>
6#include <rawrtc/peer_connection_configuration.h>
7#include <rawrtc/utils.h>
8#include <rawrtcc/code.h>
9#include <rawrtcdc/sctp_transport.h>
10#include <re.h>
11#include <limits.h> // INT_MAX
12
13/*
14 * Destructor for an existing peer connection configuration.
15 */
16static void rawrtc_peer_connection_configuration_destroy(void* arg) {
17 struct rawrtc_peer_connection_configuration* const configuration = arg;
18
19 // Un-reference
20 list_flush(&configuration->certificates);
21 list_flush(&configuration->ice_servers);
22}
23
24/*
25 * Create a new peer connection configuration.
26 * `*configurationp` must be unreferenced.
27 */
28enum rawrtc_code rawrtc_peer_connection_configuration_create(
29 struct rawrtc_peer_connection_configuration** const configurationp, // de-referenced
30 enum rawrtc_ice_gather_policy const gather_policy) {
31 struct rawrtc_peer_connection_configuration* configuration;
32
33 // Check arguments
34 if (!configurationp) {
35 return RAWRTC_CODE_INVALID_ARGUMENT;
36 }
37
38 // Allocate
39 configuration =
40 mem_zalloc(sizeof(*configuration), rawrtc_peer_connection_configuration_destroy);
41 if (!configuration) {
42 return RAWRTC_CODE_NO_MEMORY;
43 }
44
45 // Set fields/reference
46 configuration->gather_policy = gather_policy;
47 list_init(&configuration->ice_servers);
48 list_init(&configuration->certificates);
49 configuration->sctp_sdp_05 = true;
50 configuration->sctp.send_buffer_length = 0;
51 configuration->sctp.receive_buffer_length = 0;
52 configuration->sctp.congestion_ctrl_algorithm = RAWRTC_SCTP_TRANSPORT_CONGESTION_CTRL_RFC2581;
53 configuration->sctp.mtu = 0;
54 configuration->sctp.mtu_discovery = false;
55
56 // Set pointer and return
57 *configurationp = configuration;
58 return RAWRTC_CODE_SUCCESS;
59}
60
61/*
62 * Add an ICE server instance to the peer connection configuration.
63 */
64enum rawrtc_code rawrtc_peer_connection_configuration_add_ice_server_internal(
65 struct rawrtc_peer_connection_configuration* const configuration,
66 struct rawrtc_ice_server* const server) {
67 // Check arguments
68 if (!configuration || !server) {
69 return RAWRTC_CODE_INVALID_ARGUMENT;
70 }
71
72 // Add to configuration
73 list_append(&configuration->ice_servers, &server->le, server);
74 return RAWRTC_CODE_SUCCESS;
75}
76
77/*
78 * Add an ICE server to the peer connection configuration.
79 */
80enum rawrtc_code rawrtc_peer_connection_configuration_add_ice_server(
81 struct rawrtc_peer_connection_configuration* const configuration,
82 char* const* const urls, // copied
83 size_t const n_urls,
84 char* const username, // nullable, copied
85 char* const credential, // nullable, copied
86 enum rawrtc_ice_credential_type const credential_type) {
87 struct rawrtc_ice_server* server;
88 enum rawrtc_code error;
89
90 // Check arguments
91 if (!configuration) {
92 return RAWRTC_CODE_INVALID_ARGUMENT;
93 }
94
95 // Ensure there are less than 2^8 servers
96 // TODO: This check should be in some common location
97 if (list_count(&configuration->ice_servers) == UINT8_MAX) {
98 return RAWRTC_CODE_INSUFFICIENT_SPACE;
99 }
100
101 // Create ICE server
102 error = rawrtc_ice_server_create(&server, urls, n_urls, username, credential, credential_type);
103 if (error) {
104 return error;
105 }
106
107 // Add to configuration
108 return rawrtc_peer_connection_configuration_add_ice_server_internal(configuration, server);
109}
110
111/*
112 * Get ICE servers from the peer connection configuration.
113 * `*serversp` must be unreferenced.
114 */
115enum rawrtc_code rawrtc_peer_connection_configuration_get_ice_servers(
116 struct rawrtc_ice_servers** const serversp, // de-referenced
117 struct rawrtc_peer_connection_configuration* const configuration) {
118 // Check arguments
119 if (!serversp || !configuration) {
120 return RAWRTC_CODE_INVALID_ARGUMENT;
121 }
122
123 // Hand out list as array
124 // Note: ICE servers handed out cannot be added to other lists
125 // without copying since the items are only referenced.
126 return rawrtc_list_to_array(
127 (struct rawrtc_array_container**) serversp, &configuration->ice_servers, true);
128}
129
130/*
131 * Add a certificate to the peer connection configuration to be used
132 * instead of an ephemerally generated one.
133 */
134enum rawrtc_code rawrtc_peer_connection_configuration_add_certificate(
135 struct rawrtc_peer_connection_configuration* configuration,
136 struct rawrtc_certificate* const certificate // copied
137) {
138 enum rawrtc_code error;
139 struct rawrtc_certificate* certificate_copy;
140
141 // Check arguments
142 if (!configuration || !certificate) {
143 return RAWRTC_CODE_INVALID_ARGUMENT;
144 }
145
146 // Copy certificate
147 // Note: Copying is needed as the 'le' element cannot be associated to multiple lists
148 error = rawrtc_certificate_copy(&certificate_copy, certificate);
149 if (error) {
150 return error;
151 }
152
153 // Append to list
154 list_append(&configuration->certificates, &certificate_copy->le, certificate_copy);
155 return RAWRTC_CODE_SUCCESS;
156}
157
158/*
159 * Get certificates from the peer connection configuration.
160 * `*certificatesp` must be unreferenced.
161 */
162enum rawrtc_code rawrtc_peer_connection_configuration_get_certificates(
163 struct rawrtc_certificates** const certificatesp, // de-referenced
164 struct rawrtc_peer_connection_configuration* const configuration) {
165 // Check arguments
166 if (!certificatesp || !configuration) {
167 return RAWRTC_CODE_INVALID_ARGUMENT;
168 }
169
170 // Hand out list as array
171 // Note: Certificates handed out cannot be added to other lists
172 // without copying since the items are only referenced.
173 return rawrtc_list_to_array(
174 (struct rawrtc_array_container**) certificatesp, &configuration->certificates, true);
175}
176
177/*
178 * Set whether to use legacy SDP for data channel parameter encoding.
179 * Note: Legacy SDP for data channels is on by default due to parsing problems in Chrome.
180 */
181enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_sdp_05(
182 struct rawrtc_peer_connection_configuration* configuration, bool const on) {
183 // Check parameters
184 if (!configuration) {
185 return RAWRTC_CODE_INVALID_ARGUMENT;
186 }
187
188 // Set
189 configuration->sctp_sdp_05 = on;
190 return RAWRTC_CODE_SUCCESS;
191}
192
193/*
194 * Set the SCTP transport's send and receive buffer length in bytes.
195 * If both values are zero, the default buffer length will be used. Otherwise,
196 * zero is invalid.
197 */
198enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_buffer_length(
199 struct rawrtc_peer_connection_configuration* configuration,
200 uint32_t const send_buffer_length,
201 uint32_t const receive_buffer_length) {
202 // Check arguments
203 if (!configuration || send_buffer_length > INT_MAX || receive_buffer_length > INT_MAX ||
204 (send_buffer_length == 0 && receive_buffer_length != 0) ||
205 (send_buffer_length != 0 && receive_buffer_length == 0)) {
206 return RAWRTC_CODE_INVALID_ARGUMENT;
207 }
208
209 // Set length for send/receive buffer
210 configuration->sctp.send_buffer_length = send_buffer_length;
211 configuration->sctp.receive_buffer_length = receive_buffer_length;
212 return RAWRTC_CODE_SUCCESS;
213}
214
215/*
216 * Set the SCTP transport's congestion control algorithm.
217 */
218enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_congestion_ctrl_algorithm(
219 struct rawrtc_peer_connection_configuration* configuration,
220 enum rawrtc_sctp_transport_congestion_ctrl const algorithm) {
221 // Check arguments
222 if (!configuration) {
223 return RAWRTC_CODE_INVALID_ARGUMENT;
224 }
225
226 // Set
227 configuration->sctp.congestion_ctrl_algorithm = algorithm;
228 return RAWRTC_CODE_SUCCESS;
229}
230
231/*
232 * Set the SCTP transport's maximum transmission unit (MTU).
233 * A value of zero indicates that the default MTU should be used.
234 */
235enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_mtu(
236 struct rawrtc_peer_connection_configuration* configuration, uint32_t const mtu) {
237 // Check arguments
238 if (!configuration) {
239 return RAWRTC_CODE_INVALID_ARGUMENT;
240 }
241
242 // Set
243 configuration->sctp.mtu = mtu;
244 return RAWRTC_CODE_SUCCESS;
245}
246
247/*
248 * Enable or disable MTU discovery on the SCTP transport.
249 */
250enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_mtu_discovery(
251 struct rawrtc_peer_connection_configuration* configuration, bool const on) {
252 // Check arguments
253 if (!configuration) {
254 return RAWRTC_CODE_INVALID_ARGUMENT;
255 }
256
257 // Set
258 configuration->sctp.mtu_discovery = on;
259 return RAWRTC_CODE_SUCCESS;
260}