summaryrefslogtreecommitdiff
path: root/res/res_pjsip_sdp_rtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip_sdp_rtp.c')
-rw-r--r--res/res_pjsip_sdp_rtp.c89
1 files changed, 84 insertions, 5 deletions
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index b27050ed8..d44171cf8 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->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)
{
@@ -179,6 +196,20 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
if (session->endpoint->media.bind_rtp_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0);
media_address = &temp_media_address;
+ } else {
+ struct ast_sip_transport *transport =
+ ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport",
+ session->endpoint->transport);
+
+ if (transport && transport->state) {
+ char hoststr[PJ_INET6_ADDRSTRLEN];
+
+ pj_sockaddr_print(&transport->state->host, hoststr, sizeof(hoststr), 0);
+ ast_debug(1, "Transport: %s bound to host: %s, using this for media.\n",
+ session->endpoint->transport, hoststr);
+ ast_sockaddr_parse(media_address, hoststr, 0);
+ }
+ ao2_cleanup(transport);
}
if (!(session_media->rtp = ast_rtp_instance_new(session->endpoint->media.rtp.engine, sched, media_address, NULL))) {
@@ -186,7 +217,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))) {
@@ -201,7 +231,7 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
}
if (!strcmp(session_media->stream_type, STR_AUDIO) &&
- (session->endpoint->media.tos_audio || session->endpoint->media.cos_video)) {
+ (session->endpoint->media.tos_audio || session->endpoint->media.cos_audio)) {
ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_audio,
session->endpoint->media.cos_audio, "SIP RTP Audio");
} else if (!strcmp(session_media->stream_type, STR_VIDEO) &&
@@ -555,6 +585,13 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
continue;
}
+ if (session->endpoint->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;
@@ -851,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->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)
@@ -895,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 ||
@@ -1065,6 +1127,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;
@@ -1228,6 +1293,12 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
attr->name = STR_SENDRECV;
media->attr[media->attr_count++] = attr;
+ /* If we've got rtcp-mux enabled, just unconditionally offer it in all SDPs */
+ if (session->endpoint->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;
@@ -1262,6 +1333,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
@@ -1293,7 +1369,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->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);
@@ -1387,10 +1465,11 @@ static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struc
ast_sockaddr_parse(&addr, host, PARSE_PORT_FORBID);
/* Is the address within the SDP inside the same network? */
- if (ast_apply_ha(transport_state->localnet, &addr) == AST_SENSE_ALLOW) {
+ if (transport_state->localnet
+ && ast_apply_ha(transport_state->localnet, &addr) == AST_SENSE_ALLOW) {
return;
}
-
+ ast_debug(5, "Setting media address to %s\n", transport->external_media_address);
pj_strdup2(tdata->pool, &stream->conn->addr, transport->external_media_address);
}