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 78fa818c1b
commit 2451d4e455
12 changed files with 781 additions and 259 deletions

View File

@@ -1172,20 +1172,20 @@ 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 *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
RAII_VAR(struct ast_sip_transport_state *, transport_state, ast_sip_get_transport_state(registration->transport), ao2_cleanup);
if (!transport || !transport->state) {
if (!transport_state) {
ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
" for outbound registration", registration->transport);
return -1;
}
if (transport->state->transport) {
if (transport_state->transport) {
selector.type = PJSIP_TPSELECTOR_TRANSPORT;
selector.u.transport = transport->state->transport;
} else if (transport->state->factory) {
selector.u.transport = transport_state->transport;
} else if (transport_state->factory) {
selector.type = PJSIP_TPSELECTOR_LISTENER;
selector.u.listener = transport->state->factory;
selector.u.listener = transport_state->factory;
} else {
return -1;
}