mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-13 16:21:01 +00:00
Merge "res_pjsip_refer/session: Calls dropped during transfer" into 13
This commit is contained in:
@@ -153,6 +153,10 @@ struct ast_sip_session {
|
|||||||
struct ast_sip_aor *aor;
|
struct ast_sip_aor *aor;
|
||||||
/*! From header saved at invite creation */
|
/*! From header saved at invite creation */
|
||||||
pjsip_fromto_hdr *saved_from_hdr;
|
pjsip_fromto_hdr *saved_from_hdr;
|
||||||
|
/*! Whether the end of the session should be deferred */
|
||||||
|
unsigned int defer_end:1;
|
||||||
|
/*! Session end (remote hangup) requested while termination deferred */
|
||||||
|
unsigned int ended_while_deferred:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
|
typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
|
||||||
@@ -481,6 +485,13 @@ int ast_sip_session_defer_termination(struct ast_sip_session *session);
|
|||||||
*/
|
*/
|
||||||
void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session);
|
void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief End the session if it had been previously deferred
|
||||||
|
*
|
||||||
|
* \param session The session to end if it had been deferred
|
||||||
|
*/
|
||||||
|
void ast_sip_session_end_if_deferred(struct ast_sip_session *session);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Register an SDP handler
|
* \brief Register an SDP handler
|
||||||
*
|
*
|
||||||
|
@@ -543,6 +543,7 @@ static int refer_attended_task(void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast_sip_session_end_if_deferred(attended->transferer);
|
||||||
if (response != 200) {
|
if (response != 200) {
|
||||||
if (!ast_sip_push_task(attended->transferer->serializer,
|
if (!ast_sip_push_task(attended->transferer->serializer,
|
||||||
defer_termination_cancel, attended->transferer)) {
|
defer_termination_cancel, attended->transferer)) {
|
||||||
@@ -772,6 +773,7 @@ static int refer_incoming_attended_request(struct ast_sip_session *session, pjsi
|
|||||||
|
|
||||||
/* Push it to the other session, which will have both channels with minimal locking */
|
/* Push it to the other session, which will have both channels with minimal locking */
|
||||||
if (ast_sip_push_task(other_session->serializer, refer_attended_task, attended)) {
|
if (ast_sip_push_task(other_session->serializer, refer_attended_task, attended)) {
|
||||||
|
ast_sip_session_end_if_deferred(session);
|
||||||
ast_sip_session_defer_termination_cancel(session);
|
ast_sip_session_defer_termination_cancel(session);
|
||||||
ao2_cleanup(attended);
|
ao2_cleanup(attended);
|
||||||
return 500;
|
return 500;
|
||||||
@@ -810,9 +812,12 @@ static int refer_incoming_attended_request(struct ast_sip_session *session, pjsi
|
|||||||
|
|
||||||
response = xfer_response_code2sip(ast_bridge_transfer_blind(1, session->channel,
|
response = xfer_response_code2sip(ast_bridge_transfer_blind(1, session->channel,
|
||||||
"external_replaces", context, refer_blind_callback, &refer));
|
"external_replaces", context, refer_blind_callback, &refer));
|
||||||
|
|
||||||
|
ast_sip_session_end_if_deferred(session);
|
||||||
if (response != 200) {
|
if (response != 200) {
|
||||||
ast_sip_session_defer_termination_cancel(session);
|
ast_sip_session_defer_termination_cancel(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -865,9 +870,12 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r
|
|||||||
|
|
||||||
response = xfer_response_code2sip(ast_bridge_transfer_blind(1, session->channel,
|
response = xfer_response_code2sip(ast_bridge_transfer_blind(1, session->channel,
|
||||||
exten, context, refer_blind_callback, &refer));
|
exten, context, refer_blind_callback, &refer));
|
||||||
|
|
||||||
|
ast_sip_session_end_if_deferred(session);
|
||||||
if (response != 200) {
|
if (response != 200) {
|
||||||
ast_sip_session_defer_termination_cancel(session);
|
ast_sip_session_defer_termination_cancel(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1903,6 +1903,9 @@ int ast_sip_session_defer_termination(struct ast_sip_session *session)
|
|||||||
|
|
||||||
session->defer_terminate = 1;
|
session->defer_terminate = 1;
|
||||||
|
|
||||||
|
session->defer_end = 1;
|
||||||
|
session->ended_while_deferred = 0;
|
||||||
|
|
||||||
session->scheduled_termination.id = 0;
|
session->scheduled_termination.id = 0;
|
||||||
ao2_ref(session, +1);
|
ao2_ref(session, +1);
|
||||||
session->scheduled_termination.user_data = session;
|
session->scheduled_termination.user_data = session;
|
||||||
@@ -1940,6 +1943,7 @@ void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session)
|
|||||||
/* Already canceled or timer fired. */
|
/* Already canceled or timer fired. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->defer_terminate = 0;
|
session->defer_terminate = 0;
|
||||||
|
|
||||||
if (session->terminate_while_deferred) {
|
if (session->terminate_while_deferred) {
|
||||||
@@ -1951,6 +1955,22 @@ void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session)
|
|||||||
sip_session_defer_termination_stop_timer(session);
|
sip_session_defer_termination_stop_timer(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ast_sip_session_end_if_deferred(struct ast_sip_session *session)
|
||||||
|
{
|
||||||
|
if (!session->defer_end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->defer_end = 0;
|
||||||
|
|
||||||
|
if (session->ended_while_deferred) {
|
||||||
|
/* Complete the session end started by the remote hangup. */
|
||||||
|
ast_debug(3, "Ending session (%p) after being deferred\n", session);
|
||||||
|
session->ended_while_deferred = 0;
|
||||||
|
session_end(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ast_sip_session *ast_sip_dialog_get_session(pjsip_dialog *dlg)
|
struct ast_sip_session *ast_sip_dialog_get_session(pjsip_dialog *dlg)
|
||||||
{
|
{
|
||||||
pjsip_inv_session *inv_session = pjsip_dlg_get_inv_session(dlg);
|
pjsip_inv_session *inv_session = pjsip_dlg_get_inv_session(dlg);
|
||||||
@@ -2636,6 +2656,12 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
|
if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
|
||||||
|
if (session->defer_end) {
|
||||||
|
ast_debug(3, "Deferring session (%p) end\n", session);
|
||||||
|
session->ended_while_deferred = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ast_sip_push_task(session->serializer, session_end, session)) {
|
if (ast_sip_push_task(session->serializer, session_end, session)) {
|
||||||
/* Do it anyway even though this is not the right thread. */
|
/* Do it anyway even though this is not the right thread. */
|
||||||
session_end(session);
|
session_end(session);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
LINKER_SYMBOL_PREFIXast_sip_session_terminate;
|
LINKER_SYMBOL_PREFIXast_sip_session_terminate;
|
||||||
LINKER_SYMBOL_PREFIXast_sip_session_defer_termination;
|
LINKER_SYMBOL_PREFIXast_sip_session_defer_termination;
|
||||||
LINKER_SYMBOL_PREFIXast_sip_session_defer_termination_cancel;
|
LINKER_SYMBOL_PREFIXast_sip_session_defer_termination_cancel;
|
||||||
|
LINKER_SYMBOL_PREFIXast_sip_session_end_if_deferred;
|
||||||
LINKER_SYMBOL_PREFIXast_sip_session_register_sdp_handler;
|
LINKER_SYMBOL_PREFIXast_sip_session_register_sdp_handler;
|
||||||
LINKER_SYMBOL_PREFIXast_sip_session_unregister_sdp_handler;
|
LINKER_SYMBOL_PREFIXast_sip_session_unregister_sdp_handler;
|
||||||
LINKER_SYMBOL_PREFIXast_sip_session_register_supplement;
|
LINKER_SYMBOL_PREFIXast_sip_session_register_supplement;
|
||||||
|
Reference in New Issue
Block a user