From ae33af40ef0717256c6b8d5e9a3f697cc38aadc6 Mon Sep 17 00:00:00 2001 From: Andrea Gianarda <andrea.gianarda@belledonne-communications.com> Date: Mon, 25 Nov 2024 16:05:10 +0100 Subject: [PATCH] Verify behaviour when remote puts down all inactive streams and disable all capabilities in the current params in such a scenario --- coreapi/local_conference.cpp | 6 +- src/conference/session/media-session.cpp | 44 ++++++--- tester/call_single_tester.c | 114 +++++++++++++++++++++-- tester/capability_negotiation_tester.cpp | 12 ++- 4 files changed, 148 insertions(+), 28 deletions(-) diff --git a/coreapi/local_conference.cpp b/coreapi/local_conference.cpp index 0d8ceb718c..50377bd042 100644 --- a/coreapi/local_conference.cpp +++ b/coreapi/local_conference.cpp @@ -1839,9 +1839,9 @@ bool LocalConference::validateNewParameters(const LinphonePrivate::ConferencePar return false; } - if (confParams->getConferenceAddress() != newConfParams.getConferenceAddress()) { - lError() << "Conference address change is not allowed: actual " << confParams->getConferenceAddress() - << " new value " << newConfParams.getConferenceAddress(); + if (*confParams->getConferenceAddress() != *newConfParams.getConferenceAddress()) { + lError() << "Conference address change is not allowed: actual " << *confParams->getConferenceAddress() + << " new value " << *newConfParams.getConferenceAddress(); return false; } diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index bfeda2e8ae..6c8caf3311 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -275,7 +275,8 @@ void MediaSessionPrivate::accepted() { /* Reset the internal call update flag, so it doesn't risk to be copied and used in further re-INVITEs */ getParams()->getPrivate()->setInternalCallUpdate(false); std::shared_ptr<SalMediaDescription> rmd = op->getRemoteMediaDescription(); - std::shared_ptr<SalMediaDescription> &md = op->getFinalMediaDescription(); + std::shared_ptr<SalMediaDescription> cmd = op->getFinalMediaDescription(); + std::shared_ptr<SalMediaDescription> md = cmd; if (!md && (prevState == CallSession::State::OutgoingEarlyMedia) && resultDesc) { lInfo() << "Using early media SDP since none was received with the 200 OK"; md = resultDesc; @@ -285,7 +286,7 @@ void MediaSessionPrivate::accepted() { bool updatingConference = conferenceInfo && (conferenceInfo->getState() == ConferenceInfo::State::Updated); // Do not reject media session if the client is trying to update a conference if (rejectMediaSession(rmd, md) && !updatingConference) { - lInfo() << "Rejecting media session"; + lInfo() << "Rejecting media session [" << this << "]"; md = nullptr; } @@ -437,6 +438,7 @@ void MediaSessionPrivate::accepted() { default: lInfo() << "Incompatible SDP answer received, restoring previous state [" << Utils::toString(prevState) << "]"; + resultDesc = cmd; setState(prevState, "Incompatible media parameters."); break; } @@ -797,8 +799,8 @@ void MediaSessionPrivate::updating(bool isUpdate) { SalErrorInfo sei; memset(&sei, 0, sizeof(sei)); expectMediaInAck = false; - std::shared_ptr<SalMediaDescription> &md = op->getFinalMediaDescription(); - if (rejectMediaSession(rmd, md)) { + std::shared_ptr<SalMediaDescription> &cmd = op->getFinalMediaDescription(); + if (rejectMediaSession(rmd, cmd)) { lWarning() << "Session [" << q << "] is going to be rejected because of an incompatible negotiated SDP"; sal_error_info_set(&sei, SalReasonNotAcceptable, "SIP", 0, "Incompatible SDP", nullptr); op->declineWithErrorInfo(&sei, nullptr); @@ -806,8 +808,8 @@ void MediaSessionPrivate::updating(bool isUpdate) { return; } std::shared_ptr<SalMediaDescription> &prevResultDesc = resultDesc; - if (isUpdate && prevResultDesc && md) { - int diff = md->equal(*prevResultDesc); + if (isUpdate && prevResultDesc && cmd) { + int diff = cmd->equal(*prevResultDesc); if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED | SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)) { lWarning() << "Cannot accept this update, it is changing parameters that require user approval"; sal_error_info_set(&sei, SalReasonUnknown, "SIP", 504, @@ -3504,8 +3506,14 @@ void MediaSessionPrivate::setTerminated() { LinphoneStatus MediaSessionPrivate::startAcceptUpdate(CallSession::State nextState, const string &stateInfo) { op->accept(); - std::shared_ptr<SalMediaDescription> &md = op->getFinalMediaDescription(); - if (md && !md->isEmpty()) updateStreams(md, nextState); + std::shared_ptr<SalMediaDescription> &cmd = op->getFinalMediaDescription(); + if (cmd) { + if (cmd->isEmpty()) { + resultDesc = cmd; + } else { + updateStreams(cmd, nextState); + } + } setState(nextState, stateInfo); getCurrentParams()->getPrivate()->setInConference(getParams()->getPrivate()->getInConference()); @@ -3818,6 +3826,10 @@ void MediaSessionPrivate::updateCurrentParams() const { } else { getCurrentParams()->enableRealtimeText(false); } + } else { + getCurrentParams()->enableAudio(false); + getCurrentParams()->enableVideo(false); + getCurrentParams()->enableRealtimeText(false); } getCurrentParams()->getPrivate()->setUpdateCallWhenIceCompleted(isUpdateSentWhenIceCompleted()); } @@ -3895,7 +3907,9 @@ LinphoneStatus MediaSessionPrivate::startAccept() { } updateStreams(newMd, CallSession::State::StreamsRunning); setState(CallSession::State::StreamsRunning, "Connected (streams running)"); - } else expectMediaInAck = true; + } else { + expectMediaInAck = true; + } return 0; } @@ -4835,7 +4849,7 @@ LinphoneStatus MediaSession::update(const MediaSessionParams *msp, isCapabilityNegotiationReInvite); const auto &localDesc = d->localDesc; - auto updateCompletionTask = [this, method, subject, localDesc]() -> LinphoneStatus { + auto updateCompletionTask = [this, method, subject, localDesc, isOfferer]() -> LinphoneStatus { L_D(); CallSession::State previousState = d->state; @@ -4855,17 +4869,17 @@ LinphoneStatus MediaSession::update(const MediaSessionParams *msp, // therefore the local description must be updated to include ICE candidates for every stream const auto currentLocalDesc = d->localDesc; d->localDesc = localDesc; - d->updateLocalMediaDescriptionFromIce(!getCore()->getCCore()->sip_conf.sdp_200_ack); + d->updateLocalMediaDescriptionFromIce(isOfferer); - if (getCore()->getCCore()->sip_conf.sdp_200_ack) { - d->op->setLocalMediaDescription(nullptr); - } else { + if (isOfferer) { d->op->setLocalMediaDescription(d->localDesc); + } else { + d->op->setLocalMediaDescription(nullptr); } LinphoneStatus res = d->startUpdate(method, subject); d->localDesc = currentLocalDesc; - if (getCore()->getCCore()->sip_conf.sdp_200_ack) { + if (!isOfferer) { /* We are NOT offering, set local media description after sending the call so that we are ready to * process the remote offer when it will arrive. */ d->op->setLocalMediaDescription(d->localDesc); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index c5064e4684..d7e4d539d2 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -382,8 +382,8 @@ static void simple_call_with_video_declined(void) { BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_lparams)); const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(marie_call); BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_rparams)); - const LinphoneCallParams *call_params = linphone_call_get_current_params(marie_call); - BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_params)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(marie_call); + BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_cparams)); } LinphoneCall *pauline_call = linphone_core_get_call_by_remote_address2(pauline->lc, marie->identity); BC_ASSERT_PTR_NOT_NULL(pauline_call); @@ -427,8 +427,8 @@ static void simple_call_with_video_declined(void) { if (marie_call) { const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(marie_call); BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_rparams)); - const LinphoneCallParams *call_params = linphone_call_get_current_params(marie_call); - BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_params)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(marie_call); + BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_cparams)); } if (pauline_call) { const LinphoneCallParams *call_lparams = linphone_call_get_params(pauline_call); @@ -1241,6 +1241,101 @@ static void call_with_no_audio_codec(void) { linphone_core_manager_destroy(caller); } +static void call_with_no_active_stream_on_reinvite(void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + + LinphoneVideoActivationPolicy *vpol = linphone_factory_create_video_activation_policy(linphone_factory_get()); + linphone_video_activation_policy_set_automatically_initiate(vpol, TRUE); + linphone_video_activation_policy_set_automatically_accept(vpol, TRUE); + linphone_core_set_video_activation_policy(marie->lc, vpol); + linphone_core_set_video_activation_policy(pauline->lc, vpol); + linphone_video_activation_policy_unref(vpol); + + linphone_core_enable_video_capture(marie->lc, TRUE); + linphone_core_enable_video_display(marie->lc, TRUE); + linphone_core_set_video_device(marie->lc, liblinphone_tester_mire_id); + + linphone_core_enable_video_capture(pauline->lc, TRUE); + linphone_core_enable_video_display(pauline->lc, TRUE); + linphone_core_set_video_device(pauline->lc, liblinphone_tester_mire_id); + + BC_ASSERT_TRUE(call(marie, pauline)); + + LinphoneCall *marie_call = linphone_core_get_call_by_remote_address2(marie->lc, pauline->identity); + BC_ASSERT_PTR_NOT_NULL(marie_call); + if (marie_call) { + const LinphoneCallParams *call_lparams = linphone_call_get_params(marie_call); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_lparams)); + const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(marie_call); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_rparams)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(marie_call); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_cparams)); + } + LinphoneCall *pauline_call = linphone_core_get_call_by_remote_address2(pauline->lc, marie->identity); + BC_ASSERT_PTR_NOT_NULL(pauline_call); + if (pauline_call) { + const LinphoneCallParams *call_lparams = linphone_call_get_params(pauline_call); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_lparams)); + const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(pauline_call); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_rparams)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(pauline_call); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_cparams)); + } + + linphone_config_set_int(linphone_core_get_config(pauline->lc), "sip", "defer_update_default", TRUE); + + stats initial_pauline_stat = pauline->stat; + stats initial_marie_stat = marie->stat; + LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, marie_call); + linphone_call_update(marie_call, marie_params); + linphone_call_params_unref(marie_params); + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallUpdatedByRemote, + initial_pauline_stat.number_of_LinphoneCallUpdatedByRemote + 1)); + + int pauline_defer_update = + !!linphone_config_get_int(linphone_core_get_config(pauline->lc), "sip", "defer_update_default", FALSE); + BC_ASSERT_TRUE(pauline_defer_update); + if (pauline_defer_update == TRUE) { + LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, pauline_call); + linphone_call_params_enable_audio(pauline_params, FALSE); + linphone_call_params_enable_video(pauline_params, FALSE); + linphone_call_accept_update(pauline_call, pauline_params); + linphone_call_params_unref(pauline_params); + } + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallUpdating, + initial_marie_stat.number_of_LinphoneCallUpdating + 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, + initial_pauline_stat.number_of_LinphoneCallStreamsRunning + 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, + initial_marie_stat.number_of_LinphoneCallStreamsRunning + 1)); + + if (marie_call) { + const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(marie_call); + BC_ASSERT_FALSE(linphone_call_params_audio_enabled(call_rparams)); + BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_rparams)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(marie_call); + BC_ASSERT_FALSE(linphone_call_params_audio_enabled(call_cparams)); + BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_cparams)); + } + if (pauline_call) { + const LinphoneCallParams *call_lparams = linphone_call_get_params(pauline_call); + BC_ASSERT_FALSE(linphone_call_params_audio_enabled(call_lparams)); + BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_lparams)); + const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(pauline_call); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_rparams)); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_rparams)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(pauline_call); + BC_ASSERT_FALSE(linphone_call_params_audio_enabled(call_cparams)); + BC_ASSERT_FALSE(linphone_call_params_video_enabled(call_cparams)); + } + + end_call(marie, pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void simple_call_compatibility_mode(void) { char route[256]; LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); @@ -7296,9 +7391,9 @@ static void call_with_audio_stream_added_later_on(void) { const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(marie_call); BC_ASSERT_FALSE(linphone_call_params_audio_enabled(call_rparams)); BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_rparams)); - const LinphoneCallParams *call_params = linphone_call_get_current_params(marie_call); - BC_ASSERT_FALSE(linphone_call_params_audio_enabled(call_params)); - BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_rparams)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(marie_call); + BC_ASSERT_FALSE(linphone_call_params_audio_enabled(call_cparams)); + BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_cparams)); } if (pauline_call) { const LinphoneCallParams *call_lparams = linphone_call_get_params(pauline_call); @@ -7332,8 +7427,8 @@ static void call_with_audio_stream_added_later_on(void) { const LinphoneCallParams *call_rparams = linphone_call_get_remote_params(marie_call); BC_ASSERT_TRUE(linphone_call_params_audio_enabled(call_rparams)); BC_ASSERT_TRUE(linphone_call_params_video_enabled(call_rparams)); - const LinphoneCallParams *call_params = linphone_call_get_current_params(marie_call); - BC_ASSERT_TRUE(linphone_call_params_audio_enabled(call_params)); + const LinphoneCallParams *call_cparams = linphone_call_get_current_params(marie_call); + BC_ASSERT_TRUE(linphone_call_params_audio_enabled(call_cparams)); } if (pauline_call) { const LinphoneCallParams *call_lparams = linphone_call_get_params(pauline_call); @@ -7806,6 +7901,7 @@ static test_t call2_tests[] = { TEST_NO_TAG("Call with specified codec bitrate", call_with_specified_codec_bitrate), TEST_NO_TAG("Call with maxptime", call_with_maxptime), TEST_NO_TAG("Call with no audio codec", call_with_no_audio_codec), + TEST_NO_TAG("Call with no active stream on reINVITE", call_with_no_active_stream_on_reinvite), TEST_NO_TAG("Call with in-dialog UPDATE request", call_with_in_dialog_update), TEST_NO_TAG("Call with in-dialog very early call request", call_with_very_early_call_update), TEST_NO_TAG("Call with in-dialog codec change", call_with_in_dialog_codec_change), diff --git a/tester/capability_negotiation_tester.cpp b/tester/capability_negotiation_tester.cpp index 99467e0d14..aac09f155a 100644 --- a/tester/capability_negotiation_tester.cpp +++ b/tester/capability_negotiation_tester.cpp @@ -195,8 +195,10 @@ LinphoneCoreManager *create_core_mgr_with_capability_negotiation_setup(const cha #ifdef VIDEO_ENABLED // important: VP8 has really poor performances with the mire camera, at least // on iOS - so when ever h264 is available, let's use it instead - if (linphone_core_get_payload_type(mgr->lc, "h264", -1, -1) != NULL) { + LinphonePayloadType *h264_payload = linphone_core_get_payload_type(mgr->lc, "h264", -1, -1); + if (h264_payload != NULL) { disable_all_video_codecs_except_one(mgr->lc, "h264"); + linphone_payload_type_unref(h264_payload); } linphone_core_set_video_device(mgr->lc, liblinphone_tester_mire_id); @@ -483,6 +485,8 @@ void pause_resume_calls(LinphoneCoreManager *caller, LinphoneCoreManager *callee LinphoneMediaEncryption callerEncryption = linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)); + ms_message("%s pauses call with %s", linphone_core_get_identity(callee->lc), + linphone_core_get_identity(caller->lc)); // Pause callee call BC_ASSERT_TRUE(pause_call_1(callee, calleeCall, caller, callerCall)); wait_for_until(callee->lc, caller->lc, NULL, 5, 10000); @@ -493,6 +497,8 @@ void pause_resume_calls(LinphoneCoreManager *caller, LinphoneCoreManager *callee stats caller_stat = caller->stat; stats callee_stat = callee->stat; + ms_message("%s resumes call with %s", linphone_core_get_identity(callee->lc), + linphone_core_get_identity(caller->lc)); linphone_call_resume(calleeCall); BC_ASSERT_TRUE(wait_for(callee->lc, caller->lc, &callee->stat.number_of_LinphoneCallStreamsRunning, callee_stat.number_of_LinphoneCallStreamsRunning + 1)); @@ -520,6 +526,8 @@ void pause_resume_calls(LinphoneCoreManager *caller, LinphoneCoreManager *callee check_stream_encryption(calleeCall); // Pause caller call + ms_message("%s pauses call with %s", linphone_core_get_identity(caller->lc), + linphone_core_get_identity(callee->lc)); BC_ASSERT_TRUE(pause_call_1(caller, callerCall, callee, calleeCall)); wait_for_until(callee->lc, caller->lc, NULL, 5, 10000); @@ -529,6 +537,8 @@ void pause_resume_calls(LinphoneCoreManager *caller, LinphoneCoreManager *callee caller_stat = caller->stat; callee_stat = callee->stat; + ms_message("%s resumes call with %s", linphone_core_get_identity(caller->lc), + linphone_core_get_identity(callee->lc)); linphone_call_resume(callerCall); BC_ASSERT_TRUE(wait_for(callee->lc, caller->lc, &callee->stat.number_of_LinphoneCallStreamsRunning, callee_stat.number_of_LinphoneCallStreamsRunning + 1)); -- GitLab