Skip to content
Snippets Groups Projects
Commit ffa87eca authored by Dan Cropp's avatar Dan Cropp Committed by Friendly Automation
Browse files

chan_pjsip: Incorporate channel reference count into transfer_refer().

Add channel reference count for PJSIP REFER. The call could be terminated
prior to the result of the transfer. In that scenario, when the SUBSCRIBE/NOTIFY
occurred several minutes later, it would attempt to access a session which was
no longer valid.  Terminate event subscription if pjsip_xfer_initiate() or
pjsip_xfer_send_request() fails in transfer_refer().

ASTERISK-29201 #close
Reported-by: Dan Cropp

Change-Id: I3fd92fd14b4e3844d3d7b0f60fe417a4df5f2435
parent 4274a4a7
No related branches found
No related tags found
3 merge requests!138Merge branch asterisk-20.3.0 into devel properly,!123Merge asterisk '20.3.0' into devel,!118Draft: manager: AOC-S support for AOCMessage
...@@ -1922,8 +1922,7 @@ static pjsip_module refer_callback_module = { ...@@ -1922,8 +1922,7 @@ static pjsip_module refer_callback_module = {
*/ */
static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event) static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
{ {
struct ast_sip_session *session; struct ast_channel *chan;
struct ast_channel *chan = NULL;
enum ast_control_transfer message = AST_TRANSFER_SUCCESS; enum ast_control_transfer message = AST_TRANSFER_SUCCESS;
int res = 0; int res = 0;
...@@ -1931,12 +1930,7 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event) ...@@ -1931,12 +1930,7 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
return; return;
} }
session = pjsip_evsub_get_mod_data(sub, refer_callback_module.id); chan = pjsip_evsub_get_mod_data(sub, refer_callback_module.id);
if (!session) {
return;
}
chan = session->channel;
if (!chan) { if (!chan) {
return; return;
} }
...@@ -1962,7 +1956,9 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event) ...@@ -1962,7 +1956,9 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
*/ */
if (refer_sub && !pj_stricmp2(&refer_sub->hvalue, "false")) { if (refer_sub && !pj_stricmp2(&refer_sub->hvalue, "false")) {
/* Since no subscription is desired, assume that call has been transferred successfully. */ /* Since no subscription is desired, assume that call has been transferred successfully. */
/* Channel reference will be released at end of function */
/* Terminate subscription. */ /* Terminate subscription. */
pjsip_evsub_set_mod_data(sub, refer_callback_module.id, NULL);
pjsip_evsub_terminate(sub, PJ_TRUE); pjsip_evsub_terminate(sub, PJ_TRUE);
res = -1; res = -1;
} }
...@@ -2027,7 +2023,8 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event) ...@@ -2027,7 +2023,8 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
} }
if (res) { if (res) {
ast_queue_control_data(session->channel, AST_CONTROL_TRANSFER, &message, sizeof(message)); ast_queue_control_data(chan, AST_CONTROL_TRANSFER, &message, sizeof(message));
ao2_ref(chan, -1);
} }
} }
...@@ -2040,28 +2037,29 @@ static void transfer_refer(struct ast_sip_session *session, const char *target) ...@@ -2040,28 +2037,29 @@ static void transfer_refer(struct ast_sip_session *session, const char *target)
const char *ref_by_val; const char *ref_by_val;
char local_info[pj_strlen(&session->inv_session->dlg->local.info_str) + 1]; char local_info[pj_strlen(&session->inv_session->dlg->local.info_str) + 1];
struct pjsip_evsub_user xfer_cb; struct pjsip_evsub_user xfer_cb;
struct ast_channel *chan = session->channel;
pj_bzero(&xfer_cb, sizeof(xfer_cb)); pj_bzero(&xfer_cb, sizeof(xfer_cb));
xfer_cb.on_evsub_state = &xfer_client_on_evsub_state; xfer_cb.on_evsub_state = &xfer_client_on_evsub_state;
if (pjsip_xfer_create_uac(session->inv_session->dlg, &xfer_cb, &sub) != PJ_SUCCESS) { if (pjsip_xfer_create_uac(session->inv_session->dlg, &xfer_cb, &sub) != PJ_SUCCESS) {
message = AST_TRANSFER_FAILED; message = AST_TRANSFER_FAILED;
ast_queue_control_data(session->channel, AST_CONTROL_TRANSFER, &message, sizeof(message)); ast_queue_control_data(chan, AST_CONTROL_TRANSFER, &message, sizeof(message));
return; return;
} }
pjsip_evsub_set_mod_data(sub, refer_callback_module.id, session); /* refer_callback_module requires a reference to chan
* which will be released in xfer_client_on_evsub_state()
* when the implicit REFER subscription terminates */
pjsip_evsub_set_mod_data(sub, refer_callback_module.id, chan);
ao2_ref(chan, +1);
if (pjsip_xfer_initiate(sub, pj_cstr(&tmp, target), &packet) != PJ_SUCCESS) { if (pjsip_xfer_initiate(sub, pj_cstr(&tmp, target), &packet) != PJ_SUCCESS) {
message = AST_TRANSFER_FAILED; goto failure;
ast_queue_control_data(session->channel, AST_CONTROL_TRANSFER, &message, sizeof(message));
pjsip_evsub_terminate(sub, PJ_FALSE);
return;
} }
ref_by_val = pbx_builtin_getvar_helper(session->channel, "SIPREFERREDBYHDR"); ref_by_val = pbx_builtin_getvar_helper(chan, "SIPREFERREDBYHDR");
if (!ast_strlen_zero(ref_by_val)) { if (!ast_strlen_zero(ref_by_val)) {
ast_sip_add_header(packet, "Referred-By", ref_by_val); ast_sip_add_header(packet, "Referred-By", ref_by_val);
} else { } else {
...@@ -2069,7 +2067,17 @@ static void transfer_refer(struct ast_sip_session *session, const char *target) ...@@ -2069,7 +2067,17 @@ static void transfer_refer(struct ast_sip_session *session, const char *target)
ast_sip_add_header(packet, "Referred-By", local_info); ast_sip_add_header(packet, "Referred-By", local_info);
} }
pjsip_xfer_send_request(sub, packet); if (pjsip_xfer_send_request(sub, packet) == PJ_SUCCESS) {
return;
}
failure:
message = AST_TRANSFER_FAILED;
ast_queue_control_data(chan, AST_CONTROL_TRANSFER, &message, sizeof(message));
pjsip_evsub_set_mod_data(sub, refer_callback_module.id, NULL);
pjsip_evsub_terminate(sub, PJ_FALSE);
ao2_ref(chan, -1);
} }
static int transfer(void *data) static int transfer(void *data)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment