• Andrea Gianarda's avatar
    Conference Factory URI: · 3a43603e
    Andrea Gianarda authored
       Set it as Address in account parameters and core in order to easily
       take advantage of address comparison, parameter management and
       compliance with RFC3261
    
    Conference:
      Allow applications to directly mute licrophone and get input device
      volume through the conference object.
      This will ensure that whatever type of confenrece is and regardless if the
      device is hosting or being a participant, the application will have only
      one interface to use and the SDK will work under the hood.
    
    Deprecated methods:
      Delete linphone_core_mute_mic and linphone_core_is_mic_muted
      Add LINPHONE_DEPRECATED to deprecated Account parameter methods
    
    Tester:
      Pass conference factory uri to ClientConference constructor instead of
      focus identity
    
    Memory leaks:
      Free data of list returned by linphone_friend_get_phone_numbers
    3a43603e
local_secure_chat_tester.cpp 19.74 KiB
/*
 * copyright (c) 2010-2023 belledonne communications sarl.
 * This file is part of Liblinphone
 * (see https://gitlab.linphone.org/BC/public/liblinphone).
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "conference/participant.h"
#include "liblinphone_tester.h"
#include "local_conference_tester_functions.h"
namespace LinphoneTest {
static void secure_group_chat_room_with_client_restart(void) {
	group_chat_room_with_client_restart_base(true);
static void secure_group_chat_room_with_invite_error(void) {
	group_chat_room_with_sip_errors_base(true, false, true);
static void secure_group_chat_room_with_subscribe_error(void) {
	group_chat_room_with_sip_errors_base(false, true, true);
static void secure_group_chat_room_with_chat_room_deleted_before_server_restart(void) {
	Focus focus("chloe_rc");
	{ // to make sure focus is destroyed after clients.
		ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), true);
		ClientConference marie2("marie_rc", focus.getConferenceFactoryAddress(), true);
		ClientConference michelle("michelle_rc", focus.getConferenceFactoryAddress(), true);
		ClientConference michelle2("michelle_rc", focus.getConferenceFactoryAddress(), true);
		stats initialFocusStats = focus.getStats();
		stats initialMarieStats = marie.getStats();
		stats initialMarie2Stats = marie2.getStats();
		stats initialMichelleStats = michelle.getStats();
		stats initialMichelle2Stats = michelle2.getStats();
		bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc());
		coresList = bctbx_list_append(coresList, marie.getLc());
		coresList = bctbx_list_append(coresList, marie2.getLc());
		coresList = bctbx_list_append(coresList, michelle.getLc());
		coresList = bctbx_list_append(coresList, michelle2.getLc());
		BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_X3dhUserCreationSuccess,
		                             initialMarieStats.number_of_X3dhUserCreationSuccess + 1,
		                             x3dhServer_creationTimeout));
		BC_ASSERT_TRUE(wait_for_list(coresList, &marie2.getStats().number_of_X3dhUserCreationSuccess,
		                             initialMarie2Stats.number_of_X3dhUserCreationSuccess + 1,
		                             x3dhServer_creationTimeout));
		BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_X3dhUserCreationSuccess,
		                             initialMichelleStats.number_of_X3dhUserCreationSuccess + 1,
		                             x3dhServer_creationTimeout));
		BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_X3dhUserCreationSuccess,
		                             initialMichelle2Stats.number_of_X3dhUserCreationSuccess + 1,
		                             x3dhServer_creationTimeout));
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie2.getLc())); BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle.getLc())); BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle2.getLc())); focus.registerAsParticipantDevice(marie); focus.registerAsParticipantDevice(marie2); focus.registerAsParticipantDevice(michelle); focus.registerAsParticipantDevice(michelle2); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie.getLc())); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie2.getLc())); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(michelle.getLc())); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(michelle2.getLc())); bctbx_list_t *participantsAddresses = NULL; Address michelleAddr = michelle.getIdentity(); participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(michelleAddr.toC())); Address michelle2Addr = michelle2.getIdentity(); participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(michelle2Addr.toC())); const char *initialSubject = "Colleagues (characters: $ £ çà)"; LinphoneChatRoomParams *params = linphone_core_create_default_chat_room_params(marie.getLc()); linphone_chat_room_params_enable_encryption(params, TRUE); linphone_chat_room_params_set_ephemeral_mode(params, LinphoneChatRoomEphemeralModeDeviceManaged); linphone_chat_room_params_set_backend(params, LinphoneChatRoomBackendFlexisipChat); linphone_chat_room_params_enable_group(params, FALSE); LinphoneChatRoom *marieCr = linphone_core_create_chat_room_2(marie.getLc(), params, initialSubject, participantsAddresses); linphone_chat_room_params_unref(params); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([&focus] { return focus.getCore().getChatRooms().size() == 1; })); for (auto chatRoom : focus.getCore().getChatRooms()) { linphone_chat_room_set_user_data(L_GET_C_BACK_PTR(chatRoom), marie.getCMgr()); } BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participants_added, initialFocusStats.number_of_participants_added + 1, 5000)); BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participant_devices_added, initialFocusStats.number_of_participant_devices_added + 2, 5000)); check_create_chat_room_client_side(coresList, marie.getCMgr(), marieCr, &initialMarieStats, participantsAddresses, initialSubject, 1); const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); // Check that the chat room is correctly created on Pauline's and Michelle's side and that the participants are // added LinphoneChatRoom *marie2Cr = check_creation_chat_room_client_side( coresList, marie2.getCMgr(), &initialMarie2Stats, confAddr, initialSubject, 1, FALSE); LinphoneChatRoom *michelleCr = check_creation_chat_room_client_side( coresList, michelle.getCMgr(), &initialMichelleStats, confAddr, initialSubject, 1, FALSE); LinphoneChatRoom *michelle2Cr = check_creation_chat_room_client_side( coresList, michelle2.getCMgr(), &initialMichelle2Stats, confAddr, initialSubject, 1, FALSE); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneConferenceStateCreated, initialMichelleStats.number_of_LinphoneConferenceStateCreated + 1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateCreated, initialMichelle2Stats.number_of_LinphoneConferenceStateCreated + 1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateCreated, initialMarieStats.number_of_LinphoneConferenceStateCreated + 1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &marie2.getStats().number_of_LinphoneConferenceStateCreated, initialMarie2Stats.number_of_LinphoneConferenceStateCreated + 1,
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
liblinphone_tester_sip_timeout)); // Send a few messages std::string msg_text = "message marie2 blabla"; LinphoneChatMessage *msg = ClientConference::sendTextMsg(marie2Cr, msg_text); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([msg] { return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); })); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([michelleCr] { return linphone_chat_room_get_unread_messages_count(michelleCr) == 1; })); LinphoneChatMessage *michelleLastMsg = michelle.getStats().last_received_chat_message; BC_ASSERT_PTR_NOT_NULL(michelleLastMsg); if (michelleLastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(michelleLastMsg), msg_text.c_str()); } linphone_chat_room_mark_as_read(michelleCr); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([michelle2Cr] { return linphone_chat_room_get_unread_messages_count(michelle2Cr) == 1; })); LinphoneChatMessage *michelle2LastMsg = michelle2.getStats().last_received_chat_message; BC_ASSERT_PTR_NOT_NULL(michelle2LastMsg); if (michelle2LastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(michelle2LastMsg), msg_text.c_str()); } linphone_chat_room_mark_as_read(michelle2Cr); linphone_chat_room_mark_as_read(marieCr); BC_ASSERT_TRUE(wait_for_list(coresList, &marie2.getStats().number_of_LinphoneMessageDisplayed, initialMarie2Stats.number_of_LinphoneMessageDisplayed + 1, liblinphone_tester_sip_timeout)); linphone_chat_message_unref(msg); msg = nullptr; msg_text = "message marie blabla"; msg = ClientConference::sendTextMsg(marieCr, msg_text); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([msg] { return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); })); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([michelleCr] { return linphone_chat_room_get_unread_messages_count(michelleCr) == 1; })); michelleLastMsg = michelle.getStats().last_received_chat_message; if (michelleLastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(michelleLastMsg), msg_text.c_str()); } BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([michelle2Cr] { return linphone_chat_room_get_unread_messages_count(michelle2Cr) == 1; })); michelle2LastMsg = michelle2.getStats().last_received_chat_message; BC_ASSERT_PTR_NOT_NULL(michelle2LastMsg); if (michelle2LastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(michelle2LastMsg), msg_text.c_str()); } linphone_chat_room_mark_as_read(marie2Cr); linphone_chat_room_mark_as_read(michelleCr); linphone_chat_room_mark_as_read(michelle2Cr); BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneMessageDisplayed, initialMarieStats.number_of_LinphoneMessageDisplayed + 1, liblinphone_tester_sip_timeout)); linphone_chat_message_unref(msg); msg = nullptr; msg_text = "message michelle2 blabla";
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
msg = ClientConference::sendTextMsg(michelle2Cr, msg_text); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([msg] { return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); })); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([marieCr] { return linphone_chat_room_get_unread_messages_count(marieCr) == 1; })); LinphoneChatMessage *marieLastMsg = marie.getStats().last_received_chat_message; BC_ASSERT_PTR_NOT_NULL(marieLastMsg); if (marieLastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(marieLastMsg), msg_text.c_str()); } BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([marie2Cr] { return linphone_chat_room_get_unread_messages_count(marie2Cr) == 1; })); LinphoneChatMessage *marie2LastMsg = marie2.getStats().last_received_chat_message; BC_ASSERT_PTR_NOT_NULL(marie2LastMsg); if (marie2LastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(marie2LastMsg), msg_text.c_str()); } linphone_chat_room_mark_as_read(michelleCr); linphone_chat_room_mark_as_read(marieCr); linphone_chat_room_mark_as_read(marie2Cr); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneMessageDisplayed, initialMichelle2Stats.number_of_LinphoneMessageDisplayed + 1, liblinphone_tester_sip_timeout)); linphone_chat_message_unref(msg); msg = nullptr; // Marie deletes the chat room char *confAddrStr = (confAddr) ? linphone_address_as_string(confAddr) : ms_strdup("<unknown>"); ms_message("%s deletes chat room %s", linphone_core_get_identity(marie.getLc()), confAddrStr); ms_free(confAddrStr); linphone_core_manager_delete_chat_room(marie.getCMgr(), marieCr, coresList); BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateTerminated, initialMarieStats.number_of_LinphoneConferenceStateTerminated + 1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneConferenceStateTerminated, initialMichelleStats.number_of_LinphoneConferenceStateTerminated + 1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateTerminated, initialMichelle2Stats.number_of_LinphoneConferenceStateTerminated + 1, liblinphone_tester_sip_timeout)); // wait bit more to detect side effect if any CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).waitUntil(chrono::seconds(5), [] { return false; }); ms_message("%s is restarting its core", linphone_core_get_identity(focus.getLc())); coresList = bctbx_list_remove(coresList, focus.getLc()); // Restart flexisip focus.reStart(); coresList = bctbx_list_append(coresList, focus.getLc()); // wait bit more to detect side effect if any CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).waitUntil(chrono::seconds(5), [] { return false; }); msg_text = "Cou cou Marieeee....."; msg = ClientConference::sendTextMsg(michelle2Cr, msg_text); BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateCreated, initialMarieStats.number_of_LinphoneConferenceStateCreated + 2,
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneConferenceStateCreated, initialMichelleStats.number_of_LinphoneConferenceStateCreated + 2, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateCreated, initialMichelle2Stats.number_of_LinphoneConferenceStateCreated + 2, liblinphone_tester_sip_timeout)); confAddr = linphone_chat_room_get_conference_address(michelle2Cr); marieCr = check_creation_chat_room_client_side(coresList, marie.getCMgr(), &initialMarieStats, confAddr, initialSubject, 1, FALSE); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([msg] { return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); })); BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([marieCr] { return linphone_chat_room_get_unread_messages_count(marieCr) == 1; })); marieLastMsg = marie.getStats().last_received_chat_message; BC_ASSERT_PTR_NOT_NULL(marieLastMsg); if (marieLastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(marieLastMsg), msg_text.c_str()); } BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([marie2Cr] { return linphone_chat_room_get_unread_messages_count(marie2Cr) == 1; })); marie2LastMsg = marie2.getStats().last_received_chat_message; BC_ASSERT_PTR_NOT_NULL(marie2LastMsg); if (marie2LastMsg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(marie2LastMsg), msg_text.c_str()); } linphone_chat_room_mark_as_read(michelleCr); linphone_chat_room_mark_as_read(marieCr); linphone_chat_room_mark_as_read(marie2Cr); BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneMessageDisplayed, initialMichelle2Stats.number_of_LinphoneMessageDisplayed + 1, liblinphone_tester_sip_timeout)); for (auto chatRoom : focus.getCore().getChatRooms()) { for (auto participant : chatRoom->getParticipants()) { // force deletion by removing devices std::shared_ptr<Address> participantAddress = participant->getAddress(); linphone_chat_room_set_participant_devices(L_GET_C_BACK_PTR(chatRoom), participantAddress->toC(), NULL); } } // wait until chatroom is deleted server side BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).wait([&focus] { return focus.getCore().getChatRooms().size() == 0; })); // wait bit more to detect side effect if any CoreManagerAssert({focus, marie, marie2, michelle, michelle2}).waitUntil(chrono::seconds(2), [] { return false; }); // to avoid creation attempt of a new chatroom LinphoneProxyConfig *config = linphone_core_get_default_proxy_config(focus.getLc()); linphone_proxy_config_edit(config); linphone_proxy_config_set_conference_factory_uri(config, NULL); linphone_proxy_config_done(config); bctbx_list_free(coresList); } }
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
static void group_chat_room_lime_server_encrypted_message(void) { group_chat_room_lime_server_message(TRUE); } static void secure_one_to_one_group_chat_room_deletion_by_server_client(void) { one_to_one_group_chat_room_deletion_by_server_client_base(TRUE); } } // namespace LinphoneTest static test_t local_conference_secure_chat_tests[] = { TEST_ONE_TAG("Secure Group chat with client restart", LinphoneTest::secure_group_chat_room_with_client_restart, "LeaksMemory"), /* beacause of coreMgr restart*/ TEST_NO_TAG("Secure group chat with INVITE session error", LinphoneTest::secure_group_chat_room_with_invite_error), TEST_NO_TAG("Secure group chat with SUBSCRIBE session error", LinphoneTest::secure_group_chat_room_with_subscribe_error), TEST_ONE_TAG("Secure group chat with chat room deleted before server restart", LinphoneTest::secure_group_chat_room_with_chat_room_deleted_before_server_restart, "LeaksMemory"), /* because of network up and down */ TEST_ONE_TAG("Secure one to one group chat deletion initiated by server and client", LinphoneTest::secure_one_to_one_group_chat_room_deletion_by_server_client, "LeaksMemory"), /* because of network up and down */ TEST_NO_TAG("Group chat Lime Server chat room encrypted message", LinphoneTest::group_chat_room_lime_server_encrypted_message)}; test_suite_t local_conference_test_suite_secure_chat = {"Local conference tester (Secure Chat)", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, sizeof(local_conference_secure_chat_tests) / sizeof(local_conference_secure_chat_tests[0]), local_conference_secure_chat_tests, 0};