res_pjsip: Fix infinite recursion when loading transports from realtime

Attempting to load a transport from realtime was forcing asterisk into an
infinite recursion loop.  The first thing transport_apply did was to do a
sorcery retrieve by id for an existing transport of the same name. For files,
this just returns the previous object from res_sorcery_config's internal
container, if any.  For realtime, the res_sourcery_realtime driver looks in the
database and finds the existing row but now it has to rehydrate it into a
sorcery object which means calling... transport_apply.  And so it goes.

The main issue with loading from realtime (apart from the loop) was that
transport stores structures and pointers directly in the ast_sip_transport
structure instead of the separate ast_transport_state structure.  This patch
separates those items into the ast_sip_transport_state structure.  The pattern
is roughly the same as res_pjsip_outbound_registration.

Although all current usages of ast_sip_transport and ast_sip_transport_state
were modified to use the new ast_sip_get_transport_state API, the original
items are left in ast_sip_transport and kept updated to maintain ABI
compatability for third-party modules.  They are marked as deprecated and
noted that they're now in ast_sip_transport_state.

ASTERISK-25606 #close
Reported-by: Martin Moučka

Change-Id: Ic7a836ea8e786e8def51fe3f8cce855ea54f5f19
This commit is contained in:
George Joseph
2016-01-29 16:56:42 -07:00
parent 7e4378770d
commit bbf3ace682
12 changed files with 781 additions and 259 deletions

View File

@@ -275,24 +275,27 @@ static int transport_read(void *data)
static int get_write_timeout(void)
{
int write_timeout = -1;
struct ao2_container *transports;
struct ao2_container *transport_states;
transports = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "transport", AST_RETRIEVE_FLAG_ALL, NULL);
transport_states = ast_sip_get_transport_states();
if (transports) {
struct ao2_iterator it_transports = ao2_iterator_init(transports, 0);
struct ast_sip_transport *transport;
if (transport_states) {
struct ao2_iterator it_transport_states = ao2_iterator_init(transport_states, 0);
struct ast_sip_transport_state *transport_state;
for (; (transport = ao2_iterator_next(&it_transports)); ao2_cleanup(transport)) {
if (transport->type != AST_TRANSPORT_WS && transport->type != AST_TRANSPORT_WSS) {
for (; (transport_state = ao2_iterator_next(&it_transport_states)); ao2_cleanup(transport_state)) {
struct ast_sip_transport *transport;
if (transport_state->type != AST_TRANSPORT_WS && transport_state->type != AST_TRANSPORT_WSS) {
continue;
}
transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id);
ast_debug(5, "Found %s transport with write timeout: %d\n",
transport->type == AST_TRANSPORT_WS ? "WS" : "WSS",
transport->write_timeout);
write_timeout = MAX(write_timeout, transport->write_timeout);
}
ao2_cleanup(transports);
ao2_iterator_destroy(&it_transport_states);
ao2_cleanup(transport_states);
}
if (write_timeout < 0) {