mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
Merge "res_pjsip/config_transport: Allow reloading transports." into 13
This commit is contained in:
7
CHANGES
7
CHANGES
@@ -47,6 +47,13 @@ res_pjproject
|
||||
|
||||
res_pjsip
|
||||
------------------
|
||||
* Transports are now reloadable. In testing, no in-progress calls were
|
||||
disrupted if the ip address or port weren't changed, but the possibility
|
||||
still exists. To make sure there are no unintentional drops, a new option
|
||||
'allow_reload', which defaults to 'no' has been added to transport. If
|
||||
left at the default, changes to the particular transport will be ignored.
|
||||
If set to 'yes', changes (if any) will be applied.
|
||||
|
||||
* Added new global option (regcontext) to pjsip. When set, Asterisk will
|
||||
dynamically create and destroy a NoOp priority 1 extension
|
||||
for a given endpoint who registers or unregisters with us.
|
||||
|
@@ -810,6 +810,12 @@
|
||||
; clients are slow to process the received
|
||||
; information. Value is in milliseconds; default
|
||||
; is 100 ms.
|
||||
;allow_reload=no ; Although transports can now be reloaded, that may not be
|
||||
; desirable because of the slight possibility of dropped
|
||||
; calls. To make sure there are no unintentional drops, if
|
||||
; this option is set to 'no' (the default) changes to the
|
||||
; particular transport will be ignored. If set to 'yes',
|
||||
; changes (if any) will be applied.
|
||||
|
||||
;==========================AOR SECTION OPTIONS=========================
|
||||
;[aor]
|
||||
|
@@ -0,0 +1,27 @@
|
||||
"""Add allow_reload to ps_transports
|
||||
|
||||
Revision ID: 3bcc0b5bc2c9
|
||||
Revises: dbc44d5a908
|
||||
Create Date: 2016-02-05 17:43:39.183785
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '3bcc0b5bc2c9'
|
||||
down_revision = 'dbc44d5a908'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects.postgresql import ENUM
|
||||
|
||||
YESNO_NAME = 'yesno_values'
|
||||
YESNO_VALUES = ['yes', 'no']
|
||||
|
||||
def upgrade():
|
||||
yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
|
||||
op.add_column('ps_transports', sa.Column('allow_reload', yesno_values))
|
||||
pass
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('ps_transports', 'allow_reload')
|
||||
pass
|
@@ -185,6 +185,8 @@ struct ast_sip_transport {
|
||||
unsigned int cos;
|
||||
/*! Write timeout */
|
||||
int write_timeout;
|
||||
/*! Allow reload */
|
||||
int allow_reload;
|
||||
};
|
||||
|
||||
#define SIP_SORCERY_DOMAIN_ALIAS_TYPE "domain_alias"
|
||||
@@ -2260,4 +2262,26 @@ struct ast_sip_transport_state *ast_sip_get_transport_state(const char *transpor
|
||||
*/
|
||||
struct ao2_container *ast_sip_get_transport_states(void);
|
||||
|
||||
/*!
|
||||
* \brief Sets pjsip_tpselector from ast_sip_transport
|
||||
* \since 13.8.0
|
||||
*
|
||||
* \param transport The transport to be used
|
||||
* \param selector The selector to be populated
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int ast_sip_set_tpselector_from_transport(const struct ast_sip_transport *transport, pjsip_tpselector *selector);
|
||||
|
||||
/*!
|
||||
* \brief Sets pjsip_tpselector from ast_sip_transport
|
||||
* \since 13.8.0
|
||||
*
|
||||
* \param transport_name The name of the transport to be used
|
||||
* \param selector The selector to be populated
|
||||
* \retval 0 success
|
||||
* \retval -1 failure
|
||||
*/
|
||||
int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector);
|
||||
|
||||
#endif /* _RES_PJSIP_H */
|
||||
|
@@ -1026,6 +1026,14 @@
|
||||
Value is in milliseconds; default is 100 ms.</para>
|
||||
</description>
|
||||
</configOption>
|
||||
<configOption name="allow_reload" default="no">
|
||||
<synopsis>Allow this transport to be reloaded.</synopsis>
|
||||
<description>
|
||||
<para>Allow this transport to be reloaded when res_pjsip is reloaded.
|
||||
This option defaults to "no" because reloading a transport may disrupt
|
||||
in-progress calls.</para>
|
||||
</description>
|
||||
</configOption>
|
||||
</configObject>
|
||||
<configObject name="contact">
|
||||
<synopsis>A way of creating an aliased name to a SIP URI</synopsis>
|
||||
@@ -2483,22 +2491,14 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sip_get_tpselector_from_endpoint(const struct ast_sip_endpoint *endpoint, pjsip_tpselector *selector)
|
||||
int ast_sip_set_tpselector_from_transport(const struct ast_sip_transport *transport, pjsip_tpselector *selector)
|
||||
{
|
||||
RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
|
||||
RAII_VAR(struct ast_sip_transport_state *, transport_state, NULL, ao2_cleanup);
|
||||
const char *transport_name = endpoint->transport;
|
||||
|
||||
if (ast_strlen_zero(transport_name)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_name);
|
||||
transport_state = ast_sip_get_transport_state(transport_name);
|
||||
|
||||
if (!transport || !transport_state) {
|
||||
ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' for endpoint '%s'\n",
|
||||
transport_name, ast_sorcery_object_get_id(endpoint));
|
||||
transport_state = ast_sip_get_transport_state(ast_sorcery_object_get_id(transport));
|
||||
if (!transport_state) {
|
||||
ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport state for '%s'\n",
|
||||
ast_sorcery_object_get_id(transport));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2521,6 +2521,35 @@ static int sip_get_tpselector_from_endpoint(const struct ast_sip_endpoint *endpo
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
|
||||
{
|
||||
RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
|
||||
|
||||
if (ast_strlen_zero(transport_name)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_name);
|
||||
if (!transport) {
|
||||
ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s'\n",
|
||||
transport_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ast_sip_set_tpselector_from_transport(transport, selector);
|
||||
}
|
||||
|
||||
static int sip_get_tpselector_from_endpoint(const struct ast_sip_endpoint *endpoint, pjsip_tpselector *selector)
|
||||
{
|
||||
const char *transport_name = endpoint->transport;
|
||||
|
||||
if (ast_strlen_zero(transport_name)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ast_sip_set_tpselector_from_transport_name(endpoint->transport, selector);
|
||||
}
|
||||
|
||||
void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
|
||||
{
|
||||
pjsip_sip_uri *sip_uri;
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <pjsip.h>
|
||||
#include <pjlib.h>
|
||||
|
||||
@@ -347,6 +348,44 @@ static void copy_state_to_transport(struct ast_sip_transport *transport)
|
||||
memcpy(&transport->external_address, &transport->state->external_address, sizeof(transport->external_address));
|
||||
}
|
||||
|
||||
static int has_state_changed(struct ast_sip_transport_state *a, struct ast_sip_transport_state *b)
|
||||
{
|
||||
if (a->type != b->type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pj_sockaddr_cmp(&a->host, &b->host)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((a->localnet || b->localnet)
|
||||
&& ((!a->localnet != !b->localnet)
|
||||
|| ast_sockaddr_cmp(&a->localnet->addr, &b->localnet->addr)
|
||||
|| ast_sockaddr_cmp(&a->localnet->netmask, &b->localnet->netmask)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_sockaddr_cmp(&a->external_address, &b->external_address)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a->tls.method != b->tls.method
|
||||
|| a->tls.ciphers_num != b->tls.ciphers_num
|
||||
|| a->tls.proto != b->tls.proto
|
||||
|| a->tls.verify_client != b->tls.verify_client
|
||||
|| a->tls.verify_server != b->tls.verify_server
|
||||
|| a->tls.require_client_cert != b->tls.require_client_cert) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(a->ciphers, b->ciphers, sizeof(pj_ssl_cipher) * fmax(a->tls.ciphers_num, b->tls.ciphers_num))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void states_cleanup(void *states)
|
||||
{
|
||||
if (states) {
|
||||
@@ -364,6 +403,9 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
|
||||
RAII_VAR(struct internal_state *, perm_state, NULL, ao2_cleanup);
|
||||
RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
|
||||
pj_status_t res = -1;
|
||||
int i;
|
||||
#define BIND_TRIES 3
|
||||
#define BIND_DELAY_US 100000
|
||||
|
||||
if (!states) {
|
||||
return -1;
|
||||
@@ -376,16 +418,16 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
|
||||
*/
|
||||
ao2_wrlock(states);
|
||||
|
||||
temp_state = internal_state_alloc(transport);
|
||||
if (!temp_state) {
|
||||
ast_log(LOG_ERROR, "Transport '%s' failed to allocate memory\n", transport_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
perm_state = find_internal_state_by_transport(transport);
|
||||
if (perm_state) {
|
||||
ast_sorcery_diff(sorcery, perm_state->transport, transport, &changes);
|
||||
if (changes) {
|
||||
if (!perm_state->change_detected) {
|
||||
perm_state->change_detected = 1;
|
||||
ast_log(LOG_WARNING, "Transport '%s' is not reloadable, maintaining previous values\n", transport_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!changes && !has_state_changed(perm_state->state, temp_state->state)) {
|
||||
/* In case someone is using the deprecated fields, reset them */
|
||||
transport->state = perm_state->state;
|
||||
copy_state_to_transport(transport);
|
||||
@@ -393,15 +435,22 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp_state = internal_state_alloc(transport);
|
||||
if (!temp_state) {
|
||||
ast_log(LOG_ERROR, "Transport '%s' failed to allocate memory\n", transport_id);
|
||||
goto error;
|
||||
if (!transport->allow_reload) {
|
||||
if (!perm_state->change_detected) {
|
||||
perm_state->change_detected = 1;
|
||||
ast_log(LOG_WARNING, "Transport '%s' is not reloadable, maintaining previous values\n", transport_id);
|
||||
}
|
||||
/* In case someone is using the deprecated fields, reset them */
|
||||
transport->state = perm_state->state;
|
||||
copy_state_to_transport(transport);
|
||||
ao2_replace(perm_state->transport, transport);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (temp_state->state->host.addr.sa_family != PJ_AF_INET && temp_state->state->host.addr.sa_family != PJ_AF_INET6) {
|
||||
ast_log(LOG_ERROR, "Transport '%s' could not be started as binding not specified\n", transport_id);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set default port if not present */
|
||||
@@ -418,20 +467,33 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Unknown address family for transport '%s', could not get external signaling address\n",
|
||||
transport_id);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_dnsmgr_lookup(transport->external_signaling_address, &temp_state->state->external_address, &temp_state->state->external_address_refresher, NULL) < 0) {
|
||||
ast_log(LOG_ERROR, "Could not create dnsmgr for external signaling address on '%s'\n", transport_id);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (transport->type == AST_TRANSPORT_UDP) {
|
||||
|
||||
for (i = 0; i < BIND_TRIES && res != PJ_SUCCESS; i++) {
|
||||
if (perm_state && perm_state->state && perm_state->state->transport) {
|
||||
pjsip_udp_transport_pause(perm_state->state->transport,
|
||||
PJSIP_UDP_TRANSPORT_DESTROY_SOCKET);
|
||||
usleep(BIND_DELAY_US);
|
||||
}
|
||||
|
||||
if (temp_state->state->host.addr.sa_family == pj_AF_INET()) {
|
||||
res = pjsip_udp_transport_start(ast_sip_get_pjsip_endpoint(), &temp_state->state->host.ipv4, NULL, transport->async_operations, &temp_state->state->transport);
|
||||
res = pjsip_udp_transport_start(ast_sip_get_pjsip_endpoint(),
|
||||
&temp_state->state->host.ipv4, NULL, transport->async_operations,
|
||||
&temp_state->state->transport);
|
||||
} else if (temp_state->state->host.addr.sa_family == pj_AF_INET6()) {
|
||||
res = pjsip_udp_transport_start6(ast_sip_get_pjsip_endpoint(), &temp_state->state->host.ipv6, NULL, transport->async_operations, &temp_state->state->transport);
|
||||
res = pjsip_udp_transport_start6(ast_sip_get_pjsip_endpoint(),
|
||||
&temp_state->state->host.ipv6, NULL, transport->async_operations,
|
||||
&temp_state->state->transport);
|
||||
}
|
||||
}
|
||||
|
||||
if (res == PJ_SUCCESS && (transport->tos || transport->cos)) {
|
||||
@@ -451,18 +513,37 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
|
||||
cfg.async_cnt = transport->async_operations;
|
||||
set_qos(transport, &cfg.qos_params);
|
||||
|
||||
res = pjsip_tcp_transport_start3(ast_sip_get_pjsip_endpoint(), &cfg, &temp_state->state->factory);
|
||||
for (i = 0; i < BIND_TRIES && res != PJ_SUCCESS; i++) {
|
||||
if (perm_state && perm_state->state && perm_state->state->factory
|
||||
&& perm_state->state->factory->destroy) {
|
||||
perm_state->state->factory->destroy(perm_state->state->factory);
|
||||
usleep(BIND_DELAY_US);
|
||||
}
|
||||
|
||||
res = pjsip_tcp_transport_start3(ast_sip_get_pjsip_endpoint(), &cfg,
|
||||
&temp_state->state->factory);
|
||||
}
|
||||
} else if (transport->type == AST_TRANSPORT_TLS) {
|
||||
if (transport->async_operations > 1 && ast_compare_versions(pj_get_version(), "2.5.0") < 0) {
|
||||
ast_log(LOG_ERROR, "Transport: %s: When protocol=tls and pjproject version < 2.5.0, async_operations can't be > 1\n",
|
||||
ast_sorcery_object_get_id(obj));
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
temp_state->state->tls.password = pj_str((char*)transport->password);
|
||||
set_qos(transport, &temp_state->state->tls.qos_params);
|
||||
|
||||
res = pjsip_tls_transport_start2(ast_sip_get_pjsip_endpoint(), &temp_state->state->tls, &temp_state->state->host, NULL, transport->async_operations, &temp_state->state->factory);
|
||||
for (i = 0; i < BIND_TRIES && res != PJ_SUCCESS; i++) {
|
||||
if (perm_state && perm_state->state && perm_state->state->factory
|
||||
&& perm_state->state->factory->destroy) {
|
||||
perm_state->state->factory->destroy(perm_state->state->factory);
|
||||
usleep(BIND_DELAY_US);
|
||||
}
|
||||
|
||||
res = pjsip_tls_transport_start2(ast_sip_get_pjsip_endpoint(), &temp_state->state->tls,
|
||||
&temp_state->state->host, NULL, transport->async_operations,
|
||||
&temp_state->state->factory);
|
||||
}
|
||||
} else if ((transport->type == AST_TRANSPORT_WS) || (transport->type == AST_TRANSPORT_WSS)) {
|
||||
if (transport->cos || transport->tos) {
|
||||
ast_log(LOG_WARNING, "TOS and COS values ignored for websocket transport\n");
|
||||
@@ -475,17 +556,16 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
|
||||
|
||||
pj_strerror(res, msg, sizeof(msg));
|
||||
ast_log(LOG_ERROR, "Transport '%s' could not be started: %s\n", ast_sorcery_object_get_id(obj), msg);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
copy_state_to_transport(transport);
|
||||
ao2_link(states, temp_state);
|
||||
if (perm_state) {
|
||||
ao2_unlink_flags(states, perm_state, OBJ_NOLOCK);
|
||||
}
|
||||
ao2_link_flags(states, temp_state, OBJ_NOLOCK);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ao2_unlink(states, temp_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! \brief Custom handler for type just makes sure the state is created */
|
||||
@@ -1209,6 +1289,7 @@ int ast_sip_initialize_sorcery_transport(void)
|
||||
ast_sorcery_object_field_register_custom(sorcery, "transport", "tos", "0", transport_tos_handler, tos_to_str, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "cos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, cos));
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "websocket_write_timeout", AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT_STR, OPT_INT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_transport, write_timeout), 1, INT_MAX);
|
||||
ast_sorcery_object_field_register(sorcery, "transport", "allow_reload", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_transport, allow_reload));
|
||||
|
||||
internal_sip_register_endpoint_formatter(&endpoint_transport_formatter);
|
||||
|
||||
|
@@ -346,6 +346,8 @@ struct sip_outbound_registration_client_state {
|
||||
unsigned int destroy:1;
|
||||
/*! \brief Non-zero if we have attempted sending a REGISTER with authentication */
|
||||
unsigned int auth_attempted:1;
|
||||
/*! \brief The name of the transport to be used for the registration */
|
||||
char *transport_name;
|
||||
};
|
||||
|
||||
/*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
|
||||
@@ -508,6 +510,7 @@ static pj_status_t registration_client_send(struct sip_outbound_registration_cli
|
||||
{
|
||||
pj_status_t status;
|
||||
int *callback_invoked;
|
||||
pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
|
||||
|
||||
callback_invoked = ast_threadstorage_get(®ister_callback_invoked, sizeof(int));
|
||||
if (!callback_invoked) {
|
||||
@@ -517,6 +520,13 @@ static pj_status_t registration_client_send(struct sip_outbound_registration_cli
|
||||
|
||||
/* Due to the message going out the callback may now be invoked, so bump the count */
|
||||
ao2_ref(client_state, +1);
|
||||
/*
|
||||
* Set the transport in case transports were reloaded.
|
||||
* When pjproject removes the extraneous error messages produced,
|
||||
* we can check status and only set the transport and resend if there was an error
|
||||
*/
|
||||
ast_sip_set_tpselector_from_transport_name(client_state->transport_name, &selector);
|
||||
pjsip_regc_set_transport(client_state->client, &selector);
|
||||
status = pjsip_regc_send(client_state->client, tdata);
|
||||
|
||||
/* If the attempt to send the message failed and the callback was not invoked we need to
|
||||
@@ -966,6 +976,7 @@ static void sip_outbound_registration_client_state_destroy(void *obj)
|
||||
{
|
||||
struct sip_outbound_registration_client_state *client_state = obj;
|
||||
|
||||
ast_free(client_state->transport_name);
|
||||
ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "-1", 1.0);
|
||||
ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "-1", 1.0,
|
||||
sip_outbound_registration_status_str(client_state->status));
|
||||
@@ -1003,6 +1014,7 @@ static struct sip_outbound_registration_state *sip_outbound_registration_state_a
|
||||
state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
|
||||
state->client_state->timer.user_data = state->client_state;
|
||||
state->client_state->timer.cb = sip_outbound_registration_timer_cb;
|
||||
state->client_state->transport_name = ast_strdup(registration->transport);
|
||||
|
||||
ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GAUGE, "+1", 1.0);
|
||||
ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GAUGE, "+1", 1.0,
|
||||
@@ -1171,25 +1183,6 @@ static int sip_outbound_registration_regc_alloc(void *data)
|
||||
|
||||
pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
|
||||
|
||||
if (!ast_strlen_zero(registration->transport)) {
|
||||
RAII_VAR(struct ast_sip_transport_state *, transport_state, ast_sip_get_transport_state(registration->transport), ao2_cleanup);
|
||||
|
||||
if (!transport_state) {
|
||||
ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
|
||||
" for outbound registration", registration->transport);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (transport_state->transport) {
|
||||
selector.type = PJSIP_TPSELECTOR_TRANSPORT;
|
||||
selector.u.transport = transport_state->transport;
|
||||
} else if (transport_state->factory) {
|
||||
selector.type = PJSIP_TPSELECTOR_LISTENER;
|
||||
selector.u.listener = transport_state->factory;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ast_assert(state->client_state->client == NULL);
|
||||
if (pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state,
|
||||
@@ -1198,6 +1191,7 @@ static int sip_outbound_registration_regc_alloc(void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_sip_set_tpselector_from_transport_name(registration->transport, &selector);
|
||||
pjsip_regc_set_transport(state->client_state->client, &selector);
|
||||
|
||||
if (!ast_strlen_zero(registration->outbound_proxy)) {
|
||||
|
@@ -1559,6 +1559,28 @@ void *ast_sip_subscription_get_header(const struct ast_sip_subscription *sub, co
|
||||
return pjsip_msg_find_hdr_by_name(msg, &name, NULL);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Wrapper for pjsip_evsub_send_request
|
||||
*
|
||||
* This function (re)sets the transport before sending to catch cases
|
||||
* where the transport might have changed.
|
||||
*
|
||||
* If pjproject gives us the ability to resend, we'll only reset the transport
|
||||
* if PJSIP_ETPNOTAVAIL is returned from send.
|
||||
*
|
||||
* \returns pj_status_t
|
||||
*/
|
||||
static pj_status_t internal_pjsip_evsub_send_request(struct sip_subscription_tree *sub_tree, pjsip_tx_data *tdata)
|
||||
{
|
||||
pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
|
||||
|
||||
ast_sip_set_tpselector_from_transport_name(sub_tree->endpoint->transport, &selector);
|
||||
pjsip_dlg_set_transport(sub_tree->dlg, &selector);
|
||||
|
||||
return pjsip_evsub_send_request(sub_tree->evsub, tdata);
|
||||
}
|
||||
|
||||
/* XXX This function is not used. */
|
||||
struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
|
||||
struct ast_sip_endpoint *endpoint, const char *resource)
|
||||
@@ -1606,7 +1628,7 @@ struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_su
|
||||
evsub = sub_tree->evsub;
|
||||
|
||||
if (pjsip_evsub_initiate(evsub, NULL, -1, &tdata) == PJ_SUCCESS) {
|
||||
pjsip_evsub_send_request(evsub, tdata);
|
||||
internal_pjsip_evsub_send_request(sub_tree, tdata);
|
||||
} else {
|
||||
/* pjsip_evsub_terminate will result in pubsub_on_evsub_state,
|
||||
* being called and terminating the subscription. Therefore, we don't
|
||||
@@ -1687,8 +1709,8 @@ static int sip_subscription_send_request(struct sip_subscription_tree *sub_tree,
|
||||
{
|
||||
#ifdef TEST_FRAMEWORK
|
||||
struct ast_sip_endpoint *endpoint = sub_tree->endpoint;
|
||||
#endif
|
||||
pjsip_evsub *evsub = sub_tree->evsub;
|
||||
#endif
|
||||
int res;
|
||||
|
||||
if (allocate_tdata_buffer(tdata)) {
|
||||
@@ -1696,7 +1718,8 @@ static int sip_subscription_send_request(struct sip_subscription_tree *sub_tree,
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = pjsip_evsub_send_request(evsub, tdata) == PJ_SUCCESS ? 0 : -1;
|
||||
res = internal_pjsip_evsub_send_request(sub_tree, tdata);
|
||||
|
||||
subscription_persistence_update(sub_tree, NULL);
|
||||
|
||||
ast_test_suite_event_notify("SUBSCRIPTION_STATE_SET",
|
||||
@@ -1705,7 +1728,7 @@ static int sip_subscription_send_request(struct sip_subscription_tree *sub_tree,
|
||||
pjsip_evsub_get_state_name(evsub),
|
||||
ast_sorcery_object_get_id(endpoint));
|
||||
|
||||
return res;
|
||||
return (res == PJ_SUCCESS ? 0 : -1);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@@ -888,10 +888,32 @@ int ast_sip_session_refresh(struct ast_sip_session *session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Wrapper for pjsip_inv_send_msg
|
||||
*
|
||||
* This function (re)sets the transport before sending to catch cases
|
||||
* where the transport might have changed.
|
||||
*
|
||||
* If pjproject gives us the ability to resend, we'll only reset the transport
|
||||
* if PJSIP_ETPNOTAVAIL is returned from send.
|
||||
*
|
||||
* \returns pj_status_t
|
||||
*/
|
||||
static pj_status_t internal_pjsip_inv_send_msg(pjsip_inv_session *inv, const char *transport_name, pjsip_tx_data *tdata)
|
||||
{
|
||||
pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
|
||||
|
||||
ast_sip_set_tpselector_from_transport_name(transport_name, &selector);
|
||||
pjsip_dlg_set_transport(inv->dlg, &selector);
|
||||
|
||||
return pjsip_inv_send_msg(inv, tdata);
|
||||
}
|
||||
|
||||
void ast_sip_session_send_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
|
||||
{
|
||||
handle_outgoing_response(session, tdata);
|
||||
pjsip_inv_send_msg(session->inv_session, tdata);
|
||||
internal_pjsip_inv_send_msg(session->inv_session, session->endpoint->transport, tdata);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1087,7 +1109,8 @@ void ast_sip_session_send_request_with_cb(struct ast_sip_session *session, pjsip
|
||||
}
|
||||
|
||||
handle_outgoing_request(session, tdata);
|
||||
pjsip_inv_send_msg(session->inv_session, tdata);
|
||||
internal_pjsip_inv_send_msg(session->inv_session, session->endpoint->transport, tdata);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1852,7 +1875,7 @@ static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct a
|
||||
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) != PJ_SUCCESS) {
|
||||
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
|
||||
}
|
||||
pjsip_inv_send_msg(inv_session, tdata);
|
||||
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
||||
return NULL;
|
||||
}
|
||||
return inv_session;
|
||||
@@ -2005,7 +2028,7 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
|
||||
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
|
||||
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
|
||||
} else {
|
||||
pjsip_inv_send_msg(inv_session, tdata);
|
||||
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2015,7 +2038,7 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
|
||||
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
|
||||
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
|
||||
} else {
|
||||
pjsip_inv_send_msg(inv_session, tdata);
|
||||
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
||||
}
|
||||
ao2_cleanup(invite);
|
||||
}
|
||||
|
Reference in New Issue
Block a user