Commit fa04627a authored by Eloi Bail's avatar Eloi Bail Committed by Guillaume Roguez
Browse files

sip: fix attended transfers

Attended transfers led to an assertion in pjsip. According to high-level
librairie pjsua, unused in Ring, and specially function pjsua_call_on_incoming,
it looks like we should not call pjsip_inv_answer when replace header is
present. This function actually leads to the pjsip assertion.
pjsip_inv_initial_answer should be rather used.

NOTIFY is still missing.

Change-Id: I2e4a09533bd33dd32b2cc61a7d9737dc1fe79738
Tuleap: #122
parent ffdbc957
......@@ -399,53 +399,51 @@ transaction_request_cb(pjsip_rx_data *rdata)
// Check if call has been transfered
pjsip_tx_data *tdata = 0;
// If Replace header present
if (replaced_dlg) {
// Always answer the new INVITE with 200 if the replaced call is in early or confirmed state.
if (pjsip_inv_answer(call->inv.get(), PJSIP_SC_OK, NULL, NULL, &response) == PJ_SUCCESS) {
if (pjsip_inv_send_msg(call->inv.get(), response) != PJ_SUCCESS)
call->inv.reset(); // FIXME: not sure if we need to continue
}
if (pjsip_inv_initial_answer(call->inv.get(), rdata, PJSIP_SC_TRYING, NULL, NULL, &tdata) != PJ_SUCCESS) {
RING_ERR("Could not create answer TRYING");
return PJ_FALSE;
}
// Get the INVITE session associated with the replaced dialog.
pjsip_inv_session *replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
if (pjsip_inv_send_msg(call->inv.get(), tdata) != PJ_SUCCESS) {
RING_ERR("Could not send msg TRYING");
return PJ_FALSE;
}
// Disconnect the "replaced" INVITE session.
if (pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, &tdata) == PJ_SUCCESS && tdata) {
pjsip_inv_send_msg(replaced_inv, tdata);
}
} else { // Proceed with normal call flow
if (pjsip_inv_initial_answer(call->inv.get(), rdata, PJSIP_SC_TRYING, NULL, NULL, &tdata) != PJ_SUCCESS) {
RING_ERR("Could not create answer TRYING");
return PJ_FALSE;
}
call->setState(Call::ConnectionState::TRYING);
if (pjsip_inv_send_msg(call->inv.get(), tdata) != PJ_SUCCESS) {
RING_ERR("Could not send msg TRYING");
return PJ_FALSE;
}
if (pjsip_inv_answer(call->inv.get(), PJSIP_SC_RINGING, NULL, NULL, &tdata) != PJ_SUCCESS) {
RING_ERR("Could not create answer RINGING");
return PJ_FALSE;
}
call->setState(Call::ConnectionState::TRYING);
// contactStr must stay in scope as long as tdata
const pj_str_t contactStr(account->getContactHeader(transport->get()));
sip_utils::addContactHeader(&contactStr, tdata);
if (pjsip_inv_answer(call->inv.get(), PJSIP_SC_RINGING, NULL, NULL, &tdata) != PJ_SUCCESS) {
RING_ERR("Could not create answer RINGING");
return PJ_FALSE;
}
if (pjsip_inv_send_msg(call->inv.get(), tdata) != PJ_SUCCESS) {
RING_ERR("Could not send msg RINGING");
return PJ_FALSE;
}
// contactStr must stay in scope as long as tdata
const pj_str_t contactStr(account->getContactHeader(transport->get()));
sip_utils::addContactHeader(&contactStr, tdata);
call->setState(Call::ConnectionState::RINGING);
if (pjsip_inv_send_msg(call->inv.get(), tdata) != PJ_SUCCESS) {
RING_ERR("Could not send msg RINGING");
return PJ_FALSE;
}
Manager::instance().incomingCall(*call, account_id);
call->setState(Call::ConnectionState::RINGING);
if (replaced_dlg) {
// Get the INVITE session associated with the replaced dialog.
auto replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
Manager::instance().incomingCall(*call, account_id);
// Disconnect the "replaced" INVITE session.
if (pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, nullptr, &tdata) == PJ_SUCCESS && tdata) {
pjsip_inv_send_msg(replaced_inv, tdata);
}
// Close call at application level
if (auto oldCallid = static_cast<SIPCall*>(replaced_inv->mod_data[mod_ua_.id]))
oldCallid->hangup(PJSIP_SC_OK);
}
return PJ_FALSE;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment