From a6f4edf032d2c1d1ab58393c47c635f5d1bcd10c Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Wed, 6 Dec 2017 14:24:03 +0000 Subject: pjsip: Ignore state changes from old transactions. When we fail over to a new target we create a new transaction and it becomes the current INVITE transaction. This does not prevent the previous transaction from raising state changes and causing the session to be prematurely disconnected if a transport error occurs immediately. This change backports a fix from PJSIP that eliminates the incorrect state change and reduces when they would be raised in the first place. ASTERISK-27408 Change-Id: Id22d087591782eee31311753d11e7eca4b95ef34 --- .../0050-dont_terminate_session_early.patch | 71 ++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 third-party/pjproject/patches/0050-dont_terminate_session_early.patch diff --git a/third-party/pjproject/patches/0050-dont_terminate_session_early.patch b/third-party/pjproject/patches/0050-dont_terminate_session_early.patch new file mode 100644 index 000000000..718968c79 --- /dev/null +++ b/third-party/pjproject/patches/0050-dont_terminate_session_early.patch @@ -0,0 +1,71 @@ +commit ca0b723e92bd76bbda1bbd14477a829eaeeb675e +Author: Joshua Colp +Date: Wed Dec 13 10:58:57 2017 +0000 + + Ignore transport error on completed transaction. + Don't disconnect call if transport error happens on transaction that is not initial INVITE transaction. + + Scenario: + + DNS lookup returning two servers. + Sending INVITE to first server over TCP. + Response received with code 503 (Service Unavailable). + Failover to second server, sending second INVITE after restarting the session. + TCP connection for the first INVITE getting disconnected and causing call disconnection (while second INVITE is still outstanding). + + This is a backport of 5714 from upstream PJSIP. + +diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c +index ac4d1949..0173cb4c 100644 +--- a/pjsip/src/pjsip-ua/sip_inv.c ++++ b/pjsip/src/pjsip-ua/sip_inv.c +@@ -4254,8 +4254,7 @@ static void inv_on_state_calling( pjsip_inv_session *inv, pjsip_event *e) + if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && + tsx->method.id != PJSIP_CANCEL_METHOD) || + tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || +- tsx->status_code == PJSIP_SC_TSX_TIMEOUT || +- tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) ++ tsx->status_code == PJSIP_SC_TSX_TIMEOUT) + { + inv_set_cause(inv, tsx->status_code, &tsx->status_text); + inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); +diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c +index 7ac3d1b7..d52b12a7 100644 +--- a/pjsip/src/pjsip/sip_transaction.c ++++ b/pjsip/src/pjsip/sip_transaction.c +@@ -2044,9 +2044,14 @@ static void transport_callback(void *token, pjsip_tx_data *tdata, + */ + lock_timer(tsx); + tsx->transport_err = (pj_status_t)-sent; +- tsx_cancel_timer(tsx, &tsx->timeout_timer); +- tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, +- TRANSPORT_ERR_TIMER); ++ /* Don't cancel timeout timer if tsx state is already ++ * PJSIP_TSX_STATE_COMPLETED (see #2076). ++ */ ++ if (tsx->state < PJSIP_TSX_STATE_COMPLETED) { ++ tsx_cancel_timer(tsx, &tsx->timeout_timer); ++ tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, ++ TRANSPORT_ERR_TIMER); ++ } + unlock_timer(tsx); + } + +@@ -2077,9 +2082,14 @@ static void tsx_tp_state_callback( pjsip_transport *tp, + */ + lock_timer(tsx); + tsx->transport_err = info->status; +- tsx_cancel_timer(tsx, &tsx->timeout_timer); +- tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, +- TRANSPORT_ERR_TIMER); ++ /* Don't cancel timeout timer if tsx state is already ++ * PJSIP_TSX_STATE_COMPLETED (see #2076). ++ */ ++ if (tsx->state < PJSIP_TSX_STATE_COMPLETED) { ++ tsx_cancel_timer(tsx, &tsx->timeout_timer); ++ tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, ++ TRANSPORT_ERR_TIMER); ++ } + unlock_timer(tsx); + } + } -- cgit v1.2.3