mirror of
https://github.com/asterisk/asterisk.git
synced 2026-07-07 23:29:20 -07:00
res_pjsip: Add external_signaling_hostname transport option
Adds a new transport option 'external_signaling_hostname' which allows a hostname or FQDN to be used in SIP Contact and Via headers instead of the automatically determined IP address. This is useful when a remote SIP endpoint requires a fully qualified domain name in these headers. The option is mutually exclusive with 'external_signaling_address' and an error is raised at transport load time if both are set simultaneously. Resolves: #1749 UserNote: A new pjsip.conf transport option 'external_signaling_hostname' has been added. When set, this value will be used in SIP Contact and Via headers instead of the automatically determined IP address. This option is mutually exclusive with 'external_signaling_address'.
This commit is contained in:
@@ -1203,6 +1203,14 @@
|
||||
; "")
|
||||
;external_signaling_port=0 ; External port for SIP signalling (default:
|
||||
; "0")
|
||||
;external_signaling_hostname= ; Value to use in SIP Contact and Via headers
|
||||
; as hostname instead of the automatically
|
||||
; determined IP address. Useful when a remote
|
||||
; SIP endpoint requires a fully qualified domain
|
||||
; name rather than an IP address. No validation
|
||||
; is performed on the provided value. Cannot be
|
||||
; set together with external_signaling_address.
|
||||
; (default: "")
|
||||
;local_net= ; Network to consider local used for NAT purposes (default: "")
|
||||
;password= ; Password required for transport (default: "")
|
||||
;protocol=udp ; Protocol to use for SIP traffic (default: "udp")
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
"""Add external_signaling_hostname to ps_transports
|
||||
|
||||
Revision ID: 2285f2ace275
|
||||
Revises: e89e30cee53f
|
||||
Create Date: 2026-06-03
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '2285f2ace275'
|
||||
down_revision = 'e89e30cee53f'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
def upgrade():
|
||||
op.add_column('ps_transports', sa.Column('external_signaling_hostname', sa.String(40)))
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('ps_transports', 'external_signaling_hostname')
|
||||
@@ -236,6 +236,8 @@ struct ast_sip_transport {
|
||||
AST_STRING_FIELD(external_media_address);
|
||||
/*! Optional domain to use for messages if provided could not be found */
|
||||
AST_STRING_FIELD(domain);
|
||||
/*! Optional FQDN to use in SIP Contact and Via headers instead of external_signaling_address */
|
||||
AST_STRING_FIELD(external_signaling_hostname);
|
||||
);
|
||||
/*! Type of transport */
|
||||
enum ast_transport type;
|
||||
|
||||
@@ -675,6 +675,15 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
|
||||
RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
|
||||
pj_status_t res = -1;
|
||||
int i;
|
||||
|
||||
/* Ensure external_signaling_address and external_signaling_hostname are mutually exclusive */
|
||||
if (!ast_strlen_zero(transport->external_signaling_address) &&
|
||||
!ast_strlen_zero(transport->external_signaling_hostname)) {
|
||||
ast_log(LOG_ERROR, "Transport '%s' has both 'external_signaling_address' and "
|
||||
"'external_signaling_hostname' set. Only one may be configured at a time.\n",
|
||||
transport_id);
|
||||
return -1;
|
||||
}
|
||||
#define BIND_TRIES 3
|
||||
#define BIND_DELAY_US 100000
|
||||
|
||||
@@ -1856,6 +1865,7 @@ int ast_sip_initialize_sorcery_transport(void)
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "password", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, password));
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "external_signaling_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, external_signaling_address));
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "external_signaling_port", "0", OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_transport, external_signaling_port), 0, 65535);
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "external_signaling_hostname", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, external_signaling_hostname));
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "external_media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, external_media_address));
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "domain", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_transport, domain));
|
||||
ast_sorcery_object_field_register_custom(sorcery, "transport", "verify_server", "", transport_tls_bool_handler, verify_server_to_str, NULL, 0, 0);
|
||||
|
||||
@@ -2448,6 +2448,25 @@
|
||||
</since>
|
||||
<synopsis>External port for SIP signalling</synopsis>
|
||||
</configOption>
|
||||
<configOption name="external_signaling_hostname">
|
||||
<since>
|
||||
<version>20.21.0</version>
|
||||
<version>22.11.0</version>
|
||||
<version>23.5.0</version>
|
||||
</since>
|
||||
<synopsis>Value to use in SIP Contact and Via headers as hostname</synopsis>
|
||||
<description><para>
|
||||
When set, this value is used in the SIP Contact and Via
|
||||
headers of outgoing messages instead of the automatically
|
||||
determined IP address. This is useful when a remote SIP
|
||||
endpoint requires a fully qualified domain name in these
|
||||
headers rather than an IP address. No validation is performed
|
||||
on the provided value. This option is mutually exclusive with
|
||||
<literal>external_signaling_address</literal> and both cannot
|
||||
be set simultaneously. If not set, existing behavior using
|
||||
<literal>external_signaling_address</literal> is preserved.
|
||||
</para></description>
|
||||
</configOption>
|
||||
<configOption name="method">
|
||||
<since>
|
||||
<version>12.2.0</version>
|
||||
|
||||
@@ -223,6 +223,9 @@
|
||||
<parameter name="ExternalSignalingPort">
|
||||
<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='transport']/configOption[@name='external_signaling_port']/synopsis/node())"/></para>
|
||||
</parameter>
|
||||
<parameter name="ExternalSignalingHostname">
|
||||
<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='transport']/configOption[@name='external_signaling_hostname']/synopsis/node())"/></para>
|
||||
</parameter>
|
||||
<parameter name="ExternalMediaAddress">
|
||||
<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='transport']/configOption[@name='external_media_address']/synopsis/node())"/></para>
|
||||
</parameter>
|
||||
|
||||
+8
-3
@@ -32,6 +32,7 @@
|
||||
#include "asterisk/res_pjsip_session.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/acl.h"
|
||||
#include "asterisk/strings.h"
|
||||
|
||||
/*! URI parameter for original host/port */
|
||||
#define AST_SIP_X_AST_ORIG_HOST "x-ast-orig-host"
|
||||
@@ -370,8 +371,12 @@ static pj_status_t process_nat(pjsip_tx_data *tdata)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ast_sockaddr_isnull(&transport_state->external_signaling_address)) {
|
||||
if (!ast_sockaddr_isnull(&transport_state->external_signaling_address) ||
|
||||
!ast_strlen_zero(transport->external_signaling_hostname)) {
|
||||
pjsip_cseq_hdr *cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg);
|
||||
const char *signaling_host = !ast_strlen_zero(transport->external_signaling_hostname) ?
|
||||
transport->external_signaling_hostname :
|
||||
ast_sockaddr_stringify_host(&transport_state->external_signaling_address);
|
||||
|
||||
/* Update the Contact header with the external address. We only do this if
|
||||
* a CSeq is not present (which should not happen - but we are extra safe),
|
||||
@@ -387,7 +392,7 @@ static pj_status_t process_nat(pjsip_tx_data *tdata)
|
||||
tdata->msg->line.status.code != PJSIP_SC_MOVED_TEMPORARILY )) {
|
||||
/* We can only rewrite the URI when one is present */
|
||||
if (uri || (uri = ast_sip_get_contact_sip_uri(tdata))) {
|
||||
pj_strdup2(tdata->pool, &uri->host, ast_sockaddr_stringify_host(&transport_state->external_signaling_address));
|
||||
pj_strdup2(tdata->pool, &uri->host, signaling_host);
|
||||
if (transport->external_signaling_port) {
|
||||
uri->port = transport->external_signaling_port;
|
||||
ast_debug(4, "Re-wrote Contact URI port to %d\n", uri->port);
|
||||
@@ -397,7 +402,7 @@ static pj_status_t process_nat(pjsip_tx_data *tdata)
|
||||
|
||||
/* Update the via header if relevant */
|
||||
if ((tdata->msg->type == PJSIP_REQUEST_MSG) && (via || (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL)))) {
|
||||
pj_strdup2(tdata->pool, &via->sent_by.host, ast_sockaddr_stringify_host(&transport_state->external_signaling_address));
|
||||
pj_strdup2(tdata->pool, &via->sent_by.host, signaling_host);
|
||||
if (transport->external_signaling_port) {
|
||||
via->sent_by.port = transport->external_signaling_port;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user