|
|
|
@ -80,6 +80,8 @@ struct sdp_media { |
|
|
|
struct sdp_attributes attributes; |
|
|
|
GQueue format_list; /* list of slice-alloc'd str objects */ |
|
|
|
enum media_type media_type_id; |
|
|
|
|
|
|
|
unsigned int legacy_osrtp:1; |
|
|
|
}; |
|
|
|
|
|
|
|
struct attribute_rtcp { |
|
|
|
@ -1536,6 +1538,73 @@ static void __sdp_t38(struct stream_params *sp, struct sdp_media *media) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void sp_free(void *p) { |
|
|
|
struct stream_params *s = p; |
|
|
|
|
|
|
|
codec_store_cleanup(&s->codecs); |
|
|
|
ice_candidates_free(&s->ice_candidates); |
|
|
|
crypto_params_sdes_queue_clear(&s->sdes_params); |
|
|
|
g_slice_free1(sizeof(*s), s); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Check the list for a legacy non-RFC OSRTP offer: |
|
|
|
// Given m= lines must be alternating between one RTP and one SRTP m= line, with matching |
|
|
|
// types between each pair. |
|
|
|
// If found, rewrite the list to pretend that only the SRTP m=line was given, and mark |
|
|
|
// the session media accordingly. |
|
|
|
// TODO: should be handled by monologue_offer_answer, without requiring OSRTP-accept to be |
|
|
|
// set for re-invites. SDP rewriting and skipping media sections should be handled by |
|
|
|
// associating offer/answer media sections directly with each other, instead of requiring |
|
|
|
// the indexing to be in order and instead of requiring all sections between monologue and sdp_media |
|
|
|
// lists to be matching. |
|
|
|
static void legacy_osrtp_accept(struct stream_params *sp, GQueue *streams, GList *prev_media_link, |
|
|
|
struct sdp_ng_flags *flags, unsigned int *num) |
|
|
|
{ |
|
|
|
if (!streams->tail) |
|
|
|
return; |
|
|
|
if (!prev_media_link) |
|
|
|
return; |
|
|
|
struct stream_params *last = streams->tail->data; |
|
|
|
|
|
|
|
if (!flags->osrtp_accept_legacy) |
|
|
|
return; |
|
|
|
|
|
|
|
// protocols must be known |
|
|
|
if (!sp->protocol) |
|
|
|
return; |
|
|
|
if (!last->protocol) |
|
|
|
return; |
|
|
|
// types must match |
|
|
|
if (sp->type_id != last->type_id) |
|
|
|
return; |
|
|
|
|
|
|
|
// we must be looking at a SRTP media section |
|
|
|
if (!sp->protocol->rtp) |
|
|
|
return; |
|
|
|
if (!sp->protocol->srtp) |
|
|
|
return; |
|
|
|
|
|
|
|
// previous one must be a plain RTP section |
|
|
|
if (!last->protocol->rtp) |
|
|
|
return; |
|
|
|
if (last->protocol->srtp) |
|
|
|
return; |
|
|
|
|
|
|
|
// is this a non-rejected SRTP section? |
|
|
|
if (sp->rtp_endpoint.port) { |
|
|
|
// looks ok. remove the previous one and only retain this one. mark it as such. |
|
|
|
g_queue_pop_tail(streams); |
|
|
|
sp_free(last); |
|
|
|
|
|
|
|
SP_SET(sp, LEGACY_OSRTP); |
|
|
|
struct sdp_media *prev_media = prev_media_link->data; |
|
|
|
prev_media->legacy_osrtp = 1; |
|
|
|
sp->index--; |
|
|
|
(*num)--; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* XXX split this function up */ |
|
|
|
int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *flags) { |
|
|
|
struct sdp_session *session; |
|
|
|
@ -1543,10 +1612,9 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl |
|
|
|
struct stream_params *sp; |
|
|
|
GList *l, *k; |
|
|
|
const char *errstr; |
|
|
|
int num; |
|
|
|
unsigned int num = 0; |
|
|
|
struct sdp_attribute *attr; |
|
|
|
|
|
|
|
num = 0; |
|
|
|
for (l = sessions->head; l; l = l->next) { |
|
|
|
session = l->data; |
|
|
|
|
|
|
|
@ -1662,6 +1730,8 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl |
|
|
|
sp->protocol = &transport_protocols[sp->protocol->osrtp_proto]; |
|
|
|
} |
|
|
|
|
|
|
|
legacy_osrtp_accept(sp, streams, k->prev, flags, &num); |
|
|
|
|
|
|
|
// a=mid |
|
|
|
attr = attr_get_by_id(&media->attributes, ATTR_MID); |
|
|
|
if (attr) |
|
|
|
@ -1707,14 +1777,6 @@ error: |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
static void sp_free(void *p) { |
|
|
|
struct stream_params *s = p; |
|
|
|
|
|
|
|
codec_store_cleanup(&s->codecs); |
|
|
|
ice_candidates_free(&s->ice_candidates); |
|
|
|
crypto_params_sdes_queue_clear(&s->sdes_params); |
|
|
|
g_slice_free1(sizeof(*s), s); |
|
|
|
} |
|
|
|
void sdp_streams_free(GQueue *q) { |
|
|
|
g_queue_clear_full(q, sp_free); |
|
|
|
} |
|
|
|
@ -2797,6 +2859,13 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu |
|
|
|
|
|
|
|
for (k = session->media_streams.head; k; k = k->next) { |
|
|
|
sdp_media = k->data; |
|
|
|
|
|
|
|
// skip over received dummy SDP sections |
|
|
|
if (sdp_media->legacy_osrtp) { |
|
|
|
skip_over(chop, &sdp_media->s); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
err = "no matching media"; |
|
|
|
if (!m) |
|
|
|
goto error; |
|
|
|
@ -2810,6 +2879,22 @@ int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologu |
|
|
|
goto error; |
|
|
|
ps = rtp_ps_link->data; |
|
|
|
|
|
|
|
// generate rejected m= line for accepted legacy OSRTP |
|
|
|
if (MEDIA_ISSET(call_media, LEGACY_OSRTP) |
|
|
|
&& call_media->protocol |
|
|
|
&& call_media->protocol->srtp) |
|
|
|
{ |
|
|
|
chopper_append_c(chop, "m="); |
|
|
|
chopper_append_str(chop, &call_media->type); |
|
|
|
const struct transport_protocol *prtp |
|
|
|
= &transport_protocols[call_media->protocol->rtp_proto]; |
|
|
|
chopper_append_c(chop, " 0 "); |
|
|
|
chopper_append_c(chop, prtp->name); |
|
|
|
chopper_append_c(chop, " "); |
|
|
|
chopper_append_str(chop, &call_media->format_str); |
|
|
|
chopper_append_c(chop, "\r\n"); |
|
|
|
} |
|
|
|
|
|
|
|
bool is_active = true; |
|
|
|
|
|
|
|
if (flags->ice_option != ICE_FORCE_RELAY && call_media->type_id != MT_MESSAGE) { |
|
|
|
|