From: Mike Bradeen Date: Mon, 5 May 2025 18:05:15 +0000 (-0600) Subject: chan_pjsip: Serialize INVITE creation on DTMF attended transfer X-Git-Tag: 21.10.0-rc1~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99402536cbf64e284507d0228e5b10f83ddc57b2;p=thirdparty%2Fasterisk.git chan_pjsip: Serialize INVITE creation on DTMF attended transfer When a call is transfered via DTMF feature code, the Transfer Target and Transferer are bridged immediately. This opens the possibilty of a race condition between the creation of an INVITE and the bridge induced colp update that can result in the set caller ID being over-written with the transferer's default info. Fixes: #1234 (cherry picked from commit a5ac74ef68535f1db0496465a664eb99bd3ff2a7) --- diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 13d1c66b06..1582fb83d7 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -2394,13 +2394,12 @@ static void update_initial_connected_line(struct ast_sip_session *session) static int call(void *data) { - struct ast_sip_channel_pvt *channel = data; - struct ast_sip_session *session = channel->session; + struct ast_sip_session *session = data; pjsip_tx_data *tdata; int res = 0; SCOPE_ENTER(1, "%s Topology: %s\n", ast_sip_session_get_name(session), - ast_str_tmp(256, ast_stream_topology_to_str(channel->session->pending_media_state->topology, &STR_TMP)) + ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP)) ); @@ -2414,7 +2413,6 @@ static int call(void *data) update_initial_connected_line(session); ast_sip_session_send_request(session, tdata); } - ao2_ref(channel, -1); SCOPE_EXIT_RTN_VALUE(res, "RC: %d\n", res); } @@ -2422,16 +2420,24 @@ static int call(void *data) static int chan_pjsip_call(struct ast_channel *ast, const char *dest, int timeout) { struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast); - SCOPE_ENTER(1, "%s Topology: %s\n", ast_sip_session_get_name(channel->session), - ast_str_tmp(256, ast_stream_topology_to_str(channel->session->pending_media_state->topology, &STR_TMP))); + struct ast_sip_session *session = ao2_bump(channel->session); + + SCOPE_ENTER(1, "%s Topology: %s\n", ast_sip_session_get_name(session), + ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP))); + + ast_channel_unlock(ast); - ao2_ref(channel, +1); - if (ast_sip_push_task(channel->session->serializer, call, channel)) { + /* The creation of the INVITE needs to be pushed synchronously to prevent a race condition + with bridging on attended transfers that can result in a loss of set Caller ID. */ + if (ast_sip_push_task_wait_serializer(session->serializer, call, session)) { ast_log(LOG_WARNING, "Error attempting to place outbound call to '%s'\n", dest); - ao2_cleanup(channel); + ao2_ref(session, -1); + ast_channel_lock(ast); SCOPE_EXIT_RTN_VALUE(-1, "Couldn't push task\n"); } + ao2_ref(session, -1); + ast_channel_lock(ast); SCOPE_EXIT_RTN_VALUE(0, "'call' task pushed\n"); }