|
|
|
@ -132,6 +132,7 @@ struct sdp_attribute { |
|
|
|
ATTR_SENDRECV, |
|
|
|
ATTR_SENDONLY, |
|
|
|
ATTR_RECVONLY, |
|
|
|
ATTR_RTCP_MUX, |
|
|
|
} attr; |
|
|
|
|
|
|
|
union { |
|
|
|
@ -154,6 +155,10 @@ static str ice_foundation_str_alt; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int has_rtcp(struct sdp_media *media); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline struct sdp_attribute *attr_get_by_id(struct sdp_attributes *a, int id) { |
|
|
|
return g_hash_table_lookup(a->id_hash, &id); |
|
|
|
} |
|
|
|
@ -522,6 +527,8 @@ static int parse_attribute(struct sdp_attribute *a) { |
|
|
|
case 'r': |
|
|
|
if (!str_cmp(&a->name, "recvonly")) |
|
|
|
a->attr = ATTR_RECVONLY; |
|
|
|
if (!str_cmp(&a->name, "rtcp-mux")) |
|
|
|
a->attr = ATTR_RTCP_MUX; |
|
|
|
break; |
|
|
|
} |
|
|
|
break; |
|
|
|
@ -831,9 +838,19 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, GHashTable *streamhash, |
|
|
|
|
|
|
|
if (!si || media->port_count != 1) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (attr_get_by_id(&media->attributes, ATTR_RTCP_MUX)) { |
|
|
|
si->rtcp_mux = 1; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
attr = attr_get_by_id(&media->attributes, ATTR_RTCP); |
|
|
|
if (!attr || !attr->u.rtcp.port_num) |
|
|
|
continue; |
|
|
|
if (attr->u.rtcp.port_num == si->stream.port) { |
|
|
|
si->rtcp_mux = 1; |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (attr->u.rtcp.port_num == si->stream.port + 1) |
|
|
|
continue; |
|
|
|
|
|
|
|
@ -949,16 +966,24 @@ static int skip_over(struct sdp_chopper *chop, str *where) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void fill_relays(struct streamrelay **rtp, struct streamrelay **rtcp, GList *m, |
|
|
|
int off, struct stream_input *sip) |
|
|
|
static int fill_relays(struct streamrelay **rtp, struct streamrelay **rtcp, GList *m, |
|
|
|
int off, struct stream_input *sip, struct sdp_media *media) |
|
|
|
{ |
|
|
|
*rtp = &((struct callstream *) m->data)->peers[off].rtps[0]; |
|
|
|
|
|
|
|
if (rtcp) { |
|
|
|
*rtcp = &((struct callstream *) m->data)->peers[off].rtps[1]; |
|
|
|
if (sip && sip->has_rtcp && m->next) |
|
|
|
*rtcp = &((struct callstream *) m->next->data)->peers[off].rtps[0]; |
|
|
|
} |
|
|
|
if (!rtcp) |
|
|
|
return 1; |
|
|
|
|
|
|
|
*rtcp = &((struct callstream *) m->data)->peers[off].rtps[1]; |
|
|
|
if (sip && sip->has_rtcp && m->next) |
|
|
|
*rtcp = &((struct callstream *) m->next->data)->peers[off].rtps[0]; |
|
|
|
|
|
|
|
if ((*rtp)->rtcp_mux) |
|
|
|
return 2; |
|
|
|
if (!has_rtcp(media)) |
|
|
|
return 3; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int replace_transport_protocol(struct sdp_chopper *chop, |
|
|
|
@ -1009,7 +1034,7 @@ static int replace_consecutive_port_count(struct sdp_chopper *chop, struct sdp_m |
|
|
|
m = m->next; |
|
|
|
if (!m) |
|
|
|
goto warn; |
|
|
|
fill_relays(&sr, NULL, m, off, NULL); |
|
|
|
fill_relays(&sr, NULL, m, off, NULL, media); |
|
|
|
if (sr->fd.localport != rtp->fd.localport + cons * 2) { |
|
|
|
warn: |
|
|
|
mylog(LOG_WARN, "Failed to handle consecutive ports"); |
|
|
|
@ -1150,6 +1175,7 @@ static int process_media_attributes(struct sdp_chopper *chop, struct sdp_attribu |
|
|
|
goto strip; |
|
|
|
|
|
|
|
case ATTR_RTCP: |
|
|
|
case ATTR_RTCP_MUX: |
|
|
|
goto strip; |
|
|
|
|
|
|
|
case ATTR_CRYPTO: |
|
|
|
@ -1188,7 +1214,12 @@ static GList *find_stream_num(GList *m, int num) { |
|
|
|
} |
|
|
|
|
|
|
|
static int has_rtcp(struct sdp_media *media) { |
|
|
|
struct sdp_session *session = media->session; |
|
|
|
struct sdp_session *session; |
|
|
|
|
|
|
|
if (!media) |
|
|
|
return 0; |
|
|
|
|
|
|
|
session = media->session; |
|
|
|
|
|
|
|
if ((media->rr == -1 ? session->rr : media->rr) != 0 |
|
|
|
&& (media->rs == -1 ? session->rs : media->rs) != 0) |
|
|
|
@ -1240,7 +1271,8 @@ static void insert_candidates(struct sdp_chopper *chop, struct streamrelay *rtp, |
|
|
|
insert_ice_address(chop, rtp); |
|
|
|
chopper_append_c(chop, " typ host\r\n"); |
|
|
|
|
|
|
|
if (has_rtcp(media)) { |
|
|
|
if (rtcp) { |
|
|
|
/* rtcp-mux only possible in answer */ |
|
|
|
chopper_append_c(chop, "a=candidate:"); |
|
|
|
chopper_append_str(chop, &ice_foundation_str); |
|
|
|
chopper_append_printf(chop, " 2 UDP %lu ", priority - 1); |
|
|
|
@ -1259,7 +1291,7 @@ static void insert_candidates_alt(struct sdp_chopper *chop, struct streamrelay * |
|
|
|
insert_ice_address_alt(chop, rtp); |
|
|
|
chopper_append_c(chop, " typ host\r\n"); |
|
|
|
|
|
|
|
if (has_rtcp(media)) { |
|
|
|
if (rtcp) { |
|
|
|
chopper_append_c(chop, "a=candidate:"); |
|
|
|
chopper_append_str(chop, &ice_foundation_str_alt); |
|
|
|
chopper_append_printf(chop, " 2 UDP %lu ", priority - 1); |
|
|
|
@ -1315,11 +1347,13 @@ static int generate_crypto(struct sdp_media *media, struct sdp_ng_flags *flags, |
|
|
|
*c = *src; |
|
|
|
mutex_unlock(&rtp->up->up->lock); |
|
|
|
|
|
|
|
mutex_lock(&rtcp->up->up->lock); |
|
|
|
c = &rtcp->crypto.out; |
|
|
|
if (!c->crypto_suite) |
|
|
|
*c = *src; |
|
|
|
mutex_unlock(&rtcp->up->up->lock); |
|
|
|
if (rtcp) { |
|
|
|
mutex_lock(&rtcp->up->up->lock); |
|
|
|
c = &rtcp->crypto.out; |
|
|
|
if (!c->crypto_suite) |
|
|
|
*c = *src; |
|
|
|
mutex_unlock(&rtcp->up->up->lock); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
@ -1356,19 +1390,21 @@ static int generate_crypto(struct sdp_media *media, struct sdp_ng_flags *flags, |
|
|
|
p, &state, &save); |
|
|
|
p += g_base64_encode_close(0, p, &state, &save); |
|
|
|
|
|
|
|
mutex_lock(&rtcp->up->up->lock); |
|
|
|
if (rtcp) { |
|
|
|
mutex_lock(&rtcp->up->up->lock); |
|
|
|
|
|
|
|
src = c; |
|
|
|
c = &rtcp->crypto.out; |
|
|
|
src = c; |
|
|
|
c = &rtcp->crypto.out; |
|
|
|
|
|
|
|
c->crypto_suite = src->crypto_suite; |
|
|
|
c->tag = src->tag; |
|
|
|
memcpy(c->master_key, src->master_key, |
|
|
|
c->crypto_suite->master_key_len); |
|
|
|
memcpy(c->master_salt, src->master_salt, |
|
|
|
c->crypto_suite->master_salt_len); |
|
|
|
c->crypto_suite = src->crypto_suite; |
|
|
|
c->tag = src->tag; |
|
|
|
memcpy(c->master_key, src->master_key, |
|
|
|
c->crypto_suite->master_key_len); |
|
|
|
memcpy(c->master_salt, src->master_salt, |
|
|
|
c->crypto_suite->master_salt_len); |
|
|
|
|
|
|
|
mutex_unlock(&rtcp->up->up->lock); |
|
|
|
mutex_unlock(&rtcp->up->up->lock); |
|
|
|
} |
|
|
|
|
|
|
|
chopper_append_c(chop, "a=crypto:"); |
|
|
|
chopper_append_printf(chop, "%u ", c->tag); |
|
|
|
@ -1387,7 +1423,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call, |
|
|
|
struct sdp_session *session; |
|
|
|
struct sdp_media *media; |
|
|
|
GList *l, *k, *m; |
|
|
|
int off, do_ice; |
|
|
|
int off, do_ice, r_flags; |
|
|
|
struct stream_input si, *sip; |
|
|
|
struct streamrelay *rtp, *rtcp; |
|
|
|
unsigned long priority; |
|
|
|
@ -1399,7 +1435,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call, |
|
|
|
for (l = sessions->head; l; l = l->next) { |
|
|
|
session = l->data; |
|
|
|
|
|
|
|
fill_relays(&rtp, &rtcp, m, off, NULL); |
|
|
|
fill_relays(&rtp, &rtcp, m, off, NULL, NULL); |
|
|
|
|
|
|
|
if (session->origin.parsed && flags->replace_origin) { |
|
|
|
if (replace_network_address(chop, &session->origin.address, rtp)) |
|
|
|
@ -1430,7 +1466,7 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call, |
|
|
|
m = find_stream_num(m, sip->stream.num); |
|
|
|
if (!m) |
|
|
|
goto error; |
|
|
|
fill_relays(&rtp, &rtcp, m, off, sip); |
|
|
|
r_flags = fill_relays(&rtp, &rtcp, m, off, sip, media); |
|
|
|
|
|
|
|
rtp->peer.protocol = flags->transport_protocol; |
|
|
|
rtcp->peer.protocol = rtp->peer.protocol; |
|
|
|
@ -1458,11 +1494,16 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call, |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (has_rtcp(media)) { |
|
|
|
if (r_flags == 0) { |
|
|
|
chopper_append_c(chop, "a=rtcp:"); |
|
|
|
chopper_append_printf(chop, "%hu", rtcp->fd.localport); |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
} |
|
|
|
else if (r_flags == 2) { |
|
|
|
chopper_append_c(chop, "a=rtcp:"); |
|
|
|
chopper_append_printf(chop, "%hu", rtp->fd.localport); |
|
|
|
chopper_append_c(chop, "\r\na=rtcp-mux\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
generate_crypto(media, flags, rtp, rtcp, chop); |
|
|
|
|
|
|
|
@ -1494,11 +1535,13 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call *call, |
|
|
|
if (!flags->ice_remove) { |
|
|
|
priority = new_priority(flags->ice_force ? NULL : media); |
|
|
|
|
|
|
|
insert_candidates(chop, rtp, rtcp, priority, media); |
|
|
|
insert_candidates(chop, rtp, (r_flags == 2) ? NULL : rtcp, |
|
|
|
priority, media); |
|
|
|
|
|
|
|
if (callmaster_has_ipv6(rtp->up->up->call->callmaster)) { |
|
|
|
priority -= 256; |
|
|
|
insert_candidates_alt(chop, rtp, rtcp, priority, media); |
|
|
|
insert_candidates_alt(chop, rtp, (r_flags == 2) ? NULL : rtcp, |
|
|
|
priority, media); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|