<p>Mark Michelson has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/5841">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_pjsip: Multistream: Configure stream maxima<br><br>This adds two new configuration options for PJSIP endpoints:<br><br>max_audio_streams: determines the maximum number of audio streams to<br>offer/accept from an endpoint. Defaults to 1.<br><br>max_video_streams: determines the maximum number of video streams to<br>offer/accept from an endpoint. Defaults to 1.<br><br>This change fixes the four tests that were failing due to the previous<br>change in this series.<br><br>Change-Id: Id4b192c06fb311428d907ece78a131fdebc29163<br>---<br>M channels/chan_pjsip.c<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip/pjsip_configuration.c<br>M res/res_pjsip_session.c<br>4 files changed, 70 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/41/5841/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c<br>index bd76110..9e60755 100644<br>--- a/channels/chan_pjsip.c<br>+++ b/channels/chan_pjsip.c<br>@@ -479,8 +479,9 @@<br> struct ast_sip_session_media *session_media;<br> <br> session_media = AST_VECTOR_GET(&session->media, i);<br>-<br>- ast_assert(session_media != NULL);<br>+ if (!session_media) {<br>+ continue;<br>+ }<br> <br> if (session_media->type == type) {<br> return ao2_bump(session_media);<br>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h<br>index ad0dc28..ecad2bf 100644<br>--- a/include/asterisk/res_pjsip.h<br>+++ b/include/asterisk/res_pjsip.h<br>@@ -680,6 +680,10 @@<br> unsigned int bind_rtp_to_media_address;<br> /*! Use RTCP-MUX */<br> unsigned int rtcp_mux;<br>+ /*! Maximum number of audio streams to offer/accept */<br>+ unsigned int max_audio_streams;<br>+ /*! Maximum number of video streams to offer/accept */<br>+ unsigned int max_video_streams;<br> };<br> <br> /*!<br>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c<br>index e6e0821..dc4226b 100644<br>--- a/res/res_pjsip/pjsip_configuration.c<br>+++ b/res/res_pjsip/pjsip_configuration.c<br>@@ -1989,6 +1989,8 @@<br> ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux));<br> ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap));<br> ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));<br>+ 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));<br>+ 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));<br> <br> if (ast_sip_initialize_sorcery_transport()) {<br> ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");<br>diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c<br>index 56acbd3..e9f5d51 100644<br>--- a/res/res_pjsip_session.c<br>+++ b/res/res_pjsip_session.c<br>@@ -259,10 +259,45 @@<br> return session_media;<br> }<br> <br>+static int limitation_reached(enum ast_media_type type, const struct ast_sip_endpoint *endpoint, int *type_streams)<br>+{<br>+ switch (type) {<br>+ case AST_MEDIA_TYPE_AUDIO:<br>+ if (type_streams[type] < endpoint->media.max_audio_streams) {<br>+ return 0;<br>+ } else {<br>+ return 1;<br>+ }<br>+ case AST_MEDIA_TYPE_VIDEO:<br>+ if (type_streams[type] < endpoint->media.max_video_streams) {<br>+ return 0;<br>+ } else {<br>+ return 1;<br>+ }<br>+ case AST_MEDIA_TYPE_IMAGE:<br>+ case AST_MEDIA_TYPE_TEXT:<br>+ /* We don't have an option for image (T.38) and text streams<br>+ * so we cap these at one<br>+ */<br>+ if (type_streams[type] > 0) {<br>+ return 1;<br>+ } else {<br>+ return 0;<br>+ }<br>+ case AST_MEDIA_TYPE_UNKNOWN:<br>+ default:<br>+ /* We don't want any unknown or "other" streams on our endpoint,<br>+ * so always just say we've reached the limit<br>+ */<br>+ return 1;<br>+ }<br>+}<br>+<br> static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sdp_session *sdp)<br> {<br> int i;<br> int handled = 0;<br>+ int type_streams[AST_MEDIA_TYPE_END] = {0};<br> <br> if (session->inv_session && session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {<br> ast_log(LOG_ERROR, "Failed to handle incoming SDP. Session has been already disconnected\n");<br>@@ -276,9 +311,15 @@<br> RAII_VAR(struct sdp_handler_list *, handler_list, NULL, ao2_cleanup);<br> struct ast_sip_session_media *session_media = NULL;<br> int res;<br>+ enum ast_media_type type;<br> <br> /* We need a null-terminated version of the media string */<br> ast_copy_pj_str(media, &sdp->media[i]->desc.media, sizeof(media));<br>+ type = ast_media_type_from_str(media);<br>+<br>+ if (limitation_reached(type, session->endpoint, type_streams)) {<br>+ continue;<br>+ }<br> <br> if (i < AST_VECTOR_SIZE(&session->media)) {<br> session_media = AST_VECTOR_GET(&session->media, i);<br>@@ -288,7 +329,7 @@<br> * on this session media. The session media destructor will ensure that<br> * all SDP handlers get a chance to free the memory they allocated<br> */<br>- session_media->type = ast_media_type_from_str(media);<br>+ session_media->type = type;<br> session_media->handler = NULL;<br> }<br> }<br>@@ -314,6 +355,7 @@<br> session_media->handler->id);<br> /* Handled by this handler. Move to the next stream */<br> handled = 1;<br>+ ++type_streams[type];<br> continue;<br> }<br> }<br>@@ -342,6 +384,7 @@<br> /* Handled by this handler. Move to the next stream */<br> session_media_set_handler(session_media, handler);<br> handled = 1;<br>+ ++type_streams[type];<br> break;<br> }<br> }<br>@@ -419,10 +462,19 @@<br> static int handle_negotiated_sdp(struct ast_sip_session *session, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote)<br> {<br> int i;<br>+ int type_streams[AST_MEDIA_TYPE_END] = {0};<br> <br> for (i = 0; i < local->media_count; ++i) {<br> struct ast_sip_session_media *session_media;<br>+ char media[20];<br>+ enum ast_media_type type;<br>+<br> if (!remote->media[i]) {<br>+ continue;<br>+ }<br>+ ast_copy_pj_str(media, &local->media[i]->desc.media, sizeof(media));<br>+ type = ast_media_type_from_str(media);<br>+ if (limitation_reached(type, session->endpoint, type_streams)) {<br> continue;<br> }<br> <br>@@ -436,6 +488,7 @@<br> if (handle_negotiated_sdp_session_media(session_media, session, local, remote, i)) {<br> return -1;<br> }<br>+ ++type_streams[type];<br> }<br> <br> return 0;<br>@@ -3038,6 +3091,7 @@<br> pjmedia_sdp_session *local;<br> struct ast_stream_topology *topology;<br> int i;<br>+ int type_streams[AST_MEDIA_TYPE_END] = {0};<br> <br> if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {<br> ast_log(LOG_ERROR, "Failed to create session SDP. Session has been already disconnected\n");<br>@@ -3075,6 +3129,11 @@<br> struct ast_stream *stream;<br> <br> stream = ast_stream_topology_get_stream(topology, i);<br>+<br>+ if (limitation_reached(ast_stream_get_type(stream), session->endpoint, type_streams)) {<br>+ continue;<br>+ }<br>+<br> if (i < AST_VECTOR_SIZE(&session->media)) {<br> session_media = AST_VECTOR_GET(&session->media, i);<br> } else {<br>@@ -3087,6 +3146,7 @@<br> if (add_sdp_streams(session_media, session, local, stream)) {<br> return NULL;<br> }<br>+ ++type_streams[ast_stream_get_type(stream)];<br> }<br> <br> /* Use the connection details of the first media stream if possible for SDP level */<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/5841">change 5841</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/5841"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Id4b192c06fb311428d907ece78a131fdebc29163 </div>
<div style="display:none"> Gerrit-Change-Number: 5841 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Mark Michelson <mmichelson@digium.com> </div>