Skip to content

Commit

Permalink
res_pjsip: Add 100rel option "peer_supported".
Browse files Browse the repository at this point in the history
This patch adds a new option to the 100rel parameter for pjsip
endpoints called "peer_supported". When an endpoint with this option
receives an incoming request and the request indicated support for the
100rel extension, then Asterisk will send 1xx responses reliably. If
the request did not indicate 100rel support, Asterisk sends 1xx
responses normally.

ASTERISK-30158

Change-Id: Id6d95ffa8f00dab118e0b386146e99f254f287ad
  • Loading branch information
maximilianfridrich authored and mbradeen committed Sep 22, 2022
1 parent 2043234 commit 492c938
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""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)
6 changes: 6 additions & 0 deletions doc/CHANGES-staging/res_pjsip_100rel_option.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
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.
16 changes: 16 additions & 0 deletions include/asterisk/res_pjsip.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,20 @@ struct ast_sip_contact_wrapper {
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
*/
Expand Down Expand Up @@ -981,6 +995,8 @@ struct ast_sip_endpoint {
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 */
Expand Down
30 changes: 27 additions & 3 deletions res/res_pjsip/pjsip_config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,33 @@
<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>
Expand Down
17 changes: 13 additions & 4 deletions res/res_pjsip/pjsip_configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,16 @@ static int prack_handler(const struct aco_option *opt, struct ast_variable *var,

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;
}

Expand All @@ -195,10 +202,12 @@ static int prack_to_str(const void *obj, const intptr_t *args, char **buf)
{
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";
}
Expand Down
15 changes: 15 additions & 0 deletions res/res_pjsip_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -3789,8 +3789,23 @@ static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct a
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) {
Expand Down

0 comments on commit 492c938

Please sign in to comment.