Commit 1373b5ad authored by Ghislain MARY's avatar Ghislain MARY

Fix call with Replaces header being answered automatically.

parent a9edb2a7
......@@ -156,6 +156,9 @@ LINPHONE_PUBLIC const SalErrorInfo *sal_op_get_error_info(const SalOp *op);
LINPHONE_PUBLIC bool_t sal_call_dialog_request_pending(const SalOp *op);
LINPHONE_PUBLIC void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling);
LINPHONE_PUBLIC SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
LINPHONE_PUBLIC const char *sal_call_get_local_tag (SalOp *op);
LINPHONE_PUBLIC const char *sal_call_get_remote_tag (SalOp *op);
LINPHONE_PUBLIC void sal_call_set_replaces (SalOp *op, const char *callId, const char *fromTag, const char *toTag);
LINPHONE_PUBLIC belle_sip_resolver_context_t *sal_resolve_a(Sal *sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data);
......
......@@ -72,6 +72,7 @@ protected:
void init ();
void accept (const CallSessionParams *params);
void acceptOrTerminateReplacedSessionInIncomingNotification ();
virtual LinphoneStatus acceptUpdate (const CallSessionParams *csp, CallSession::State nextState, const std::string &stateInfo);
LinphoneStatus checkForAcceptation ();
virtual void handleIncomingReceivedStateInIncomingNotification ();
......
......@@ -511,6 +511,22 @@ void CallSessionPrivate::accept (const CallSessionParams *csp) {
setState(CallSession::State::Connected, "Connected");
}
void CallSessionPrivate::acceptOrTerminateReplacedSessionInIncomingNotification () {
L_Q();
CallSession *replacedSession = nullptr;
if (op->getReplaces())
replacedSession = reinterpret_cast<CallSession *>(op->getReplaces()->getUserPointer());
if (replacedSession) {
if ((replacedSession->getState() == CallSession::State::Connected) || (replacedSession->getState() == CallSession::State::StreamsRunning)) {
if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "auto_answer_replacing_calls", 1)) {
q->accept();
}
} else {
replacedSession->terminate();
}
}
}
LinphoneStatus CallSessionPrivate::acceptUpdate (const CallSessionParams *csp, CallSession::State nextState, const string &stateInfo) {
return startAcceptUpdate(nextState, stateInfo);
}
......@@ -541,13 +557,11 @@ LinphoneStatus CallSessionPrivate::checkForAcceptation () {
}
void CallSessionPrivate::handleIncomingReceivedStateInIncomingNotification () {
L_Q();
/* Try to be best-effort in giving real local or routable contact address for 100Rel case */
setContactOp();
if (notifyRinging)
op->notifyRinging(false);
if (op->getReplaces() && lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "auto_answer_replacing_calls", 1))
q->accept();
acceptOrTerminateReplacedSessionInIncomingNotification();
}
bool CallSessionPrivate::isReadyForInvite () const {
......
......@@ -3592,6 +3592,7 @@ void MediaSessionPrivate::abort (const string &errorMsg) {
void MediaSessionPrivate::handleIncomingReceivedStateInIncomingNotification () {
L_Q();
/* Try to be best-effort in giving real local or routable contact address for 100Rel case */
setContactOp();
bool proposeEarlyMedia = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "incoming_calls_early_media", false);
......@@ -3599,8 +3600,8 @@ void MediaSessionPrivate::handleIncomingReceivedStateInIncomingNotification () {
q->acceptEarlyMedia();
else
op->notifyRinging(false);
if (op->getReplaces() && !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "auto_answer_replacing_calls", 1))
q->accept();
acceptOrTerminateReplacedSessionInIncomingNotification();
}
bool MediaSessionPrivate::isReadyForInvite () const {
......
......@@ -1281,15 +1281,6 @@ SalCallOp *SalCallOp::getReplaces () const {
belle_sip_header_replaces_get_from_tag(mReplaces)
);
if (!dialog) {
// For backward compatibility with liblinphone <= 3.10.2-243
dialog = belle_sip_provider_find_dialog(
mRoot->mProvider,
belle_sip_header_replaces_get_call_id(mReplaces),
belle_sip_header_replaces_get_from_tag(mReplaces),
belle_sip_header_replaces_get_to_tag(mReplaces)
);
}
if (dialog)
return reinterpret_cast<SalCallOp *>(belle_sip_dialog_get_application_data(dialog));
return nullptr;
......
......@@ -997,6 +997,27 @@ LINPHONE_PUBLIC SalMediaDescription *sal_call_get_final_media_description (SalOp
return callOp->getFinalMediaDescription();
}
LINPHONE_PUBLIC const char *sal_call_get_local_tag (SalOp *op) {
auto callOp = dynamic_cast<SalCallOp *>(op);
if (!callOp)
return nullptr;
return callOp->getLocalTag();
}
LINPHONE_PUBLIC const char *sal_call_get_remote_tag (SalOp *op) {
auto callOp = dynamic_cast<SalCallOp *>(op);
if (!callOp)
return nullptr;
return callOp->getRemoteTag();
}
LINPHONE_PUBLIC void sal_call_set_replaces (SalOp *op, const char *callId, const char *fromTag, const char *toTag) {
auto callOp = dynamic_cast<SalCallOp *>(op);
if (!callOp)
return;
callOp->setReplaces(callId, fromTag, toTag);
}
LINPHONE_PUBLIC belle_sip_resolver_context_t *sal_resolve_a (Sal *sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) {
return sal->resolveA(name, port, family, cb, data);
}
......
......@@ -1163,6 +1163,53 @@ void do_not_stop_ringing_when_declining_one_of_two_incoming_calls(void) {
linphone_core_manager_destroy(laure);
}
void no_auto_answer_on_fake_call_with_replaces_header (void) {
LinphoneCoreManager *marie1 = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *marie2 = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
bctbx_list_t *lcs = bctbx_list_append(NULL, marie1->lc);
lcs = bctbx_list_append(lcs, marie2->lc);
lcs = bctbx_list_append(lcs, pauline->lc);
LinphoneCallParams *params = linphone_core_create_call_params(marie1->lc, NULL);
linphone_call_params_set_privacy(params, LinphonePrivacyId);
LinphoneCall *call1 = linphone_core_invite_address_with_params(marie1->lc, pauline->identity, params);
linphone_call_params_unref(params);
BC_ASSERT_PTR_NOT_NULL(call1);
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 2000));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallOutgoingRinging, 1, 2000));
reset_counters(&marie1->stat);
reset_counters(&marie2->stat);
reset_counters(&pauline->stat);
const char *callId = linphone_call_log_get_call_id(linphone_call_get_call_log(call1));
BC_ASSERT_PTR_NOT_NULL(callId);
SalOp *op = linphone_call_get_op_as_sal_op(call1);
const char *fromTag = sal_call_get_local_tag(op);
const char *toTag = sal_call_get_remote_tag(op);
BC_ASSERT_PTR_NOT_NULL(fromTag);
BC_ASSERT_PTR_NOT_NULL(toTag);
params = linphone_core_create_call_params(marie2->lc, NULL);
char *headerValue = bctbx_strdup_printf("%s;from-tag=%s;to-tag=%s", callId, fromTag, toTag);
linphone_call_params_add_custom_header(params, "Replaces", headerValue);
bctbx_free(headerValue);
LinphoneCall *call2 = linphone_core_invite_address_with_params(marie2->lc, pauline->identity, params);
linphone_call_params_unref(params);
BC_ASSERT_PTR_NOT_NULL(call2);
BC_ASSERT_EQUAL(marie2->stat.number_of_LinphoneCallOutgoingProgress, 1, int, "%d");
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 2000));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallOutgoingRinging, 1, 2000));
BC_ASSERT_FALSE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected, 1, 2000));
linphone_core_manager_destroy(marie1);
linphone_core_manager_destroy(marie2);
linphone_core_manager_destroy(pauline);
bctbx_list_free(lcs);
}
test_t multi_call_tests[] = {
TEST_NO_TAG("Call waiting indication", call_waiting_indication),
TEST_NO_TAG("Call waiting indication with privacy", call_waiting_indication_with_privacy),
......@@ -1188,6 +1235,7 @@ test_t multi_call_tests[] = {
TEST_NO_TAG("Simple remote conference with shut down focus", simple_remote_conference_shut_down_focus),
TEST_NO_TAG("Eject from 3 participants in remote conference", eject_from_3_participants_remote_conference),
TEST_NO_TAG("Do not stop ringing when declining one of two incoming calls", do_not_stop_ringing_when_declining_one_of_two_incoming_calls),
TEST_NO_TAG("No auto answer on fake call with Replaces header", no_auto_answer_on_fake_call_with_replaces_header)
};
test_suite_t multi_call_test_suite = {"Multi call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
......
Markdown is supported
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