summaryrefslogtreecommitdiff
path: root/res/res_pjsip_sdp_rtp.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2017-03-16 10:46:01 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2017-03-16 10:46:01 -0500
commit84f0871cba30a9f3562f01fd347c6674d9058aad (patch)
tree6cc77f3dd72ecf4d115de5d83a42f0a8973c6d1a /res/res_pjsip_sdp_rtp.c
parentaec2a087ed51aeb6d27a9bb87cecc9f7145fd9ee (diff)
parent10fa49e3275e81860341d5ee5e0b9d15bafd9acd (diff)
Merge "Add rtcp-mux support"
Diffstat (limited to 'res/res_pjsip_sdp_rtp.c')
-rw-r--r--res/res_pjsip_sdp_rtp.c68
1 files changed, 66 insertions, 2 deletions
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index e32d2b65f..9f39256e5 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -169,6 +169,23 @@ static int rtp_check_timeout(const void *data)
return 0;
}
+/*!
+ * \brief Enable RTCP on an RTP session.
+ */
+static void enable_rtcp(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
+ const struct pjmedia_sdp_media *remote_media)
+{
+ enum ast_rtp_instance_rtcp rtcp_type;
+
+ if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
+ rtcp_type = AST_RTP_INSTANCE_RTCP_MUX;
+ } else {
+ rtcp_type = AST_RTP_INSTANCE_RTCP_STANDARD;
+ }
+
+ ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, rtcp_type);
+}
+
/*! \brief Internal function which creates an RTP instance */
static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
{
@@ -186,7 +203,6 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
return -1;
}
- ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, 1);
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_NAT, session->endpoint->media.rtp.symmetric);
if (!session->endpoint->media.rtp.ice_support && (ice = ast_rtp_instance_get_ice(session_media->rtp))) {
@@ -569,6 +585,13 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
continue;
}
+ if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux && candidate.id > 1) {
+ /* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,
+ * then we should ignore RTCP candidates.
+ */
+ continue;
+ }
+
candidate.foundation = foundation;
candidate.transport = transport;
@@ -865,6 +888,26 @@ static int setup_media_encryption(struct ast_sip_session *session,
return 0;
}
+static void set_ice_components(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
+{
+ struct ast_rtp_engine_ice *ice;
+
+ ast_assert(session_media->rtp != NULL);
+
+ ice = ast_rtp_instance_get_ice(session_media->rtp);
+ if (!session->endpoint->media.rtp.ice_support || !ice) {
+ return;
+ }
+
+ if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
+ /* We both support RTCP mux. Only one ICE component necessary */
+ ice->change_components(session_media->rtp, 1);
+ } else {
+ /* They either don't support RTCP mux or we don't know if they do yet. */
+ ice->change_components(session_media->rtp, 2);
+ }
+}
+
/*! \brief Function which negotiates an incoming media stream */
static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
@@ -909,6 +952,11 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
return -1;
}
+ session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(stream, "rtcp-mux", NULL) != NULL);
+ set_ice_components(session, session_media);
+
+ enable_rtcp(session, session_media, stream);
+
res = setup_media_encryption(session, session_media, sdp, stream);
if (res) {
if (!session->endpoint->media.rtp.encryption_optimistic ||
@@ -1087,6 +1135,9 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
return -1;
}
+ set_ice_components(session, session_media);
+ enable_rtcp(session, session_media, NULL);
+
if (!(media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media))) ||
!(media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn)))) {
return -1;
@@ -1250,6 +1301,12 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
attr->name = !session_media->locally_held ? STR_SENDRECV : STR_SENDONLY;
media->attr[media->attr_count++] = attr;
+ /* If we've got rtcp-mux enabled, just unconditionally offer it in all SDPs */
+ if (session->endpoint->media.rtcp_mux) {
+ attr = pjmedia_sdp_attr_create(pool, "rtcp-mux", NULL);
+ pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
+ }
+
/* Add the media stream to the SDP */
sdp->media[sdp->media_count++] = media;
@@ -1284,6 +1341,11 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
return -1;
}
+ session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(remote_stream, "rtcp-mux", NULL) != NULL);
+ set_ice_components(session, session_media);
+
+ enable_rtcp(session, session_media, remote_stream);
+
res = setup_media_encryption(session, session_media, remote, remote_stream);
if (!session->endpoint->media.rtp.encryption_optimistic && res) {
/* If optimistic encryption is disabled and crypto should have been enabled but was not
@@ -1315,7 +1377,9 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
return -1;
}
ast_channel_set_fd(session->channel, fdno, ast_rtp_instance_fd(session_media->rtp, 0));
- ast_channel_set_fd(session->channel, fdno + 1, ast_rtp_instance_fd(session_media->rtp, 1));
+ if (!session->endpoint->media.rtcp_mux || !session_media->remote_rtcp_mux) {
+ ast_channel_set_fd(session->channel, fdno + 1, ast_rtp_instance_fd(session_media->rtp, 1));
+ }
/* If ICE support is enabled find all the needed attributes */
process_ice_attributes(session, session_media, remote, remote_stream);