[Asterisk-code-review] chan pjsip: Multistream: Configure stream maxima (asterisk[master])

Mark Michelson asteriskteam at digium.com
Wed Jun 14 16:19:38 CDT 2017


Mark Michelson has uploaded this change for review. ( https://gerrit.asterisk.org/5841


Change subject: chan_pjsip: Multistream: Configure stream maxima
......................................................................

chan_pjsip: Multistream: Configure stream maxima

This adds two new configuration options for PJSIP endpoints:

max_audio_streams: determines the maximum number of audio streams to
offer/accept from an endpoint. Defaults to 1.

max_video_streams: determines the maximum number of video streams to
offer/accept from an endpoint. Defaults to 1.

This change fixes the four tests that were failing due to the previous
change in this series.

Change-Id: Id4b192c06fb311428d907ece78a131fdebc29163
---
M channels/chan_pjsip.c
M include/asterisk/res_pjsip.h
M res/res_pjsip/pjsip_configuration.c
M res/res_pjsip_session.c
4 files changed, 70 insertions(+), 3 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/41/5841/1

diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index bd76110..9e60755 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -479,8 +479,9 @@
 		struct ast_sip_session_media *session_media;
 
 		session_media = AST_VECTOR_GET(&session->media, i);
-
-		ast_assert(session_media != NULL);
+		if (!session_media) {
+			continue;
+		}
 
 		if (session_media->type == type) {
 			return ao2_bump(session_media);
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index ad0dc28..ecad2bf 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -680,6 +680,10 @@
 	unsigned int bind_rtp_to_media_address;
 	/*! Use RTCP-MUX */
 	unsigned int rtcp_mux;
+	/*! Maximum number of audio streams to offer/accept */
+	unsigned int max_audio_streams;
+	/*! Maximum number of video streams to offer/accept */
+	unsigned int max_video_streams;
 };
 
 /*!
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index e6e0821..dc4226b 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1989,6 +1989,8 @@
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));
+	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));
 
 	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_session.c b/res/res_pjsip_session.c
index 56acbd3..e9f5d51 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -259,10 +259,45 @@
 	return session_media;
 }
 
+static int limitation_reached(enum ast_media_type type, const struct ast_sip_endpoint *endpoint, int *type_streams)
+{
+	switch (type) {
+	case AST_MEDIA_TYPE_AUDIO:
+		if (type_streams[type] < endpoint->media.max_audio_streams) {
+			return 0;
+		} else {
+			return 1;
+		}
+	case AST_MEDIA_TYPE_VIDEO:
+		if (type_streams[type] < endpoint->media.max_video_streams) {
+			return 0;
+		} else {
+			return 1;
+		}
+	case AST_MEDIA_TYPE_IMAGE:
+	case AST_MEDIA_TYPE_TEXT:
+		/* We don't have an option for image (T.38) and text streams
+		 * so we cap these at one
+		 */
+		if (type_streams[type] > 0) {
+			return 1;
+		} else {
+			return 0;
+		}
+	case AST_MEDIA_TYPE_UNKNOWN:
+	default:
+		/* We don't want any unknown or "other" streams on our endpoint,
+		 * so always just say we've reached the limit
+		 */
+		return 1;
+	}
+}
+
 static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sdp_session *sdp)
 {
 	int i;
 	int handled = 0;
+	int type_streams[AST_MEDIA_TYPE_END] = {0};
 
 	if (session->inv_session && session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
 		ast_log(LOG_ERROR, "Failed to handle incoming SDP. Session has been already disconnected\n");
@@ -276,9 +311,15 @@
 		RAII_VAR(struct sdp_handler_list *, handler_list, NULL, ao2_cleanup);
 		struct ast_sip_session_media *session_media = NULL;
 		int res;
+		enum ast_media_type type;
 
 		/* We need a null-terminated version of the media string */
 		ast_copy_pj_str(media, &sdp->media[i]->desc.media, sizeof(media));
+		type = ast_media_type_from_str(media);
+
+		if (limitation_reached(type, session->endpoint, type_streams)) {
+			continue;
+		}
 
 		if (i < AST_VECTOR_SIZE(&session->media)) {
 			session_media = AST_VECTOR_GET(&session->media, i);
@@ -288,7 +329,7 @@
 				 * on this session media. The session media destructor will ensure that
 				 * all SDP handlers get a chance to free the memory they allocated
 				 */
-				session_media->type = ast_media_type_from_str(media);
+				session_media->type = type;
 				session_media->handler = NULL;
 			}
 		}
@@ -314,6 +355,7 @@
 					session_media->handler->id);
 				/* Handled by this handler. Move to the next stream */
 				handled = 1;
+				++type_streams[type];
 				continue;
 			}
 		}
@@ -342,6 +384,7 @@
 				/* Handled by this handler. Move to the next stream */
 				session_media_set_handler(session_media, handler);
 				handled = 1;
+				++type_streams[type];
 				break;
 			}
 		}
@@ -419,10 +462,19 @@
 static int handle_negotiated_sdp(struct ast_sip_session *session, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote)
 {
 	int i;
+	int type_streams[AST_MEDIA_TYPE_END] = {0};
 
 	for (i = 0; i < local->media_count; ++i) {
 		struct ast_sip_session_media *session_media;
+		char media[20];
+		enum ast_media_type type;
+
 		if (!remote->media[i]) {
+			continue;
+		}
+		ast_copy_pj_str(media, &local->media[i]->desc.media, sizeof(media));
+		type = ast_media_type_from_str(media);
+		if (limitation_reached(type, session->endpoint, type_streams)) {
 			continue;
 		}
 
@@ -436,6 +488,7 @@
 		if (handle_negotiated_sdp_session_media(session_media, session, local, remote, i)) {
 			return -1;
 		}
+		++type_streams[type];
 	}
 
 	return 0;
@@ -3038,6 +3091,7 @@
 	pjmedia_sdp_session *local;
 	struct ast_stream_topology *topology;
 	int i;
+	int type_streams[AST_MEDIA_TYPE_END] = {0};
 
 	if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
 		ast_log(LOG_ERROR, "Failed to create session SDP. Session has been already disconnected\n");
@@ -3075,6 +3129,11 @@
 		struct ast_stream *stream;
 
 		stream = ast_stream_topology_get_stream(topology, i);
+
+		if (limitation_reached(ast_stream_get_type(stream), session->endpoint, type_streams)) {
+			continue;
+		}
+
 		if (i < AST_VECTOR_SIZE(&session->media)) {
 			session_media = AST_VECTOR_GET(&session->media, i);
 		} else {
@@ -3087,6 +3146,7 @@
 		if (add_sdp_streams(session_media, session, local, stream)) {
 			return NULL;
 		}
+		++type_streams[ast_stream_get_type(stream)];
 	}
 
 	/* Use the connection details of the first media stream if possible for SDP level */

-- 
To view, visit https://gerrit.asterisk.org/5841
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id4b192c06fb311428d907ece78a131fdebc29163
Gerrit-Change-Number: 5841
Gerrit-PatchSet: 1
Gerrit-Owner: Mark Michelson <mmichelson at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20170614/fb59936d/attachment.html>


More information about the asterisk-code-review mailing list