blob: eed012582aac5001310e81ebaf0da85e29dbeea5 [file] [log] [blame]
#include "candidate.h"
#include <rawrtc/ice_candidate.h>
#include <rawrtc/peer_connection_ice_candidate.h>
#include <rawrtcc/code.h>
#include <rawrtcc/utils.h>
#include <re.h>
/*
* Encode the ICE candidate into SDP.
* `*sdpp` will be set to a copy of the SDP attribute that must be
* unreferenced.
*
* Note: This is equivalent to the `candidate` attribute of the W3C
* WebRTC specification's `RTCIceCandidateInit`.
*/
enum rawrtc_code rawrtc_peer_connection_ice_candidate_get_sdp(
char** const sdpp, // de-referenced
struct rawrtc_peer_connection_ice_candidate* const candidate) {
enum rawrtc_code error;
char* foundation = NULL;
uint16_t component_id = 1;
enum rawrtc_ice_protocol protocol;
char const* protocol_str;
uint32_t priority;
char* ip = NULL;
uint16_t port;
enum rawrtc_ice_candidate_type type;
char const* type_str;
struct mbuf* sdp = NULL;
char* related_address = NULL;
uint16_t related_port = 0;
enum rawrtc_ice_tcp_candidate_type tcp_type = RAWRTC_ICE_TCP_CANDIDATE_TYPE_ACTIVE;
char const* tcp_type_str;
// Check arguments
if (!sdpp || !candidate) {
return RAWRTC_CODE_INVALID_ARGUMENT;
}
// Get values for mandatory fields
error = rawrtc_ice_candidate_get_foundation(&foundation, candidate->candidate);
if (error) {
goto out;
}
// TODO: Get component ID from candidate/gatherer/transport
error = rawrtc_ice_candidate_get_protocol(&protocol, candidate->candidate);
if (error) {
goto out;
}
error = rawrtc_ice_candidate_get_priority(&priority, candidate->candidate);
if (error) {
goto out;
}
error = rawrtc_ice_candidate_get_ip(&ip, candidate->candidate);
if (error) {
goto out;
}
error = rawrtc_ice_candidate_get_port(&port, candidate->candidate);
if (error) {
goto out;
}
error = rawrtc_ice_candidate_get_type(&type, candidate->candidate);
if (error) {
goto out;
}
error = rawrtc_ice_candidate_get_related_address(&related_address, candidate->candidate);
if (error && error != RAWRTC_CODE_NO_VALUE) {
goto out;
}
error = rawrtc_ice_candidate_get_related_port(&related_port, candidate->candidate);
if (error && error != RAWRTC_CODE_NO_VALUE) {
goto out;
}
protocol_str = rawrtc_ice_protocol_to_str(protocol);
type_str = rawrtc_ice_candidate_type_to_str(type);
// Initialise SDP attribute buffer
sdp = mbuf_alloc(RAWRTC_PEER_CONNECTION_CANDIDATE_DEFAULT_SIZE);
if (!sdp) {
error = RAWRTC_CODE_NO_MEMORY;
goto out;
}
// Encode candidate's mandatory fields
error = rawrtc_error_to_code(mbuf_printf(
sdp, "candidate:%s %" PRIu16 " %s %" PRIu32 " %s %" PRIu16 " typ %s", foundation,
component_id, protocol_str, priority, ip, port, type_str));
if (error) {
goto out;
}
if (related_address) {
error = rawrtc_error_to_code(mbuf_printf(sdp, " raddr %s", related_address));
if (error) {
goto out;
}
}
if (related_port > 0) {
error = rawrtc_error_to_code(mbuf_printf(sdp, " rport %" PRIu16, related_port));
if (error) {
goto out;
}
}
// Get value for 'tcptype' extension field and encode it (if available)
error = rawrtc_ice_candidate_get_tcp_type(&tcp_type, candidate->candidate);
switch (error) {
case RAWRTC_CODE_SUCCESS:
tcp_type_str = rawrtc_ice_tcp_candidate_type_to_str(tcp_type);
mbuf_printf(sdp, " tcptype %s", tcp_type_str);
break;
case RAWRTC_CODE_NO_VALUE:
break;
default:
goto out;
}
// Copy SDP attribute
error = rawrtc_sdprintf(sdpp, "%b", sdp->buf, sdp->end);
if (error) {
goto out;
}
out:
// Un-reference
mem_deref(related_address);
mem_deref(sdp);
mem_deref(ip);
mem_deref(foundation);
return error;
}
/*
* Get the media stream identification tag the ICE candidate is
* associated to.
* `*midp` will be set to a copy of the candidate's mid and must be
* unreferenced.
*
* Return `RAWRTC_CODE_NO_VALUE` in case no 'mid' has been set.
* Otherwise, `RAWRTC_CODE_SUCCESS` will be returned and `*midp* must
* be unreferenced.
*/
enum rawrtc_code rawrtc_peer_connection_ice_candidate_get_sdp_mid(
char** const midp, // de-referenced
struct rawrtc_peer_connection_ice_candidate* const candidate) {
// Check arguments
if (!midp || !candidate) {
return RAWRTC_CODE_INVALID_ARGUMENT;
}
// Copy mid (if any)
if (candidate->mid) {
return rawrtc_strdup(midp, candidate->mid);
} else {
return RAWRTC_CODE_NO_VALUE;
}
}
/*
* Get the media stream line index the ICE candidate is associated to.
* Return `RAWRTC_CODE_NO_VALUE` in case no media line index has been
* set.
*/
enum rawrtc_code rawrtc_peer_connection_ice_candidate_get_sdp_media_line_index(
uint8_t* const media_line_index, // de-referenced
struct rawrtc_peer_connection_ice_candidate* const candidate) {
// Check arguments
if (!media_line_index || !candidate) {
return RAWRTC_CODE_INVALID_ARGUMENT;
}
// Set media line index (if any)
if (candidate->media_line_index >= 0 && candidate->media_line_index <= UINT8_MAX) {
*media_line_index = (uint8_t) candidate->media_line_index;
return RAWRTC_CODE_SUCCESS;
} else {
return RAWRTC_CODE_NO_VALUE;
}
}
/*
* Get the username fragment the ICE candidate is associated to.
* `*username_fragmentp` will be set to a copy of the candidate's
* username fragment and must be unreferenced.
*
* Return `RAWRTC_CODE_NO_VALUE` in case no username fragment has been
* set. Otherwise, `RAWRTC_CODE_SUCCESS` will be returned and
* `*username_fragmentp* must be unreferenced.
*/
enum rawrtc_code rawrtc_peer_connection_ice_candidate_get_username_fragment(
char** const username_fragmentp, // de-referenced
struct rawrtc_peer_connection_ice_candidate* const candidate) {
// Check arguments
if (!username_fragmentp || !candidate) {
return RAWRTC_CODE_INVALID_ARGUMENT;
}
// Copy username fragment (if any)
if (candidate->username_fragment) {
return rawrtc_strdup(username_fragmentp, candidate->username_fragment);
} else {
return RAWRTC_CODE_NO_VALUE;
}
}
/*
* Get the underlying ORTC ICE candidate from the ICE candidate.
* `*ortc_candidatep` must be unreferenced.
*/
enum rawrtc_code rawrtc_peer_connection_ice_candidate_get_ortc_candidate(
struct rawrtc_ice_candidate** const ortc_candidatep, // de-referenced
struct rawrtc_peer_connection_ice_candidate* const candidate) {
// Check arguments
if (!ortc_candidatep || !candidate) {
return RAWRTC_CODE_INVALID_ARGUMENT;
}
// Reference ORTC ICE candidate
*ortc_candidatep = mem_ref(candidate->candidate);
return RAWRTC_CODE_SUCCESS;
}