summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Joseph <gjoseph@digium.com>2017-11-08 09:44:24 -0600
committerGerrit Code Review <gerrit2@gerrit.digium.api>2017-11-08 09:44:24 -0600
commit62c3a68c279501430476d35df42a43272fe20c4a (patch)
treeb4aff0d1bfa2f58bae599811bced201c1881c598
parent9670040e2eac80978f4ecbc0cbae341adcbcf39b (diff)
parent6032fb973b8f9d7e52105656c877be525f7317f8 (diff)
Merge "AST-2017-011 - res_pjsip_session: session leak when a call is rejected" into 14
-rw-r--r--res/res_pjsip_session.c80
1 files changed, 42 insertions, 38 deletions
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 808477c0f..8ad6d3ce4 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2686,6 +2686,36 @@ static void session_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
/* XXX STUB */
}
+static int session_end_if_disconnected(int id, pjsip_inv_session *inv)
+{
+ struct ast_sip_session *session;
+
+ if (inv->state != PJSIP_INV_STATE_DISCONNECTED) {
+ return 0;
+ }
+
+ /*
+ * We are locking because ast_sip_dialog_get_session() needs
+ * the dialog locked to get the session by other threads.
+ */
+ pjsip_dlg_inc_lock(inv->dlg);
+ session = inv->mod_data[id];
+ inv->mod_data[id] = NULL;
+ pjsip_dlg_dec_lock(inv->dlg);
+
+ /*
+ * Pass the session ref held by session->inv_session to
+ * session_end_completion().
+ */
+ if (session
+ && ast_sip_push_task(session->serializer, session_end_completion, session)) {
+ /* Do it anyway even though this is not the right thread. */
+ session_end_completion(session);
+ }
+
+ return 1;
+}
+
static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
{
ast_sip_session_response_cb cb;
@@ -2710,6 +2740,17 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
/* The session has ended. Ignore the transaction change. */
return;
}
+
+ /*
+ * If the session is disconnected really nothing else to do unless currently transacting
+ * a BYE. If a BYE then hold off destruction until the transaction timeout occurs. This
+ * has to be done for BYEs because sometimes the dialog can be in a disconnected
+ * state but the BYE request transaction has not yet completed.
+ */
+ if (tsx->method.id != PJSIP_BYE_METHOD && session_end_if_disconnected(id, inv)) {
+ return;
+ }
+
switch (e->body.tsx_state.type) {
case PJSIP_EVENT_TX_MSG:
/* When we create an outgoing request, we do not have access to the transaction that
@@ -2832,49 +2873,12 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
}
break;
case PJSIP_EVENT_TRANSPORT_ERROR:
- if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
- /*
- * Clear the module data now to block session_inv_on_state_changed()
- * from calling session_end() if it hasn't already done so.
- */
- inv->mod_data[id] = NULL;
-
- /*
- * Pass the session ref held by session->inv_session to
- * session_end_completion().
- */
- if (session
- && ast_sip_push_task(session->serializer, session_end_completion, session)) {
- /* Do it anyway even though this is not the right thread. */
- session_end_completion(session);
- }
- return;
- }
- break;
case PJSIP_EVENT_TIMER:
/*
* The timer event is run by the pjsip monitor thread and not
* by the session serializer.
*/
- if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
- /*
- * We are locking because ast_sip_dialog_get_session() needs
- * the dialog locked to get the session by other threads.
- */
- pjsip_dlg_inc_lock(inv->dlg);
- session = inv->mod_data[id];
- inv->mod_data[id] = NULL;
- pjsip_dlg_dec_lock(inv->dlg);
-
- /*
- * Pass the session ref held by session->inv_session to
- * session_end_completion().
- */
- if (session
- && ast_sip_push_task(session->serializer, session_end_completion, session)) {
- /* Do it anyway even though this is not the right thread. */
- session_end_completion(session);
- }
+ if (session_end_if_disconnected(id, inv)) {
return;
}
break;