From ac3da7a2a1af15f108a63feaeffc914e3ff3e14d Mon Sep 17 00:00:00 2001 From: sauwming Date: Thu, 16 Mar 2023 15:47:29 +0800 Subject: [PATCH 1/4] Respond with ACK first before hanging up call for dialog fork --- pjsip/src/pjsip/sip_dialog.c | 2 +- pjsip/src/pjsip/sip_ua_layer.c | 2 +- pjsip/src/pjsua-lib/pjsua_call.c | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c index cda05fbb6e..56eec17853 100644 --- a/pjsip/src/pjsip/sip_dialog.c +++ b/pjsip/src/pjsip/sip_dialog.c @@ -1920,7 +1920,7 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata ) pjsip_dlg_inc_lock(dlg); /* Check that rdata already has dialog in mod_data. */ - pj_assert(pjsip_rdata_get_dlg(rdata) == dlg); + //pj_assert(pjsip_rdata_get_dlg(rdata) == dlg); /* Keep the response's status code */ res_code = rdata->msg_info.msg->line.status.code; diff --git a/pjsip/src/pjsip/sip_ua_layer.c b/pjsip/src/pjsip/sip_ua_layer.c index e6a7eaa9f3..99ea9281a7 100644 --- a/pjsip/src/pjsip/sip_ua_layer.c +++ b/pjsip/src/pjsip/sip_ua_layer.c @@ -895,7 +895,7 @@ static pj_bool_t mod_ua_on_rx_response(pjsip_rx_data *rdata) if (mod_ua.param.on_dlg_forked) { dlg = (*mod_ua.param.on_dlg_forked)(dlg_set->dlg_list.next, rdata); - if (dlg == NULL) { + if (dlg == NULL || dlg != dlg_set->dlg_list.next) { pj_mutex_unlock(mod_ua.mutex); return PJ_TRUE; } diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 4915331696..ef760f8bfe 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -5116,6 +5116,9 @@ pjsip_dialog* on_dlg_forked(pjsip_dialog *dlg, pjsip_rx_data *res) pjsip_dlg_inc_lock(forked_dlg); + /* Respond with ACK first */ + pjsip_dlg_on_rx_response(forked_dlg, res); + /* Disconnect the call */ status = pjsip_dlg_create_request(forked_dlg, pjsip_get_bye_method(), -1, &bye); From b37825b68ed8b77d8304f333eaafe37256e04a22 Mon Sep 17 00:00:00 2001 From: sauwming Date: Fri, 17 Mar 2023 13:18:52 +0800 Subject: [PATCH 2/4] Add API pjsip_rdata_set_dlg() and fix sipp script --- pjsip/include/pjsip/sip_dialog.h | 17 +++++++++++++++++ pjsip/src/pjsip/sip_dialog.c | 2 +- pjsip/src/pjsip/sip_ua_layer.c | 5 +++++ pjsip/src/pjsua-lib/pjsua_call.c | 1 + tests/pjsua/scripts-sipp/uas-forked-200.xml | 8 +++----- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/pjsip/include/pjsip/sip_dialog.h b/pjsip/include/pjsip/sip_dialog.h index da2ec95fb3..15881482c2 100644 --- a/pjsip/include/pjsip/sip_dialog.h +++ b/pjsip/include/pjsip/sip_dialog.h @@ -614,6 +614,23 @@ PJ_DECL(void) pjsip_dlg_dec_lock( pjsip_dialog *dlg ); PJ_DECL(pj_grp_lock_t *) pjsip_dlg_get_lock( pjsip_dialog *dlg ); +/** + * Set the dialog instance in the incoming rdata. + * + * Note that if an incoming message matches an existing dialog, the user + * agent will put the matching dialog instance in the rdata, so typically + * application does not need to call this function directly. + * In other words, this function is only useful if application needs to + * associate the incoming rdata with the dialog instance before the user + * agent sets it (such as in the context of module that runs in priority + * number lower than PJSIP_MOD_PRIORITY_UA_PROXY_LAYER). + * + * @param rdata Incoming message buffer. + * @param dlg The dialog. + */ +PJ_DECL(void) pjsip_rdata_set_dlg( pjsip_rx_data *rdata, pjsip_dialog *dlg); + + /** * Get the dialog instance in the incoming rdata. If an incoming message * matches an existing dialog, the user agent must have put the matching diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c index 56eec17853..cda05fbb6e 100644 --- a/pjsip/src/pjsip/sip_dialog.c +++ b/pjsip/src/pjsip/sip_dialog.c @@ -1920,7 +1920,7 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata ) pjsip_dlg_inc_lock(dlg); /* Check that rdata already has dialog in mod_data. */ - //pj_assert(pjsip_rdata_get_dlg(rdata) == dlg); + pj_assert(pjsip_rdata_get_dlg(rdata) == dlg); /* Keep the response's status code */ res_code = rdata->msg_info.msg->line.status.code; diff --git a/pjsip/src/pjsip/sip_ua_layer.c b/pjsip/src/pjsip/sip_ua_layer.c index 99ea9281a7..08a91a7747 100644 --- a/pjsip/src/pjsip/sip_ua_layer.c +++ b/pjsip/src/pjsip/sip_ua_layer.c @@ -448,6 +448,11 @@ PJ_DEF(pj_status_t) pjsip_ua_unregister_dlg( pjsip_user_agent *ua, } +PJ_DEF(void) pjsip_rdata_set_dlg( pjsip_rx_data *rdata, pjsip_dialog *dlg) +{ + rdata->endpt_info.mod_data[mod_ua.mod.id] = dlg; +} + PJ_DEF(pjsip_dialog*) pjsip_rdata_get_dlg( pjsip_rx_data *rdata ) { return (pjsip_dialog*) rdata->endpt_info.mod_data[mod_ua.mod.id]; diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index ef760f8bfe..84b34b9799 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -5117,6 +5117,7 @@ pjsip_dialog* on_dlg_forked(pjsip_dialog *dlg, pjsip_rx_data *res) pjsip_dlg_inc_lock(forked_dlg); /* Respond with ACK first */ + pjsip_rdata_set_dlg(res, forked_dlg); pjsip_dlg_on_rx_response(forked_dlg, res); /* Disconnect the call */ diff --git a/tests/pjsua/scripts-sipp/uas-forked-200.xml b/tests/pjsua/scripts-sipp/uas-forked-200.xml index 2b7a1cb567..ef1da50e78 100644 --- a/tests/pjsua/scripts-sipp/uas-forked-200.xml +++ b/tests/pjsua/scripts-sipp/uas-forked-200.xml @@ -97,6 +97,9 @@ ]]> + + + @@ -115,11 +118,6 @@ - - - - - From 23468195e25d3303983251d43a52325656453fcd Mon Sep 17 00:00:00 2001 From: sauwming Date: Fri, 17 Mar 2023 16:10:58 +0800 Subject: [PATCH 3/4] Send ACK manually in on_dlg_forked() --- pjsip/include/pjsip/sip_dialog.h | 17 ----------------- pjsip/src/pjsip/sip_ua_layer.c | 7 +------ pjsip/src/pjsua-lib/pjsua_call.c | 8 +++++--- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/pjsip/include/pjsip/sip_dialog.h b/pjsip/include/pjsip/sip_dialog.h index 15881482c2..da2ec95fb3 100644 --- a/pjsip/include/pjsip/sip_dialog.h +++ b/pjsip/include/pjsip/sip_dialog.h @@ -614,23 +614,6 @@ PJ_DECL(void) pjsip_dlg_dec_lock( pjsip_dialog *dlg ); PJ_DECL(pj_grp_lock_t *) pjsip_dlg_get_lock( pjsip_dialog *dlg ); -/** - * Set the dialog instance in the incoming rdata. - * - * Note that if an incoming message matches an existing dialog, the user - * agent will put the matching dialog instance in the rdata, so typically - * application does not need to call this function directly. - * In other words, this function is only useful if application needs to - * associate the incoming rdata with the dialog instance before the user - * agent sets it (such as in the context of module that runs in priority - * number lower than PJSIP_MOD_PRIORITY_UA_PROXY_LAYER). - * - * @param rdata Incoming message buffer. - * @param dlg The dialog. - */ -PJ_DECL(void) pjsip_rdata_set_dlg( pjsip_rx_data *rdata, pjsip_dialog *dlg); - - /** * Get the dialog instance in the incoming rdata. If an incoming message * matches an existing dialog, the user agent must have put the matching diff --git a/pjsip/src/pjsip/sip_ua_layer.c b/pjsip/src/pjsip/sip_ua_layer.c index 08a91a7747..e6a7eaa9f3 100644 --- a/pjsip/src/pjsip/sip_ua_layer.c +++ b/pjsip/src/pjsip/sip_ua_layer.c @@ -448,11 +448,6 @@ PJ_DEF(pj_status_t) pjsip_ua_unregister_dlg( pjsip_user_agent *ua, } -PJ_DEF(void) pjsip_rdata_set_dlg( pjsip_rx_data *rdata, pjsip_dialog *dlg) -{ - rdata->endpt_info.mod_data[mod_ua.mod.id] = dlg; -} - PJ_DEF(pjsip_dialog*) pjsip_rdata_get_dlg( pjsip_rx_data *rdata ) { return (pjsip_dialog*) rdata->endpt_info.mod_data[mod_ua.mod.id]; @@ -900,7 +895,7 @@ static pj_bool_t mod_ua_on_rx_response(pjsip_rx_data *rdata) if (mod_ua.param.on_dlg_forked) { dlg = (*mod_ua.param.on_dlg_forked)(dlg_set->dlg_list.next, rdata); - if (dlg == NULL || dlg != dlg_set->dlg_list.next) { + if (dlg == NULL) { pj_mutex_unlock(mod_ua.mutex); return PJ_TRUE; } diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 84b34b9799..5587da78e2 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -5106,7 +5106,7 @@ pjsip_dialog* on_dlg_forked(pjsip_dialog *dlg, pjsip_rx_data *res) res->msg_info.msg->line.status.code/100 == 2) { pjsip_dialog *forked_dlg; - pjsip_tx_data *bye; + pjsip_tx_data *bye, *ack; pj_status_t status; /* Create forked dialog */ @@ -5117,8 +5117,10 @@ pjsip_dialog* on_dlg_forked(pjsip_dialog *dlg, pjsip_rx_data *res) pjsip_dlg_inc_lock(forked_dlg); /* Respond with ACK first */ - pjsip_rdata_set_dlg(res, forked_dlg); - pjsip_dlg_on_rx_response(forked_dlg, res); + status = pjsip_dlg_create_request(forked_dlg, &pjsip_ack_method, + res->msg_info.cseq->cseq, &ack); + if (status == PJ_SUCCESS) + pjsip_dlg_send_request(forked_dlg, ack, -1, NULL); /* Disconnect the call */ status = pjsip_dlg_create_request(forked_dlg, pjsip_get_bye_method(), From 0c915f81e16eea8322fc429625ba1c5c0876670c Mon Sep 17 00:00:00 2001 From: sauwming Date: Fri, 17 Mar 2023 16:24:28 +0800 Subject: [PATCH 4/4] Add checking if ACK has been sent before --- pjsip/include/pjsip/sip_dialog.h | 1 + pjsip/src/pjsip/sip_dialog.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pjsip/include/pjsip/sip_dialog.h b/pjsip/include/pjsip/sip_dialog.h index da2ec95fb3..dd842677e3 100644 --- a/pjsip/include/pjsip/sip_dialog.h +++ b/pjsip/include/pjsip/sip_dialog.h @@ -160,6 +160,7 @@ struct pjsip_dialog pj_bool_t uac_has_2xx;/**< UAC has received 2xx response? */ pj_bool_t secure; /**< Use secure transport? */ pj_bool_t add_allow; /**< Add Allow header in requests? */ + pj_bool_t ack_sent; /**< ACK has been sent? */ pjsip_cid_hdr *call_id; /**< Call-ID header. */ pjsip_route_hdr route_set; /**< Route set. */ pj_bool_t route_set_frozen; /**< Route set has been set. */ diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c index cda05fbb6e..4a5dd0d14b 100644 --- a/pjsip/src/pjsip/sip_dialog.c +++ b/pjsip/src/pjsip/sip_dialog.c @@ -1363,6 +1363,8 @@ PJ_DEF(pj_status_t) pjsip_dlg_send_request( pjsip_dialog *dlg, } } else { + dlg->ack_sent = PJ_TRUE; + /* Set transport selector */ pjsip_tx_data_set_transport(tdata, &dlg->tp_sel); @@ -2079,7 +2081,8 @@ void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata ) pj_status_t status; if (rdata->msg_info.cseq->method.id==PJSIP_INVITE_METHOD && - rdata->msg_info.msg->line.status.code/100 == 2) + rdata->msg_info.msg->line.status.code/100 == 2 && + !dlg->ack_sent) { pjsip_tx_data *ack;