summaryrefslogtreecommitdiff
path: root/res/res_pjsip_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip_session.c')
-rw-r--r--res/res_pjsip_session.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 9c01d3ccf..5b75f3c7e 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1524,6 +1524,7 @@ void ast_sip_session_terminate(struct ast_sip_session *session, int response)
pjsip_tx_data *packet = NULL;
if (session->defer_terminate) {
+ session->terminate_while_deferred = 1;
return;
}
@@ -1559,17 +1560,16 @@ void ast_sip_session_terminate(struct ast_sip_session *session, int response)
static int session_termination_task(void *data)
{
- RAII_VAR(struct ast_sip_session *, session, data, ao2_cleanup);
- pjsip_tx_data *packet = NULL;
-
- if (!session->inv_session) {
- return 0;
- }
+ struct ast_sip_session *session = data;
- if (pjsip_inv_end_session(session->inv_session, 603, NULL, &packet) == PJ_SUCCESS) {
- ast_sip_session_send_request(session, packet);
+ if (session->defer_terminate) {
+ session->defer_terminate = 0;
+ if (session->inv_session) {
+ ast_sip_session_terminate(session, 0);
+ }
}
+ ao2_ref(session, -1);
return 0;
}
@@ -1582,9 +1582,13 @@ static void session_termination_cb(pj_timer_heap_t *timer_heap, struct pj_timer_
}
}
-void ast_sip_session_defer_termination(struct ast_sip_session *session)
+int ast_sip_session_defer_termination(struct ast_sip_session *session)
{
pj_time_val delay = { .sec = 60, };
+ int res;
+
+ /* The session should not have an active deferred termination request. */
+ ast_assert(!session->defer_terminate);
session->defer_terminate = 1;
@@ -1593,7 +1597,31 @@ void ast_sip_session_defer_termination(struct ast_sip_session *session)
session->scheduled_termination.user_data = session;
session->scheduled_termination.cb = session_termination_cb;
- if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &session->scheduled_termination, &delay) != PJ_SUCCESS) {
+ res = (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(),
+ &session->scheduled_termination, &delay) != PJ_SUCCESS) ? -1 : 0;
+ if (res) {
+ session->defer_terminate = 0;
+ ao2_ref(session, -1);
+ }
+ return res;
+}
+
+void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session)
+{
+ if (!session->defer_terminate) {
+ /* Already canceled or timer fired. */
+ return;
+ }
+ session->defer_terminate = 0;
+
+ if (session->terminate_while_deferred) {
+ /* Complete the termination started by the upper layer. */
+ ast_sip_session_terminate(session, 0);
+ }
+
+ /* Stop the termination timer if it is still running. */
+ if (pj_timer_heap_cancel(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
+ &session->scheduled_termination)) {
ao2_ref(session, -1);
}
}