Squashed 'third_party/rawrtc/rawrtc/' content from commit aa3ae4b24

Change-Id: I38a655a4259b62f591334e90a1315bd4e7e4d8ec
git-subtree-dir: third_party/rawrtc/rawrtc
git-subtree-split: aa3ae4b247275cc6e69c30613b3a4ba7fdc82d1b
diff --git a/src/peer_connection_configuration/configuration.c b/src/peer_connection_configuration/configuration.c
new file mode 100644
index 0000000..c1f2b71
--- /dev/null
+++ b/src/peer_connection_configuration/configuration.c
@@ -0,0 +1,260 @@
+#include "configuration.h"
+#include "../certificate/certificate.h"
+#include "../ice_server/server.h"
+#include "../utils/utils.h"
+#include <rawrtc/ice_gather_options.h>
+#include <rawrtc/peer_connection_configuration.h>
+#include <rawrtc/utils.h>
+#include <rawrtcc/code.h>
+#include <rawrtcdc/sctp_transport.h>
+#include <re.h>
+#include <limits.h>  // INT_MAX
+
+/*
+ * Destructor for an existing peer connection configuration.
+ */
+static void rawrtc_peer_connection_configuration_destroy(void* arg) {
+    struct rawrtc_peer_connection_configuration* const configuration = arg;
+
+    // Un-reference
+    list_flush(&configuration->certificates);
+    list_flush(&configuration->ice_servers);
+}
+
+/*
+ * Create a new peer connection configuration.
+ * `*configurationp` must be unreferenced.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_create(
+    struct rawrtc_peer_connection_configuration** const configurationp,  // de-referenced
+    enum rawrtc_ice_gather_policy const gather_policy) {
+    struct rawrtc_peer_connection_configuration* configuration;
+
+    // Check arguments
+    if (!configurationp) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Allocate
+    configuration =
+        mem_zalloc(sizeof(*configuration), rawrtc_peer_connection_configuration_destroy);
+    if (!configuration) {
+        return RAWRTC_CODE_NO_MEMORY;
+    }
+
+    // Set fields/reference
+    configuration->gather_policy = gather_policy;
+    list_init(&configuration->ice_servers);
+    list_init(&configuration->certificates);
+    configuration->sctp_sdp_05 = true;
+    configuration->sctp.send_buffer_length = 0;
+    configuration->sctp.receive_buffer_length = 0;
+    configuration->sctp.congestion_ctrl_algorithm = RAWRTC_SCTP_TRANSPORT_CONGESTION_CTRL_RFC2581;
+    configuration->sctp.mtu = 0;
+    configuration->sctp.mtu_discovery = false;
+
+    // Set pointer and return
+    *configurationp = configuration;
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Add an ICE server instance to the peer connection configuration.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_add_ice_server_internal(
+    struct rawrtc_peer_connection_configuration* const configuration,
+    struct rawrtc_ice_server* const server) {
+    // Check arguments
+    if (!configuration || !server) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Add to configuration
+    list_append(&configuration->ice_servers, &server->le, server);
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Add an ICE server to the peer connection configuration.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_add_ice_server(
+    struct rawrtc_peer_connection_configuration* const configuration,
+    char* const* const urls,  // copied
+    size_t const n_urls,
+    char* const username,  // nullable, copied
+    char* const credential,  // nullable, copied
+    enum rawrtc_ice_credential_type const credential_type) {
+    struct rawrtc_ice_server* server;
+    enum rawrtc_code error;
+
+    // Check arguments
+    if (!configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Ensure there are less than 2^8 servers
+    // TODO: This check should be in some common location
+    if (list_count(&configuration->ice_servers) == UINT8_MAX) {
+        return RAWRTC_CODE_INSUFFICIENT_SPACE;
+    }
+
+    // Create ICE server
+    error = rawrtc_ice_server_create(&server, urls, n_urls, username, credential, credential_type);
+    if (error) {
+        return error;
+    }
+
+    // Add to configuration
+    return rawrtc_peer_connection_configuration_add_ice_server_internal(configuration, server);
+}
+
+/*
+ * Get ICE servers from the peer connection configuration.
+ * `*serversp` must be unreferenced.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_get_ice_servers(
+    struct rawrtc_ice_servers** const serversp,  // de-referenced
+    struct rawrtc_peer_connection_configuration* const configuration) {
+    // Check arguments
+    if (!serversp || !configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Hand out list as array
+    // Note: ICE servers handed out cannot be added to other lists
+    //       without copying since the items are only referenced.
+    return rawrtc_list_to_array(
+        (struct rawrtc_array_container**) serversp, &configuration->ice_servers, true);
+}
+
+/*
+ * Add a certificate to the peer connection configuration to be used
+ * instead of an ephemerally generated one.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_add_certificate(
+    struct rawrtc_peer_connection_configuration* configuration,
+    struct rawrtc_certificate* const certificate  // copied
+) {
+    enum rawrtc_code error;
+    struct rawrtc_certificate* certificate_copy;
+
+    // Check arguments
+    if (!configuration || !certificate) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Copy certificate
+    // Note: Copying is needed as the 'le' element cannot be associated to multiple lists
+    error = rawrtc_certificate_copy(&certificate_copy, certificate);
+    if (error) {
+        return error;
+    }
+
+    // Append to list
+    list_append(&configuration->certificates, &certificate_copy->le, certificate_copy);
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Get certificates from the peer connection configuration.
+ * `*certificatesp` must be unreferenced.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_get_certificates(
+    struct rawrtc_certificates** const certificatesp,  // de-referenced
+    struct rawrtc_peer_connection_configuration* const configuration) {
+    // Check arguments
+    if (!certificatesp || !configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Hand out list as array
+    // Note: Certificates handed out cannot be added to other lists
+    //       without copying since the items are only referenced.
+    return rawrtc_list_to_array(
+        (struct rawrtc_array_container**) certificatesp, &configuration->certificates, true);
+}
+
+/*
+ * Set whether to use legacy SDP for data channel parameter encoding.
+ * Note: Legacy SDP for data channels is on by default due to parsing problems in Chrome.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_sdp_05(
+    struct rawrtc_peer_connection_configuration* configuration, bool const on) {
+    // Check parameters
+    if (!configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Set
+    configuration->sctp_sdp_05 = on;
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Set the SCTP transport's send and receive buffer length in bytes.
+ * If both values are zero, the default buffer length will be used. Otherwise,
+ * zero is invalid.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_buffer_length(
+    struct rawrtc_peer_connection_configuration* configuration,
+    uint32_t const send_buffer_length,
+    uint32_t const receive_buffer_length) {
+    // Check arguments
+    if (!configuration || send_buffer_length > INT_MAX || receive_buffer_length > INT_MAX ||
+        (send_buffer_length == 0 && receive_buffer_length != 0) ||
+        (send_buffer_length != 0 && receive_buffer_length == 0)) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Set length for send/receive buffer
+    configuration->sctp.send_buffer_length = send_buffer_length;
+    configuration->sctp.receive_buffer_length = receive_buffer_length;
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Set the SCTP transport's congestion control algorithm.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_congestion_ctrl_algorithm(
+    struct rawrtc_peer_connection_configuration* configuration,
+    enum rawrtc_sctp_transport_congestion_ctrl const algorithm) {
+    // Check arguments
+    if (!configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Set
+    configuration->sctp.congestion_ctrl_algorithm = algorithm;
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Set the SCTP transport's maximum transmission unit (MTU).
+ * A value of zero indicates that the default MTU should be used.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_mtu(
+    struct rawrtc_peer_connection_configuration* configuration, uint32_t const mtu) {
+    // Check arguments
+    if (!configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Set
+    configuration->sctp.mtu = mtu;
+    return RAWRTC_CODE_SUCCESS;
+}
+
+/*
+ * Enable or disable MTU discovery on the SCTP transport.
+ */
+enum rawrtc_code rawrtc_peer_connection_configuration_set_sctp_mtu_discovery(
+    struct rawrtc_peer_connection_configuration* configuration, bool const on) {
+    // Check arguments
+    if (!configuration) {
+        return RAWRTC_CODE_INVALID_ARGUMENT;
+    }
+
+    // Set
+    configuration->sctp.mtu_discovery = on;
+    return RAWRTC_CODE_SUCCESS;
+}