|
|
|
@ -1788,62 +1788,63 @@ static int replace_transport_protocol(struct sdp_chopper *chop, |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int replace_format_str(struct sdp_chopper *chop, |
|
|
|
struct sdp_media *media, struct call_media *cm) |
|
|
|
{ |
|
|
|
static int print_format_str(GString *s, struct call_media *cm) { |
|
|
|
if (!cm->format_str.s) |
|
|
|
return 0; |
|
|
|
chopper_append_c(chop, " "); |
|
|
|
chopper_append_str(chop, &cm->format_str); |
|
|
|
if (skip_over(chop, &media->formats)) |
|
|
|
return -1; |
|
|
|
g_string_append(s, " "); |
|
|
|
g_string_append_len(s, cm->format_str.s, cm->format_str.len); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int replace_codec_list(struct sdp_chopper *chop, |
|
|
|
struct sdp_media *media, struct call_media *cm) |
|
|
|
{ |
|
|
|
if (proto_is_not_rtp(cm->protocol)) |
|
|
|
return replace_format_str(chop, media, cm); |
|
|
|
static int print_codec_list(GString *s, struct call_media *media) { |
|
|
|
if (proto_is_not_rtp(media->protocol)) |
|
|
|
return print_format_str(s, media); |
|
|
|
|
|
|
|
if (cm->codecs.codec_prefs.length == 0) |
|
|
|
if (media->codecs.codec_prefs.length == 0) |
|
|
|
return 0; // legacy protocol or usage error |
|
|
|
|
|
|
|
for (GList *l = cm->codecs.codec_prefs.head; l; l = l->next) { |
|
|
|
for (GList *l = media->codecs.codec_prefs.head; l; l = l->next) { |
|
|
|
struct rtp_payload_type *pt = l->data; |
|
|
|
chopper_append_printf(chop, " %u", pt->payload_type); |
|
|
|
g_string_append_printf(s, " %u", pt->payload_type); |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int replace_codec_list(struct sdp_chopper *chop, |
|
|
|
struct sdp_media *media, struct call_media *cm) |
|
|
|
{ |
|
|
|
if (skip_over(chop, &media->formats)) |
|
|
|
return -1; |
|
|
|
return 0; |
|
|
|
|
|
|
|
return print_codec_list(chop->output, cm); |
|
|
|
} |
|
|
|
|
|
|
|
static void insert_codec_parameters(struct sdp_chopper *chop, struct call_media *cm) { |
|
|
|
static void insert_codec_parameters(GString *s, struct call_media *cm) { |
|
|
|
for (GList *l = cm->codecs.codec_prefs.head; l; l = l->next) { |
|
|
|
struct rtp_payload_type *pt = l->data; |
|
|
|
if (!pt->encoding_with_params.len) |
|
|
|
continue; |
|
|
|
chopper_append_printf(chop, "a=rtpmap:%u " STR_FORMAT "\r\n", |
|
|
|
g_string_append_printf(s, "a=rtpmap:%u " STR_FORMAT "\r\n", |
|
|
|
pt->payload_type, |
|
|
|
STR_FMT(&pt->encoding_with_params)); |
|
|
|
if (pt->format_parameters.len) { |
|
|
|
chopper_append_printf(chop, "a=fmtp:%u " STR_FORMAT "\r\n", |
|
|
|
g_string_append_printf(s, "a=fmtp:%u " STR_FORMAT "\r\n", |
|
|
|
pt->payload_type, |
|
|
|
STR_FMT(&pt->format_parameters)); |
|
|
|
} |
|
|
|
for (GList *l = pt->rtcp_fb.head; l; l = l->next) { |
|
|
|
str *fb = l->data; |
|
|
|
chopper_append_printf(chop, "a=rtcp-fb:%u " STR_FORMAT "\r\n", |
|
|
|
g_string_append_printf(s, "a=rtcp-fb:%u " STR_FORMAT "\r\n", |
|
|
|
pt->payload_type, |
|
|
|
STR_FMT(fb)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void insert_sdp_attributes(struct sdp_chopper *chop, struct call_media *cm) { |
|
|
|
static void insert_sdp_attributes(GString *gs, struct call_media *cm) { |
|
|
|
for (GList *l = cm->sdp_attributes.head; l; l = l->next) { |
|
|
|
str *s = l->data; |
|
|
|
chopper_append_printf(chop, "a=" STR_FORMAT "\r\n", |
|
|
|
g_string_append_printf(gs, "a=" STR_FORMAT "\r\n", |
|
|
|
STR_FMT(s)); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1910,7 +1911,7 @@ warn: |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int insert_ice_address(struct sdp_chopper *chop, struct stream_fd *sfd, struct sdp_ng_flags *flags) { |
|
|
|
static int insert_ice_address(GString *s, struct stream_fd *sfd, struct sdp_ng_flags *flags) { |
|
|
|
char buf[64]; |
|
|
|
int len; |
|
|
|
|
|
|
|
@ -1919,25 +1920,25 @@ static int insert_ice_address(struct sdp_chopper *chop, struct stream_fd *sfd, s |
|
|
|
sockaddr_print_buf(&flags->parsed_media_address)); |
|
|
|
else |
|
|
|
call_stream_address46(buf, sfd->stream, SAF_ICE, &len, sfd->local_intf, 0); |
|
|
|
chopper_append(chop, buf, len); |
|
|
|
chopper_append_printf(chop, " %u", sfd->socket.local.port); |
|
|
|
g_string_append_len(s, buf, len); |
|
|
|
g_string_append_printf(s, " %u", sfd->socket.local.port); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int insert_raddr_rport(struct sdp_chopper *chop, struct stream_fd *sfd, struct sdp_ng_flags *flags) { |
|
|
|
static int insert_raddr_rport(GString *s, struct stream_fd *sfd, struct sdp_ng_flags *flags) { |
|
|
|
char buf[64]; |
|
|
|
int len; |
|
|
|
|
|
|
|
chopper_append_c(chop, " raddr "); |
|
|
|
g_string_append(s, " raddr "); |
|
|
|
if (!is_addr_unspecified(&flags->parsed_media_address)) |
|
|
|
len = sprintf(buf, "%s", |
|
|
|
sockaddr_print_buf(&flags->parsed_media_address)); |
|
|
|
else |
|
|
|
call_stream_address46(buf, sfd->stream, SAF_ICE, &len, sfd->local_intf, 0); |
|
|
|
chopper_append(chop, buf, len); |
|
|
|
chopper_append_c(chop, " rport "); |
|
|
|
chopper_append_printf(chop, "%u", sfd->socket.local.port); |
|
|
|
g_string_append_len(s, buf, len); |
|
|
|
g_string_append(s, " rport "); |
|
|
|
g_string_append_printf(s, "%u", sfd->socket.local.port); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
@ -2205,7 +2206,7 @@ out: |
|
|
|
*lprefp = lpref; |
|
|
|
} |
|
|
|
|
|
|
|
static void insert_candidate(struct sdp_chopper *chop, struct stream_fd *sfd, |
|
|
|
static void insert_candidate(GString *s, struct stream_fd *sfd, |
|
|
|
unsigned int type_pref, unsigned int local_pref, enum ice_candidate_type type, |
|
|
|
struct sdp_ng_flags *flags) |
|
|
|
{ |
|
|
|
@ -2217,19 +2218,19 @@ static void insert_candidate(struct sdp_chopper *chop, struct stream_fd *sfd, |
|
|
|
local_pref = ifa->unique_id; |
|
|
|
|
|
|
|
priority = ice_priority_pref(type_pref, local_pref, ps->component); |
|
|
|
chopper_append_c(chop, "a=candidate:"); |
|
|
|
chopper_append_str(chop, &ifa->ice_foundation); |
|
|
|
chopper_append_printf(chop, " %u UDP %lu ", ps->component, priority); |
|
|
|
insert_ice_address(chop, sfd, flags); |
|
|
|
chopper_append_c(chop, " typ "); |
|
|
|
chopper_append_c(chop, ice_candidate_type_str(type)); |
|
|
|
g_string_append(s, "a=candidate:"); |
|
|
|
g_string_append_printf(s, STR_FORMAT, STR_FMT(&ifa->ice_foundation)); |
|
|
|
g_string_append_printf(s, " %u UDP %lu ", ps->component, priority); |
|
|
|
insert_ice_address(s, sfd, flags); |
|
|
|
g_string_append(s, " typ "); |
|
|
|
g_string_append(s, ice_candidate_type_str(type)); |
|
|
|
/* raddr and rport are required for non-host candidates: rfc5245 section-15.1 */ |
|
|
|
if(type != ICT_HOST) |
|
|
|
insert_raddr_rport(chop, sfd, flags); |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
insert_raddr_rport(s, sfd, flags); |
|
|
|
g_string_append(s, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
static void insert_sfd_candidates(struct sdp_chopper *chop, struct packet_stream *ps, |
|
|
|
static void insert_sfd_candidates(GString *s, struct packet_stream *ps, |
|
|
|
unsigned int type_pref, unsigned int local_pref, enum ice_candidate_type type, |
|
|
|
struct sdp_ng_flags *flags) |
|
|
|
{ |
|
|
|
@ -2238,14 +2239,14 @@ static void insert_sfd_candidates(struct sdp_chopper *chop, struct packet_stream |
|
|
|
|
|
|
|
for (l = ps->sfds.head; l; l = l->next) { |
|
|
|
sfd = l->data; |
|
|
|
insert_candidate(chop, sfd, type_pref, local_pref, type, flags); |
|
|
|
insert_candidate(s, sfd, type_pref, local_pref, type, flags); |
|
|
|
|
|
|
|
if (local_pref != -1) |
|
|
|
local_pref++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void insert_candidates(struct sdp_chopper *chop, struct packet_stream *rtp, struct packet_stream *rtcp, |
|
|
|
static void insert_candidates(GString *s, struct packet_stream *rtp, struct packet_stream *rtcp, |
|
|
|
struct sdp_ng_flags *flags, struct sdp_media *sdp_media) |
|
|
|
{ |
|
|
|
const struct local_intf *ifa; |
|
|
|
@ -2260,7 +2261,7 @@ static void insert_candidates(struct sdp_chopper *chop, struct packet_stream *rt |
|
|
|
cand_type = ICT_HOST; |
|
|
|
if (flags->ice_option == ICE_FORCE_RELAY) |
|
|
|
cand_type = ICT_RELAY; |
|
|
|
if (MEDIA_ISSET(media, PASSTHRU)) |
|
|
|
if (MEDIA_ISSET(media, PASSTHRU) && sdp_media) |
|
|
|
new_priority(sdp_media, cand_type, &type_pref, &local_pref); |
|
|
|
else { |
|
|
|
type_pref = ice_type_preference(cand_type); |
|
|
|
@ -2271,35 +2272,35 @@ static void insert_candidates(struct sdp_chopper *chop, struct packet_stream *rt |
|
|
|
|
|
|
|
if (ag && AGENT_ISSET(ag, COMPLETED)) { |
|
|
|
ifa = rtp->selected_sfd->local_intf; |
|
|
|
insert_candidate(chop, rtp->selected_sfd, type_pref, ifa->unique_id, cand_type, flags); |
|
|
|
insert_candidate(s, rtp->selected_sfd, type_pref, ifa->unique_id, cand_type, flags); |
|
|
|
if (rtcp) /* rtcp-mux only possible in answer */ |
|
|
|
insert_candidate(chop, rtcp->selected_sfd, type_pref, ifa->unique_id, cand_type, flags); |
|
|
|
insert_candidate(s, rtcp->selected_sfd, type_pref, ifa->unique_id, cand_type, flags); |
|
|
|
|
|
|
|
if (flags->opmode == OP_OFFER && AGENT_ISSET(ag, CONTROLLING)) { |
|
|
|
GQueue rc; |
|
|
|
GList *l; |
|
|
|
chopper_append_c(chop, "a=remote-candidates:"); |
|
|
|
g_string_append(s, "a=remote-candidates:"); |
|
|
|
ice_remote_candidates(&rc, ag); |
|
|
|
for (l = rc.head; l; l = l->next) { |
|
|
|
if (l != rc.head) |
|
|
|
chopper_append_c(chop, " "); |
|
|
|
g_string_append(s, " "); |
|
|
|
cand = l->data; |
|
|
|
chopper_append_printf(chop, "%lu %s %u", cand->component_id, |
|
|
|
g_string_append_printf(s, "%lu %s %u", cand->component_id, |
|
|
|
sockaddr_print_buf(&cand->endpoint.address), cand->endpoint.port); |
|
|
|
} |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
g_string_append(s, "\r\n"); |
|
|
|
g_queue_clear(&rc); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
insert_sfd_candidates(chop, rtp, type_pref, local_pref, cand_type, flags); |
|
|
|
insert_sfd_candidates(s, rtp, type_pref, local_pref, cand_type, flags); |
|
|
|
|
|
|
|
if (rtcp) /* rtcp-mux only possible in answer */ |
|
|
|
insert_sfd_candidates(chop, rtcp, type_pref, local_pref, cand_type, flags); |
|
|
|
insert_sfd_candidates(s, rtcp, type_pref, local_pref, cand_type, flags); |
|
|
|
} |
|
|
|
|
|
|
|
static void insert_dtls(struct call_media *media, struct sdp_chopper *chop) { |
|
|
|
static void insert_dtls(GString *s, struct call_media *media) { |
|
|
|
char hexbuf[DTLS_MAX_DIGEST_LEN * 3 + 2]; |
|
|
|
unsigned char *p; |
|
|
|
char *o; |
|
|
|
@ -2346,16 +2347,18 @@ static void insert_dtls(struct call_media *media, struct sdp_chopper *chop) { |
|
|
|
else if (MEDIA_ISSET(media, SETUP_ACTIVE)) |
|
|
|
actpass = "active"; |
|
|
|
|
|
|
|
chopper_append_c(chop, "a=setup:"); |
|
|
|
chopper_append_c(chop, actpass); |
|
|
|
chopper_append_c(chop, "\r\na=fingerprint:"); |
|
|
|
chopper_append_c(chop, hf->name); |
|
|
|
chopper_append_c(chop, " "); |
|
|
|
chopper_append(chop, hexbuf, o - hexbuf); |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
g_string_append(s, "a=setup:"); |
|
|
|
g_string_append(s, actpass); |
|
|
|
g_string_append(s, "\r\na=fingerprint:"); |
|
|
|
g_string_append(s, hf->name); |
|
|
|
g_string_append(s, " "); |
|
|
|
g_string_append_len(s, hexbuf, o - hexbuf); |
|
|
|
g_string_append(s, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
static void insert_crypto1(struct call_media *media, struct sdp_chopper *chop, struct crypto_params_sdes *cps, struct sdp_ng_flags *flags) { |
|
|
|
static void insert_crypto1(GString *s, struct call_media *media, struct crypto_params_sdes *cps, |
|
|
|
struct sdp_ng_flags *flags) |
|
|
|
{ |
|
|
|
char b64_buf[((SRTP_MAX_MASTER_KEY_LEN + SRTP_MAX_MASTER_SALT_LEN) / 3 + 1) * 4 + 4]; |
|
|
|
char *p; |
|
|
|
int state = 0, save = 0, i; |
|
|
|
@ -2379,37 +2382,35 @@ static void insert_crypto1(struct call_media *media, struct sdp_chopper *chop, s |
|
|
|
p--; |
|
|
|
} |
|
|
|
|
|
|
|
chopper_append_c(chop, "a=crypto:"); |
|
|
|
chopper_append_printf(chop, "%u ", cps->tag); |
|
|
|
chopper_append_c(chop, cps->params.crypto_suite->name); |
|
|
|
chopper_append_c(chop, " inline:"); |
|
|
|
chopper_append(chop, b64_buf, p - b64_buf); |
|
|
|
g_string_append(s, "a=crypto:"); |
|
|
|
g_string_append_printf(s, "%u ", cps->tag); |
|
|
|
g_string_append(s, cps->params.crypto_suite->name); |
|
|
|
g_string_append(s, " inline:"); |
|
|
|
g_string_append_len(s, b64_buf, p - b64_buf); |
|
|
|
if (flags->sdes_lifetime) |
|
|
|
chopper_append_c(chop, "|2^31"); |
|
|
|
g_string_append(s, "|2^31"); |
|
|
|
if (cps->params.mki_len) { |
|
|
|
ull = 0; |
|
|
|
for (i = 0; i < cps->params.mki_len && i < sizeof(ull); i++) |
|
|
|
ull |= (unsigned long long) cps->params.mki[cps->params.mki_len - i - 1] << (i * 8); |
|
|
|
chopper_append_printf(chop, "|%llu:%u", ull, cps->params.mki_len); |
|
|
|
g_string_append_printf(s, "|%llu:%u", ull, cps->params.mki_len); |
|
|
|
} |
|
|
|
if (cps->params.session_params.unencrypted_srtp) |
|
|
|
chopper_append_c(chop, " UNENCRYPTED_SRTP"); |
|
|
|
g_string_append(s, " UNENCRYPTED_SRTP"); |
|
|
|
if (cps->params.session_params.unencrypted_srtcp) |
|
|
|
chopper_append_c(chop, " UNENCRYPTED_SRTCP"); |
|
|
|
g_string_append(s, " UNENCRYPTED_SRTCP"); |
|
|
|
if (cps->params.session_params.unauthenticated_srtp) |
|
|
|
chopper_append_c(chop, " UNAUTHENTICATED_SRTP"); |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
g_string_append(s, " UNAUTHENTICATED_SRTP"); |
|
|
|
g_string_append(s, "\r\n"); |
|
|
|
} |
|
|
|
static void insert_crypto(struct call_media *media, struct sdp_chopper *chop, struct sdp_ng_flags *flags) { |
|
|
|
static void insert_crypto(GString *s, struct call_media *media, struct sdp_ng_flags *flags) { |
|
|
|
for (GList *l = media->sdes_out.head; l; l = l->next) |
|
|
|
insert_crypto1(media, chop, l->data, flags); |
|
|
|
insert_crypto1(s, media, l->data, flags); |
|
|
|
} |
|
|
|
static void insert_rtcp_attr(struct sdp_chopper *chop, struct packet_stream *ps, |
|
|
|
const struct sdp_ng_flags *flags) |
|
|
|
{ |
|
|
|
static void insert_rtcp_attr(GString *s, struct packet_stream *ps, const struct sdp_ng_flags *flags) { |
|
|
|
if (flags->no_rtcp_attr) |
|
|
|
return; |
|
|
|
chopper_append_printf(chop, "a=rtcp:%u", ps->selected_sfd->socket.local.port); |
|
|
|
g_string_append_printf(s, "a=rtcp:%u", ps->selected_sfd->socket.local.port); |
|
|
|
if (flags->full_rtcp_attr) { |
|
|
|
char buf[64]; |
|
|
|
int len; |
|
|
|
@ -2419,9 +2420,9 @@ static void insert_rtcp_attr(struct sdp_chopper *chop, struct packet_stream *ps, |
|
|
|
sockaddr_print_buf(&flags->parsed_media_address)); |
|
|
|
else |
|
|
|
call_stream_address46(buf, ps, SAF_NG, &len, NULL, 0); |
|
|
|
chopper_append_printf(chop, " IN %.*s", len, buf); |
|
|
|
g_string_append_printf(s, " IN %.*s", len, buf); |
|
|
|
} |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
g_string_append(s, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -2460,16 +2461,118 @@ dup: |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void print_sendrecv(GString *s, struct call_media *media) { |
|
|
|
if (MEDIA_ARESET2(media, SEND, RECV)) |
|
|
|
g_string_append(s, "a=sendrecv\r\n"); |
|
|
|
else if (MEDIA_ISSET(media, SEND)) |
|
|
|
g_string_append(s, "a=sendonly\r\n"); |
|
|
|
else if (MEDIA_ISSET(media, RECV)) |
|
|
|
g_string_append(s, "a=recvonly\r\n"); |
|
|
|
else |
|
|
|
g_string_append(s, "a=inactive\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct packet_stream *print_rtcp(GString *s, struct call_media *media, GList *rtp_ps_link, |
|
|
|
struct sdp_ng_flags *flags) |
|
|
|
{ |
|
|
|
struct packet_stream *ps = rtp_ps_link->data; |
|
|
|
struct packet_stream *ps_rtcp = NULL; |
|
|
|
|
|
|
|
if (ps->rtcp_sibling) { |
|
|
|
ps_rtcp = ps->rtcp_sibling; |
|
|
|
GList *rtcp_ps_link = rtp_ps_link->next; |
|
|
|
if (!rtcp_ps_link) |
|
|
|
return NULL; |
|
|
|
assert(rtcp_ps_link->data == ps_rtcp); |
|
|
|
} |
|
|
|
|
|
|
|
if (proto_is_rtp(media->protocol)) { |
|
|
|
if (MEDIA_ISSET(media, RTCP_MUX) |
|
|
|
&& (flags->opmode == OP_ANSWER || flags->opmode == OP_OTHER |
|
|
|
|| (flags->opmode == OP_OFFER |
|
|
|
&& flags->rtcp_mux_require))) |
|
|
|
{ |
|
|
|
insert_rtcp_attr(s, ps, flags); |
|
|
|
g_string_append(s, "a=rtcp-mux\r\n"); |
|
|
|
ps_rtcp = NULL; |
|
|
|
} |
|
|
|
else if (ps_rtcp && flags->ice_option != ICE_FORCE_RELAY) { |
|
|
|
insert_rtcp_attr(s, ps_rtcp, flags); |
|
|
|
if (MEDIA_ISSET(media, RTCP_MUX)) |
|
|
|
g_string_append(s, "a=rtcp-mux\r\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
ps_rtcp = NULL; |
|
|
|
|
|
|
|
return ps_rtcp; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static struct packet_stream *print_sdp_media_section(GString *s, struct call_media *media, |
|
|
|
struct sdp_media *sdp_media, |
|
|
|
struct sdp_ng_flags *flags, |
|
|
|
GList *rtp_ps_link, bool is_active, bool force_end_of_ice) |
|
|
|
{ |
|
|
|
struct packet_stream *ps_rtcp = NULL; |
|
|
|
|
|
|
|
if (is_active) { |
|
|
|
if (media->media_id.s) { |
|
|
|
g_string_append(s, "a=mid:"); |
|
|
|
g_string_append_printf(s, STR_FORMAT, STR_FMT(&media->media_id)); |
|
|
|
g_string_append(s, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
if (proto_is_rtp(media->protocol)) |
|
|
|
insert_codec_parameters(s, media); |
|
|
|
|
|
|
|
insert_sdp_attributes(s, media); |
|
|
|
|
|
|
|
if (!flags->original_sendrecv) |
|
|
|
print_sendrecv(s, media); |
|
|
|
|
|
|
|
ps_rtcp = print_rtcp(s, media, rtp_ps_link, flags); |
|
|
|
|
|
|
|
insert_crypto(s, media, flags); |
|
|
|
insert_dtls(s, media); |
|
|
|
|
|
|
|
if (proto_is_rtp(media->protocol) && media->ptime) |
|
|
|
g_string_append_printf(s, "a=ptime:%i\r\n", media->ptime); |
|
|
|
|
|
|
|
if (MEDIA_ISSET(media, ICE) && media->ice_agent) { |
|
|
|
g_string_append(s, "a=ice-ufrag:"); |
|
|
|
g_string_append_printf(s, STR_FORMAT, STR_FMT(&media->ice_agent->ufrag[1])); |
|
|
|
g_string_append(s, "\r\na=ice-pwd:"); |
|
|
|
g_string_append_printf(s, STR_FORMAT, STR_FMT(&media->ice_agent->pwd[1])); |
|
|
|
g_string_append(s, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
if (MEDIA_ISSET(media, TRICKLE_ICE) && media->ice_agent) |
|
|
|
g_string_append(s, "a=ice-options:trickle\r\n"); |
|
|
|
if (MEDIA_ISSET(media, ICE)) |
|
|
|
insert_candidates(s, rtp_ps_link->data, ps_rtcp, flags, sdp_media); |
|
|
|
} |
|
|
|
|
|
|
|
if (MEDIA_ISSET(media, TRICKLE_ICE) && media->ice_agent) |
|
|
|
g_string_append(s, "a=end-of-candidates\r\n"); |
|
|
|
else if (force_end_of_ice) |
|
|
|
g_string_append(s, "a=end-of-candidates\r\n"); |
|
|
|
|
|
|
|
return ps_rtcp; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* called with call->master_lock held in W */ |
|
|
|
int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologue *monologue, |
|
|
|
struct sdp_ng_flags *flags) |
|
|
|
{ |
|
|
|
struct sdp_session *session; |
|
|
|
struct sdp_media *sdp_media; |
|
|
|
GList *l, *k, *m, *j; |
|
|
|
GList *l, *k, *m, *rtp_ps_link; |
|
|
|
int media_index, sess_conn; |
|
|
|
struct call_media *call_media; |
|
|
|
struct packet_stream *ps, *ps_rtcp; |
|
|
|
struct packet_stream *ps; |
|
|
|
const char *err = NULL; |
|
|
|
|
|
|
|
m = monologue->medias.head; |
|
|
|
@ -2485,10 +2588,10 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu |
|
|
|
if (call_media->index != media_index) |
|
|
|
goto error; |
|
|
|
err = "no matching session media stream"; |
|
|
|
j = call_media->streams.head; |
|
|
|
if (!j) |
|
|
|
rtp_ps_link = call_media->streams.head; |
|
|
|
if (!rtp_ps_link) |
|
|
|
goto error; |
|
|
|
ps = j->data; |
|
|
|
ps = rtp_ps_link->data; |
|
|
|
|
|
|
|
err = "error while processing o= line"; |
|
|
|
if (!monologue->sdp_username) |
|
|
|
@ -2578,10 +2681,12 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu |
|
|
|
if (call_media->index != media_index) |
|
|
|
goto error; |
|
|
|
err = "no matching media stream"; |
|
|
|
j = call_media->streams.head; |
|
|
|
if (!j) |
|
|
|
rtp_ps_link = call_media->streams.head; |
|
|
|
if (!rtp_ps_link) |
|
|
|
goto error; |
|
|
|
ps = j->data; |
|
|
|
ps = rtp_ps_link->data; |
|
|
|
|
|
|
|
bool is_active = true; |
|
|
|
|
|
|
|
if (flags->ice_option != ICE_FORCE_RELAY && call_media->type_id != MT_MESSAGE) { |
|
|
|
err = "failed to replace media type"; |
|
|
|
@ -2591,7 +2696,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu |
|
|
|
if (replace_media_port(chop, sdp_media, ps)) |
|
|
|
goto error; |
|
|
|
err = "failed to replace media port count"; |
|
|
|
if (replace_consecutive_port_count(chop, sdp_media, ps, j)) |
|
|
|
if (replace_consecutive_port_count(chop, sdp_media, ps, rtp_ps_link)) |
|
|
|
goto error; |
|
|
|
err = "failed to replace media protocol"; |
|
|
|
if (replace_transport_protocol(chop, sdp_media, call_media)) |
|
|
|
@ -2613,6 +2718,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu |
|
|
|
if (synth_session_connection(chop, sdp_media)) |
|
|
|
goto error; |
|
|
|
// leave everything untouched |
|
|
|
is_active = false; |
|
|
|
goto next; |
|
|
|
} |
|
|
|
|
|
|
|
@ -2623,83 +2729,11 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu |
|
|
|
copy_up_to_end_of(chop, &sdp_media->s); |
|
|
|
|
|
|
|
if (!sdp_media->port_num || !ps->selected_sfd) |
|
|
|
goto next; |
|
|
|
|
|
|
|
if (call_media->media_id.s) { |
|
|
|
chopper_append_c(chop, "a=mid:"); |
|
|
|
chopper_append_str(chop, &call_media->media_id); |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
if (proto_is_rtp(call_media->protocol)) |
|
|
|
insert_codec_parameters(chop, call_media); |
|
|
|
|
|
|
|
insert_sdp_attributes(chop, call_media); |
|
|
|
|
|
|
|
ps_rtcp = NULL; |
|
|
|
if (ps->rtcp_sibling) { |
|
|
|
ps_rtcp = ps->rtcp_sibling; |
|
|
|
j = j->next; |
|
|
|
err = "no RTCP sibling"; |
|
|
|
if (!j) |
|
|
|
goto error; |
|
|
|
assert(j->data == ps_rtcp); |
|
|
|
} |
|
|
|
|
|
|
|
if (!flags->original_sendrecv) { |
|
|
|
if (MEDIA_ARESET2(call_media, SEND, RECV)) |
|
|
|
chopper_append_c(chop, "a=sendrecv\r\n"); |
|
|
|
else if (MEDIA_ISSET(call_media, SEND)) |
|
|
|
chopper_append_c(chop, "a=sendonly\r\n"); |
|
|
|
else if (MEDIA_ISSET(call_media, RECV)) |
|
|
|
chopper_append_c(chop, "a=recvonly\r\n"); |
|
|
|
else |
|
|
|
chopper_append_c(chop, "a=inactive\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
if (proto_is_rtp(call_media->protocol)) { |
|
|
|
if (MEDIA_ISSET(call_media, RTCP_MUX) |
|
|
|
&& (flags->opmode == OP_ANSWER |
|
|
|
|| (flags->opmode == OP_OFFER |
|
|
|
&& flags->rtcp_mux_require))) |
|
|
|
{ |
|
|
|
insert_rtcp_attr(chop, ps, flags); |
|
|
|
chopper_append_c(chop, "a=rtcp-mux\r\n"); |
|
|
|
ps_rtcp = NULL; |
|
|
|
} |
|
|
|
else if (ps_rtcp && flags->ice_option != ICE_FORCE_RELAY) { |
|
|
|
insert_rtcp_attr(chop, ps_rtcp, flags); |
|
|
|
if (MEDIA_ISSET(call_media, RTCP_MUX)) |
|
|
|
chopper_append_c(chop, "a=rtcp-mux\r\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
ps_rtcp = NULL; |
|
|
|
|
|
|
|
insert_crypto(call_media, chop, flags); |
|
|
|
insert_dtls(call_media, chop); |
|
|
|
|
|
|
|
if (proto_is_rtp(call_media->protocol) && call_media->ptime) |
|
|
|
chopper_append_printf(chop, "a=ptime:%i\r\n", call_media->ptime); |
|
|
|
|
|
|
|
if (MEDIA_ISSET(call_media, ICE) && call_media->ice_agent) { |
|
|
|
chopper_append_c(chop, "a=ice-ufrag:"); |
|
|
|
chopper_append_str(chop, &call_media->ice_agent->ufrag[1]); |
|
|
|
chopper_append_c(chop, "\r\na=ice-pwd:"); |
|
|
|
chopper_append_str(chop, &call_media->ice_agent->pwd[1]); |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
if (MEDIA_ISSET(call_media, TRICKLE_ICE) && call_media->ice_agent) |
|
|
|
chopper_append_c(chop, "a=ice-options:trickle\r\n"); |
|
|
|
if (MEDIA_ISSET(call_media, ICE)) |
|
|
|
insert_candidates(chop, ps, ps_rtcp, flags, sdp_media); |
|
|
|
is_active = false; |
|
|
|
|
|
|
|
next: |
|
|
|
if (MEDIA_ISSET(call_media, TRICKLE_ICE) && call_media->ice_agent) |
|
|
|
chopper_append_c(chop, "a=end-of-candidates\r\n"); |
|
|
|
else if (attr_get_by_id(&sdp_media->attributes, ATTR_END_OF_CANDIDATES)) |
|
|
|
chopper_append_c(chop, "a=end-of-candidates\r\n"); |
|
|
|
print_sdp_media_section(chop->output, call_media, sdp_media,flags, rtp_ps_link, is_active, |
|
|
|
attr_get_by_id(&sdp_media->attributes, ATTR_END_OF_CANDIDATES)); |
|
|
|
|
|
|
|
media_index++; |
|
|
|
m = m->next; |
|
|
|
|