summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorKevin Harwell <kharwell@digium.com>2017-07-10 18:17:44 -0500
committerKevin Harwell <kharwell@digium.com>2017-07-13 18:19:35 -0500
commit7da6ddda30ab9291ec810fa88d4219145616bae8 (patch)
tree89ad7fa5ae53b18a0a6412e85903ff7d8cd9d58b /res
parent0f45c979a3de00b320e05ba93309cf412e9e2702 (diff)
res_pjsip: Add "webrtc" configuration option
This patch creates a new configuration option called "webrtc". When enabled it defaults and enables the following options that are needed in order for webrtc to work in Asterisk: rtcp-mux, use_avpf, ice_support, and use_received_transport=enabled media_encryption=dtls dtls_verify=fingerprint dtls_setup=actpass When "webrtc" is enabled, this patch also parses the "msid" media level attribute from an SDP. It will also appropriately add it onto the outgoing session when applicable. Lastly, when "webrtc" is enabled h264 RTCP FIR feedback frames are now sent. ASTERISK-27119 #close Change-Id: I5ec02e07c5d5b9ad86a34fdf31bf2f9da9aac6fd
Diffstat (limited to 'res')
-rw-r--r--res/res_pjsip.c24
-rw-r--r--res/res_pjsip.exports.in1
-rw-r--r--res/res_pjsip/pjsip_configuration.c27
-rw-r--r--res/res_pjsip_sdp_rtp.c63
-rw-r--r--res/res_pjsip_session.c9
5 files changed, 118 insertions, 6 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index ee5c5fe5e..02112113c 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -1010,6 +1010,18 @@
underlying transport. Note that enabling bundle will also enable the rtcp_mux option.
</para></description>
</configOption>
+ <configOption name="webrtc" default="no">
+ <synopsis>Defaults and enables some options that are relevant to WebRTC</synopsis>
+ <description><para>
+ When set to "yes" this also enables the following values that are needed in
+ order for basic WebRTC support to work: rtcp_mux, use_avpf, ice_support, and
+ use_received_transport. The following configuration settings also get defaulted
+ as follows:</para>
+ <para>media_encryption=dtls</para>
+ <para>dtls_verify=fingerprint</para>
+ <para>dtls_setup=actpass</para>
+ </description>
+ </configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
@@ -4244,6 +4256,18 @@ void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
dest[chars_to_copy] = '\0';
}
+int ast_copy_pj_str2(char **dest, const pj_str_t *src)
+{
+ int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src));
+
+ if (res < 0) {
+ *dest = NULL;
+ }
+
+ return res;
+}
+
+
int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
{
pjsip_media_type compare;
diff --git a/res/res_pjsip.exports.in b/res/res_pjsip.exports.in
index 8b62abbfe..4adecd419 100644
--- a/res/res_pjsip.exports.in
+++ b/res/res_pjsip.exports.in
@@ -2,6 +2,7 @@
global:
LINKER_SYMBOL_PREFIXast_sip_*;
LINKER_SYMBOL_PREFIXast_copy_pj_str;
+ LINKER_SYMBOL_PREFIXast_copy_pj_str2;
LINKER_SYMBOL_PREFIXast_pjsip_rdata_get_endpoint;
local:
*;
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index c60173721..9f9de36fa 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1363,8 +1363,30 @@ static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *o
return -1;
}
- if (endpoint->media.bundle) {
- endpoint->media.rtcp_mux = 1;
+ endpoint->media.rtcp_mux |= endpoint->media.bundle;
+
+ /*
+ * If webrtc has been enabled then enable those attributes, and default
+ * some, that are needed in order for webrtc to work.
+ */
+ endpoint->media.bundle |= endpoint->media.webrtc;
+ endpoint->media.rtcp_mux |= endpoint->media.webrtc;
+ endpoint->media.rtp.use_avpf |= endpoint->media.webrtc;
+ endpoint->media.rtp.ice_support |= endpoint->media.webrtc;
+ endpoint->media.rtp.use_received_transport |= endpoint->media.webrtc;
+
+ if (endpoint->media.webrtc) {
+ endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;
+ endpoint->media.rtp.dtls_cfg.enabled = 1;
+ endpoint->media.rtp.dtls_cfg.default_setup = AST_RTP_DTLS_SETUP_ACTPASS;
+ endpoint->media.rtp.dtls_cfg.verify = AST_RTP_DTLS_VERIFY_FINGERPRINT;
+
+ if (ast_strlen_zero(endpoint->media.rtp.dtls_cfg.certfile) ||
+ (ast_strlen_zero(endpoint->media.rtp.dtls_cfg.cafile))) {
+ ast_log(LOG_ERROR, "WebRTC can't be enabled on endpoint '%s' - a DTLS cert "
+ "or ca file has not been specified", ast_sorcery_object_get_id(endpoint));
+ return -1;
+ }
}
return 0;
@@ -1990,6 +2012,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_audio_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_audio_streams));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_video_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_video_streams));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bundle", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.bundle));
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "webrtc", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.webrtc));
if (ast_sip_initialize_sorcery_transport()) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 4ec811528..a2e7f8f92 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -1025,6 +1025,65 @@ static void process_ssrc_attributes(struct ast_sip_session *session, struct ast_
}
}
+static void process_msid_attribute(struct ast_sip_session *session,
+ struct ast_sip_session_media *session_media, pjmedia_sdp_media *media)
+{
+ pjmedia_sdp_attr *attr;
+
+ if (!session->endpoint->media.webrtc) {
+ return;
+ }
+
+ attr = pjmedia_sdp_media_find_attr2(media, "msid", NULL);
+ if (attr) {
+ ast_free(session_media->msid);
+ ast_copy_pj_str2(&session_media->msid, &attr->value);
+ }
+}
+
+static void add_msid_to_stream(struct ast_sip_session *session,
+ struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
+{
+ pj_str_t stmp;
+ pjmedia_sdp_attr *attr;
+
+ if (!session->endpoint->media.webrtc) {
+ return;
+ }
+
+ if (ast_strlen_zero(session_media->msid)) {
+ char uuid1[AST_UUID_STR_LEN], uuid2[AST_UUID_STR_LEN];
+
+ if (ast_asprintf(&session_media->msid, "{%s} {%s}",
+ ast_uuid_generate_str(uuid1, sizeof(uuid1)),
+ ast_uuid_generate_str(uuid2, sizeof(uuid2))) < 0) {
+ session_media->msid = NULL;
+ return;
+ }
+ }
+
+ attr = pjmedia_sdp_attr_create(pool, "msid", pj_cstr(&stmp, session_media->msid));
+ pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
+}
+
+static void add_rtcp_fb_to_stream(struct ast_sip_session *session,
+ struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
+{
+ pj_str_t stmp;
+ pjmedia_sdp_attr *attr;
+
+ if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
+ return;
+ }
+
+ /*
+ * For now just automatically add it the stream even though it hasn't
+ * necessarily been negotiated.
+ */
+ attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* ccm fir"));
+ pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
+}
+
/*! \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 pjmedia_sdp_session *sdp,
@@ -1068,7 +1127,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session,
}
process_ssrc_attributes(session, session_media, stream);
-
+ process_msid_attribute(session, session_media, stream);
session_media_transport = ast_sip_session_media_get_transport(session, session_media);
if (session_media_transport == session_media || !session_media->bundled) {
@@ -1527,6 +1586,8 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
}
add_ssrc_to_stream(session, session_media, pool, media);
+ add_msid_to_stream(session, session_media, pool, media);
+ add_rtcp_fb_to_stream(session, session_media, pool, media);
/* Add the media stream to the SDP */
sdp->media[sdp->media_count++] = media;
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 315db6df5..fe3680f3b 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -395,6 +395,7 @@ static void session_media_dtor(void *obj)
}
ast_free(session_media->mid);
+ ast_free(session_media->msid);
}
struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_session *session,
@@ -3573,15 +3574,17 @@ static int add_bundle_groups(struct ast_sip_session *session, pj_pool_t *pool, p
int index, mid_id;
struct sip_session_media_bundle_group *bundle_group;
+ if (session->endpoint->media.webrtc) {
+ attr = pjmedia_sdp_attr_create(pool, "msid-semantic", pj_cstr(&stmp, "WMS *"));
+ pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr);
+ }
+
if (!session->endpoint->media.bundle) {
return 0;
}
memset(bundle_groups, 0, sizeof(bundle_groups));
- attr = pjmedia_sdp_attr_create(pool, "msid-semantic", pj_cstr(&stmp, "WMS *"));
- pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr);
-
/* Build the bundle group layout so we can then add it to the SDP */
for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) {
struct ast_sip_session_media *session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);