--- /dev/null
+"""Add peer_supported to 100rel
+
+Revision ID: 539f68bede2c
+Revises: 9f3692b1654b
+Create Date: 2022-08-10 09:36:16.576049
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '539f68bede2c'
+down_revision = '9f3692b1654b'
+
+from alembic import op
+from sqlalchemy.dialects.postgresql import ENUM
+import sqlalchemy as sa
+
+
+OLD_ENUM = ['no', 'required', 'yes']
+NEW_ENUM = ['no', 'required', 'peer_supported', 'yes']
+
+old_type = sa.Enum(*OLD_ENUM, name='pjsip_100rel_values')
+new_type = sa.Enum(*NEW_ENUM, name='pjsip_100rel_values_v2')
+
+def upgrade():
+ context = op.get_context()
+
+ # Upgrading to this revision WILL clear your directmedia values.
+ if context.bind.dialect.name != 'postgresql':
+ op.alter_column('ps_endpoints', '100rel',
+ type_=new_type,
+ existing_type=old_type)
+ else:
+ enum = ENUM(*NEW_ENUM, name='pjsip_100rel_values_v2')
+ enum.create(op.get_bind(), checkfirst=False)
+
+ op.execute('ALTER TABLE ps_endpoints ALTER COLUMN 100rel TYPE'
+ ' pjsip_100rel_values_v2 USING'
+ ' 100rel::text::pjsip_100rel_values_v2')
+
+ ENUM(name="pjsip_100rel_values").drop(op.get_bind(), checkfirst=False)
+
+def downgrade():
+ context = op.get_context()
+
+ if context.bind.dialect.name != 'postgresql':
+ op.alter_column('ps_endpoints', '100rel',
+ type_=old_type,
+ existing_type=new_type)
+ else:
+ enum = ENUM(*OLD_ENUM, name='pjsip_100rel_values')
+ enum.create(op.get_bind(), checkfirst=False)
+
+ op.execute('ALTER TABLE ps_endpoints ALTER COLUMN 100rel TYPE'
+ ' pjsip_100rel_values USING'
+ ' 100rel::text::pjsip_100rel_values')
+
+ ENUM(name="pjsip_100rel_values_v2").drop(op.get_bind(), checkfirst=False)
--- /dev/null
+Subject: res_pjsip
+
+A new option named "peer_supported" has been added to the endpoint option
+100rel. When set to this option, Asterisk sends provisional responses
+reliably if the peer supports it. If the peer does not support reliable
+provisional responses, Asterisk sends them normally.
struct ast_sip_contact *contact;
};
+/*!
+ * \brief 100rel modes for SIP endpoints
+ */
+enum ast_sip_100rel_mode {
+ /*! Do not support 100rel. (no) */
+ AST_SIP_100REL_UNSUPPORTED = 0,
+ /*! As UAC, indicate 100rel support in Supported header. (yes) */
+ AST_SIP_100REL_SUPPORTED,
+ /*! As UAS, send 1xx responses reliably, if the UAC indicated its support. Otherwise same as AST_SIP_100REL_SUPPORTED. (peer_supported) */
+ AST_SIP_100REL_PEER_SUPPORTED,
+ /*! Require the use of 100rel. (required) */
+ AST_SIP_100REL_REQUIRED,
+};
+
/*!
* \brief DTMF modes for SIP endpoints
*/
AST_STRING_FIELD_EXTENDED(geoloc_incoming_call_profile);
/*! The name of the geoloc profile to apply when Asterisk sends a call to this endpoint */
AST_STRING_FIELD_EXTENDED(geoloc_outgoing_call_profile);
+ /*! 100rel mode to use with this endpoint */
+ enum ast_sip_100rel_mode rel100;
};
/*! URI parameter for symmetric transport */
<synopsis>Allow support for RFC3262 provisional ACK tags</synopsis>
<description>
<enumlist>
- <enum name="no" />
- <enum name="required" />
- <enum name="yes" />
+ <enum name="no">
+ <para>If set to <literal>no</literal>, do not support transmission of
+ reliable provisional responses. As UAS, if an incoming request contains 100rel
+ in the Required header, it is rejected with 420 Bad Extension.</para>
+ </enum>
+ <enum name="required">
+ <para>If set to <literal>required</literal>, require provisional responses to
+ be sent and received reliably. As UAS, incoming requests without 100rel
+ in the Supported header are rejected with 421 Extension Required. As UAC,
+ outgoing requests will have 100rel in the Required header.</para>
+ </enum>
+ <enum name="peer_supported">
+ <para>If set to <literal>peer_supported</literal>, send provisional responses
+ reliably if the request by the peer contained 100rel in the Supported or
+ Require header. As UAS, if an incoming request contains 100rel in the Supported
+ header, send 1xx responses reliably. If the request by the peer does not contain 100rel
+ in the Supported and Require header, send responses normally. As UAC, outgoing requests
+ will contain 100rel in the Supported header.</para>
+ </enum>
+ <enum name="yes">
+ <para>If set to <literal>yes</literal>, indicate the support of reliable provisional
+ responses and PRACK them if required by the peer. As UAS, if the incoming request
+ contains 100rel in the Supported header but not in the Required header, send 1xx
+ responses normally. If the incoming request contains 100rel in the Required header,
+ send 1xx responses reliably. As UAC add 100rel to the Supported header and PRACK 1xx
+ responses if required.</para>
+ </enum>
</enumlist>
</description>
</configOption>
if (ast_true(var->value)) {
endpoint->extensions.flags |= PJSIP_INV_SUPPORT_100REL;
+ endpoint->rel100 = AST_SIP_100REL_SUPPORTED;
+ } else if (!strcasecmp(var->value, "peer_supported")) {
+ endpoint->extensions.flags |= PJSIP_INV_SUPPORT_100REL;
+ endpoint->rel100 = AST_SIP_100REL_PEER_SUPPORTED;
} else if (!strcasecmp(var->value, "required")) {
endpoint->extensions.flags |= PJSIP_INV_REQUIRE_100REL;
- } else if (!ast_false(var->value)){
+ endpoint->rel100 = AST_SIP_100REL_REQUIRED;
+ } else if (ast_false(var->value)) {
+ endpoint->rel100 = AST_SIP_100REL_UNSUPPORTED;
+ } else {
return -1;
}
{
const struct ast_sip_endpoint *endpoint = obj;
- if (endpoint->extensions.flags & PJSIP_INV_REQUIRE_100REL) {
- *buf = "required";
- } else if (endpoint->extensions.flags & PJSIP_INV_SUPPORT_100REL) {
+ if (endpoint->rel100 == AST_SIP_100REL_SUPPORTED) {
*buf = "yes";
+ } else if (endpoint->rel100 == AST_SIP_100REL_PEER_SUPPORTED) {
+ *buf = "peer_supported";
+ } else if (endpoint->rel100 == AST_SIP_100REL_REQUIRED) {
+ *buf = "required";
} else {
*buf = "no";
}
pjsip_dialog *dlg;
pjsip_inv_session *inv_session;
unsigned int options = endpoint->extensions.flags;
+ const pj_str_t STR_100REL = { "100rel", 6};
+ unsigned int i;
pj_status_t dlg_status = PJ_EUNKNOWN;
+ /*
+ * If 100rel is set to "peer_supported" on the endpoint and the peer indicated support for 100rel
+ * in the Supported header, send 1xx responses reliably by adding PJSIP_INV_REQUIRE_100REL to pjsip_inv_options flags.
+ */
+ if (endpoint->rel100 == AST_SIP_100REL_PEER_SUPPORTED && rdata->msg_info.supported != NULL) {
+ for (i = 0; i < rdata->msg_info.supported->count; ++i) {
+ if (pj_stricmp(&rdata->msg_info.supported->values[i], &STR_100REL) == 0) {
+ options |= PJSIP_INV_REQUIRE_100REL;
+ break;
+ }
+ }
+ }
+
if (pjsip_inv_verify_request(rdata, &options, NULL, NULL, ast_sip_get_pjsip_endpoint(), &tdata) != PJ_SUCCESS) {
if (tdata) {
if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {