summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/res_pjsip.c5
-rw-r--r--res/res_pjsip_sdp_rtp.c31
-rw-r--r--res/res_pjsip_session.c194
3 files changed, 58 insertions, 172 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 69feabafb..e63d02f6a 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -385,9 +385,8 @@
decline media offers not using the AVPF or SAVPF profile.
</para><para>
If set to <literal>no</literal>, res_pjsip will use the AVP or SAVP RTP
- profile for all media offers on outbound calls and media updates, but will
- accept either the AVP/AVPF or SAVP/SAVPF RTP profile for all inbound
- media offers.
+ profile for all media offers on outbound calls and media updates, and will
+ decline media offers not using the AVP or SAVP profile.
</para></description>
</configOption>
<configOption name="force_avp" default="no">
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 2aa8acc38..1f863008f 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -247,9 +247,10 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi
struct ast_str *thembuf = ast_str_alloca(64);
ast_rtp_codecs_payloads_destroy(&codecs);
- ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n",
- ast_format_cap_get_names(peer, &usbuf),
- ast_format_cap_get_names(caps, &thembuf));
+ ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
+ session_media->stream_type,
+ ast_format_cap_get_names(caps, &usbuf),
+ ast_format_cap_get_names(peer, &thembuf));
return -1;
}
@@ -521,12 +522,11 @@ static enum ast_sip_session_media_encryption check_endpoint_media_transport(
const struct pjmedia_sdp_media *stream)
{
enum ast_sip_session_media_encryption incoming_encryption;
+ char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1];
- if (endpoint->media.rtp.use_avpf) {
- char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1];
- if (transport_end != 'F') {
- return AST_SIP_MEDIA_TRANSPORT_INVALID;
- }
+ if ((transport_end == 'F' && !endpoint->media.rtp.use_avpf)
+ || (transport_end != 'F' && endpoint->media.rtp.use_avpf)) {
+ return AST_SIP_MEDIA_TRANSPORT_INVALID;
}
incoming_encryption = get_media_encryption_type(stream->desc.transport);
@@ -727,8 +727,15 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
+ /* If port is 0, ignore this media stream */
+ if (!stream->desc.port) {
+ ast_debug(3, "Media stream '%s' is already declined\n", session_media->stream_type);
+ return 0;
+ }
+
/* If no type formats have been configured reject this stream */
if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
+ ast_debug(3, "Endpoint has no codecs for media type '%s', declining stream\n", session_media->stream_type);
return 0;
}
@@ -760,7 +767,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
}
if (set_caps(session, session_media, stream)) {
- return -1;
+ return 0;
}
return 1;
}
@@ -1061,6 +1068,10 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
return 1;
}
+ if (!local_stream->desc.port || !remote_stream->desc.port) {
+ return 1;
+ }
+
/* Ensure incoming transport is compatible with the endpoint's configuration */
if (!session->endpoint->media.rtp.use_received_transport &&
check_endpoint_media_transport(session->endpoint, remote_stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
@@ -1088,7 +1099,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
ast_sockaddr_set_port(addrs, remote_stream->desc.port);
ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
if (set_caps(session, session_media, local_stream)) {
- return -1;
+ return 1;
}
if ((fdno = media_type_to_fdno(media_type)) < 0) {
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 56187211f..d5dc98e9d 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -186,160 +186,10 @@ void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler *
ao2_callback_data(sdp_handlers, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, remove_handler, (void *)stream_type, handler);
}
-static int validate_port_hash(const void *obj, int flags)
-{
- const int *port = obj;
- return *port;
-}
-
-static int validate_port_cmp(void *obj, void *arg, int flags)
-{
- int *port1 = obj;
- int *port2 = arg;
-
- return *port1 == *port2 ? CMP_MATCH | CMP_STOP : 0;
-}
-
-struct bundle_assoc {
- int port;
- char tag[1];
-};
-
-static int bundle_assoc_hash(const void *obj, int flags)
-{
- const struct bundle_assoc *assoc = obj;
- const char *tag = flags & OBJ_KEY ? obj : assoc->tag;
-
- return ast_str_hash(tag);
-}
-
-static int bundle_assoc_cmp(void *obj, void *arg, int flags)
-{
- struct bundle_assoc *assoc1 = obj;
- struct bundle_assoc *assoc2 = arg;
- const char *tag2 = flags & OBJ_KEY ? arg : assoc2->tag;
-
- return strcmp(assoc1->tag, tag2) ? 0 : CMP_MATCH | CMP_STOP;
-}
-
-/* return must be ast_freed */
-static pjmedia_sdp_attr *media_get_mid(pjmedia_sdp_media *media)
-{
- pjmedia_sdp_attr *attr = pjmedia_sdp_media_find_attr2(media, "mid", NULL);
- if (!attr) {
- return NULL;
- }
-
- return attr;
-}
-
-static int get_bundle_port(const pjmedia_sdp_session *sdp, const char *mid)
-{
- int i;
- for (i = 0; i < sdp->media_count; ++i) {
- pjmedia_sdp_attr *mid_attr = media_get_mid(sdp->media[i]);
- if (mid_attr && !pj_strcmp2(&mid_attr->value, mid)) {
- return sdp->media[i]->desc.port;
- }
- }
-
- return -1;
-}
-
-static int validate_incoming_sdp(const pjmedia_sdp_session *sdp)
-{
- int i;
- RAII_VAR(struct ao2_container *, portlist, ao2_container_alloc(5, validate_port_hash, validate_port_cmp), ao2_cleanup);
- RAII_VAR(struct ao2_container *, bundle_assoc_list, ao2_container_alloc(5, bundle_assoc_hash, bundle_assoc_cmp), ao2_cleanup);
-
- /* check for bundles (for websocket RTP multiplexing, there can be more than one) */
- for (i = 0; i < sdp->attr_count; ++i) {
- char *bundle_list;
- int bundle_port = 0;
- if (pj_stricmp2(&sdp->attr[i]->name, "group")) {
- continue;
- }
-
- /* check to see if this group is a bundle */
- if (7 >= sdp->attr[i]->value.slen || pj_strnicmp2(&sdp->attr[i]->value, "bundle ", 7)) {
- continue;
- }
-
- bundle_list = ast_alloca(sdp->attr[i]->value.slen - 6);
- strncpy(bundle_list, sdp->attr[i]->value.ptr + 7, sdp->attr[i]->value.slen - 7);
- bundle_list[sdp->attr[i]->value.slen - 7] = '\0';
- while (bundle_list) {
- char *item;
- RAII_VAR(struct bundle_assoc *, assoc, NULL, ao2_cleanup);
- item = strsep(&bundle_list, " ,");
- if (!bundle_port) {
- RAII_VAR(int *, port, ao2_alloc(sizeof(int), NULL), ao2_cleanup);
- RAII_VAR(int *, port_match, NULL, ao2_cleanup);
- bundle_port = get_bundle_port(sdp, item);
- if (bundle_port < 0) {
- return -1;
- }
- port_match = ao2_find(portlist, &bundle_port, OBJ_KEY);
- if (port_match) {
- /* bundle port aready consumed by a different bundle */
- return -1;
- }
- *port = bundle_port;
- ao2_link(portlist, port);
- }
- assoc = ao2_alloc(sizeof(*assoc) + strlen(item), NULL);
- if (!assoc) {
- return -1;
- }
-
- /* safe use of strcpy */
- strcpy(assoc->tag, item);
- assoc->port = bundle_port;
- ao2_link(bundle_assoc_list, assoc);
- }
- }
-
- /* validate all streams */
- for (i = 0; i < sdp->media_count; ++i) {
- RAII_VAR(int *, port, ao2_alloc(sizeof(int), NULL), ao2_cleanup);
- RAII_VAR(int *, port_match, NULL, ao2_cleanup);
-
- *port = sdp->media[i]->desc.port;
- port_match = ao2_find(portlist, port, OBJ_KEY);
- if (port_match) {
- RAII_VAR(struct bundle_assoc *, assoc, NULL, ao2_cleanup);
- pjmedia_sdp_attr *mid = media_get_mid(sdp->media[i]);
- char *mid_val;
-
- if (!mid) {
- /* not part of a bundle */
- return -1;
- }
-
- mid_val = ast_alloca(mid->value.slen + 1);
- strncpy(mid_val, mid->value.ptr, mid->value.slen);
- mid_val[mid->value.slen] = '\0';
-
- assoc = ao2_find(bundle_assoc_list, mid_val, OBJ_KEY);
- if (!assoc || assoc->port != *port) {
- /* This port already exists elsewhere in the SDP
- * and is not an appropriate bundle port, fail
- * catastrophically */
- return -1;
- }
- }
- ao2_link(portlist, port);
- }
- return 0;
-}
-
static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sdp_session *sdp)
{
int i;
-
- if (validate_incoming_sdp(sdp)) {
- return -1;
- }
+ int handled = 0;
for (i = 0; i < sdp->media_count; ++i) {
/* See if there are registered handlers for this media stream type */
@@ -361,14 +211,22 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
if (session_media->handler) {
handler = session_media->handler;
+ ast_debug(1, "Negotiating incoming SDP media stream '%s' using %s SDP handler\n",
+ session_media->stream_type,
+ session_media->handler->id);
res = handler->negotiate_incoming_sdp_stream(session, session_media, sdp,
sdp->media[i]);
- if (res <= 0) {
- /* Catastrophic failure or ignored by assigned handler. Abort! */
+ if (res < 0) {
+ /* Catastrophic failure. Abort! */
return -1;
+ } else if (res > 0) {
+ ast_debug(1, "Media stream '%s' handled by %s\n",
+ session_media->stream_type,
+ session_media->handler->id);
+ /* Handled by this handler. Move to the next stream */
+ handled = 1;
+ continue;
}
- /* Handled by this handler. Move to the next stream */
- continue;
}
handler_list = ao2_find(sdp_handlers, media, OBJ_KEY);
@@ -377,6 +235,9 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
continue;
}
AST_LIST_TRAVERSE(&handler_list->list, handler, next) {
+ ast_debug(1, "Negotiating incoming SDP media stream '%s' using %s SDP handler\n",
+ session_media->stream_type,
+ handler->id);
res = handler->negotiate_incoming_sdp_stream(session, session_media, sdp,
sdp->media[i]);
if (res < 0) {
@@ -384,12 +245,19 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
return -1;
}
if (res > 0) {
+ ast_debug(1, "Media stream '%s' handled by %s\n",
+ session_media->stream_type,
+ handler->id);
/* Handled by this handler. Move to the next stream */
session_media->handler = handler;
+ handled = 1;
break;
}
}
}
+ if (!handled) {
+ return -1;
+ }
return 0;
}
@@ -429,9 +297,15 @@ static int handle_negotiated_sdp_session_media(void *obj, void *arg, int flags)
handler = session_media->handler;
if (handler) {
+ ast_debug(1, "Applying negotiated SDP media stream '%s' using %s SDP handler\n",
+ session_media->stream_type,
+ handler->id);
res = handler->apply_negotiated_sdp_stream(session, session_media, local,
local->media[i], remote, remote->media[i]);
if (res >= 0) {
+ ast_debug(1, "Applied negotiated SDP media stream '%s' using %s SDP handler\n",
+ session_media->stream_type,
+ handler->id);
return CMP_MATCH;
}
return 0;
@@ -443,6 +317,9 @@ static int handle_negotiated_sdp_session_media(void *obj, void *arg, int flags)
continue;
}
AST_LIST_TRAVERSE(&handler_list->list, handler, next) {
+ ast_debug(1, "Applying negotiated SDP media stream '%s' using %s SDP handler\n",
+ session_media->stream_type,
+ handler->id);
res = handler->apply_negotiated_sdp_stream(session, session_media, local,
local->media[i], remote, remote->media[i]);
if (res < 0) {
@@ -450,6 +327,9 @@ static int handle_negotiated_sdp_session_media(void *obj, void *arg, int flags)
return 0;
}
if (res > 0) {
+ ast_debug(1, "Applied negotiated SDP media stream '%s' using %s SDP handler\n",
+ session_media->stream_type,
+ handler->id);
/* Handled by this handler. Move to the next stream */
session_media->handler = handler;
return CMP_MATCH;
@@ -827,10 +707,6 @@ static int sdp_requires_deferral(struct ast_sip_session *session, const pjmedia_
{
int i;
- if (validate_incoming_sdp(sdp)) {
- return 0;
- }
-
for (i = 0; i < sdp->media_count; ++i) {
/* See if there are registered handlers for this media stream type */
char media[20];