<p>George Joseph <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/14629">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Kevin Harwell: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ACN: res_pjsip endpoint options<br><br>This commit adds the endpoint options required to control<br>Advanced Codec Negotiation.<br><br>incoming_offer_codec_prefs<br>outgoing_offer_codec_prefs<br>incoming_answer_codec_prefs<br>outgoing_answer_codec_prefs<br><br>The documentation may need tweaking and some additional edits<br>added, especially for the "answer" prefs. That'll be handled<br>when things finalize.<br><br>This commit is safe to merge as it doens't alter any existing<br>functionality nor does it alter the previous codec negotiation<br>work which may now be obsolete.<br><br>Change-Id: I920ba925d7dd36430dfd2ebd9d82d23f123d0e11<br>---<br>M configs/samples/pjsip.conf.sample<br>A contrib/ast-db-manage/config/versions/b80485ff4dd0_add_pjsip_endpoint_acn_options.py<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip.c<br>M res/res_pjsip/pjsip_configuration.c<br>5 files changed, 434 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample</span><br><span>index a559dfa..cdb585d 100644</span><br><span>--- a/configs/samples/pjsip.conf.sample</span><br><span>+++ b/configs/samples/pjsip.conf.sample</span><br><span>@@ -839,6 +839,54 @@</span><br><span> ; at the end of the joint list.</span><br><span> ; remote_first - Include only the first codec in</span><br><span> ; the remote list.</span><br><span style="color: hsl(120, 100%, 40%);">+;incoming_offer_codec_prefs=; This is a string that describes how the codecs</span><br><span style="color: hsl(120, 100%, 40%);">+ ; specified on an incoming SDP offer (pending) are</span><br><span style="color: hsl(120, 100%, 40%);">+ ; reconciled with the codecs specified on an endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+ ; (configured) before being sent to the Asterisk core.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; The string actually specifies 4 name:value pair</span><br><span style="color: hsl(120, 100%, 40%);">+ ; parameters separated by commas. Whitespace is</span><br><span style="color: hsl(120, 100%, 40%);">+ ; ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; prefer: <pending | configured>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; operation: <intersect | only_preferred</span><br><span style="color: hsl(120, 100%, 40%);">+ ; | only_nonpreferred>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; keep: <first | all>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; transcode: <allow | prevent></span><br><span style="color: hsl(120, 100%, 40%);">+;outgoing_offer_codec_prefs=; This is a string that describes how the codecs</span><br><span style="color: hsl(120, 100%, 40%);">+ ; specified in the topology that comes from the</span><br><span style="color: hsl(120, 100%, 40%);">+ ; Asterisk core (pending) are reconciled with the</span><br><span style="color: hsl(120, 100%, 40%);">+ ; codecs specified on an endpoint (configured)</span><br><span style="color: hsl(120, 100%, 40%);">+ ; when sending an SDP offer.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; The string actually specifies 4 name:value pair</span><br><span style="color: hsl(120, 100%, 40%);">+ ; parameters separated by commas. Whitespace is</span><br><span style="color: hsl(120, 100%, 40%);">+ ; ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; prefer: <pending | configured>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; operation: <intersect | union</span><br><span style="color: hsl(120, 100%, 40%);">+ ; | only_preferred | only_nonpreferred>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; keep: <first | all>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; transcode: <allow | prevent></span><br><span style="color: hsl(120, 100%, 40%);">+;incoming_answer_codec_prefs=; This is a string that describes how the codecs</span><br><span style="color: hsl(120, 100%, 40%);">+ ; specified in an incoming SDP answer (pending)</span><br><span style="color: hsl(120, 100%, 40%);">+ ; are reconciled with the codecs specified on an</span><br><span style="color: hsl(120, 100%, 40%);">+ ; endpoint (configured) when receiving an SDP</span><br><span style="color: hsl(120, 100%, 40%);">+ ; answer.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; The string actually specifies 4 name:value pair</span><br><span style="color: hsl(120, 100%, 40%);">+ ; parameters separated by commas. Whitespace is</span><br><span style="color: hsl(120, 100%, 40%);">+ ; ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; prefer: <pending | configured>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; operation: <intersect | union</span><br><span style="color: hsl(120, 100%, 40%);">+ ; | only_preferred | only_nonpreferred>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; keep: <first | all></span><br><span style="color: hsl(120, 100%, 40%);">+;outgoing_answer_codec_prefs=; This is a string that describes how the codecs</span><br><span style="color: hsl(120, 100%, 40%);">+ ; that come from the core (pending) are reconciled</span><br><span style="color: hsl(120, 100%, 40%);">+ ; with the codecs specified on an endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+ ; (configured) when sending an SDP answer.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; The string actually specifies 4 name:value pair</span><br><span style="color: hsl(120, 100%, 40%);">+ ; parameters separated by commas. Whitespace is</span><br><span style="color: hsl(120, 100%, 40%);">+ ; ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+ ; prefer: <pending | configured>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; operation: <intersect | union</span><br><span style="color: hsl(120, 100%, 40%);">+ ; | only_preferred | only_nonpreferred>,</span><br><span style="color: hsl(120, 100%, 40%);">+ ; keep: <first | all></span><br><span> ;preferred_codec_only=no ; Respond to a SIP invite with the single most</span><br><span> ; preferred codec rather than advertising all joint</span><br><span> ; codec capabilities. This limits the other side's</span><br><span>diff --git a/contrib/ast-db-manage/config/versions/b80485ff4dd0_add_pjsip_endpoint_acn_options.py b/contrib/ast-db-manage/config/versions/b80485ff4dd0_add_pjsip_endpoint_acn_options.py</span><br><span>new file mode 100644</span><br><span>index 0000000..241185a</span><br><span>--- /dev/null</span><br><span>+++ b/contrib/ast-db-manage/config/versions/b80485ff4dd0_add_pjsip_endpoint_acn_options.py</span><br><span>@@ -0,0 +1,29 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""Add pjsip endpoint ACN options</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Revision ID: b80485ff4dd0</span><br><span style="color: hsl(120, 100%, 40%);">+Revises: fbb7766f17bc</span><br><span style="color: hsl(120, 100%, 40%);">+Create Date: 2020-07-06 08:29:53.974820</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# revision identifiers, used by Alembic.</span><br><span style="color: hsl(120, 100%, 40%);">+revision = 'b80485ff4dd0'</span><br><span style="color: hsl(120, 100%, 40%);">+down_revision = '79290b511e4b'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from alembic import op</span><br><span style="color: hsl(120, 100%, 40%);">+import sqlalchemy as sa</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+max_value_length = 128</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def upgrade():</span><br><span style="color: hsl(120, 100%, 40%);">+ op.add_column('ps_endpoints', sa.Column('incoming_offer_codec_prefs', sa.String(max_value_length)))</span><br><span style="color: hsl(120, 100%, 40%);">+ op.add_column('ps_endpoints', sa.Column('outgoing_offer_codec_prefs', sa.String(max_value_length)))</span><br><span style="color: hsl(120, 100%, 40%);">+ op.add_column('ps_endpoints', sa.Column('incoming_answer_codec_prefs', sa.String(max_value_length)))</span><br><span style="color: hsl(120, 100%, 40%);">+ op.add_column('ps_endpoints', sa.Column('outgoing_answer_codec_prefs', sa.String(max_value_length)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def downgrade():</span><br><span style="color: hsl(120, 100%, 40%);">+ op.drop_column('ps_endpoints', 'incoming_offer_codecs_prefs')</span><br><span style="color: hsl(120, 100%, 40%);">+ op.drop_column('ps_endpoints', 'outgoing_offer_codecs_prefs')</span><br><span style="color: hsl(120, 100%, 40%);">+ op.drop_column('ps_endpoints', 'incoming_answer_codecs_prefs')</span><br><span style="color: hsl(120, 100%, 40%);">+ op.drop_column('ps_endpoints', 'outgoing_answer_codecs_prefs')</span><br><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index 2993103..0ca29ff 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -49,6 +49,7 @@</span><br><span> /* Needed for ast_sip_for_each_channel_snapshot struct */</span><br><span> #include "asterisk/stasis_channels.h"</span><br><span> #include "asterisk/stasis_endpoints.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/stream.h"</span><br><span> </span><br><span> #define PJSIP_MINVERSION(m,n,p) (((m << 24) | (n << 16) | (p << 8)) >= PJ_VERSION_NUM)</span><br><span> </span><br><span>@@ -802,6 +803,14 @@</span><br><span> struct ast_flags incoming_call_offer_pref;</span><br><span> /*! Codec preference for an outgoing offer */</span><br><span> struct ast_flags outgoing_call_offer_pref;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Codec negotiation prefs for incoming offers */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_stream_codec_negotiation_prefs incoming_offer_codec_prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Codec negotiation prefs for outgoing offers */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_stream_codec_negotiation_prefs outgoing_offer_codec_prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Codec negotiation prefs for incoming answers */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_stream_codec_negotiation_prefs incoming_answer_codec_prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Codec negotiation prefs for outgoing answers */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_stream_codec_negotiation_prefs outgoing_answer_codec_prefs;</span><br><span> };</span><br><span> </span><br><span> /*!</span><br><span>diff --git a/res/res_pjsip.c b/res/res_pjsip.c</span><br><span>index 32907e3..847a14c 100644</span><br><span>--- a/res/res_pjsip.c</span><br><span>+++ b/res/res_pjsip.c</span><br><span>@@ -102,6 +102,239 @@</span><br><span> <configOption name="allow"></span><br><span> <synopsis>Media Codec(s) to allow</synopsis></span><br><span> </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="incoming_offer_codec_prefs"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Codec negotiation prefs for incoming offers.</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ This is a string that describes how the codecs</span><br><span style="color: hsl(120, 100%, 40%);">+ specified on an incoming SDP offer (pending) are reconciled with the codecs specified</span><br><span style="color: hsl(120, 100%, 40%);">+ on an endpoint (configured) before being sent to the Asterisk core.</span><br><span style="color: hsl(120, 100%, 40%);">+ The string actually specifies 4 <literal>name:value</literal> pair parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ separated by commas. Whitespace is ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="prefer: < pending | configured >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="pending"><para>The codec list from the caller. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="configured"><para>The codec list from the endpoint.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="operation : < intersect | only_preferred | only_nonpreferred >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="intersect"><para>Only common codecs with the preferred codecs first. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_preferred"><para>Use only the preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_nonpreferred"><para>Use only the non-preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="keep : < all | first >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="all"><para>After the operation, keep all codecs. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="first"><para>After the operation, keep only the first codec.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="transcode : < allow | prevent >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="allow"><para>Allow transcoding. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="prevent"><para>Prevent transcoding.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <example></span><br><span style="color: hsl(120, 100%, 40%);">+ incoming_offer_codec_prefs = prefer: pending, operation: intersect, keep: all, transcode: allow</span><br><span style="color: hsl(120, 100%, 40%);">+ </example></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Prefer the codecs coming from the caller. Use only the ones that are common.</span><br><span style="color: hsl(120, 100%, 40%);">+ keeping the order of the preferred list. Keep all codecs in the result. Allow transcoding.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="outgoing_offer_codec_prefs"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Codec negotiation prefs for outgoing offers.</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ This is a string that describes how the codecs specified in the topology that</span><br><span style="color: hsl(120, 100%, 40%);">+ comes from the Asterisk core (pending) are reconciled with the codecs specified on an</span><br><span style="color: hsl(120, 100%, 40%);">+ endpoint (configured) when sending an SDP offer.</span><br><span style="color: hsl(120, 100%, 40%);">+ The string actually specifies 4 <literal>name:value</literal> pair parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ separated by commas. Whitespace is ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="prefer: < pending | configured >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="pending"><para>The codec list from the core. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="configured"><para>The codec list from the endpoint.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="operation : < union | intersect | only_preferred | only_nonpreferred >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="union"><para>Merge the lists with the preferred codecs first. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="intersect"><para>Only common codecs with the preferred codecs first. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_preferred"><para>Use only the preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_nonpreferred"><para>Use only the non-preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="keep : < all | first >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="all"><para>After the operation, keep all codecs. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="first"><para>After the operation, keep only the first codec.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="transcode : < allow | prevent >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="allow"><para>Allow transcoding. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="prevent"><para>Prevent transcoding.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <example></span><br><span style="color: hsl(120, 100%, 40%);">+ outgoing_offer_codec_prefs = prefer: configured, operation: union, keep: first, transcode: prevent</span><br><span style="color: hsl(120, 100%, 40%);">+ </example></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Prefer the codecs coming from the endpoint. Merge them with the codecs from the core</span><br><span style="color: hsl(120, 100%, 40%);">+ keeping the order of the preferred list. Keep only the first one. No transcoding allowed.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="incoming_answer_codec_prefs"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Codec negotiation prefs for incoming answers.</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ This is a string that describes how the codecs specified in an incoming SDP answer</span><br><span style="color: hsl(120, 100%, 40%);">+ (pending) are reconciled with the codecs specified on an endpoint (configured)</span><br><span style="color: hsl(120, 100%, 40%);">+ when receiving an SDP answer.</span><br><span style="color: hsl(120, 100%, 40%);">+ The string actually specifies 4 <literal>name:value</literal> pair parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ separated by commas. Whitespace is ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="prefer: < pending | configured >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="pending"><para>The codec list in the received SDP answer. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="configured"><para>The codec list from the endpoint.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="operation : < union | intersect | only_preferred | only_nonpreferred >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="union"><para>Merge the lists with the preferred codecs first.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="intersect"><para>Only common codecs with the preferred codecs first. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_preferred"><para>Use only the preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_nonpreferred"><para>Use only the non-preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="keep : < all | first >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="all"><para>After the operation, keep all codecs. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="first"><para>After the operation, keep only the first codec.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="transcode : < allow | prevent >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ The transcode parameter is ignored when processing answers.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <example></span><br><span style="color: hsl(120, 100%, 40%);">+ incoming_answer_codec_prefs = keep: first</span><br><span style="color: hsl(120, 100%, 40%);">+ </example></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Use the defaults but keep oinly the first codec.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="outgoing_answer_codec_prefs"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Codec negotiation prefs for outgoing answers.</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ This is a string that describes how the codecs that come from the core (pending)</span><br><span style="color: hsl(120, 100%, 40%);">+ are reconciled with the codecs specified on an endpoint (configured)</span><br><span style="color: hsl(120, 100%, 40%);">+ when sending an SDP answer.</span><br><span style="color: hsl(120, 100%, 40%);">+ The string actually specifies 4 <literal>name:value</literal> pair parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ separated by commas. Whitespace is ignored and they may be specified in any order.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="prefer: < pending | configured >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="pending"><para>The codec list that came from the core. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="configured"><para>The codec list from the endpoint.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="operation : < union | intersect | only_preferred | only_nonpreferred >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="union"><para>Merge the lists with the preferred codecs first.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="intersect"><para>Only common codecs with the preferred codecs first. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_preferred"><para>Use only the preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="only_nonpreferred"><para>Use only the non-preferred codecs.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="keep : < all | first >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="all"><para>After the operation, keep all codecs. (default)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="first"><para>After the operation, keep only the first codec.</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="transcode : < allow | prevent >"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ The transcode parameter is ignored when processing answers.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ </enum></span><br><span style="color: hsl(120, 100%, 40%);">+ </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ <example></span><br><span style="color: hsl(120, 100%, 40%);">+ incoming_answer_codec_prefs = keep: first</span><br><span style="color: hsl(120, 100%, 40%);">+ </example></span><br><span style="color: hsl(120, 100%, 40%);">+ <para></span><br><span style="color: hsl(120, 100%, 40%);">+ Use the defaults but keep oinly the first codec.</span><br><span style="color: hsl(120, 100%, 40%);">+ </para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ </configOption></span><br><span> <configOption name="allow_overlap" default="yes"></span><br><span> <synopsis>Enable RFC3578 overlap dialing support.</synopsis></span><br><span> </configOption></span><br><span>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c</span><br><span>index f95ee9e..e3eab8a 100644</span><br><span>--- a/res/res_pjsip/pjsip_configuration.c</span><br><span>+++ b/res/res_pjsip/pjsip_configuration.c</span><br><span>@@ -1166,6 +1166,109 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int codec_prefs_handler(const struct aco_option *opt,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *var, void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_sip_endpoint *endpoint = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_stream_codec_negotiation_prefs prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *error_message = ast_str_create(128);</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_stream_codec_negotiation_prefs_prefer_values default_prefer;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_stream_codec_negotiation_prefs_operation_values default_operation;</span><br><span style="color: hsl(120, 100%, 40%);">+ int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = ast_stream_codec_prefs_parse(var->value, &prefs, &error_message);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Endpoint '%s': %s for option '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_get_id(endpoint), ast_str_buffer(error_message), var->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(error_message);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(error_message);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(var->name, "incoming_offer_codec_prefs") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prefs.operation == CODEC_NEGOTIATION_OPERATION_UNION) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Endpoint '%s': Codec preference '%s' has invalid value '%s' for option: '%s'",</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_get_id(endpoint),</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_stream_codec_param_to_str(CODEC_NEGOTIATION_PARAM_OPERATION),</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_stream_codec_operation_to_str(CODEC_NEGOTIATION_OPERATION_UNION),</span><br><span style="color: hsl(120, 100%, 40%);">+ var->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ endpoint->media.incoming_offer_codec_prefs = prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (strcmp(var->name, "outgoing_offer_codec_prefs") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ endpoint->media.outgoing_offer_codec_prefs = prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_operation = CODEC_NEGOTIATION_OPERATION_UNION;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (strcmp(var->name, "incoming_answer_codec_prefs") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ endpoint->media.incoming_answer_codec_prefs = prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (strcmp(var->name, "outgoing_answer_codec_prefs") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ endpoint->media.outgoing_answer_codec_prefs = prefs;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_prefer = CODEC_NEGOTIATION_PREFER_PENDING;</span><br><span style="color: hsl(120, 100%, 40%);">+ default_operation = CODEC_NEGOTIATION_OPERATION_INTERSECT;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prefs.prefer == CODEC_NEGOTIATION_PREFER_UNSPECIFIED) {</span><br><span style="color: hsl(120, 100%, 40%);">+ prefs.prefer = default_prefer;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prefs.operation == CODEC_NEGOTIATION_OPERATION_UNSPECIFIED) {</span><br><span style="color: hsl(120, 100%, 40%);">+ prefs.operation = default_operation;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prefs.keep == CODEC_NEGOTIATION_KEEP_UNSPECIFIED) {</span><br><span style="color: hsl(120, 100%, 40%);">+ prefs.keep = CODEC_NEGOTIATION_KEEP_ALL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prefs.transcode == CODEC_NEGOTIATION_TRANSCODE_UNSPECIFIED) {</span><br><span style="color: hsl(120, 100%, 40%);">+ prefs.transcode = CODEC_NEGOTIATION_TRANSCODE_ALLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int codec_prefs_to_str(const struct ast_stream_codec_negotiation_prefs *prefs,</span><br><span style="color: hsl(120, 100%, 40%);">+ const void *obj, const intptr_t *args, char **buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *codecs = ast_str_create(AST_STREAM_MAX_CODEC_PREFS_LENGTH);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!codecs) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *buf = ast_strdup(ast_stream_codec_prefs_to_str(prefs, &codecs));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(codecs);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int incoming_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_sip_endpoint *endpoint = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ return codec_prefs_to_str(&endpoint->media.incoming_offer_codec_prefs, obj, args, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int outgoing_offer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_sip_endpoint *endpoint = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ return codec_prefs_to_str(&endpoint->media.outgoing_offer_codec_prefs, obj, args, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int incoming_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_sip_endpoint *endpoint = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ return codec_prefs_to_str(&endpoint->media.incoming_answer_codec_prefs, obj, args, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int outgoing_answer_codec_prefs_to_str(const void *obj, const intptr_t *args, char **buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_sip_endpoint *endpoint = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ return codec_prefs_to_str(&endpoint->media.outgoing_answer_codec_prefs, obj, args, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void *sip_nat_hook_alloc(const char *name)</span><br><span> {</span><br><span> return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);</span><br><span>@@ -2025,6 +2128,18 @@</span><br><span> call_offer_pref_handler, incoming_call_offer_pref_to_str, NULL, 0, 0);</span><br><span> ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outgoing_call_offer_pref", "remote",</span><br><span> call_offer_pref_handler, outgoing_call_offer_pref_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "incoming_offer_codec_prefs",</span><br><span style="color: hsl(120, 100%, 40%);">+ "prefer: pending, operation: intersect, keep: all, transcode: allow",</span><br><span style="color: hsl(120, 100%, 40%);">+ codec_prefs_handler, incoming_offer_codec_prefs_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outgoing_offer_codec_prefs",</span><br><span style="color: hsl(120, 100%, 40%);">+ "prefer: pending, operation: union, keep: all, transcode: allow",</span><br><span style="color: hsl(120, 100%, 40%);">+ codec_prefs_handler, outgoing_offer_codec_prefs_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "incoming_answer_codec_prefs",</span><br><span style="color: hsl(120, 100%, 40%);">+ "prefer: pending, operation: intersect, keep: all",</span><br><span style="color: hsl(120, 100%, 40%);">+ codec_prefs_handler, incoming_answer_codec_prefs_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outgoing_answer_codec_prefs",</span><br><span style="color: hsl(120, 100%, 40%);">+ "prefer: pending, operation: intersect, keep: all",</span><br><span style="color: hsl(120, 100%, 40%);">+ codec_prefs_handler, outgoing_answer_codec_prefs_to_str, NULL, 0, 0);</span><br><span> </span><br><span> if (ast_sip_initialize_sorcery_transport()) {</span><br><span> ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/14629">change 14629</a>. To unsubscribe, or for help writing mail filters, 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/c/asterisk/+/14629"/><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-Change-Id: I920ba925d7dd36430dfd2ebd9d82d23f123d0e11 </div>
<div style="display:none"> Gerrit-Change-Number: 14629 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-CC: Stanislav Abramenkov <stas.abramenkov@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>