|
|
|
@ -46,6 +46,7 @@
|
|
|
|
|
#include "asterisk/acl.h"
|
|
|
|
|
#include "asterisk/features_config.h"
|
|
|
|
|
#include "asterisk/pickup.h"
|
|
|
|
|
#include "asterisk/test.h"
|
|
|
|
|
|
|
|
|
|
#define SDP_HANDLER_BUCKETS 11
|
|
|
|
|
|
|
|
|
@ -2687,14 +2688,49 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
|
|
|
|
|
}
|
|
|
|
|
} else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
|
|
|
|
|
if (inv->cancelling && tsx->status_code == PJSIP_SC_OK) {
|
|
|
|
|
/* This is a race condition detailed in RFC 5407 section 3.1.2.
|
|
|
|
|
* We sent a CANCEL at the same time that the UAS sent us a 200 OK for
|
|
|
|
|
* the original INVITE. As a result, we have now received a 200 OK for
|
|
|
|
|
* a cancelled call. Our role is to immediately send a BYE to end the
|
|
|
|
|
* dialog.
|
|
|
|
|
int sdp_negotiation_done =
|
|
|
|
|
pjmedia_sdp_neg_get_state(inv->neg) == PJMEDIA_SDP_NEG_STATE_DONE;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We can get here for the following reasons.
|
|
|
|
|
*
|
|
|
|
|
* 1) The race condition detailed in RFC5407 section 3.1.2.
|
|
|
|
|
* We sent a CANCEL at the same time that the UAS sent us a
|
|
|
|
|
* 200 OK with a valid SDP for the original INVITE. As a
|
|
|
|
|
* result, we have now received a 200 OK for a cancelled
|
|
|
|
|
* call and the SDP negotiation is complete. We need to
|
|
|
|
|
* immediately send a BYE to end the dialog.
|
|
|
|
|
*
|
|
|
|
|
* 2) We sent a CANCEL and hit the race condition but the
|
|
|
|
|
* UAS sent us an invalid SDP with the 200 OK. In this case
|
|
|
|
|
* the SDP negotiation is incomplete and PJPROJECT has
|
|
|
|
|
* already sent the BYE for us because of the invalid SDP.
|
|
|
|
|
*
|
|
|
|
|
* 3) We didn't send a CANCEL but the UAS sent us an invalid
|
|
|
|
|
* SDP with the 200 OK. In this case the SDP negotiation is
|
|
|
|
|
* incomplete and PJPROJECT has already sent the BYE for us
|
|
|
|
|
* because of the invalid SDP.
|
|
|
|
|
*/
|
|
|
|
|
if (pjsip_inv_end_session(inv, 500, NULL, &tdata) == PJ_SUCCESS
|
|
|
|
|
ast_test_suite_event_notify("PJSIP_SESSION_CANCELED",
|
|
|
|
|
"Endpoint: %s\r\n"
|
|
|
|
|
"Channel: %s\r\n"
|
|
|
|
|
"Message: %s\r\n"
|
|
|
|
|
"SDP: %s",
|
|
|
|
|
ast_sorcery_object_get_id(session->endpoint),
|
|
|
|
|
session->channel ? ast_channel_name(session->channel) : "",
|
|
|
|
|
pjsip_rx_data_get_info(e->body.tsx_state.src.rdata),
|
|
|
|
|
sdp_negotiation_done ? "complete" : "incomplete");
|
|
|
|
|
if (!sdp_negotiation_done) {
|
|
|
|
|
ast_debug(1, "Endpoint '%s(%s)': Incomplete SDP negotiation cancelled session. %s\n",
|
|
|
|
|
ast_sorcery_object_get_id(session->endpoint),
|
|
|
|
|
session->channel ? ast_channel_name(session->channel) : "",
|
|
|
|
|
pjsip_rx_data_get_info(e->body.tsx_state.src.rdata));
|
|
|
|
|
} else if (pjsip_inv_end_session(inv, 500, NULL, &tdata) == PJ_SUCCESS
|
|
|
|
|
&& tdata) {
|
|
|
|
|
ast_debug(1, "Endpoint '%s(%s)': Ending session due to RFC5407 race condition. %s\n",
|
|
|
|
|
ast_sorcery_object_get_id(session->endpoint),
|
|
|
|
|
session->channel ? ast_channel_name(session->channel) : "",
|
|
|
|
|
pjsip_rx_data_get_info(e->body.tsx_state.src.rdata));
|
|
|
|
|
ast_sip_session_send_request(session, tdata);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|