diff --git a/coreapi/remote_conference.cpp b/coreapi/remote_conference.cpp index 6f9bccbaa23d2e46561d44cefce8b842d63d9d59..56de53f6ee45a6c789271e79877221c514cf273f 100644 --- a/coreapi/remote_conference.cpp +++ b/coreapi/remote_conference.cpp @@ -966,9 +966,11 @@ void RemoteConference::onFocusCallStateChanged(LinphoneCallState state) { } const auto &confState = ref->getState(); - // Do not send updates if the conference is ending or about to end + auto ms = static_pointer_cast<MediaSession>(session); + // Do not send updates if the conference is ending or about to end or the call is in temporary state if ((confState != ConferenceInterface::State::Terminated) && - (confState != ConferenceInterface::State::TerminationPending) && scheduleUpdate) { + (confState != ConferenceInterface::State::TerminationPending) && scheduleUpdate && + ms->getPrivate()->canSoundResourcesBeFreed()) { lInfo() << "Executing scheduled update of the focus session of conference " << (getConferenceAddress() ? getConferenceAddress()->toString() : std::string("<address-not-defined>")); if (updateMainSession() == 0) { @@ -1372,6 +1374,7 @@ void RemoteConference::onParticipantDeviceRemoved( auto session = static_pointer_cast<MediaSession>(getMainSession()); const MediaSessionParams *params = session->getMediaParams(); + const auto &deviceAddress = device->getAddress(); const auto &confSecurityLevel = confParams->getSecurityLevel(); const auto &audioAvailable = device->getStreamAvailability(LinphoneStreamTypeAudio); const auto audioNeedsReInvite = ((confSecurityLevel == ConferenceParams::SecurityLevel::EndToEnd) && @@ -1380,13 +1383,13 @@ void RemoteConference::onParticipantDeviceRemoved( const auto videoNeedsReInvite = (confParams->videoEnabled() && params->videoEnabled()); if ((audioNeedsReInvite || videoNeedsReInvite) && (getState() == ConferenceInterface::State::Created) && - !isMe(device->getAddress()) && (device->getTimeOfJoining() >= 0)) { - auto updateSession = [this, device]() -> LinphoneStatus { - lInfo() << "Sending re-INVITE in order to update streams because participant device " - << *device->getAddress() << " has been removed from conference " << *getConferenceAddress(); + !isMe(deviceAddress) && (device->getTimeOfJoining() >= 0)) { + auto updateSession = [this, deviceAddress]() -> LinphoneStatus { + lInfo() << "Sending re-INVITE in order to update streams because participant device " << *deviceAddress + << " has been removed from conference " << *getConferenceAddress(); auto ret = updateMainSession(); if (ret != 0) { - lInfo() << "re-INVITE to update streams because participant device " << *device->getAddress() + lInfo() << "re-INVITE to update streams because participant device " << *deviceAddress << " has been removed from conference " << *getConferenceAddress() << " cannot be sent right now"; } diff --git a/src/c-wrapper/internal/c-tools.h b/src/c-wrapper/internal/c-tools.h index 40675027b896e862cad8cb9ba2e0249e7e5cb769..77e692fc9de423d1228b106d682c56cce92c6746 100644 --- a/src/c-wrapper/internal/c-tools.h +++ b/src/c-wrapper/internal/c-tools.h @@ -367,6 +367,11 @@ public: WrappedBaseObject<CppType> *wrappedObject = reinterpret_cast<WrappedBaseObject<CppType> *>(cObject); std::shared_ptr<CppType> oldCppObject; + // Keep the pointer to the memory address of the old C pointer in order to free it should it be needed + void *value = cppObject->getCBackPtr(); + if (value && static_cast<WrappedBaseObject<CppType> *>(value)->owner == WrappedObjectOwner::Internal) + belle_sip_object_unref(value); + if (wrappedObject->owner == WrappedObjectOwner::Internal) { oldCppObject = wrappedObject->weakCppPtr.lock(); wrappedObject->weakCppPtr = cppObject; @@ -395,6 +400,11 @@ public: if (reinterpret_cast<WrappedClonableObject<CppType> *>(cObject)->owner == WrappedObjectOwner::External) delete *cppObjectAddr; + // Keep the pointer to the memory address of the old C pointer in order to free it should it be needed + void *value = cppObject->getCBackPtr(); + if (value && static_cast<WrappedBaseObject<CppType> *>(value)->owner == WrappedObjectOwner::Internal) + belle_sip_object_unref(value); + *cppObjectAddr = cppObject; (*cppObjectAddr)->setCBackPtr(cObject); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 6bf0e6659a8ea998a01d1a9b268ce4739032aefd..b2ac30b9b1161d636e5164abb80b41be93c383d9 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -1732,9 +1732,11 @@ list<ParticipantImdnState> ChatMessage::getParticipantsByImdnState(ChatMessage:: unique_ptr<MainDb> &mainDb = chatRoom->getCore()->getPrivate()->mainDb; shared_ptr<EventLog> eventLog = mainDb->getEvent(mainDb, getStorageId()); list<MainDb::ParticipantState> dbResults = mainDb->getChatMessageParticipantsByImdnState(eventLog, state); - auto sender = chatRoom->findParticipant(getFromAddress()); + const auto &from = getFromAddress(); + auto sender = chatRoom->isMe(from) ? chatRoom->getMe() : chatRoom->findParticipant(from); for (const auto &dbResult : dbResults) { - auto participant = chatRoom->findParticipant(dbResult.address); + const auto &pAddress = dbResult.address; + auto participant = chatRoom->isMe(pAddress) ? chatRoom->getMe() : chatRoom->findParticipant(pAddress); if (participant && (participant != sender)) result.emplace_back(participant, dbResult.state, dbResult.timestamp); } diff --git a/src/chat/chat-room/server-group-chat-room.cpp b/src/chat/chat-room/server-group-chat-room.cpp index 115f9adc5539cdf8932d6db35223bf5eefa14cc9..eeb6407e1e14acf5ed6d286bc604854b390d94d3 100644 --- a/src/chat/chat-room/server-group-chat-room.cpp +++ b/src/chat/chat-room/server-group-chat-room.cpp @@ -1566,16 +1566,14 @@ ServerGroupChatRoom::ServerGroupChatRoom(const shared_ptr<Core> &core, ServerGroupChatRoom::~ServerGroupChatRoom() { lInfo() << this << " destroyed."; - if (getConference()->getConferenceId().isValid()) { - try { - if (getCore()->getPrivate()->localListEventHandler) { - getCore()->getPrivate()->localListEventHandler->removeHandler( - static_pointer_cast<LocalConference>(getConference())->eventHandler.get()); - } - getCore()->getPrivate()->unregisterListener(this); - } catch (const bad_weak_ptr &) { - // Unable to unregister listener here. Core is destroyed and the listener doesn't exist. + try { + if (getCore()->getPrivate()->localListEventHandler) { + getCore()->getPrivate()->localListEventHandler->removeHandler( + static_pointer_cast<LocalConference>(getConference())->eventHandler.get()); } + getCore()->getPrivate()->unregisterListener(this); + } catch (const bad_weak_ptr &) { + // Unable to unregister listener here. Core is destroyed and the listener doesn't exist. } }; diff --git a/src/conference/handlers/local-conference-event-handler.cpp b/src/conference/handlers/local-conference-event-handler.cpp index 80a4d80a7af9743489fdb919aea7f0eed4cc0154..c631121259960b49f32d7d437154eed6aed30aab 100644 --- a/src/conference/handlers/local-conference-event-handler.cpp +++ b/src/conference/handlers/local-conference-event-handler.cpp @@ -1021,11 +1021,11 @@ LinphoneStatus LocalConferenceEventHandler::subscribeReceived(const shared_ptr<E oldEv->terminate(); } if ((evLastNotify == 0) || (deviceState == ParticipantDevice::State::Joining)) { - lInfo() << "Sending initial notify of conference [" << conf->getConferenceAddress() + lInfo() << "Sending initial notify of conference [" << conferenceAddressString << "] to: " << *device->getAddress() << " with last notif set to " << conf->getLastNotify(); if (deviceState == ParticipantDevice::State::Present) { lInfo() << "Device " << *device->getAddress() << " is already part of conference [" - << conf->getConferenceAddress() + << conferenceAddressString << "] hence send full state to be sure the client and the server are on the same page"; } else { conf->setLastNotify(lastNotify + 1); @@ -1042,7 +1042,7 @@ LinphoneStatus LocalConferenceEventHandler::subscribeReceived(const shared_ptr<E } } else if (evLastNotify < lastNotify) { lInfo() << "Sending all missed notify [" << evLastNotify << "-" << lastNotify << "] for conference [" - << conf->getConferenceAddress() << "] to: " << *participant->getAddress(); + << conferenceAddressString << "] to: " << *participant->getAddress(); const int fullStateTrigger = linphone_config_get_int(linphone_core_get_config(conf->getCore()->getCCore()), "misc", @@ -1059,7 +1059,7 @@ LinphoneStatus LocalConferenceEventHandler::subscribeReceived(const shared_ptr<E } } else if (evLastNotify > lastNotify) { lWarning() << "Last notify received by client [" << evLastNotify << "] for conference [" - << conf->getConferenceAddress() << "] should not be higher than last notify sent by server [" + << conferenceAddressString << "] should not be higher than last notify sent by server [" << lastNotify << "] - sending a notify full state in an attempt to recover from this situation"; notifyFullState(createNotifyFullState(ev), device); } else { diff --git a/src/nat/ice-service.cpp b/src/nat/ice-service.cpp index 15fe6c780058dec9408b886aec7e7fd11be8aba0..a559808b929f60a9ae666b1a62bafdde983b3493 100644 --- a/src/nat/ice-service.cpp +++ b/src/nat/ice-service.cpp @@ -551,20 +551,26 @@ void IceService::updateFromRemoteMediaDescription(const std::shared_ptr<SalMedia // Create ICE check lists if needed and parse ICE attributes. createIceCheckListsAndParseIceAttributes(remoteDesc, iceRestarted); - for (size_t i = 0; i < remoteDesc->streams.size(); i++) { - const auto &remoteDescStream = remoteDesc->streams[i]; + size_t i; + for (i = 0; i < mStreamsGroup.getStreams().size(); i++) { IceCheckList *cl = ice_session_check_list(mIceSession, (int)i); if (!cl) continue; - if (!remoteDescStream.enabled() || (remoteDescStream.getRtpPort() == 0) || - (remoteDescStream.getDirection() == SalStreamInactive)) { - /* - * rtp_port == 0 is true when it is a secondary stream part of bundle. - */ - ice_session_remove_check_list_from_idx(mIceSession, static_cast<unsigned int>(i)); - auto stream = mStreamsGroup.getStream(i); - stream->setIceCheckList(nullptr); - stream->iceStateChanged(); + if (i < remoteDesc->streams.size()) { + const auto &remoteDescStream = remoteDesc->streams[i]; + if (remoteDescStream.enabled() && remoteDescStream.getRtpPort() != 0 && + remoteDescStream.getDirection() != SalStreamInactive) { + /* + * rtp_port == 0 is true when it is a secondary stream part of bundle. + */ + /* Stream still needs ICE */ + continue; + } } + /* This stream is unused or no longer needs ICE, remove its check list */ + ice_session_remove_check_list_from_idx(mIceSession, static_cast<unsigned int>(i)); + auto stream = mStreamsGroup.getStream(i); + stream->setIceCheckList(nullptr); + stream->iceStateChanged(); } clearUnusedIceCandidates(localDesc, remoteDesc, !isOffer); ice_session_check_mismatch(mIceSession); diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 4f999fbfa3d9908faa18c637283ad82de1eb4d12..dcf24fc11dd6bf56f33131a36462c380efe33683 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -278,6 +278,7 @@ set(SOURCE_FILES_C tunnel_tester.c vcard_tester.c video_quality_tester.c + local_chat_tester_functions.cpp local_conference_tester_functions.cpp local_scheduled_conference_tester.cpp local_ice_conference_tester.cpp diff --git a/tester/audio-quality-tester.cpp b/tester/audio-quality-tester.cpp index 6c809e66da1ba9d697f6d9a1cf9a64c0a9380861..24a4f08f837ac531903a7989b5f5d7df418f4894 100644 --- a/tester/audio-quality-tester.cpp +++ b/tester/audio-quality-tester.cpp @@ -498,4 +498,5 @@ test_suite_t audio_quality_test_suite = {"Audio Call quality", liblinphone_tester_after_each, sizeof(audio_quality_tests) / sizeof(audio_quality_tests[0]), audio_quality_tests, - 750}; + 750, + 2}; diff --git a/tester/audio_video_conference_tester.c b/tester/audio_video_conference_tester.c index 059f022d08d577dd82bb828ecd6bfc17f961fc7d..d8bcc1dcbaac70c241e176525f8faff0b516a3d1 100644 --- a/tester/audio_video_conference_tester.c +++ b/tester/audio_video_conference_tester.c @@ -12472,7 +12472,8 @@ test_suite_t audio_video_conference_basic_test_suite = {"Audio video conference sizeof(audio_video_conference_basic_tests) / sizeof(audio_video_conference_basic_tests[0]), audio_video_conference_basic_tests, - 0}; + 0, + 4}; test_suite_t audio_video_conference_basic2_test_suite = {"Audio video conference 2 (Basic)", NULL, @@ -12482,7 +12483,8 @@ test_suite_t audio_video_conference_basic2_test_suite = {"Audio video conference sizeof(audio_video_conference_basic2_tests) / sizeof(audio_video_conference_basic2_tests[0]), audio_video_conference_basic2_tests, - 0}; + 0, + 4}; test_suite_t audio_conference_test_suite = {"Audio conference", NULL, @@ -12491,7 +12493,8 @@ test_suite_t audio_conference_test_suite = {"Audio conference", liblinphone_tester_after_each, sizeof(audio_conference_tests) / sizeof(audio_conference_tests[0]), audio_conference_tests, - 0}; + 0, + 2}; test_suite_t audio_conference_local_participant_test_suite = {"Audio conference (Local participant)", NULL, @@ -12501,6 +12504,7 @@ test_suite_t audio_conference_local_participant_test_suite = {"Audio conference sizeof(audio_conference_local_participant_tests) / sizeof(audio_conference_local_participant_tests[0]), audio_conference_local_participant_tests, + 0, 0}; test_suite_t audio_conference_remote_participant_test_suite = {"Audio conference (Remote participant)", @@ -12511,6 +12515,7 @@ test_suite_t audio_conference_remote_participant_test_suite = {"Audio conference sizeof(audio_conference_remote_participant_tests) / sizeof(audio_conference_remote_participant_tests[0]), audio_conference_remote_participant_tests, + 0, 0}; test_suite_t video_conference_test_suite = {"Video conference", @@ -12520,7 +12525,8 @@ test_suite_t video_conference_test_suite = {"Video conference", liblinphone_tester_after_each, sizeof(video_conference_tests) / sizeof(video_conference_tests[0]), video_conference_tests, - 0}; + 0, + 4}; test_suite_t video_conference_layout_test_suite = {"Video conference (Layout)", NULL, @@ -12530,7 +12536,8 @@ test_suite_t video_conference_layout_test_suite = {"Video conference (Layout)", sizeof(video_conference_layout_tests) / sizeof(video_conference_layout_tests[0]), video_conference_layout_tests, - 0}; + 0, + 4}; test_suite_t ice_conference_test_suite = {"ICE conference", NULL, @@ -12539,4 +12546,5 @@ test_suite_t ice_conference_test_suite = {"ICE conference", liblinphone_tester_after_each, sizeof(ice_conference_tests) / sizeof(ice_conference_tests[0]), ice_conference_tests, - 0}; + 0, + 4}; diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c index e377f4d374d29344fb9451242a1ab9c160d93a85..7a6636c010223fb5c906da5f628223293677ea6b 100644 --- a/tester/group_chat_tester.c +++ b/tester/group_chat_tester.c @@ -706,7 +706,7 @@ void check_create_chat_room_client_side(bctbx_list_t *lcs, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomConferenceJoined, initialStats->number_of_LinphoneChatRoomConferenceJoined + 1, - liblinphone_tester_sip_timeout)); + 2 * liblinphone_tester_sip_timeout)); // FIXME: Small hack to handle situation where the core resubscribes to the chat room wait_for_list(lcs, NULL, 0, 1000); @@ -9124,7 +9124,7 @@ test_t group_chat4_tests[] = { TEST_NO_TAG("Send refer to all participants devices", group_chat_room_send_refer_to_all_devices), TEST_NO_TAG("Admin add device and doesn't lose admin status", group_chat_room_add_device), TEST_NO_TAG("Send multiple is composing", multiple_is_composing_notification), - TEST_ONE_TAG("Fallback to basic chat room", group_chat_room_fallback_to_basic_chat_room, "LeaksMemory"), + TEST_NO_TAG("Fallback to basic chat room", group_chat_room_fallback_to_basic_chat_room), TEST_NO_TAG("Group chat room creation fails if invited participants don't support it", group_chat_room_creation_fails_if_invited_participants_dont_support_it), TEST_NO_TAG("Group chat room creation successful if at least one invited participant supports it", diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 7f0b13b8eaab09f7b4fdddd034d63b75a99aaf67..8f7865b4063e2218c6807e5c71d97e4dffe829f4 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -483,7 +483,7 @@ void liblinphone_tester_add_suite_with_default_time(test_suite_t *suite, int ave } void liblinphone_tester_add_suites(void) { - liblinphone_tester_add_suite_with_default_time(&setup_test_suite, 157); + liblinphone_tester_add_suite_with_default_time(&setup_test_suite, 282); liblinphone_tester_add_suite_with_default_time(®ister_test_suite, 267); #ifdef HAVE_ADVANCED_IM liblinphone_tester_add_suite_with_default_time(&group_chat_test_suite, 230); @@ -507,7 +507,8 @@ void liblinphone_tester_add_suites(void) { liblinphone_tester_add_suite_with_default_time( &local_conference_test_suite_scheduled_conference_audio_only_participant, 581); liblinphone_tester_add_suite_with_default_time(&local_conference_test_suite_scheduled_ice_conference, 563); - liblinphone_tester_add_suite_with_default_time(&local_conference_test_suite_inpromptu_conference, 504); + liblinphone_tester_add_suite_with_default_time(&local_conference_test_suite_inpromptu_conference, 384); + liblinphone_tester_add_suite_with_default_time(&local_conference_test_suite_encrypted_inpromptu_conference, 150); liblinphone_tester_add_suite_with_default_time(&local_conference_test_suite_inpromptu_mismatch_conference, 210); liblinphone_tester_add_suite_with_default_time(&local_conference_test_suite_chat_basic, 481); liblinphone_tester_add_suite_with_default_time(&local_conference_test_suite_chat_advanced, 300); @@ -598,7 +599,7 @@ void liblinphone_tester_add_suites(void) { liblinphone_tester_add_suite_with_default_time(&complex_sip_call_test_suite, 0); #endif #ifdef VCARD_ENABLED - liblinphone_tester_add_suite_with_default_time(&vcard_test_suite, 58); + liblinphone_tester_add_suite_with_default_time(&vcard_test_suite, 210); #endif liblinphone_tester_add_suite_with_default_time(&utils_test_suite, 0); liblinphone_tester_add_suite_with_default_time(&call_with_rtp_bundle_test_suite, 148); @@ -628,7 +629,7 @@ void liblinphone_tester_init(void (*ftester_printf)(int level, const char *fmt, bc_tester_init(ftester_printf, ORTP_MESSAGE, ORTP_ERROR, "rcfiles"); liblinphone_tester_add_suites(); bc_tester_set_max_parallel_suites(32); /* empiricaly defined as sustainable for our lab 12 threads machine.*/ - bc_tester_set_global_timeout(20 * 60); /* 20 mn max */ + bc_tester_set_global_timeout(30 * 60); /* 20 mn max */ } int liblinphone_tester_set_log_file(const char *filename) { diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 230fb257bf7cdce4058cc18907a2ec9b82e90ec3..a9705b971ab76ae13d3440add4fcce15ff7331aa 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -147,6 +147,7 @@ extern test_suite_t local_conference_test_suite_scheduled_conference_advanced; extern test_suite_t local_conference_test_suite_scheduled_conference_audio_only_participant; extern test_suite_t local_conference_test_suite_scheduled_ice_conference; extern test_suite_t local_conference_test_suite_inpromptu_conference; +extern test_suite_t local_conference_test_suite_encrypted_inpromptu_conference; extern test_suite_t local_conference_test_suite_inpromptu_mismatch_conference; extern test_suite_t external_domain_test_suite; extern test_suite_t potential_configuration_graph_test_suite; @@ -937,7 +938,7 @@ create_mgr_for_conference(const char *rc_file, bool_t check_for_proxies, const c void setup_mgr_for_conference(LinphoneCoreManager *mgr, const char *conference_version); void setup_conference_info_cbs(LinphoneCoreManager *mgr); void destroy_mgr_in_conference(LinphoneCoreManager *mgr); -void check_conference_ssrc(LinphoneConference *local_conference, LinphoneConference *remote_conference); +bool check_conference_ssrc(LinphoneConference *local_conference, LinphoneConference *remote_conference); void check_conference_medias(LinphoneConference *local_conference, LinphoneConference *remote_conference); LinphoneStatus add_participant_to_local_conference_through_invite(bctbx_list_t *lcs, LinphoneCoreManager *conf_mgr, diff --git a/tester/local_chat_imdn_tester.cpp b/tester/local_chat_imdn_tester.cpp index f4362cd301ab11c7962861c99a6cbf016fe82ec9..30cb45194093728333200348dd2d027b5031855b 100644 --- a/tester/local_chat_imdn_tester.cpp +++ b/tester/local_chat_imdn_tester.cpp @@ -537,8 +537,7 @@ group_chat_room_with_client_idmn_after_restart_base(bool_t encrypted, bool_t add if (lastMsg) { bctbx_list_t *displayed_list = linphone_chat_message_get_participants_by_imdn_state( lastMsg, LinphoneChatMessageStateDisplayed); - const size_t expected_displayed_number = - ((client->lc == pauline.getLc()) ? 2 : 1) + (add_participant ? 1 : 0); + size_t expected_displayed_number = 2 + (add_participant ? 1 : 0); ret &= (bctbx_list_size(displayed_list) == expected_displayed_number); bctbx_list_free_with_data(displayed_list, (bctbx_list_free_func)linphone_participant_imdn_state_unref); @@ -601,7 +600,7 @@ group_chat_room_with_client_idmn_after_restart_base(bool_t encrypted, bool_t add laure.getCMgr(), pauline.getCMgr()}) { BC_ASSERT_TRUE( CoreManagerAssert({focus, marie, michelle, michelle2, berthe, laure, pauline}) - .wait([client, &berthe, &pauline, &add_participant, &confAddr] { + .wait([client, &berthe, &add_participant, &confAddr] { const LinphoneAddress *deviceAddr = linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(client->lc)); LinphoneChatRoom *cr = @@ -615,8 +614,7 @@ group_chat_room_with_client_idmn_after_restart_base(bool_t encrypted, bool_t add if (lastMsg) { bctbx_list_t *displayed_list = linphone_chat_message_get_participants_by_imdn_state( lastMsg, LinphoneChatMessageStateDisplayed); - size_t expected_displayed_number = - ((client->lc == pauline.getLc()) ? 3 : 2) + (add_participant ? 1 : 0); + size_t expected_displayed_number = 3 + (add_participant ? 1 : 0); ret &= (bctbx_list_size(displayed_list) == expected_displayed_number); bctbx_list_free_with_data(displayed_list, (bctbx_list_free_func)linphone_participant_imdn_state_unref); diff --git a/tester/local_chat_tester.cpp b/tester/local_chat_tester.cpp index 4c31b50c111a55ee8bf9bf47838faab0790efd87..a4641bc064982c1c6d3f1de3b0d5bbd5e8e4daba 100644 --- a/tester/local_chat_tester.cpp +++ b/tester/local_chat_tester.cpp @@ -885,7 +885,10 @@ static void group_chat_room_with_client_registering_with_short_register_expires( const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores{focus, marie, michelle, berthe}; for (const ConfCoreManager &core : cores) { - BC_ASSERT_TRUE(checkChatroom(focus, core, -1)); + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, michelle, berthe}).waitUntil(chrono::seconds(10), [&focus, &core] { + return checkChatroom(focus, core, -1); + })); for (auto chatRoom : core.getCore().getChatRooms()) { BC_ASSERT_EQUAL(chatRoom->getParticipants().size(), ((focus.getLc() == core.getLc())) ? 3 : 2, size_t, "%zu"); @@ -1073,12 +1076,18 @@ static void group_chat_room_with_client_restart_removed_from_server(void) { BC_ASSERT_FALSE( wait_for_list(coresList, &michelle.getStats().number_of_LinphoneSubscriptionOutgoingProgress, 2, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneSubscriptionActive, 1, + liblinphone_tester_sip_timeout)); + michelleCr = linphone_core_search_chat_room(michelle.getLc(), NULL, michelleContact, confAddr, NULL); BC_ASSERT_PTR_NOT_NULL(michelleCr); const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores{focus, marie, michelle, berthe}; for (const ConfCoreManager &core : cores) { - BC_ASSERT_TRUE(checkChatroom(focus, core, -1)); + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, michelle, berthe}).waitUntil(chrono::seconds(10), [&focus, &core] { + return checkChatroom(focus, core, -1); + })); for (auto chatRoom : core.getCore().getChatRooms()) { BC_ASSERT_EQUAL(chatRoom->getParticipants().size(), ((focus.getLc() == core.getLc())) ? 3 : 2, size_t, "%zu"); @@ -1405,7 +1414,10 @@ static void group_chat_room_with_client_removed_while_stopped_base(bool_t use_re const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores{focus, marie, berthe, berthe2}; for (const ConfCoreManager &core : cores) { - BC_ASSERT_TRUE(checkChatroom(focus, core, -1)); + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, michelle, berthe}).waitUntil(chrono::seconds(10), [&focus, &core] { + return checkChatroom(focus, core, -1); + })); for (auto chatRoom : core.getCore().getChatRooms()) { BC_ASSERT_EQUAL(chatRoom->getParticipants().size(), ((focus.getLc() == core.getLc())) ? 2 : 1, size_t, "%zu"); @@ -1521,6 +1533,7 @@ static void group_chat_room_with_creator_without_groupchat_capability_in_registe linphone_chat_room_params_set_subject(params, initialSubject); LinphoneChatRoom *marieCr = linphone_core_create_chat_room_6(marie.getLc(), params, NULL, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); linphone_chat_room_params_unref(params); BC_ASSERT_PTR_NOT_NULL(marieCr); // linphone_core_create_chat_room_6 takes a ref to the chatroom @@ -1662,6 +1675,7 @@ static void group_chat_room_with_creator_without_groupchat_capability(void) { linphone_chat_room_params_set_subject(params, initialSubject); LinphoneChatRoom *chatRoom = linphone_core_create_chat_room_6(marie.getLc(), params, NULL, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); linphone_chat_room_params_unref(params); BC_ASSERT_PTR_NOT_NULL(chatRoom); // linphone_core_create_chat_room_6 takes a ref to the chatroom @@ -1789,6 +1803,7 @@ static void group_chat_room_bulk_notify_to_participant(void) { Address laureAddr = laure.getIdentity(); participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(laureAddr.toC())); linphone_chat_room_add_participants(marieCr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure.getCMgr(), &initialLaureStats, confAddr, newSubject, 3, FALSE); @@ -2322,6 +2337,7 @@ static void multidomain_group_chat_room(void) { participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(laureAddr.toC())); linphone_chat_room_add_participants(marieCr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneConferenceStateCreationPending, initialLaureStats.number_of_LinphoneConferenceStateCreationPending + 1, @@ -2362,6 +2378,7 @@ static void multidomain_group_chat_room(void) { participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(laureAddr.toC())); linphone_chat_room_add_participants(marieCrfocusAuth1DotExampleDotOrg, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneConferenceStateCreationPending, initialLaureStats.number_of_LinphoneConferenceStateCreationPending + 2, liblinphone_tester_sip_timeout)); @@ -2768,17 +2785,18 @@ static void group_chat_room_with_duplications(void) { } bctbx_list_free_with_data(devices, (bctbx_list_free_func)belle_sip_object_unref); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, laure}).wait([&laure, &nbChatrooms] { - if (laure.getCore().getChatRooms().size() != static_cast<size_t>(2 * nbChatrooms)) { - return false; - } - for (auto chatRoom : laure.getCore().getChatRooms()) { - if (chatRoom->getState() != ChatRoom::State::Created) { - return false; - } - } - return true; - })); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, laure}) + .waitUntil(chrono::seconds(20), [&laure, &nbChatrooms] { + if (laure.getCore().getChatRooms().size() != static_cast<size_t>(2 * nbChatrooms)) { + return false; + } + for (auto chatRoom : laure.getCore().getChatRooms()) { + if (chatRoom->getState() != ChatRoom::State::Created) { + return false; + } + } + return true; + })); BC_ASSERT_EQUAL(laure.getCore().getChatRooms().size(), 2 * nbChatrooms, size_t, "%zu"); @@ -2935,6 +2953,8 @@ static void group_chat_room_with_duplications(void) { // Delete Laure's chatrooms by retrieving their conference address from Marie's ones. // This will allow to verify that there is no duplicate chatroom in stored by Laure's core for (auto chatRoom : marie.getCore().getChatRooms()) { + stats marie_stat = marie.getStats(); + stats pauline_stat = pauline.getStats(); const auto &conferenceAddress = chatRoom->getConferenceAddress(); LinphoneAddress *laureLocalAddress = linphone_account_get_contact_address(linphone_core_get_default_account(laure.getLc())); @@ -2944,6 +2964,13 @@ static void group_chat_room_with_duplications(void) { linphone_chat_room_add_callbacks(laureCr, cbs); linphone_chat_room_cbs_unref(cbs); linphone_core_manager_delete_chat_room(laure.getCMgr(), laureCr, coresList); + + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_participants_removed, + marie_stat.number_of_participants_removed + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_participants_removed, + pauline_stat.number_of_participants_removed + 1, + liblinphone_tester_sip_timeout)); } BC_ASSERT_EQUAL(laure.getCore().getChatRooms().size(), 0, size_t, "%zu"); diff --git a/tester/local_chat_tester_functions.cpp b/tester/local_chat_tester_functions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dff0d5608a757ff2d03e3da7cb8d2c785ba0b169 --- /dev/null +++ b/tester/local_chat_tester_functions.cpp @@ -0,0 +1,1487 @@ +/* + * copyright (c) 2010-2022 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 "chat/encryption/encryption-engine.h" +#include "conference/participant.h" +#include "local_conference_tester_functions.h" +#include "shared_tester_functions.h" + +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + +namespace LinphoneTest { + +void sendEphemeralMessageInAdminMode(Focus &focus, + ClientConference &sender, + ClientConference &recipient, + LinphoneChatRoom *senderCr, + LinphoneChatRoom *recipientCr, + const std::string basicText, + const int noMsg) { + + bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); + coresList = bctbx_list_append(coresList, sender.getLc()); + coresList = bctbx_list_append(coresList, recipient.getLc()); + + bctbx_list_t *senderHistory = linphone_chat_room_get_history(senderCr, 0); + auto initialSenderMessages = (int)bctbx_list_size(senderHistory); + bctbx_list_free_with_data(senderHistory, (bctbx_list_free_func)linphone_chat_message_unref); + + bctbx_list_t *recipientHistory = linphone_chat_room_get_history(recipientCr, 0); + auto initialRecipientMessages = (int)bctbx_list_size(recipientHistory); + bctbx_list_free_with_data(recipientHistory, (bctbx_list_free_func)linphone_chat_message_unref); + + int initialUnreadMessages = linphone_chat_room_get_unread_messages_count(recipientCr); + + auto sender_stat = sender.getStats(); + auto recipient_stat = recipient.getStats(); + + std::list<LinphoneChatMessage *> messages; + // Marie sends messages + for (int i = 0; i < noMsg; i++) { + const std::string text = basicText + std::to_string(i); + messages.push_back(_send_message_ephemeral(senderCr, text.c_str(), TRUE)); + } + + senderHistory = linphone_chat_room_get_history(senderCr, 0); + BC_ASSERT_EQUAL((int)bctbx_list_size(senderHistory), (noMsg + initialSenderMessages), int, "%i"); + set_ephemeral_cbs(senderHistory); + + BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneMessageReceived, + recipient_stat.number_of_LinphoneMessageReceived + noMsg, 11000)); + + // Check that the message has been delivered to Pauline + for (const auto &msg : messages) { + BC_ASSERT_TRUE(CoreManagerAssert({focus, sender, recipient}).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, sender, recipient}).wait([&, recipientCr] { + return linphone_chat_room_get_unread_messages_count(recipientCr) == (noMsg + initialUnreadMessages); + })); + + recipientHistory = linphone_chat_room_get_history(recipientCr, 0); + BC_ASSERT_EQUAL((int)bctbx_list_size(recipientHistory), (noMsg + initialRecipientMessages), int, "%i"); + set_ephemeral_cbs(recipientHistory); + + BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageDeliveredToUser, + sender_stat.number_of_LinphoneMessageDeliveredToUser + noMsg, + liblinphone_tester_sip_timeout)); + + // Pauline marks the message as read, check that the state is now displayed on Marie's side + linphone_chat_room_mark_as_read(recipientCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageDisplayed, + sender_stat.number_of_LinphoneMessageDisplayed + noMsg, + liblinphone_tester_sip_timeout)); + + BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneChatRoomEphemeralTimerStarted, + sender_stat.number_of_LinphoneChatRoomEphemeralTimerStarted + noMsg, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneChatRoomEphemeralTimerStarted, + recipient_stat.number_of_LinphoneChatRoomEphemeralTimerStarted + noMsg, + liblinphone_tester_sip_timeout)); + + BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageEphemeralTimerStarted, + sender_stat.number_of_LinphoneMessageEphemeralTimerStarted + noMsg, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneMessageEphemeralTimerStarted, + recipient_stat.number_of_LinphoneMessageEphemeralTimerStarted + noMsg, + liblinphone_tester_sip_timeout)); + + BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneChatRoomEphemeralDeleted, + sender_stat.number_of_LinphoneChatRoomEphemeralDeleted + noMsg, 15000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneChatRoomEphemeralDeleted, + recipient_stat.number_of_LinphoneChatRoomEphemeralDeleted + noMsg, 15000)); + + BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageEphemeralDeleted, + sender_stat.number_of_LinphoneMessageEphemeralDeleted + noMsg, 15000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneMessageEphemeralDeleted, + recipient_stat.number_of_LinphoneMessageEphemeralDeleted + noMsg, 15000)); + + bctbx_list_free_with_data(recipientHistory, (bctbx_list_free_func)linphone_chat_message_unref); + bctbx_list_free_with_data(senderHistory, (bctbx_list_free_func)linphone_chat_message_unref); + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, sender, recipient}).waitUntil(chrono::seconds(2), [] { return false; }); + + recipientHistory = linphone_chat_room_get_history(recipientCr, 0); + BC_ASSERT_EQUAL((int)bctbx_list_size(recipientHistory), initialRecipientMessages, int, "%i"); + senderHistory = linphone_chat_room_get_history(senderCr, 0); + BC_ASSERT_EQUAL((int)bctbx_list_size(senderHistory), initialSenderMessages, int, "%i"); + + for (auto &msg : messages) { + linphone_chat_message_unref(msg); + } + + bctbx_list_free_with_data(recipientHistory, (bctbx_list_free_func)linphone_chat_message_unref); + bctbx_list_free_with_data(senderHistory, (bctbx_list_free_func)linphone_chat_message_unref); + bctbx_list_free(coresList); +} + +bool checkChatroom(Focus &focus, const ConfCoreManager &core, const time_t baseJoiningTime) { + const auto &chatRooms = core.getCore().getChatRooms(); + if (chatRooms.size() < 1) { + return false; + } + + for (const auto &chatRoom : chatRooms) { + auto participants = chatRoom->getParticipants(); + if (focus.getLc() != core.getLc()) { + participants.push_back(chatRoom->getMe()); + } + for (const auto &participant : participants) { + for (const auto &device : participant->getDevices()) { + if (device->getState() != ParticipantDevice::State::Present) { + return false; + } + if (linphone_participant_device_is_in_conference(device->toC()) == FALSE) { + return false; + } + if ((baseJoiningTime >= 0) && + (linphone_participant_device_get_time_of_joining(device->toC()) >= baseJoiningTime)) { + return false; + } + } + } + } + return true; +} + +void group_chat_room_server_admin_managed_messages_base(bool_t encrypted) { + Focus focus("chloe_rc"); + { // to make sure focus is destroyed after clients. + ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); + + focus.registerAsParticipantDevice(marie); + focus.registerAsParticipantDevice(pauline); + + linphone_core_set_default_ephemeral_lifetime(marie.getLc(), 25); + + // Enable IMDN + 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(pauline.getLc())); + + bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); + coresList = bctbx_list_append(coresList, marie.getLc()); + coresList = bctbx_list_append(coresList, pauline.getLc()); + Address paulineAddr = pauline.getIdentity(); + bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(paulineAddr.toC())); + + stats chloe_stat = focus.getStats(); + stats marie_stat = marie.getStats(); + stats pauline_stat = pauline.getStats(); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues (characters: $ £ çà )"; + const LinphoneChatRoomEphemeralMode adminMode = LinphoneChatRoomEphemeralModeAdminManaged; + LinphoneChatRoomParams *params = linphone_core_create_default_chat_room_params(marie.getLc()); + + linphone_chat_room_params_enable_group(params, FALSE); + linphone_chat_room_params_enable_encryption(params, FALSE); + linphone_chat_room_params_set_ephemeral_mode(params, adminMode); + linphone_chat_room_params_set_ephemeral_lifetime(params, 5); + linphone_chat_room_params_set_backend(params, LinphoneChatRoomBackendFlexisipChat); + + LinphoneChatRoom *marieCr = create_chat_room_client_side_with_params( + coresList, marie.getCMgr(), &marie_stat, participantsAddresses, initialSubject, params); + linphone_chat_room_params_unref(params); + BC_ASSERT_PTR_NOT_NULL(marieCr); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline.getCMgr(), &pauline_stat, + confAddr, initialSubject, 1, FALSE); + + BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_mode(marieCr), adminMode, int, "%d"); + BC_ASSERT_TRUE(linphone_chat_room_ephemeral_enabled(marieCr)); + BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_lifetime(marieCr), 5, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_mode(paulineCr), adminMode, int, "%d"); + BC_ASSERT_TRUE(linphone_chat_room_ephemeral_enabled(paulineCr)); + BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_lifetime(paulineCr), 5, int, "%d"); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline}).wait([&focus] { + for (auto chatRoom : focus.getCore().getChatRooms()) { + for (auto participant : chatRoom->getParticipants()) { + for (auto device : participant->getDevices()) + if (device->getState() != ParticipantDevice::State::Present) { + return false; + } + } + } + return true; + })); + + chloe_stat = focus.getStats(); + marie_stat = marie.getStats(); + pauline_stat = pauline.getStats(); + + constexpr int noMsg = 10; + sendEphemeralMessageInAdminMode(focus, marie, pauline, marieCr, paulineCr, "Hello ", noMsg); + + 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, pauline}).wait([&focus] { + return focus.getCore().getChatRooms().size() == 0; + })); + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, marie, pauline}).waitUntil(chrono::seconds(2), [] { return false; }); + + // to avoid creation attempt of a new chatroom + auto config = focus.getDefaultProxyConfig(); + linphone_proxy_config_edit(config); + linphone_proxy_config_set_conference_factory_uri(config, NULL); + linphone_proxy_config_done(config); + + bctbx_list_free(coresList); + } +} + +void group_chat_room_with_client_restart_base(bool encrypted) { + Focus focus("chloe_rc"); + { // to make sure focus is destroyed after clients. + ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference michelle("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference laure("laure_tcp_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference berthe("berthe_rc", focus.getConferenceFactoryAddress(), encrypted); + + focus.registerAsParticipantDevice(marie); + focus.registerAsParticipantDevice(michelle); + focus.registerAsParticipantDevice(laure); + focus.registerAsParticipantDevice(berthe); + + bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); + coresList = bctbx_list_append(coresList, marie.getLc()); + coresList = bctbx_list_append(coresList, michelle.getLc()); + coresList = bctbx_list_append(coresList, laure.getLc()); + coresList = bctbx_list_append(coresList, berthe.getLc()); + bctbx_list_t *participantsAddresses = NULL; + Address michelleAddr = michelle.getIdentity(); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(michelleAddr.toC())); + Address bertheAddr = berthe.getIdentity(); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(bertheAddr.toC())); + + stats initialMarieStats = marie.getStats(); + stats initialMichelleStats = michelle.getStats(); + stats initialBertheStats = berthe.getStats(); + stats initialLaureStats = laure.getStats(); + + if (encrypted) { + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(berthe.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(laure.getLc())); + } + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues (characters: $ £ çà )"; + LinphoneChatRoom *marieCr = create_chat_room_client_side_with_expected_number_of_participants( + coresList, marie.getCMgr(), &initialMarieStats, participantsAddresses, initialSubject, 2, encrypted, + LinphoneChatRoomEphemeralModeDeviceManaged); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Michelle's side and that the participants are added + LinphoneChatRoom *michelleCr = check_creation_chat_room_client_side( + coresList, michelle.getCMgr(), &initialMichelleStats, confAddr, initialSubject, 2, FALSE); + + LinphoneChatRoom *bertheCr = check_creation_chat_room_client_side( + coresList, berthe.getCMgr(), &initialBertheStats, confAddr, initialSubject, 2, FALSE); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, laure, berthe}).wait([&focus] { + for (const auto &chatRoom : focus.getCore().getChatRooms()) { + for (const auto &participant : chatRoom->getParticipants()) { + for (const auto &device : participant->getDevices()) { + if (device->getState() != ParticipantDevice::State::Present) { + return false; + } + } + } + } + return true; + })); + + 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, &berthe.getStats().number_of_LinphoneConferenceStateCreated, + initialBertheStats.number_of_LinphoneConferenceStateCreated + 1, + liblinphone_tester_sip_timeout)); + + // Marie now changes the subject + const char *newSubject = "Let's go drink a beer"; + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_subject_changed, + initialMarieStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_subject_changed, + initialMichelleStats.number_of_subject_changed + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_subject_changed, + initialBertheStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(michelleCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(bertheCr), newSubject); + + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelleCr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(bertheCr), 2, int, "%d"); + + const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores2{focus, marie, michelle, berthe}; + for (const ConfCoreManager &core : cores2) { + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, michelle, berthe, laure}) + .waitUntil(chrono::seconds(10), [&focus, &core] { return checkChatroom(focus, core, -1); })); + }; + + ClientConference michelle2("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); + stats initialMichelle2Stats = michelle2.getStats(); + coresList = bctbx_list_append(coresList, michelle2.getLc()); + if (encrypted) { + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle2.getLc())); + } + + focus.registerAsParticipantDevice(michelle2); + + LinphoneAddress *michelle2Contact = linphone_address_clone( + linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(michelle2.getLc()))); + char *michelle2ContactString = linphone_address_as_string(michelle2Contact); + ms_message("%s is adding device %s", linphone_core_get_identity(focus.getLc()), michelle2ContactString); + ms_free(michelle2ContactString); + focus.registerAsParticipantDevice(michelle2); + + // Notify chat room that a participant has registered + bctbx_list_t *devices = NULL; + const LinphoneAddress *deviceAddr = linphone_proxy_config_get_contact(michelle.getDefaultProxyConfig()); + LinphoneParticipantDeviceIdentity *identity = + linphone_factory_create_participant_device_identity(linphone_factory_get(), deviceAddr, ""); + bctbx_list_t *specs = linphone_core_get_linphone_specs_list(michelle.getLc()); + linphone_participant_device_identity_set_capability_descriptor_2(identity, specs); + bctbx_list_free_with_data(specs, ms_free); + devices = bctbx_list_append(devices, identity); + + deviceAddr = linphone_proxy_config_get_contact(michelle2.getDefaultProxyConfig()); + identity = linphone_factory_create_participant_device_identity(linphone_factory_get(), deviceAddr, ""); + specs = linphone_core_get_linphone_specs_list(michelle2.getLc()); + linphone_participant_device_identity_set_capability_descriptor_2(identity, specs); + bctbx_list_free_with_data(specs, ms_free); + devices = bctbx_list_append(devices, identity); + + for (auto chatRoom : focus.getCore().getChatRooms()) { + linphone_chat_room_set_participant_devices(L_GET_C_BACK_PTR(chatRoom), michelle.getCMgr()->identity, + devices); + } + bctbx_list_free_with_data(devices, (bctbx_list_free_func)belle_sip_object_unref); + + LinphoneChatRoom *michelle2Cr = check_creation_chat_room_client_side( + coresList, michelle2.getCMgr(), &initialMichelle2Stats, confAddr, newSubject, 2, FALSE); + BC_ASSERT_PTR_NOT_NULL(michelle2Cr); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateCreated, + initialMichelle2Stats.number_of_LinphoneConferenceStateCreated + 1, + liblinphone_tester_sip_timeout)); + + const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores3{focus, marie, michelle, michelle2, + berthe}; + for (const ConfCoreManager &core : cores3) { + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, michelle, michelle2, berthe, laure}) + .waitUntil(chrono::seconds(10), [&focus, &core] { return checkChatroom(focus, core, -1); })); + }; + + initialMarieStats = marie.getStats(); + initialMichelleStats = michelle.getStats(); + initialBertheStats = berthe.getStats(); + initialLaureStats = laure.getStats(); + + Address laureAddr = laure.getIdentity(); + participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(laureAddr.toC())); + ms_message("%s is adding participant %s", linphone_core_get_identity(focus.getLc()), + linphone_core_get_identity(laure.getLc())); + linphone_chat_room_add_participants(marieCr, participantsAddresses); + bctbx_list_free(participantsAddresses); + + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure.getCMgr(), &initialLaureStats, + confAddr, newSubject, 3, FALSE); + BC_ASSERT_PTR_NOT_NULL(laureCr); + + BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneConferenceStateCreationPending, + initialLaureStats.number_of_LinphoneConferenceStateCreationPending + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneConferenceStateCreated, + initialLaureStats.number_of_LinphoneConferenceStateCreated + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneChatRoomConferenceJoined, + initialLaureStats.number_of_LinphoneChatRoomConferenceJoined + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_participants_added, + initialMarieStats.number_of_participants_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_participants_added, + initialBertheStats.number_of_participants_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participants_added, + initialMichelleStats.number_of_participants_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_participants_added, + initialMichelle2Stats.number_of_participants_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_participant_devices_added, + initialMarieStats.number_of_participant_devices_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_participant_devices_added, + initialBertheStats.number_of_participant_devices_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participant_devices_added, + initialMichelleStats.number_of_participant_devices_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_participant_devices_added, + initialMichelle2Stats.number_of_participant_devices_added + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(bertheCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelleCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelle2Cr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 3, int, "%d"); + + const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores{focus, marie, michelle, + michelle2, laure, berthe}; + for (const ConfCoreManager &core : cores) { + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}) + .waitUntil(chrono::seconds(10), [&focus, &core] { return checkChatroom(focus, core, -1); })); + for (auto chatRoom : core.getCore().getChatRooms()) { + BC_ASSERT_EQUAL(chatRoom->getParticipants().size(), ((focus.getLc() == core.getLc())) ? 4 : 3, size_t, + "%zu"); + BC_ASSERT_STRING_EQUAL(chatRoom->getSubject().c_str(), newSubject); + } + }; + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(chrono::seconds(1), [] { + return false; + }); + + time_t participantAddedTime = ms_time(nullptr); + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(chrono::seconds(10), [] { + 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()); + for (auto chatRoom : focus.getCore().getChatRooms()) { + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(L_GET_C_BACK_PTR(chatRoom)), 4, int, "%d"); + } + + michelle2ContactString = linphone_address_as_string(michelle2Contact); + ms_message("%s is restarting its core", michelle2ContactString); + ms_free(michelle2ContactString); + coresList = bctbx_list_remove(coresList, michelle2.getLc()); + // Restart michelle + michelle2.reStart(); + coresList = bctbx_list_append(coresList, michelle2.getLc()); + + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateCreated, 1, + liblinphone_tester_sip_timeout)); + LinphoneAddress *michelleDeviceAddr = + linphone_address_clone(linphone_proxy_config_get_contact(michelle2.getDefaultProxyConfig())); + michelle2Cr = michelle2.searchChatRoom(michelleDeviceAddr, confAddr); + BC_ASSERT_PTR_NOT_NULL(michelle2Cr); + for (const ConfCoreManager &core : cores) { + BC_ASSERT_TRUE(checkChatroom(focus, core, participantAddedTime)); + for (auto chatRoom : core.getCore().getChatRooms()) { + BC_ASSERT_EQUAL(chatRoom->getParticipants().size(), ((focus.getLc() == core.getLc())) ? 4 : 3, size_t, + "%zu"); + BC_ASSERT_STRING_EQUAL(chatRoom->getSubject().c_str(), newSubject); + } + } + + LinphoneChatMessage *msg = linphone_chat_room_create_message_from_utf8(michelle2Cr, "back with you"); + linphone_chat_message_send(msg); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([marieCr] { + return linphone_chat_room_get_unread_messages_count(marieCr) == 1; + })); + linphone_chat_message_unref(msg); + msg = NULL; + + msg = linphone_chat_room_create_message_from_utf8(marieCr, "welcome back"); + linphone_chat_message_send(msg); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([michelleCr] { + return linphone_chat_room_get_unread_messages_count(michelleCr) == 1; + })); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([michelle2Cr] { + return linphone_chat_room_get_unread_messages_count(michelle2Cr) == 1; + })); + linphone_chat_message_unref(msg); + msg = NULL; + + msg = linphone_chat_room_create_message_from_utf8(michelleCr, "message blabla"); + linphone_chat_message_send(msg); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([marieCr] { + return linphone_chat_room_get_unread_messages_count(marieCr) == 2; + })); + linphone_chat_message_unref(msg); + + CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(std::chrono::seconds(2), [] { + return false; + }); + + 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, michelle, michelle2, laure, berthe}).wait([&focus] { + return focus.getCore().getChatRooms().size() == 0; + })); + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(chrono::seconds(2), [] { + return false; + }); + + // to avoid creation attempt of a new chatroom + auto config = focus.getDefaultProxyConfig(); + linphone_proxy_config_edit(config); + linphone_proxy_config_set_conference_factory_uri(config, NULL); + linphone_proxy_config_done(config); + + linphone_address_unref(michelle2Contact); + linphone_address_unref(michelleDeviceAddr); + bctbx_list_free(coresList); + } +} + +static void chat_room_participant_added_sip_error(LinphoneChatRoom *cr, + BCTBX_UNUSED(const LinphoneEventLog *event_log)) { + bctbx_list_t *participants = linphone_chat_room_get_participants(cr); + if (bctbx_list_size(participants) == 2) { + LinphoneCoreManager *initiator = (LinphoneCoreManager *)linphone_chat_room_get_user_data(cr); + ms_message("Turning off network for core %s", linphone_core_get_identity(initiator->lc)); + linphone_core_set_network_reachable(initiator->lc, FALSE); + } + if (participants) { + bctbx_list_free_with_data(participants, (bctbx_list_free_func)linphone_participant_unref); + } +} + +static void +server_core_chat_room_state_changed_sip_error(LinphoneCore *core, LinphoneChatRoom *cr, LinphoneChatRoomState state) { + Focus *focus = (Focus *)(((LinphoneCoreManager *)linphone_core_get_user_data(core))->user_info); + switch (state) { + case LinphoneChatRoomStateInstantiated: { + LinphoneChatRoomCbs *cbs = linphone_factory_create_chat_room_cbs(linphone_factory_get()); + linphone_chat_room_cbs_set_participant_added(cbs, chat_room_participant_added_sip_error); + linphone_chat_room_add_callbacks(cr, cbs); + linphone_chat_room_cbs_set_user_data(cbs, focus); + linphone_chat_room_cbs_unref(cbs); + break; + } + default: + break; + } +} + +void group_chat_room_with_sip_errors_base(bool invite_error, bool subscribe_error, bool encrypted) { + Focus focus("chloe_rc"); + { // to make sure focus is destroyed after clients. + ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference laure("laure_tcp_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference berthe("berthe_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference michelle("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference michelle2("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); + + stats initialFocusStats = focus.getStats(); + stats initialMarieStats = marie.getStats(); + stats initialMichelleStats = michelle.getStats(); + stats initialMichelle2Stats = michelle2.getStats(); + stats initialLaureStats = laure.getStats(); + stats initialBertheStats = berthe.getStats(); + stats initialPaulineStats = pauline.getStats(); + + bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); + coresList = bctbx_list_append(coresList, marie.getLc()); + coresList = bctbx_list_append(coresList, michelle.getLc()); + coresList = bctbx_list_append(coresList, michelle2.getLc()); + coresList = bctbx_list_append(coresList, pauline.getLc()); + coresList = bctbx_list_append(coresList, laure.getLc()); + coresList = bctbx_list_append(coresList, berthe.getLc()); + + if (encrypted) { + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(pauline.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(laure.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle2.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(berthe.getLc())); + } + + linphone_core_set_network_reachable(marie.getLc(), FALSE); + linphone_core_set_network_reachable(berthe.getLc(), FALSE); + + char *spec = bctbx_strdup_printf("groupchat/1.1"); + linphone_core_remove_linphone_spec(marie.getLc(), "groupchat"); + linphone_core_add_linphone_spec(marie.getLc(), spec); + linphone_core_remove_linphone_spec(berthe.getLc(), "groupchat"); + linphone_core_add_linphone_spec(berthe.getLc(), spec); + bctbx_free(spec); + + linphone_core_set_network_reachable(marie.getLc(), TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneRegistrationOk, + initialMarieStats.number_of_LinphoneRegistrationOk + 1, + liblinphone_tester_sip_timeout)); + linphone_core_set_network_reachable(berthe.getLc(), TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_LinphoneRegistrationOk, + initialBertheStats.number_of_LinphoneRegistrationOk + 1, + liblinphone_tester_sip_timeout)); + + initialMarieStats = marie.getStats(); + initialBertheStats = berthe.getStats(); + + std::list<LinphoneCoreManager *> shutdownNetworkClients; + std::list<stats> initialStatsList; + if (invite_error) { + shutdownNetworkClients.push_back(michelle2.getCMgr()); + initialStatsList.push_back(michelle2.getStats()); + shutdownNetworkClients.push_back(berthe.getCMgr()); + initialStatsList.push_back(berthe.getStats()); + } else if (subscribe_error) { + shutdownNetworkClients.push_back(marie.getCMgr()); + initialStatsList.push_back(marie.getStats()); + shutdownNetworkClients.push_back(michelle2.getCMgr()); + initialStatsList.push_back(michelle2.getStats()); + shutdownNetworkClients.push_back(berthe.getCMgr()); + initialStatsList.push_back(berthe.getStats()); + } + + focus.registerAsParticipantDevice(marie); + focus.registerAsParticipantDevice(michelle); + focus.registerAsParticipantDevice(michelle2); + focus.registerAsParticipantDevice(pauline); + focus.registerAsParticipantDevice(berthe); + + if (invite_error) { + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_chat_room_state_changed(cbs, server_core_chat_room_state_changed_sip_error); + linphone_core_add_callbacks(focus.getLc(), cbs); + linphone_core_cbs_unref(cbs); + } + + 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(michelle.getLc())); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(michelle2.getLc())); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline.getLc())); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(laure.getLc())); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(berthe.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())); + Address bertheAddr = berthe.getIdentity(); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(bertheAddr.toC())); + Address paulineAddr = pauline.getIdentity(); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(paulineAddr.toC())); + + const char *initialSubject = "Colleagues (characters: $ £ çà )"; + int participantsAddressesSize = (int)bctbx_list_size(participantsAddresses); + LinphoneChatRoomParams *params = linphone_core_create_default_chat_room_params(marie.getLc()); + + linphone_chat_room_params_enable_encryption(params, encrypted); + linphone_chat_room_params_set_ephemeral_mode(params, LinphoneChatRoomEphemeralModeDeviceManaged); + linphone_chat_room_params_set_backend(params, LinphoneChatRoomBackendFlexisipChat); + linphone_chat_room_params_enable_group(params, participantsAddressesSize > 1 ? TRUE : FALSE); + // Marie creates a new group chat room + LinphoneChatRoom *marieCr = + linphone_core_create_chat_room_2(marie.getLc(), params, initialSubject, participantsAddresses); + linphone_chat_room_params_unref(params); + if (marieCr) linphone_chat_room_unref(marieCr); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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()); + } + + for (const auto &client : shutdownNetworkClients) { + stats &initialStats = initialStatsList.front(); + BC_ASSERT_TRUE(wait_for_list(coresList, &client->stat.number_of_LinphoneConferenceStateCreated, + initialStats.number_of_LinphoneConferenceStateCreated + 1, + liblinphone_tester_sip_timeout)); + char *proxy_contact_str = linphone_address_as_string( + linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(client->lc))); + ms_message("Disabling network of core %s (contact %s)", linphone_core_get_identity(client->lc), + proxy_contact_str); + ms_free(proxy_contact_str); + linphone_core_set_network_reachable(client->lc, FALSE); + initialStatsList.pop_front(); + } + + BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participants_added, + initialFocusStats.number_of_participants_added + 4, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participant_devices_added, + initialFocusStats.number_of_participant_devices_added + 5, 5000)); + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}) + .waitUntil(chrono::seconds(60), [] { return false; }); + + check_create_chat_room_client_side(coresList, marie.getCMgr(), marieCr, &initialMarieStats, + participantsAddresses, initialSubject, 2); + 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 *michelleCr = check_creation_chat_room_client_side( + coresList, michelle.getCMgr(), &initialMichelleStats, confAddr, initialSubject, 3, FALSE); + LinphoneChatRoom *michelle2Cr = check_creation_chat_room_client_side( + coresList, michelle2.getCMgr(), &initialMichelle2Stats, confAddr, initialSubject, 3, FALSE); + LinphoneChatRoom *bertheCr = check_creation_chat_room_client_side( + coresList, berthe.getCMgr(), &initialBertheStats, confAddr, initialSubject, 3, FALSE); + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side( + coresList, pauline.getCMgr(), &initialPaulineStats, confAddr, initialSubject, 3, 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, &berthe.getStats().number_of_LinphoneConferenceStateCreated, + initialBertheStats.number_of_LinphoneConferenceStateCreated + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneConferenceStateCreated, + initialPaulineStats.number_of_LinphoneConferenceStateCreated + 1, + liblinphone_tester_sip_timeout)); + + std::string msg_text = "message michelle blabla"; + LinphoneChatMessage *msg = ClientConference::sendTextMsg(michelleCr, msg_text); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { + return (msg && (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered)); + })); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { + return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; + })); + LinphoneChatMessage *paulineLastMsg = pauline.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); + if (paulineLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); + } + linphone_chat_room_mark_as_read(paulineCr); + + BC_ASSERT_FALSE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneMessageDisplayed, + initialMichelleStats.number_of_LinphoneMessageDisplayed + 1, 3000)); + + if (invite_error || subscribe_error) { + char *marie_proxy_contact_str = linphone_address_as_string( + linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(marie.getLc()))); + ms_message("Enabling network of core %s (contact %s)", linphone_core_get_identity(marie.getLc()), + marie_proxy_contact_str); + ms_free(marie_proxy_contact_str); + if (invite_error) { + initialMarieStats = marie.getStats(); + } + linphone_core_set_network_reachable(marie.getLc(), TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneRegistrationOk, + initialMarieStats.number_of_LinphoneRegistrationOk + 1, + liblinphone_tester_sip_timeout)); + marieCr = check_creation_chat_room_client_side(coresList, marie.getCMgr(), &initialMarieStats, confAddr, + initialSubject, 3, TRUE); + } + + focus.registerAsParticipantDevice(laure); + Address laureAddr = laure.getIdentity(); + linphone_chat_room_add_participant(marieCr, linphone_address_ref(laureAddr.toC())); + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side( + coresList, laure.getCMgr(), &initialPaulineStats, confAddr, initialSubject, 4, FALSE); + + BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participants_added, + initialFocusStats.number_of_participants_added + 4, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participant_devices_added, + initialFocusStats.number_of_participant_devices_added + 5, 5000)); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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()); + } + + msg_text = "message laure blabla"; + LinphoneChatMessage *msg2 = ClientConference::sendTextMsg(laureCr, msg_text); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg2] { + return (linphone_chat_message_get_state(msg2) == LinphoneChatMessageStateDelivered); + })); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { + return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; + })); + paulineLastMsg = pauline.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); + if (paulineLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([marieCr] { + return linphone_chat_room_get_unread_messages_count(marieCr) == 2; + })); + 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, pauline, michelle, michelle2, laure, berthe}).wait([michelleCr] { + return linphone_chat_room_get_unread_messages_count(michelleCr) == 1; + })); + LinphoneChatMessage *michelleLastMsg = michelle.getStats().last_received_chat_message; + if (michelleLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(michelleLastMsg), msg_text.c_str()); + } + + linphone_chat_room_mark_as_read(paulineCr); + linphone_chat_room_mark_as_read(marieCr); + linphone_chat_room_mark_as_read(michelleCr); + + BC_ASSERT_FALSE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneMessageDisplayed, + initialLaureStats.number_of_LinphoneMessageDisplayed + 1, 3000)); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { + bctbx_list_t *displayed_list = + linphone_chat_message_get_participants_by_imdn_state(msg, LinphoneChatMessageStateDisplayed); + size_t displayed = bctbx_list_size(displayed_list); + bctbx_list_free_with_data(displayed_list, (bctbx_list_free_func)linphone_participant_imdn_state_unref); + return (displayed == 2); + })); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg2] { + bctbx_list_t *displayed_list = + linphone_chat_message_get_participants_by_imdn_state(msg2, LinphoneChatMessageStateDisplayed); + size_t displayed = bctbx_list_size(displayed_list); + bctbx_list_free_with_data(displayed_list, (bctbx_list_free_func)linphone_participant_imdn_state_unref); + return (displayed == 3); + })); + + if (invite_error || subscribe_error) { + char *michelle2_proxy_contact_str = linphone_address_as_string( + linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(michelle2.getLc()))); + ms_message("Enabling network of core %s (contact %s)", linphone_core_get_identity(michelle2.getLc()), + michelle2_proxy_contact_str); + ms_free(michelle2_proxy_contact_str); + initialMichelle2Stats = michelle2.getStats(); + linphone_core_set_network_reachable(michelle2.getLc(), TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneRegistrationOk, + initialMichelle2Stats.number_of_LinphoneRegistrationOk + 1, + liblinphone_tester_sip_timeout)); + michelle2Cr = check_creation_chat_room_client_side(coresList, michelle2.getCMgr(), &initialMichelle2Stats, + confAddr, initialSubject, 4, FALSE); + + char *berthe_proxy_contact_str = linphone_address_as_string( + linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(berthe.getLc()))); + ms_message("Enabling network of core %s (contact %s)", linphone_core_get_identity(berthe.getLc()), + berthe_proxy_contact_str); + ms_free(berthe_proxy_contact_str); + initialBertheStats = berthe.getStats(); + linphone_core_set_network_reachable(berthe.getLc(), TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_LinphoneRegistrationOk, + initialBertheStats.number_of_LinphoneRegistrationOk + 1, + liblinphone_tester_sip_timeout)); + bertheCr = check_creation_chat_room_client_side(coresList, berthe.getCMgr(), &initialBertheStats, confAddr, + initialSubject, 4, FALSE); + } + + LinphoneChatMessage *michelle2LastMsg = NULL; + if (!invite_error) { + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([michelle2Cr] { + return linphone_chat_room_get_history_size(michelle2Cr) == 2; + })); + 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); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { + return linphone_chat_room_get_history_size(bertheCr) == 2; + })); + + LinphoneChatMessage *bertheLastMsg = berthe.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); + if (bertheLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); + } + linphone_chat_room_mark_as_read(bertheCr); + + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneMessageDisplayed, + initialMichelleStats.number_of_LinphoneMessageDisplayed + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneMessageDisplayed, + initialLaureStats.number_of_LinphoneMessageDisplayed + 1, + liblinphone_tester_sip_timeout)); + + linphone_chat_message_unref(msg); + msg = nullptr; + linphone_chat_message_unref(msg2); + msg2 = nullptr; + + // Marie now changes the subject + const char *newSubject = "Let's go drink a beer"; + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_subject_changed, + initialMarieStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_subject_changed, + initialMichelleStats.number_of_subject_changed + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_subject_changed, + initialMichelle2Stats.number_of_subject_changed + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_subject_changed, + initialPaulineStats.number_of_subject_changed + 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_subject_changed, + initialLaureStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_subject_changed, + initialBertheStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(michelleCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(michelle2Cr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(bertheCr), newSubject); + + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelleCr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelle2Cr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(bertheCr), 4, int, "%d"); + + msg_text = "message marie blabla"; + msg = ClientConference::sendTextMsg(marieCr, msg_text); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { + return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; + })); + paulineLastMsg = pauline.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); + if (paulineLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([laureCr] { + return linphone_chat_room_get_unread_messages_count(laureCr) == 1; + })); + LinphoneChatMessage *laureLastMsg = laure.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(laureLastMsg); + if (laureLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), msg_text.c_str()); + } + + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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, pauline, michelle, michelle2, laure, berthe}).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()); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { + return linphone_chat_room_get_unread_messages_count(bertheCr) == 1; + })); + bertheLastMsg = berthe.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); + if (bertheLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); + } + + linphone_chat_room_mark_as_read(michelleCr); + linphone_chat_room_mark_as_read(michelle2Cr); + linphone_chat_room_mark_as_read(paulineCr); + linphone_chat_room_mark_as_read(laureCr); + linphone_chat_room_mark_as_read(bertheCr); + + 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"; + msg = ClientConference::sendTextMsg(michelle2Cr, msg_text); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { + return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; + })); + paulineLastMsg = pauline.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); + if (paulineLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { + return linphone_chat_room_get_unread_messages_count(bertheCr) == 1; + })); + bertheLastMsg = berthe.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); + if (bertheLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([laureCr] { + return linphone_chat_room_get_unread_messages_count(laureCr) == 1; + })); + laureLastMsg = laure.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(laureLastMsg); + if (laureLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), msg_text.c_str()); + } + + 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, pauline, michelle, michelle2, laure, berthe}).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()); + } + + linphone_chat_room_mark_as_read(michelleCr); + linphone_chat_room_mark_as_read(marieCr); + linphone_chat_room_mark_as_read(paulineCr); + linphone_chat_room_mark_as_read(laureCr); + linphone_chat_room_mark_as_read(bertheCr); + + 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; + + msg_text = "message pauline blabla"; + msg = ClientConference::sendTextMsg(paulineCr, msg_text); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { + return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); + })); + + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { + return linphone_chat_room_get_unread_messages_count(bertheCr) == 1; + })); + bertheLastMsg = berthe.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); + if (bertheLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); + } + + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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, pauline, michelle, michelle2, laure, berthe}).wait([laureCr] { + return linphone_chat_room_get_unread_messages_count(laureCr) == 1; + })); + laureLastMsg = laure.getStats().last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(laureLastMsg); + if (laureLastMsg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), msg_text.c_str()); + } + + BC_ASSERT_TRUE( + CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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(michelleCr); + linphone_chat_room_mark_as_read(michelle2Cr); + linphone_chat_room_mark_as_read(marieCr); + linphone_chat_room_mark_as_read(laureCr); + linphone_chat_room_mark_as_read(bertheCr); + + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneMessageDisplayed, + initialPaulineStats.number_of_LinphoneMessageDisplayed + 1, + liblinphone_tester_sip_timeout)); + linphone_chat_message_unref(msg); + msg = nullptr; + + CoreManagerAssert({focus, marie}).waitUntil(std::chrono::seconds(1), [] { return false; }); + + CoreManagerAssert({focus, marie}).waitUntil(std::chrono::seconds(2), [] { return false; }); + + 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, pauline, michelle, michelle2, laure, berthe}).wait([&focus] { + return focus.getCore().getChatRooms().size() == 0; + })); + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}) + .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); + } +} + +void group_chat_room_lime_server_message(bool encrypted) { + Focus focus("chloe_rc"); + LinphoneChatMessage *msg; + { // to make sure focus is destroyed after clients. + linphone_core_enable_lime_x3dh(focus.getLc(), true); + + ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference laure("laure_tcp_rc", focus.getConferenceFactoryAddress(), encrypted); + + focus.registerAsParticipantDevice(marie); + focus.registerAsParticipantDevice(pauline); + focus.registerAsParticipantDevice(laure); + + stats marie_stat = marie.getStats(); + stats pauline_stat = pauline.getStats(); + stats laure_stat = laure.getStats(); + bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); + coresList = bctbx_list_append(coresList, marie.getLc()); + coresList = bctbx_list_append(coresList, pauline.getLc()); + coresList = bctbx_list_append(coresList, laure.getLc()); + + if (encrypted) { + auto rawEncryptionSuccess = 0; + + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(pauline.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(laure.getLc())); + + // Test the raw encryption/decryption + auto marieEncryptionEngine = L_GET_CPP_PTR_FROM_C_OBJECT(marie.getCMgr()->lc)->getEncryptionEngine(); + char *deviceId = linphone_address_as_string_uri_only( + linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(marie.getLc()))); + std::string marieAddressString{deviceId}; + bctbx_free(deviceId); + auto paulineEncryptionEngine = L_GET_CPP_PTR_FROM_C_OBJECT(pauline.getCMgr()->lc)->getEncryptionEngine(); + deviceId = linphone_address_as_string_uri_only( + linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(pauline.getLc()))); + std::string paulineAddressString{deviceId}; + bctbx_free(deviceId); + + std::string messageString = "This is my message to you Rudy"; + std::string ADString = "These are my AD to you Rudy"; + auto message = std::make_shared<std::vector<uint8_t>>(messageString.cbegin(), messageString.cend()); + auto AD = std::make_shared<std::vector<uint8_t>>(ADString.cbegin(), ADString.cend()); + std::vector<uint8_t> cipherText{}; + + marieEncryptionEngine->rawEncrypt( + marieAddressString, std::list<std::string>{paulineAddressString}, message, AD, + [&rawEncryptionSuccess, &cipherText, paulineAddressString]( + const bool status, std::unordered_map<std::string, std::vector<uint8_t>> cipherTexts) { + auto search = cipherTexts.find(paulineAddressString); + if (status && search != cipherTexts.end()) { + rawEncryptionSuccess++; + cipherText = cipherTexts[paulineAddressString]; + } + }); + + BC_ASSERT_TRUE(wait_for_list(coresList, &rawEncryptionSuccess, 1, x3dhServer_creationTimeout)); + if (rawEncryptionSuccess == 1) { + // try to decrypt only if encryption was a success + std::vector<uint8_t> plainText{}; + BC_ASSERT_TRUE(paulineEncryptionEngine->rawDecrypt(paulineAddressString, marieAddressString, *AD, + cipherText, plainText)); + std::string plainTextString{plainText.cbegin(), plainText.cend()}; + BC_ASSERT_TRUE(plainTextString == messageString); + } + } + + Address paulineAddr = pauline.getIdentity(); + Address laureAddr = laure.getIdentity(); + bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(paulineAddr.toC())); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(laureAddr.toC())); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = + create_chat_room_client_side(coresList, marie.getCMgr(), &marie_stat, participantsAddresses, initialSubject, + encrypted, LinphoneChatRoomEphemeralModeDeviceManaged); + BC_ASSERT_PTR_NOT_NULL(marieCr); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline.getCMgr(), &pauline_stat, + confAddr, initialSubject, 2, FALSE); + BC_ASSERT_PTR_NOT_NULL(paulineCr); + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure.getCMgr(), &laure_stat, + confAddr, initialSubject, 2, FALSE); + BC_ASSERT_PTR_NOT_NULL(laureCr); + if (paulineCr && laureCr) { + // Marie sends the message + const char *marieMessage = "Hey ! What's up ?"; + msg = _send_message_ephemeral(marieCr, marieMessage, FALSE); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneMessageReceived, + pauline_stat.number_of_LinphoneMessageReceived + 1, + liblinphone_tester_sip_timeout)); + LinphoneChatMessage *paulineLastMsg = pauline.getStats().last_received_chat_message; + BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneMessageReceived, + laure_stat.number_of_LinphoneMessageReceived + 1, + liblinphone_tester_sip_timeout)); + LinphoneChatMessage *laureLastMsg = laure.getStats().last_received_chat_message; + linphone_chat_message_unref(msg); + if (paulineLastMsg && laureLastMsg) { + // Check that the message was correctly decrypted if encrypted + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), marieMessage); + LinphoneAddress *marieAddr = marie.getCMgr()->identity; + BC_ASSERT_TRUE( + linphone_address_weak_equal(marieAddr, linphone_chat_message_get_from_address(paulineLastMsg))); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), marieMessage); + BC_ASSERT_TRUE( + linphone_address_weak_equal(marieAddr, linphone_chat_message_get_from_address(laureLastMsg))); + } + } + + 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, pauline, laure}).wait([&focus] { + return focus.getCore().getChatRooms().size() == 0; + })); + + // wait bit more to detect side effect if any + CoreManagerAssert({focus, marie, pauline, laure}).waitUntil(chrono::seconds(2), [] { return false; }); + + // to avoid creation attempt of a new chatroom + auto config = focus.getDefaultProxyConfig(); + linphone_proxy_config_edit(config); + linphone_proxy_config_set_conference_factory_uri(config, NULL); + linphone_proxy_config_done(config); + + bctbx_list_free(coresList); + } +} + +void one_to_one_group_chat_room_deletion_by_server_client_base(bool encrypted) { + Focus focus("chloe_rc"); + LinphoneChatMessage *msg; + { // to make sure focus is destroyed after clients. + linphone_core_enable_lime_x3dh(focus.getLc(), true); + + ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); + ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); + + focus.registerAsParticipantDevice(marie); + focus.registerAsParticipantDevice(pauline); + + stats marie_stat = marie.getStats(); + stats pauline_stat = pauline.getStats(); + bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); + coresList = bctbx_list_append(coresList, marie.getLc()); + coresList = bctbx_list_append(coresList, pauline.getLc()); + + if (encrypted) { + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); + BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(pauline.getLc())); + } + + Address paulineAddr = pauline.getIdentity(); + bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(paulineAddr.toC())); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = + create_chat_room_client_side(coresList, marie.getCMgr(), &marie_stat, participantsAddresses, initialSubject, + encrypted, LinphoneChatRoomEphemeralModeDeviceManaged); + BC_ASSERT_PTR_NOT_NULL(marieCr); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline.getCMgr(), &pauline_stat, + confAddr, initialSubject, 1, FALSE); + BC_ASSERT_PTR_NOT_NULL(paulineCr); + + if (paulineCr && marieCr) { + // Marie sends the message + const char *marieMessage = "Hey ! What's up ?"; + msg = _send_message(marieCr, marieMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneMessageReceived, + pauline_stat.number_of_LinphoneMessageReceived + 1, + liblinphone_tester_sip_timeout)); + LinphoneChatMessage *paulineLastMsg = pauline.getStats().last_received_chat_message; + linphone_chat_message_unref(msg); + BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); + + // Check that the message was correctly decrypted if encrypted + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), marieMessage); + LinphoneAddress *marieAddr = marie.getCMgr()->identity; + BC_ASSERT_TRUE( + linphone_address_weak_equal(marieAddr, linphone_chat_message_get_from_address(paulineLastMsg))); + + LinphoneAddress *localAddr = linphone_address_clone(linphone_chat_room_get_local_address(paulineCr)); + LinphoneAddress *peerAddr = linphone_address_clone(linphone_chat_room_get_peer_address(paulineCr)); + + // Restart pauline so that she has to send an INVITE and BYE it to exit the chatroom + coresList = bctbx_list_remove(coresList, pauline.getLc()); + pauline.reStart(); + coresList = bctbx_list_append(coresList, pauline.getLc()); + paulineCr = linphone_core_search_chat_room(pauline.getLc(), NULL, localAddr, peerAddr, NULL); + BC_ASSERT_PTR_NOT_NULL(paulineCr); + + LinphoneChatRoom *focusCr = linphone_core_search_chat_room(focus.getLc(), NULL, NULL, peerAddr, NULL); + BC_ASSERT_PTR_NOT_NULL(focusCr); + + LinphoneParticipant *paulineParticipant = NULL; + LinphoneParticipantDevice *paulineDevice = NULL; + + if (focusCr) { + paulineParticipant = linphone_chat_room_find_participant(focusCr, localAddr); + BC_ASSERT_PTR_NOT_NULL(paulineParticipant); + if (paulineParticipant) { + paulineDevice = linphone_participant_find_device(paulineParticipant, localAddr); + BC_ASSERT_PTR_NOT_NULL(paulineDevice); + } + } + + linphone_address_unref(localAddr); + linphone_address_unref(peerAddr); + + OrtpNetworkSimulatorParams simparams = {0}; + simparams.mode = OrtpNetworkSimulatorOutbound; + simparams.enabled = TRUE; + simparams.max_bandwidth = 430000; /*we first limit to 430 kbit/s*/ + simparams.max_buffer_size = (int)simparams.max_bandwidth; + simparams.latency = 60; + simparams.loss_rate = 90; + linphone_core_set_network_simulator_params(pauline.getLc(), &simparams); + linphone_core_set_network_simulator_params(focus.getLc(), &simparams); + + linphone_core_delete_chat_room(marie.getLc(), marieCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateDeleted, + marie_stat.number_of_LinphoneConferenceStateDeleted + 1, + liblinphone_tester_sip_timeout)); + + // wait until chatroom is deleted server side + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline}).wait([&paulineDevice] { + return (paulineDevice) ? (linphone_participant_device_get_state(paulineDevice) == + LinphoneParticipantDeviceStateLeaving) + : false; + })); + + BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_LinphoneChatRoomSessionReleased, 1, + liblinphone_tester_sip_timeout)); + + linphone_core_delete_chat_room(pauline.getLc(), paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneConferenceStateDeleted, + pauline_stat.number_of_LinphoneConferenceStateDeleted + 1, + liblinphone_tester_sip_timeout)); + } + } +} + +} // namespace LinphoneTest diff --git a/tester/local_conference_edition_tester.cpp b/tester/local_conference_edition_tester.cpp index 2930cd0b81beb2ed06da65482dbfe1525e154f3e..b3ca9070665795ae69e91f28bf8f550d5568d045 100644 --- a/tester/local_conference_edition_tester.cpp +++ b/tester/local_conference_edition_tester.cpp @@ -487,7 +487,10 @@ static void edit_simple_conference_base(bool_t from_organizer, bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, lise}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } diff --git a/tester/local_conference_tester_functions.cpp b/tester/local_conference_tester_functions.cpp index 10548cd40a5a9e0a9168395227cef25bbe13d858..22e44f1d83cb6ade9b192df7d3192418cff54d4d 100644 --- a/tester/local_conference_tester_functions.cpp +++ b/tester/local_conference_tester_functions.cpp @@ -19,8 +19,6 @@ */ #include "local_conference_tester_functions.h" -#include "chat/encryption/encryption-engine.h" -#include "conference/participant.h" #include "shared_tester_functions.h" #ifdef _MSC_VER @@ -34,1441 +32,6 @@ void setup_conference_info_cbs(LinphoneCoreManager *mgr) { namespace LinphoneTest { -void sendEphemeralMessageInAdminMode(Focus &focus, - ClientConference &sender, - ClientConference &recipient, - LinphoneChatRoom *senderCr, - LinphoneChatRoom *recipientCr, - const std::string basicText, - const int noMsg) { - - bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); - coresList = bctbx_list_append(coresList, sender.getLc()); - coresList = bctbx_list_append(coresList, recipient.getLc()); - - bctbx_list_t *senderHistory = linphone_chat_room_get_history(senderCr, 0); - auto initialSenderMessages = (int)bctbx_list_size(senderHistory); - bctbx_list_free_with_data(senderHistory, (bctbx_list_free_func)linphone_chat_message_unref); - - bctbx_list_t *recipientHistory = linphone_chat_room_get_history(recipientCr, 0); - auto initialRecipientMessages = (int)bctbx_list_size(recipientHistory); - bctbx_list_free_with_data(recipientHistory, (bctbx_list_free_func)linphone_chat_message_unref); - - int initialUnreadMessages = linphone_chat_room_get_unread_messages_count(recipientCr); - - auto sender_stat = sender.getStats(); - auto recipient_stat = recipient.getStats(); - - std::list<LinphoneChatMessage *> messages; - // Marie sends messages - for (int i = 0; i < noMsg; i++) { - const std::string text = basicText + std::to_string(i); - messages.push_back(_send_message_ephemeral(senderCr, text.c_str(), TRUE)); - } - - senderHistory = linphone_chat_room_get_history(senderCr, 0); - BC_ASSERT_EQUAL((int)bctbx_list_size(senderHistory), (noMsg + initialSenderMessages), int, "%i"); - set_ephemeral_cbs(senderHistory); - - BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneMessageReceived, - recipient_stat.number_of_LinphoneMessageReceived + noMsg, 11000)); - - // Check that the message has been delivered to Pauline - for (const auto &msg : messages) { - BC_ASSERT_TRUE(CoreManagerAssert({focus, sender, recipient}).wait([msg] { - return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); - })); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, sender, recipient}).wait([&, recipientCr] { - return linphone_chat_room_get_unread_messages_count(recipientCr) == (noMsg + initialUnreadMessages); - })); - - recipientHistory = linphone_chat_room_get_history(recipientCr, 0); - BC_ASSERT_EQUAL((int)bctbx_list_size(recipientHistory), (noMsg + initialRecipientMessages), int, "%i"); - set_ephemeral_cbs(recipientHistory); - - BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageDeliveredToUser, - sender_stat.number_of_LinphoneMessageDeliveredToUser + noMsg, - liblinphone_tester_sip_timeout)); - - // Pauline marks the message as read, check that the state is now displayed on Marie's side - linphone_chat_room_mark_as_read(recipientCr); - BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageDisplayed, - sender_stat.number_of_LinphoneMessageDisplayed + noMsg, - liblinphone_tester_sip_timeout)); - - BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneChatRoomEphemeralTimerStarted, - sender_stat.number_of_LinphoneChatRoomEphemeralTimerStarted + noMsg, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneChatRoomEphemeralTimerStarted, - recipient_stat.number_of_LinphoneChatRoomEphemeralTimerStarted + noMsg, - liblinphone_tester_sip_timeout)); - - BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageEphemeralTimerStarted, - sender_stat.number_of_LinphoneMessageEphemeralTimerStarted + noMsg, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneMessageEphemeralTimerStarted, - recipient_stat.number_of_LinphoneMessageEphemeralTimerStarted + noMsg, - liblinphone_tester_sip_timeout)); - - BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneChatRoomEphemeralDeleted, - sender_stat.number_of_LinphoneChatRoomEphemeralDeleted + noMsg, 15000)); - BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneChatRoomEphemeralDeleted, - recipient_stat.number_of_LinphoneChatRoomEphemeralDeleted + noMsg, 15000)); - - BC_ASSERT_TRUE(wait_for_list(coresList, &sender.getStats().number_of_LinphoneMessageEphemeralDeleted, - sender_stat.number_of_LinphoneMessageEphemeralDeleted + noMsg, 15000)); - BC_ASSERT_TRUE(wait_for_list(coresList, &recipient.getStats().number_of_LinphoneMessageEphemeralDeleted, - recipient_stat.number_of_LinphoneMessageEphemeralDeleted + noMsg, 15000)); - - bctbx_list_free_with_data(recipientHistory, (bctbx_list_free_func)linphone_chat_message_unref); - bctbx_list_free_with_data(senderHistory, (bctbx_list_free_func)linphone_chat_message_unref); - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, sender, recipient}).waitUntil(chrono::seconds(2), [] { return false; }); - - recipientHistory = linphone_chat_room_get_history(recipientCr, 0); - BC_ASSERT_EQUAL((int)bctbx_list_size(recipientHistory), initialRecipientMessages, int, "%i"); - senderHistory = linphone_chat_room_get_history(senderCr, 0); - BC_ASSERT_EQUAL((int)bctbx_list_size(senderHistory), initialSenderMessages, int, "%i"); - - for (auto &msg : messages) { - linphone_chat_message_unref(msg); - } - - bctbx_list_free_with_data(recipientHistory, (bctbx_list_free_func)linphone_chat_message_unref); - bctbx_list_free_with_data(senderHistory, (bctbx_list_free_func)linphone_chat_message_unref); - bctbx_list_free(coresList); -} - -bool checkChatroom(Focus &focus, const ConfCoreManager &core, const time_t baseJoiningTime) { - const auto &chatRooms = core.getCore().getChatRooms(); - if (chatRooms.size() < 1) { - return false; - } - - for (const auto &chatRoom : chatRooms) { - auto participants = chatRoom->getParticipants(); - if (focus.getLc() != core.getLc()) { - participants.push_back(chatRoom->getMe()); - } - for (const auto &participant : participants) { - for (const auto &device : participant->getDevices()) { - if (device->getState() != ParticipantDevice::State::Present) { - return false; - } - if (linphone_participant_device_is_in_conference(device->toC()) == FALSE) { - return false; - } - if ((baseJoiningTime >= 0) && - (linphone_participant_device_get_time_of_joining(device->toC()) >= baseJoiningTime)) { - return false; - } - } - } - } - return true; -} - -void group_chat_room_server_admin_managed_messages_base(bool_t encrypted) { - Focus focus("chloe_rc"); - { // to make sure focus is destroyed after clients. - ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); - - focus.registerAsParticipantDevice(marie); - focus.registerAsParticipantDevice(pauline); - - linphone_core_set_default_ephemeral_lifetime(marie.getLc(), 25); - - // Enable IMDN - 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(pauline.getLc())); - - bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); - coresList = bctbx_list_append(coresList, marie.getLc()); - coresList = bctbx_list_append(coresList, pauline.getLc()); - Address paulineAddr = pauline.getIdentity(); - bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(paulineAddr.toC())); - - stats chloe_stat = focus.getStats(); - stats marie_stat = marie.getStats(); - stats pauline_stat = pauline.getStats(); - - // Marie creates a new group chat room - const char *initialSubject = "Colleagues (characters: $ £ çà )"; - const LinphoneChatRoomEphemeralMode adminMode = LinphoneChatRoomEphemeralModeAdminManaged; - LinphoneChatRoomParams *params = linphone_core_create_default_chat_room_params(marie.getLc()); - - linphone_chat_room_params_enable_group(params, FALSE); - linphone_chat_room_params_enable_encryption(params, FALSE); - linphone_chat_room_params_set_ephemeral_mode(params, adminMode); - linphone_chat_room_params_set_ephemeral_lifetime(params, 5); - linphone_chat_room_params_set_backend(params, LinphoneChatRoomBackendFlexisipChat); - - LinphoneChatRoom *marieCr = create_chat_room_client_side_with_params( - coresList, marie.getCMgr(), &marie_stat, participantsAddresses, initialSubject, params); - linphone_chat_room_params_unref(params); - BC_ASSERT_PTR_NOT_NULL(marieCr); - const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); - - // Check that the chat room is correctly created on Pauline's side and that the participants are added - LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline.getCMgr(), &pauline_stat, - confAddr, initialSubject, 1, FALSE); - - BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_mode(marieCr), adminMode, int, "%d"); - BC_ASSERT_TRUE(linphone_chat_room_ephemeral_enabled(marieCr)); - BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_lifetime(marieCr), 5, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_mode(paulineCr), adminMode, int, "%d"); - BC_ASSERT_TRUE(linphone_chat_room_ephemeral_enabled(paulineCr)); - BC_ASSERT_EQUAL(linphone_chat_room_get_ephemeral_lifetime(paulineCr), 5, int, "%d"); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline}).wait([&focus] { - for (auto chatRoom : focus.getCore().getChatRooms()) { - for (auto participant : chatRoom->getParticipants()) { - for (auto device : participant->getDevices()) - if (device->getState() != ParticipantDevice::State::Present) { - return false; - } - } - } - return true; - })); - - chloe_stat = focus.getStats(); - marie_stat = marie.getStats(); - pauline_stat = pauline.getStats(); - - constexpr int noMsg = 10; - sendEphemeralMessageInAdminMode(focus, marie, pauline, marieCr, paulineCr, "Hello ", noMsg); - - 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, pauline}).wait([&focus] { - return focus.getCore().getChatRooms().size() == 0; - })); - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, marie, pauline}).waitUntil(chrono::seconds(2), [] { return false; }); - - // to avoid creation attempt of a new chatroom - auto config = focus.getDefaultProxyConfig(); - linphone_proxy_config_edit(config); - linphone_proxy_config_set_conference_factory_uri(config, NULL); - linphone_proxy_config_done(config); - - bctbx_list_free(coresList); - } -} - -void group_chat_room_with_client_restart_base(bool encrypted) { - Focus focus("chloe_rc"); - { // to make sure focus is destroyed after clients. - ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference michelle("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference laure("laure_tcp_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference berthe("berthe_rc", focus.getConferenceFactoryAddress(), encrypted); - - focus.registerAsParticipantDevice(marie); - focus.registerAsParticipantDevice(michelle); - focus.registerAsParticipantDevice(laure); - focus.registerAsParticipantDevice(berthe); - - bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); - coresList = bctbx_list_append(coresList, marie.getLc()); - coresList = bctbx_list_append(coresList, michelle.getLc()); - coresList = bctbx_list_append(coresList, laure.getLc()); - coresList = bctbx_list_append(coresList, berthe.getLc()); - bctbx_list_t *participantsAddresses = NULL; - Address michelleAddr = michelle.getIdentity(); - participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(michelleAddr.toC())); - Address bertheAddr = berthe.getIdentity(); - participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(bertheAddr.toC())); - - stats initialMarieStats = marie.getStats(); - stats initialMichelleStats = michelle.getStats(); - stats initialBertheStats = berthe.getStats(); - stats initialLaureStats = laure.getStats(); - - if (encrypted) { - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(berthe.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(laure.getLc())); - } - - // Marie creates a new group chat room - const char *initialSubject = "Colleagues (characters: $ £ çà )"; - LinphoneChatRoom *marieCr = create_chat_room_client_side_with_expected_number_of_participants( - coresList, marie.getCMgr(), &initialMarieStats, participantsAddresses, initialSubject, 2, encrypted, - LinphoneChatRoomEphemeralModeDeviceManaged); - const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); - - // Check that the chat room is correctly created on Michelle's side and that the participants are added - LinphoneChatRoom *michelleCr = check_creation_chat_room_client_side( - coresList, michelle.getCMgr(), &initialMichelleStats, confAddr, initialSubject, 2, FALSE); - - LinphoneChatRoom *bertheCr = check_creation_chat_room_client_side( - coresList, berthe.getCMgr(), &initialBertheStats, confAddr, initialSubject, 2, FALSE); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, laure, berthe}).wait([&focus] { - for (const auto &chatRoom : focus.getCore().getChatRooms()) { - for (const auto &participant : chatRoom->getParticipants()) { - for (const auto &device : participant->getDevices()) { - if (device->getState() != ParticipantDevice::State::Present) { - return false; - } - } - } - } - return true; - })); - - 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, &berthe.getStats().number_of_LinphoneConferenceStateCreated, - initialBertheStats.number_of_LinphoneConferenceStateCreated + 1, - liblinphone_tester_sip_timeout)); - - // Marie now changes the subject - const char *newSubject = "Let's go drink a beer"; - linphone_chat_room_set_subject(marieCr, newSubject); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_subject_changed, - initialMarieStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_subject_changed, - initialMichelleStats.number_of_subject_changed + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_subject_changed, - initialBertheStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(michelleCr), newSubject); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(bertheCr), newSubject); - - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 2, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelleCr), 2, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(bertheCr), 2, int, "%d"); - - const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores2{focus, marie, michelle, berthe}; - for (const ConfCoreManager &core : cores2) { - BC_ASSERT_TRUE( - CoreManagerAssert({focus, marie, michelle, berthe, laure}) - .waitUntil(chrono::seconds(10), [&focus, &core] { return checkChatroom(focus, core, -1); })); - }; - - ClientConference michelle2("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); - stats initialMichelle2Stats = michelle2.getStats(); - coresList = bctbx_list_append(coresList, michelle2.getLc()); - if (encrypted) { - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle2.getLc())); - } - - focus.registerAsParticipantDevice(michelle2); - - LinphoneAddress *michelle2Contact = linphone_address_clone( - linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(michelle2.getLc()))); - char *michelle2ContactString = linphone_address_as_string(michelle2Contact); - ms_message("%s is adding device %s", linphone_core_get_identity(focus.getLc()), michelle2ContactString); - ms_free(michelle2ContactString); - focus.registerAsParticipantDevice(michelle2); - - // Notify chat room that a participant has registered - bctbx_list_t *devices = NULL; - const LinphoneAddress *deviceAddr = linphone_proxy_config_get_contact(michelle.getDefaultProxyConfig()); - LinphoneParticipantDeviceIdentity *identity = - linphone_factory_create_participant_device_identity(linphone_factory_get(), deviceAddr, ""); - bctbx_list_t *specs = linphone_core_get_linphone_specs_list(michelle.getLc()); - linphone_participant_device_identity_set_capability_descriptor_2(identity, specs); - bctbx_list_free_with_data(specs, ms_free); - devices = bctbx_list_append(devices, identity); - - deviceAddr = linphone_proxy_config_get_contact(michelle2.getDefaultProxyConfig()); - identity = linphone_factory_create_participant_device_identity(linphone_factory_get(), deviceAddr, ""); - specs = linphone_core_get_linphone_specs_list(michelle2.getLc()); - linphone_participant_device_identity_set_capability_descriptor_2(identity, specs); - bctbx_list_free_with_data(specs, ms_free); - devices = bctbx_list_append(devices, identity); - - for (auto chatRoom : focus.getCore().getChatRooms()) { - linphone_chat_room_set_participant_devices(L_GET_C_BACK_PTR(chatRoom), michelle.getCMgr()->identity, - devices); - } - bctbx_list_free_with_data(devices, (bctbx_list_free_func)belle_sip_object_unref); - - LinphoneChatRoom *michelle2Cr = check_creation_chat_room_client_side( - coresList, michelle2.getCMgr(), &initialMichelle2Stats, confAddr, newSubject, 2, FALSE); - BC_ASSERT_PTR_NOT_NULL(michelle2Cr); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateCreated, - initialMichelle2Stats.number_of_LinphoneConferenceStateCreated + 1, - liblinphone_tester_sip_timeout)); - - const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores3{focus, marie, michelle, michelle2, - berthe}; - for (const ConfCoreManager &core : cores3) { - BC_ASSERT_TRUE( - CoreManagerAssert({focus, marie, michelle, michelle2, berthe, laure}) - .waitUntil(chrono::seconds(10), [&focus, &core] { return checkChatroom(focus, core, -1); })); - }; - - initialMarieStats = marie.getStats(); - initialMichelleStats = michelle.getStats(); - initialBertheStats = berthe.getStats(); - initialLaureStats = laure.getStats(); - - Address laureAddr = laure.getIdentity(); - participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(laureAddr.toC())); - ms_message("%s is adding participant %s", linphone_core_get_identity(focus.getLc()), - linphone_core_get_identity(laure.getLc())); - linphone_chat_room_add_participants(marieCr, participantsAddresses); - bctbx_list_free(participantsAddresses); - - LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure.getCMgr(), &initialLaureStats, - confAddr, newSubject, 3, FALSE); - BC_ASSERT_PTR_NOT_NULL(laureCr); - - BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneConferenceStateCreationPending, - initialLaureStats.number_of_LinphoneConferenceStateCreationPending + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneConferenceStateCreated, - initialLaureStats.number_of_LinphoneConferenceStateCreated + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneChatRoomConferenceJoined, - initialLaureStats.number_of_LinphoneChatRoomConferenceJoined + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_participants_added, - initialMarieStats.number_of_participants_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_participants_added, - initialBertheStats.number_of_participants_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participants_added, - initialMichelleStats.number_of_participants_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_participants_added, - initialMichelle2Stats.number_of_participants_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_participant_devices_added, - initialMarieStats.number_of_participant_devices_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_participant_devices_added, - initialBertheStats.number_of_participant_devices_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participant_devices_added, - initialMichelleStats.number_of_participant_devices_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_participant_devices_added, - initialMichelle2Stats.number_of_participant_devices_added + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 3, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(bertheCr), 3, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelleCr), 3, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelle2Cr), 3, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 3, int, "%d"); - - const std::initializer_list<std::reference_wrapper<ConfCoreManager>> cores{focus, marie, michelle, - michelle2, laure, berthe}; - for (const ConfCoreManager &core : cores) { - BC_ASSERT_TRUE( - CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}) - .waitUntil(chrono::seconds(10), [&focus, &core] { return checkChatroom(focus, core, -1); })); - for (auto chatRoom : core.getCore().getChatRooms()) { - BC_ASSERT_EQUAL(chatRoom->getParticipants().size(), ((focus.getLc() == core.getLc())) ? 4 : 3, size_t, - "%zu"); - BC_ASSERT_STRING_EQUAL(chatRoom->getSubject().c_str(), newSubject); - } - }; - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(chrono::seconds(1), [] { - return false; - }); - - time_t participantAddedTime = ms_time(nullptr); - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(chrono::seconds(10), [] { - 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()); - for (auto chatRoom : focus.getCore().getChatRooms()) { - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(L_GET_C_BACK_PTR(chatRoom)), 4, int, "%d"); - } - - michelle2ContactString = linphone_address_as_string(michelle2Contact); - ms_message("%s is restarting its core", michelle2ContactString); - ms_free(michelle2ContactString); - coresList = bctbx_list_remove(coresList, michelle2.getLc()); - // Restart michelle - michelle2.reStart(); - coresList = bctbx_list_append(coresList, michelle2.getLc()); - - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateCreated, 1, - liblinphone_tester_sip_timeout)); - LinphoneAddress *michelleDeviceAddr = - linphone_address_clone(linphone_proxy_config_get_contact(michelle2.getDefaultProxyConfig())); - michelle2Cr = michelle2.searchChatRoom(michelleDeviceAddr, confAddr); - BC_ASSERT_PTR_NOT_NULL(michelle2Cr); - for (const ConfCoreManager &core : cores) { - BC_ASSERT_TRUE(checkChatroom(focus, core, participantAddedTime)); - for (auto chatRoom : core.getCore().getChatRooms()) { - BC_ASSERT_EQUAL(chatRoom->getParticipants().size(), ((focus.getLc() == core.getLc())) ? 4 : 3, size_t, - "%zu"); - BC_ASSERT_STRING_EQUAL(chatRoom->getSubject().c_str(), newSubject); - } - } - - LinphoneChatMessage *msg = linphone_chat_room_create_message_from_utf8(michelle2Cr, "back with you"); - linphone_chat_message_send(msg); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([msg] { - return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); - })); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([marieCr] { - return linphone_chat_room_get_unread_messages_count(marieCr) == 1; - })); - linphone_chat_message_unref(msg); - msg = NULL; - - msg = linphone_chat_room_create_message_from_utf8(marieCr, "welcome back"); - linphone_chat_message_send(msg); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([msg] { - return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); - })); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([michelleCr] { - return linphone_chat_room_get_unread_messages_count(michelleCr) == 1; - })); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([michelle2Cr] { - return linphone_chat_room_get_unread_messages_count(michelle2Cr) == 1; - })); - linphone_chat_message_unref(msg); - msg = NULL; - - msg = linphone_chat_room_create_message_from_utf8(michelleCr, "message blabla"); - linphone_chat_message_send(msg); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([msg] { - return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); - })); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).wait([marieCr] { - return linphone_chat_room_get_unread_messages_count(marieCr) == 2; - })); - linphone_chat_message_unref(msg); - - CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(std::chrono::seconds(2), [] { - return false; - }); - - 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, michelle, michelle2, laure, berthe}).wait([&focus] { - return focus.getCore().getChatRooms().size() == 0; - })); - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, marie, michelle, michelle2, laure, berthe}).waitUntil(chrono::seconds(2), [] { - return false; - }); - - // to avoid creation attempt of a new chatroom - auto config = focus.getDefaultProxyConfig(); - linphone_proxy_config_edit(config); - linphone_proxy_config_set_conference_factory_uri(config, NULL); - linphone_proxy_config_done(config); - - linphone_address_unref(michelle2Contact); - linphone_address_unref(michelleDeviceAddr); - bctbx_list_free(coresList); - } -} - -static void chat_room_participant_added_sip_error(LinphoneChatRoom *cr, - BCTBX_UNUSED(const LinphoneEventLog *event_log)) { - bctbx_list_t *participants = linphone_chat_room_get_participants(cr); - if (bctbx_list_size(participants) == 2) { - LinphoneCoreManager *initiator = (LinphoneCoreManager *)linphone_chat_room_get_user_data(cr); - ms_message("Turning off network for core %s", linphone_core_get_identity(initiator->lc)); - linphone_core_set_network_reachable(initiator->lc, FALSE); - } - if (participants) { - bctbx_list_free_with_data(participants, (bctbx_list_free_func)linphone_participant_unref); - } -} - -static void -server_core_chat_room_state_changed_sip_error(LinphoneCore *core, LinphoneChatRoom *cr, LinphoneChatRoomState state) { - Focus *focus = (Focus *)(((LinphoneCoreManager *)linphone_core_get_user_data(core))->user_info); - switch (state) { - case LinphoneChatRoomStateInstantiated: { - LinphoneChatRoomCbs *cbs = linphone_factory_create_chat_room_cbs(linphone_factory_get()); - linphone_chat_room_cbs_set_participant_added(cbs, chat_room_participant_added_sip_error); - linphone_chat_room_add_callbacks(cr, cbs); - linphone_chat_room_cbs_set_user_data(cbs, focus); - linphone_chat_room_cbs_unref(cbs); - break; - } - default: - break; - } -} - -void group_chat_room_with_sip_errors_base(bool invite_error, bool subscribe_error, bool encrypted) { - Focus focus("chloe_rc"); - { // to make sure focus is destroyed after clients. - ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference laure("laure_tcp_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference berthe("berthe_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference michelle("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference michelle2("michelle_rc", focus.getConferenceFactoryAddress(), encrypted); - - stats initialFocusStats = focus.getStats(); - stats initialMarieStats = marie.getStats(); - stats initialMichelleStats = michelle.getStats(); - stats initialMichelle2Stats = michelle2.getStats(); - stats initialLaureStats = laure.getStats(); - stats initialBertheStats = berthe.getStats(); - stats initialPaulineStats = pauline.getStats(); - - bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); - coresList = bctbx_list_append(coresList, marie.getLc()); - coresList = bctbx_list_append(coresList, michelle.getLc()); - coresList = bctbx_list_append(coresList, michelle2.getLc()); - coresList = bctbx_list_append(coresList, pauline.getLc()); - coresList = bctbx_list_append(coresList, laure.getLc()); - coresList = bctbx_list_append(coresList, berthe.getLc()); - - if (encrypted) { - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(pauline.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(laure.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle2.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(berthe.getLc())); - } - - linphone_core_set_network_reachable(marie.getLc(), FALSE); - linphone_core_set_network_reachable(berthe.getLc(), FALSE); - - char *spec = bctbx_strdup_printf("groupchat/1.1"); - linphone_core_remove_linphone_spec(marie.getLc(), "groupchat"); - linphone_core_add_linphone_spec(marie.getLc(), spec); - linphone_core_remove_linphone_spec(berthe.getLc(), "groupchat"); - linphone_core_add_linphone_spec(berthe.getLc(), spec); - bctbx_free(spec); - - linphone_core_set_network_reachable(marie.getLc(), TRUE); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneRegistrationOk, - initialMarieStats.number_of_LinphoneRegistrationOk + 1, - liblinphone_tester_sip_timeout)); - linphone_core_set_network_reachable(berthe.getLc(), TRUE); - BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_LinphoneRegistrationOk, - initialBertheStats.number_of_LinphoneRegistrationOk + 1, - liblinphone_tester_sip_timeout)); - - initialMarieStats = marie.getStats(); - initialBertheStats = berthe.getStats(); - - std::list<LinphoneCoreManager *> shutdownNetworkClients; - std::list<stats> initialStatsList; - if (invite_error) { - shutdownNetworkClients.push_back(michelle2.getCMgr()); - initialStatsList.push_back(michelle2.getStats()); - shutdownNetworkClients.push_back(berthe.getCMgr()); - initialStatsList.push_back(berthe.getStats()); - } else if (subscribe_error) { - shutdownNetworkClients.push_back(marie.getCMgr()); - initialStatsList.push_back(marie.getStats()); - shutdownNetworkClients.push_back(michelle2.getCMgr()); - initialStatsList.push_back(michelle2.getStats()); - shutdownNetworkClients.push_back(berthe.getCMgr()); - initialStatsList.push_back(berthe.getStats()); - } - - focus.registerAsParticipantDevice(marie); - focus.registerAsParticipantDevice(michelle); - focus.registerAsParticipantDevice(michelle2); - focus.registerAsParticipantDevice(pauline); - focus.registerAsParticipantDevice(berthe); - - if (invite_error) { - LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); - linphone_core_cbs_set_chat_room_state_changed(cbs, server_core_chat_room_state_changed_sip_error); - linphone_core_add_callbacks(focus.getLc(), cbs); - linphone_core_cbs_unref(cbs); - } - - 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(michelle.getLc())); - linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(michelle2.getLc())); - linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline.getLc())); - linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(laure.getLc())); - linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(berthe.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())); - Address bertheAddr = berthe.getIdentity(); - participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(bertheAddr.toC())); - Address paulineAddr = pauline.getIdentity(); - participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(paulineAddr.toC())); - - const char *initialSubject = "Colleagues (characters: $ £ çà )"; - int participantsAddressesSize = (int)bctbx_list_size(participantsAddresses); - LinphoneChatRoomParams *params = linphone_core_create_default_chat_room_params(marie.getLc()); - - linphone_chat_room_params_enable_encryption(params, encrypted); - linphone_chat_room_params_set_ephemeral_mode(params, LinphoneChatRoomEphemeralModeDeviceManaged); - linphone_chat_room_params_set_backend(params, LinphoneChatRoomBackendFlexisipChat); - linphone_chat_room_params_enable_group(params, participantsAddressesSize > 1 ? TRUE : FALSE); - // Marie creates a new group chat room - LinphoneChatRoom *marieCr = - linphone_core_create_chat_room_2(marie.getLc(), params, initialSubject, participantsAddresses); - linphone_chat_room_params_unref(params); - if (marieCr) linphone_chat_room_unref(marieCr); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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()); - } - - for (const auto &client : shutdownNetworkClients) { - stats &initialStats = initialStatsList.front(); - BC_ASSERT_TRUE(wait_for_list(coresList, &client->stat.number_of_LinphoneConferenceStateCreated, - initialStats.number_of_LinphoneConferenceStateCreated + 1, - liblinphone_tester_sip_timeout)); - char *proxy_contact_str = linphone_address_as_string( - linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(client->lc))); - ms_message("Disabling network of core %s (contact %s)", linphone_core_get_identity(client->lc), - proxy_contact_str); - ms_free(proxy_contact_str); - linphone_core_set_network_reachable(client->lc, FALSE); - initialStatsList.pop_front(); - } - - BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participants_added, - initialFocusStats.number_of_participants_added + 4, 5000)); - BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participant_devices_added, - initialFocusStats.number_of_participant_devices_added + 5, 5000)); - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}) - .waitUntil(chrono::seconds(60), [] { return false; }); - - check_create_chat_room_client_side(coresList, marie.getCMgr(), marieCr, &initialMarieStats, - participantsAddresses, initialSubject, 2); - 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 *michelleCr = check_creation_chat_room_client_side( - coresList, michelle.getCMgr(), &initialMichelleStats, confAddr, initialSubject, 3, FALSE); - LinphoneChatRoom *michelle2Cr = check_creation_chat_room_client_side( - coresList, michelle2.getCMgr(), &initialMichelle2Stats, confAddr, initialSubject, 3, FALSE); - LinphoneChatRoom *bertheCr = check_creation_chat_room_client_side( - coresList, berthe.getCMgr(), &initialBertheStats, confAddr, initialSubject, 3, FALSE); - LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side( - coresList, pauline.getCMgr(), &initialPaulineStats, confAddr, initialSubject, 3, 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, &berthe.getStats().number_of_LinphoneConferenceStateCreated, - initialBertheStats.number_of_LinphoneConferenceStateCreated + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneConferenceStateCreated, - initialPaulineStats.number_of_LinphoneConferenceStateCreated + 1, - liblinphone_tester_sip_timeout)); - - std::string msg_text = "message michelle blabla"; - LinphoneChatMessage *msg = ClientConference::sendTextMsg(michelleCr, msg_text); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { - return (msg && (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered)); - })); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { - return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; - })); - LinphoneChatMessage *paulineLastMsg = pauline.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); - if (paulineLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); - } - linphone_chat_room_mark_as_read(paulineCr); - - BC_ASSERT_FALSE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneMessageDisplayed, - initialMichelleStats.number_of_LinphoneMessageDisplayed + 1, 3000)); - - if (invite_error || subscribe_error) { - char *marie_proxy_contact_str = linphone_address_as_string( - linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(marie.getLc()))); - ms_message("Enabling network of core %s (contact %s)", linphone_core_get_identity(marie.getLc()), - marie_proxy_contact_str); - ms_free(marie_proxy_contact_str); - linphone_core_set_network_reachable(marie.getLc(), TRUE); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneRegistrationOk, - initialMarieStats.number_of_LinphoneRegistrationOk + 1, - liblinphone_tester_sip_timeout)); - marieCr = check_creation_chat_room_client_side(coresList, marie.getCMgr(), &initialMarieStats, confAddr, - initialSubject, 3, TRUE); - } - - focus.registerAsParticipantDevice(laure); - Address laureAddr = laure.getIdentity(); - linphone_chat_room_add_participant(marieCr, linphone_address_ref(laureAddr.toC())); - LinphoneChatRoom *laureCr = check_creation_chat_room_client_side( - coresList, laure.getCMgr(), &initialPaulineStats, confAddr, initialSubject, 4, FALSE); - - BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participants_added, - initialFocusStats.number_of_participants_added + 4, 5000)); - BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_participant_devices_added, - initialFocusStats.number_of_participant_devices_added + 5, 5000)); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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()); - } - - msg_text = "message laure blabla"; - LinphoneChatMessage *msg2 = ClientConference::sendTextMsg(laureCr, msg_text); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg2] { - return (linphone_chat_message_get_state(msg2) == LinphoneChatMessageStateDelivered); - })); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { - return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; - })); - paulineLastMsg = pauline.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); - if (paulineLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([marieCr] { - return linphone_chat_room_get_unread_messages_count(marieCr) == 2; - })); - 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, pauline, michelle, michelle2, laure, berthe}).wait([michelleCr] { - return linphone_chat_room_get_unread_messages_count(michelleCr) == 1; - })); - LinphoneChatMessage *michelleLastMsg = michelle.getStats().last_received_chat_message; - if (michelleLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(michelleLastMsg), msg_text.c_str()); - } - - linphone_chat_room_mark_as_read(paulineCr); - linphone_chat_room_mark_as_read(marieCr); - linphone_chat_room_mark_as_read(michelleCr); - - BC_ASSERT_FALSE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneMessageDisplayed, - initialLaureStats.number_of_LinphoneMessageDisplayed + 1, 3000)); - - if (invite_error || subscribe_error) { - char *michelle2_proxy_contact_str = linphone_address_as_string( - linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(michelle2.getLc()))); - ms_message("Enabling network of core %s (contact %s)", linphone_core_get_identity(michelle2.getLc()), - michelle2_proxy_contact_str); - ms_free(michelle2_proxy_contact_str); - linphone_core_set_network_reachable(michelle2.getLc(), TRUE); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneRegistrationOk, - initialMichelle2Stats.number_of_LinphoneRegistrationOk + 1, - liblinphone_tester_sip_timeout)); - michelle2Cr = check_creation_chat_room_client_side(coresList, michelle2.getCMgr(), &initialMichelle2Stats, - confAddr, initialSubject, 4, FALSE); - - char *berthe_proxy_contact_str = linphone_address_as_string( - linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(berthe.getLc()))); - ms_message("Enabling network of core %s (contact %s)", linphone_core_get_identity(berthe.getLc()), - berthe_proxy_contact_str); - ms_free(berthe_proxy_contact_str); - linphone_core_set_network_reachable(berthe.getLc(), TRUE); - BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_LinphoneRegistrationOk, - initialBertheStats.number_of_LinphoneRegistrationOk + 1, - liblinphone_tester_sip_timeout)); - bertheCr = check_creation_chat_room_client_side(coresList, berthe.getCMgr(), &initialBertheStats, confAddr, - initialSubject, 4, FALSE); - } - - LinphoneChatMessage *michelle2LastMsg = NULL; - if (!invite_error) { - - BC_ASSERT_TRUE( - CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([michelle2Cr] { - return linphone_chat_room_get_history_size(michelle2Cr) == 2; - })); - 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); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { - return linphone_chat_room_get_history_size(bertheCr) == 2; - })); - - LinphoneChatMessage *bertheLastMsg = berthe.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); - if (bertheLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); - } - linphone_chat_room_mark_as_read(bertheCr); - - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneMessageDisplayed, - initialMichelleStats.number_of_LinphoneMessageDisplayed + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneMessageDisplayed, - initialLaureStats.number_of_LinphoneMessageDisplayed + 1, - liblinphone_tester_sip_timeout)); - - linphone_chat_message_unref(msg); - msg = nullptr; - linphone_chat_message_unref(msg2); - msg2 = nullptr; - - // Marie now changes the subject - const char *newSubject = "Let's go drink a beer"; - linphone_chat_room_set_subject(marieCr, newSubject); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_subject_changed, - initialMarieStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_subject_changed, - initialMichelleStats.number_of_subject_changed + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_subject_changed, - initialMichelle2Stats.number_of_subject_changed + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_subject_changed, - initialPaulineStats.number_of_subject_changed + 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_subject_changed, - initialLaureStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_subject_changed, - initialBertheStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout)); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(michelleCr), newSubject); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(michelle2Cr), newSubject); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); - BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(bertheCr), newSubject); - - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelleCr), 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(michelle2Cr), 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(bertheCr), 4, int, "%d"); - - msg_text = "message marie blabla"; - msg = ClientConference::sendTextMsg(marieCr, msg_text); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { - return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); - })); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { - return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; - })); - paulineLastMsg = pauline.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); - if (paulineLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([laureCr] { - return linphone_chat_room_get_unread_messages_count(laureCr) == 1; - })); - LinphoneChatMessage *laureLastMsg = laure.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(laureLastMsg); - if (laureLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), msg_text.c_str()); - } - - BC_ASSERT_TRUE( - CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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, pauline, michelle, michelle2, laure, berthe}).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()); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { - return linphone_chat_room_get_unread_messages_count(bertheCr) == 1; - })); - bertheLastMsg = berthe.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); - if (bertheLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); - } - - linphone_chat_room_mark_as_read(michelleCr); - linphone_chat_room_mark_as_read(michelle2Cr); - linphone_chat_room_mark_as_read(paulineCr); - linphone_chat_room_mark_as_read(laureCr); - linphone_chat_room_mark_as_read(bertheCr); - - 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"; - msg = ClientConference::sendTextMsg(michelle2Cr, msg_text); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { - return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); - })); - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([paulineCr] { - return linphone_chat_room_get_unread_messages_count(paulineCr) == 1; - })); - paulineLastMsg = pauline.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); - if (paulineLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), msg_text.c_str()); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { - return linphone_chat_room_get_unread_messages_count(bertheCr) == 1; - })); - bertheLastMsg = berthe.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); - if (bertheLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([laureCr] { - return linphone_chat_room_get_unread_messages_count(laureCr) == 1; - })); - laureLastMsg = laure.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(laureLastMsg); - if (laureLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), msg_text.c_str()); - } - - 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, pauline, michelle, michelle2, laure, berthe}).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()); - } - - linphone_chat_room_mark_as_read(michelleCr); - linphone_chat_room_mark_as_read(marieCr); - linphone_chat_room_mark_as_read(paulineCr); - linphone_chat_room_mark_as_read(laureCr); - linphone_chat_room_mark_as_read(bertheCr); - - 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; - - msg_text = "message pauline blabla"; - msg = ClientConference::sendTextMsg(paulineCr, msg_text); - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] { - return (linphone_chat_message_get_state(msg) == LinphoneChatMessageStateDelivered); - })); - - BC_ASSERT_TRUE( - CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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, pauline, michelle, michelle2, laure, berthe}).wait([bertheCr] { - return linphone_chat_room_get_unread_messages_count(bertheCr) == 1; - })); - bertheLastMsg = berthe.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(bertheLastMsg); - if (bertheLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(bertheLastMsg), msg_text.c_str()); - } - - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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, pauline, michelle, michelle2, laure, berthe}).wait([laureCr] { - return linphone_chat_room_get_unread_messages_count(laureCr) == 1; - })); - laureLastMsg = laure.getStats().last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(laureLastMsg); - if (laureLastMsg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), msg_text.c_str()); - } - - BC_ASSERT_TRUE( - CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).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(michelleCr); - linphone_chat_room_mark_as_read(michelle2Cr); - linphone_chat_room_mark_as_read(marieCr); - linphone_chat_room_mark_as_read(laureCr); - linphone_chat_room_mark_as_read(bertheCr); - - BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneMessageDisplayed, - initialPaulineStats.number_of_LinphoneMessageDisplayed + 1, - liblinphone_tester_sip_timeout)); - linphone_chat_message_unref(msg); - msg = nullptr; - - CoreManagerAssert({focus, marie}).waitUntil(std::chrono::seconds(1), [] { return false; }); - - CoreManagerAssert({focus, marie}).waitUntil(std::chrono::seconds(2), [] { return false; }); - - 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, pauline, michelle, michelle2, laure, berthe}).wait([&focus] { - return focus.getCore().getChatRooms().size() == 0; - })); - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}) - .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); - } -} - -void group_chat_room_lime_server_message(bool encrypted) { - Focus focus("chloe_rc"); - LinphoneChatMessage *msg; - { // to make sure focus is destroyed after clients. - linphone_core_enable_lime_x3dh(focus.getLc(), true); - - ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference laure("laure_tcp_rc", focus.getConferenceFactoryAddress(), encrypted); - - focus.registerAsParticipantDevice(marie); - focus.registerAsParticipantDevice(pauline); - focus.registerAsParticipantDevice(laure); - - stats marie_stat = marie.getStats(); - stats pauline_stat = pauline.getStats(); - stats laure_stat = laure.getStats(); - bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); - coresList = bctbx_list_append(coresList, marie.getLc()); - coresList = bctbx_list_append(coresList, pauline.getLc()); - coresList = bctbx_list_append(coresList, laure.getLc()); - - if (encrypted) { - auto rawEncryptionSuccess = 0; - - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(pauline.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(laure.getLc())); - - // Test the raw encryption/decryption - auto marieEncryptionEngine = L_GET_CPP_PTR_FROM_C_OBJECT(marie.getCMgr()->lc)->getEncryptionEngine(); - char *deviceId = linphone_address_as_string_uri_only( - linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(marie.getLc()))); - std::string marieAddressString{deviceId}; - bctbx_free(deviceId); - auto paulineEncryptionEngine = L_GET_CPP_PTR_FROM_C_OBJECT(pauline.getCMgr()->lc)->getEncryptionEngine(); - deviceId = linphone_address_as_string_uri_only( - linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(pauline.getLc()))); - std::string paulineAddressString{deviceId}; - bctbx_free(deviceId); - - std::string messageString = "This is my message to you Rudy"; - std::string ADString = "These are my AD to you Rudy"; - auto message = std::make_shared<std::vector<uint8_t>>(messageString.cbegin(), messageString.cend()); - auto AD = std::make_shared<std::vector<uint8_t>>(ADString.cbegin(), ADString.cend()); - std::vector<uint8_t> cipherText{}; - - marieEncryptionEngine->rawEncrypt( - marieAddressString, std::list<std::string>{paulineAddressString}, message, AD, - [&rawEncryptionSuccess, &cipherText, paulineAddressString]( - const bool status, std::unordered_map<std::string, std::vector<uint8_t>> cipherTexts) { - auto search = cipherTexts.find(paulineAddressString); - if (status && search != cipherTexts.end()) { - rawEncryptionSuccess++; - cipherText = cipherTexts[paulineAddressString]; - } - }); - - BC_ASSERT_TRUE(wait_for_list(coresList, &rawEncryptionSuccess, 1, x3dhServer_creationTimeout)); - if (rawEncryptionSuccess == 1) { - // try to decrypt only if encryption was a success - std::vector<uint8_t> plainText{}; - BC_ASSERT_TRUE(paulineEncryptionEngine->rawDecrypt(paulineAddressString, marieAddressString, *AD, - cipherText, plainText)); - std::string plainTextString{plainText.cbegin(), plainText.cend()}; - BC_ASSERT_TRUE(plainTextString == messageString); - } - } - - Address paulineAddr = pauline.getIdentity(); - Address laureAddr = laure.getIdentity(); - bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(paulineAddr.toC())); - participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_ref(laureAddr.toC())); - - // Marie creates a new group chat room - const char *initialSubject = "Colleagues"; - LinphoneChatRoom *marieCr = - create_chat_room_client_side(coresList, marie.getCMgr(), &marie_stat, participantsAddresses, initialSubject, - encrypted, LinphoneChatRoomEphemeralModeDeviceManaged); - BC_ASSERT_PTR_NOT_NULL(marieCr); - const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); - - // Check that the chat room is correctly created on Pauline's side and that the participants are added - LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline.getCMgr(), &pauline_stat, - confAddr, initialSubject, 2, FALSE); - BC_ASSERT_PTR_NOT_NULL(paulineCr); - LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure.getCMgr(), &laure_stat, - confAddr, initialSubject, 2, FALSE); - BC_ASSERT_PTR_NOT_NULL(laureCr); - if (paulineCr && laureCr) { - // Marie sends the message - const char *marieMessage = "Hey ! What's up ?"; - msg = _send_message_ephemeral(marieCr, marieMessage, FALSE); - BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneMessageReceived, - pauline_stat.number_of_LinphoneMessageReceived + 1, - liblinphone_tester_sip_timeout)); - LinphoneChatMessage *paulineLastMsg = pauline.getStats().last_received_chat_message; - BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_LinphoneMessageReceived, - laure_stat.number_of_LinphoneMessageReceived + 1, - liblinphone_tester_sip_timeout)); - LinphoneChatMessage *laureLastMsg = laure.getStats().last_received_chat_message; - linphone_chat_message_unref(msg); - if (paulineLastMsg && laureLastMsg) { - // Check that the message was correctly decrypted if encrypted - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), marieMessage); - LinphoneAddress *marieAddr = marie.getCMgr()->identity; - BC_ASSERT_TRUE( - linphone_address_weak_equal(marieAddr, linphone_chat_message_get_from_address(paulineLastMsg))); - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(laureLastMsg), marieMessage); - BC_ASSERT_TRUE( - linphone_address_weak_equal(marieAddr, linphone_chat_message_get_from_address(laureLastMsg))); - } - } - - 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, pauline, laure}).wait([&focus] { - return focus.getCore().getChatRooms().size() == 0; - })); - - // wait bit more to detect side effect if any - CoreManagerAssert({focus, marie, pauline, laure}).waitUntil(chrono::seconds(2), [] { return false; }); - - // to avoid creation attempt of a new chatroom - auto config = focus.getDefaultProxyConfig(); - linphone_proxy_config_edit(config); - linphone_proxy_config_set_conference_factory_uri(config, NULL); - linphone_proxy_config_done(config); - - bctbx_list_free(coresList); - } -} - -void one_to_one_group_chat_room_deletion_by_server_client_base(bool encrypted) { - Focus focus("chloe_rc"); - LinphoneChatMessage *msg; - { // to make sure focus is destroyed after clients. - linphone_core_enable_lime_x3dh(focus.getLc(), true); - - ClientConference marie("marie_rc", focus.getConferenceFactoryAddress(), encrypted); - ClientConference pauline("pauline_rc", focus.getConferenceFactoryAddress(), encrypted); - - focus.registerAsParticipantDevice(marie); - focus.registerAsParticipantDevice(pauline); - - stats marie_stat = marie.getStats(); - stats pauline_stat = pauline.getStats(); - bctbx_list_t *coresList = bctbx_list_append(NULL, focus.getLc()); - coresList = bctbx_list_append(coresList, marie.getLc()); - coresList = bctbx_list_append(coresList, pauline.getLc()); - - if (encrypted) { - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(marie.getLc())); - BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(pauline.getLc())); - } - - Address paulineAddr = pauline.getIdentity(); - bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_ref(paulineAddr.toC())); - - // Marie creates a new group chat room - const char *initialSubject = "Colleagues"; - LinphoneChatRoom *marieCr = - create_chat_room_client_side(coresList, marie.getCMgr(), &marie_stat, participantsAddresses, initialSubject, - encrypted, LinphoneChatRoomEphemeralModeDeviceManaged); - BC_ASSERT_PTR_NOT_NULL(marieCr); - const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); - - // Check that the chat room is correctly created on Pauline's side and that the participants are added - LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline.getCMgr(), &pauline_stat, - confAddr, initialSubject, 1, FALSE); - BC_ASSERT_PTR_NOT_NULL(paulineCr); - - if (paulineCr && marieCr) { - // Marie sends the message - const char *marieMessage = "Hey ! What's up ?"; - msg = _send_message(marieCr, marieMessage); - BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneMessageReceived, - pauline_stat.number_of_LinphoneMessageReceived + 1, - liblinphone_tester_sip_timeout)); - LinphoneChatMessage *paulineLastMsg = pauline.getStats().last_received_chat_message; - linphone_chat_message_unref(msg); - BC_ASSERT_PTR_NOT_NULL(paulineLastMsg); - - // Check that the message was correctly decrypted if encrypted - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_utf8_text(paulineLastMsg), marieMessage); - LinphoneAddress *marieAddr = marie.getCMgr()->identity; - BC_ASSERT_TRUE( - linphone_address_weak_equal(marieAddr, linphone_chat_message_get_from_address(paulineLastMsg))); - - LinphoneAddress *localAddr = linphone_address_clone(linphone_chat_room_get_local_address(paulineCr)); - LinphoneAddress *peerAddr = linphone_address_clone(linphone_chat_room_get_peer_address(paulineCr)); - - // Restart pauline so that she has to send an INVITE and BYE it to exit the chatroom - coresList = bctbx_list_remove(coresList, pauline.getLc()); - pauline.reStart(); - coresList = bctbx_list_append(coresList, pauline.getLc()); - paulineCr = linphone_core_search_chat_room(pauline.getLc(), NULL, localAddr, peerAddr, NULL); - BC_ASSERT_PTR_NOT_NULL(paulineCr); - - LinphoneChatRoom *focusCr = linphone_core_search_chat_room(focus.getLc(), NULL, NULL, peerAddr, NULL); - BC_ASSERT_PTR_NOT_NULL(focusCr); - - LinphoneParticipant *paulineParticipant = NULL; - LinphoneParticipantDevice *paulineDevice = NULL; - - if (focusCr) { - paulineParticipant = linphone_chat_room_find_participant(focusCr, localAddr); - BC_ASSERT_PTR_NOT_NULL(paulineParticipant); - if (paulineParticipant) { - paulineDevice = linphone_participant_find_device(paulineParticipant, localAddr); - BC_ASSERT_PTR_NOT_NULL(paulineDevice); - } - } - - linphone_address_unref(localAddr); - linphone_address_unref(peerAddr); - - OrtpNetworkSimulatorParams simparams = {0}; - simparams.mode = OrtpNetworkSimulatorOutbound; - simparams.enabled = TRUE; - simparams.max_bandwidth = 430000; /*we first limit to 430 kbit/s*/ - simparams.max_buffer_size = (int)simparams.max_bandwidth; - simparams.latency = 60; - simparams.loss_rate = 90; - linphone_core_set_network_simulator_params(pauline.getLc(), &simparams); - linphone_core_set_network_simulator_params(focus.getLc(), &simparams); - - linphone_core_delete_chat_room(marie.getLc(), marieCr); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateDeleted, - marie_stat.number_of_LinphoneConferenceStateDeleted + 1, - liblinphone_tester_sip_timeout)); - - // wait until chatroom is deleted server side - BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline}).wait([&paulineDevice] { - return (paulineDevice) ? (linphone_participant_device_get_state(paulineDevice) == - LinphoneParticipantDeviceStateLeaving) - : false; - })); - - BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_LinphoneChatRoomSessionReleased, 1, - liblinphone_tester_sip_timeout)); - - linphone_core_delete_chat_room(pauline.getLc(), paulineCr); - BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneConferenceStateDeleted, - pauline_stat.number_of_LinphoneConferenceStateDeleted + 1, - liblinphone_tester_sip_timeout)); - } - } -} - void conference_scheduler_state_changed(LinphoneConferenceScheduler *scheduler, LinphoneConferenceSchedulerState state) { stats *stat = get_stats(linphone_conference_scheduler_get_core(scheduler)); @@ -2162,20 +725,26 @@ void wait_for_conference_streams(std::initializer_list<std::reference_wrapper<Co for (const auto &m : members) { LinphoneCoreManager *mMgr = m.first; LinphoneCall *pcall = linphone_core_get_call_by_remote_address2(mMgr->lc, confAddr); - call_check &= (pcall != nullptr); - LinphoneCall *call = linphone_core_get_call_by_remote_address2(mgr->lc, mMgr->identity); - call_check &= (call != nullptr); - if (call) { - calls.push_back(call); + call_check &= + (pcall != nullptr) && (linphone_call_get_state(pcall) == LinphoneCallStateStreamsRunning); + + LinphoneCall *fcall = linphone_core_get_call_by_remote_address2(mgr->lc, mMgr->identity); + call_check &= + (fcall != nullptr) && (linphone_call_get_state(fcall) == LinphoneCallStateStreamsRunning); + if (fcall) { + calls.push_back(fcall); } else { calls.push_back(nullptr); } } } else { - LinphoneCall *call = linphone_core_get_call_by_remote_address2(mgr->lc, confAddr); - call_check &= (call != nullptr); - if (call) { - calls.push_back(call); + LinphoneCall *fcall = linphone_core_get_call_by_remote_address2(focus->lc, mgr->identity); + call_check &= (fcall != nullptr) && (linphone_call_get_state(fcall) == LinphoneCallStateStreamsRunning); + + LinphoneCall *pcall = linphone_core_get_call_by_remote_address2(mgr->lc, confAddr); + call_check &= (pcall != nullptr) && (linphone_call_get_state(pcall) == LinphoneCallStateStreamsRunning); + if (pcall) { + calls.push_back(pcall); } else { calls.push_back(nullptr); } @@ -2189,8 +758,8 @@ void wait_for_conference_streams(std::initializer_list<std::reference_wrapper<Co const SalMediaDescription *call_result_desc = _linphone_call_get_result_desc(call); call_check &= ((call_result_desc->nbActiveStreamsOfType(SalAudio) == nb_audio_streams) && (call_result_desc->nbActiveStreamsOfType(SalVideo) == nb_video_streams) && - (call_result_desc->nbActiveStreamsOfType(SalText) == nb_text_streams) && - (linphone_call_get_state(call) == LinphoneCallStateStreamsRunning)); + (call_result_desc->nbActiveStreamsOfType(SalText) == nb_text_streams)); + ; } } @@ -3032,7 +1601,10 @@ void create_conference_base(time_t start_time, bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -3046,7 +1618,8 @@ void create_conference_base(time_t start_time, for (auto mgr : conferenceMgrs) { if (mgr != marie.getCMgr()) { - BC_ASSERT_TRUE(wait_for_list(coresList, &mgr->stat.number_of_LinphoneParticipantDeviceMuted, 1, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &mgr->stat.number_of_LinphoneParticipantDeviceMuted, 1, + liblinphone_tester_sip_timeout)); } if (mgr != focus.getCMgr()) { LinphoneCall *c1 = linphone_core_get_call_by_remote_address2(mgr->lc, focus.getCMgr()->identity); @@ -3286,7 +1859,10 @@ void create_conference_base(time_t start_time, bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -5028,9 +3604,11 @@ void create_conference_with_late_participant_addition_base(time_t start_time, BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneCallStreamsRunning, marie_stat.number_of_LinphoneCallStreamsRunning + 1, liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneCallStreamsRunning, - marie_stat.number_of_LinphoneCallStreamsRunning + 2, + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneSubscriptionActive, + marie_stat.number_of_LinphoneSubscriptionActive + 1, liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_NotifyFullStateReceived, + marie_stat.number_of_NotifyFullStateReceived + 1, liblinphone_tester_sip_timeout)); LinphoneConference *oconference = linphone_core_search_conference_2(marie.getLc(), confAddr); if (BC_ASSERT_PTR_NOT_NULL(oconference)) { @@ -5050,7 +3628,9 @@ void create_conference_with_late_participant_addition_base(time_t start_time, if (pcall) { LinphoneCallLog *call_log = linphone_call_get_call_log(pcall); BC_ASSERT_TRUE(linphone_call_log_was_conference(call_log)); - linphone_call_accept(pcall); + if (start_time < 0) { + linphone_call_accept(pcall); + } } } } @@ -5218,7 +3798,10 @@ void create_conference_with_late_participant_addition_base(time_t start_time, bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } LinphoneConference *conference = linphone_core_search_conference_2(mgr->lc, confAddr); @@ -5828,7 +4411,10 @@ void two_overlapping_conferences_base(bool_t same_organizer, bool_t dialout) { bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference1, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference1, &pconference] { + return check_conference_ssrc(fconference1, pconference); + })); } } } @@ -6095,7 +4681,10 @@ void two_overlapping_conferences_base(bool_t same_organizer, bool_t dialout) { bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference2, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference2, &pconference] { + return check_conference_ssrc(fconference2, pconference); + })); } } } @@ -6736,7 +5325,10 @@ void create_one_participant_conference_toggle_video_base(LinphoneConferenceLayou bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -7663,7 +6255,10 @@ void create_conference_with_active_call_base(bool_t dialout) { bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } LinphoneConference *conference = linphone_core_search_conference_2(mgr->lc, confAddr); @@ -8066,7 +6661,10 @@ void create_simple_conference_merging_calls_base(bool_t enable_ice, LinphoneAddress *uri = mgr->identity; LinphoneConference *pconference = linphone_core_search_conference(mgr->lc, NULL, uri, confAddr, NULL); BC_ASSERT_PTR_NOT_NULL(pconference); - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } focus_stat = focus.getStats(); diff --git a/tester/local_conference_tester_functions.h b/tester/local_conference_tester_functions.h index d37710f68585935f25d1fafed8e10e3bd6332b28..474f723c40b9f922d49ad3be35f9581df57b8659 100644 --- a/tester/local_conference_tester_functions.h +++ b/tester/local_conference_tester_functions.h @@ -183,8 +183,10 @@ public: << " is sending message with text " << text; msg = linphone_chat_room_create_message_from_utf8(cr, text.c_str()); BC_ASSERT_PTR_NOT_NULL(msg); - LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + LinphoneChatMessageCbs *cbs = linphone_factory_create_chat_message_cbs(linphone_factory_get()); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_add_callbacks(msg, cbs); + linphone_chat_message_cbs_unref(cbs); linphone_chat_message_send(msg); } return msg; diff --git a/tester/local_ice_conference_tester.cpp b/tester/local_ice_conference_tester.cpp index 5c38c8ccbfe0179446754abce385facd1848947d..119cbf6361ded7cb7b80ae1883cbf789ad10162f 100644 --- a/tester/local_ice_conference_tester.cpp +++ b/tester/local_ice_conference_tester.cpp @@ -336,7 +336,10 @@ static void abort_call_to_ice_conference(void) { bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } diff --git a/tester/local_inpromptu_conference_tester.cpp b/tester/local_inpromptu_conference_tester.cpp index 8b00e725bcd8061064df2fef66e079a0929b4639..5b8fa3138005162d1e4008ca1fc8e11ab84a035f 100644 --- a/tester/local_inpromptu_conference_tester.cpp +++ b/tester/local_inpromptu_conference_tester.cpp @@ -523,7 +523,10 @@ static void create_conference_dial_out_base(bool_t send_ics, bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } LinphoneConference *conference = linphone_core_search_conference_2(mgr->lc, confAddr); @@ -1368,7 +1371,10 @@ static void create_simple_conference_dial_out_with_some_calls_declined_base(Linp bctbx_list_free_with_data(participants_list, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } bctbx_list_t *devices = linphone_conference_get_participant_device_list(pconference); @@ -1850,12 +1856,14 @@ static void simple_dial_out_conference_with_no_payloads(void) { } // namespace LinphoneTest -static test_t local_conference_inpromptu_conference_tests[] = { - TEST_NO_TAG("Create simple dial out conference", LinphoneTest::create_simple_conference_dial_out), +static test_t local_conference_encrypted_inpromptu_conference_tests[] = { TEST_NO_TAG("Create simple point-to-point encrypted dial out conference", LinphoneTest::create_simple_point_to_point_encrypted_conference_dial_out), TEST_NO_TAG("Create simple end-to-end encrypted dial out conference", - LinphoneTest::create_simple_end_to_end_encrypted_conference_dial_out), + LinphoneTest::create_simple_end_to_end_encrypted_conference_dial_out)}; + +static test_t local_conference_inpromptu_conference_tests[] = { + TEST_NO_TAG("Create simple dial out conference", LinphoneTest::create_simple_conference_dial_out), TEST_NO_TAG("Create simple dial out conference and ICS sent", LinphoneTest::create_simple_conference_dial_out_and_ics), TEST_NO_TAG("Create simple dial out conference with late participant addition", @@ -1889,6 +1897,19 @@ static test_t local_conference_inpromptu_mismatch_conference_tests[] = { TEST_NO_TAG("Simple dial out conference with no payloads", LinphoneTest::simple_dial_out_conference_with_no_payloads)}; +test_suite_t local_conference_test_suite_encrypted_inpromptu_conference = { + "Local conference tester (Inpromptu Encrypted Conference)", + NULL, + NULL, + liblinphone_tester_before_each, + liblinphone_tester_after_each, + sizeof(local_conference_encrypted_inpromptu_conference_tests) / + sizeof(local_conference_encrypted_inpromptu_conference_tests[0]), + local_conference_encrypted_inpromptu_conference_tests, + 0, + 8 /*cpu_weight : video encnrypted conference uses more resources */ +}; + test_suite_t local_conference_test_suite_inpromptu_conference = { "Local conference tester (Inpromptu Conference)", NULL, @@ -1910,4 +1931,5 @@ test_suite_t local_conference_test_suite_inpromptu_mismatch_conference = { sizeof(local_conference_inpromptu_mismatch_conference_tests) / sizeof(local_conference_inpromptu_mismatch_conference_tests[0]), local_conference_inpromptu_mismatch_conference_tests, - 0}; + 0, + 4}; diff --git a/tester/local_scheduled_conference_tester.cpp b/tester/local_scheduled_conference_tester.cpp index 4c5b6c8820ce978979c3ca9f92bf4447c165653d..166ce73de1d9dd0a4f7c5b8e21502a26c1b6c1fe 100644 --- a/tester/local_scheduled_conference_tester.cpp +++ b/tester/local_scheduled_conference_tester.cpp @@ -536,7 +536,10 @@ static void create_conference_with_audio_only_participants_base(LinphoneConferen bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -683,7 +686,10 @@ static void create_conference_with_audio_only_participants_base(LinphoneConferen bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -1140,7 +1146,10 @@ static void create_conference_with_codec_mismatch_base(bool_t organizer_codec_mi bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle, berthe}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -1488,7 +1497,10 @@ static void create_conference_with_server_restart_base(bool_t organizer_first) { bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -1778,7 +1790,10 @@ static void create_simple_conference_with_update_deferred(void) { bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure, michelle}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } @@ -2242,7 +2257,10 @@ static void change_active_speaker(void) { bctbx_list_free_with_data(participants, (void (*)(void *))linphone_participant_unref); if (mgr != focus.getCMgr()) { - check_conference_ssrc(fconference, pconference); + BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, laure}) + .waitUntil(chrono::seconds(10), [&fconference, &pconference] { + return check_conference_ssrc(fconference, pconference); + })); } } } diff --git a/tester/main-db-tester.cpp b/tester/main-db-tester.cpp index dbc9867fa4679ab63201bdb5bbf5966eac7ab0ac..57226cd8740e2eb64ffbca54026b5fb1c4534cf5 100644 --- a/tester/main-db-tester.cpp +++ b/tester/main-db-tester.cpp @@ -28,6 +28,11 @@ #include "private.h" #include "tools/tester.h" +#ifndef _WIN32 +#include <sys/resource.h> +#include <sys/time.h> +#endif + // ============================================================================= using namespace std; @@ -356,12 +361,21 @@ static void get_chat_rooms() { } static void load_a_lot_of_chatrooms(void) { +#ifndef _WIN32 + int current_priority = getpriority(PRIO_PROCESS, 0); + int err = setpriority(PRIO_PROCESS, 0, -20); + if (err != 0) { + ms_warning("load_a_lot_of_chatrooms(): setpriority failed [%s]- the time measurement may be unreliable", + strerror(errno)); + } +#endif + chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); MainDbProvider provider("db/chatrooms.db"); chrono::high_resolution_clock::time_point end = chrono::high_resolution_clock::now(); long ms = (long)chrono::duration_cast<chrono::milliseconds>(end - start).count(); #ifdef ENABLE_SANITIZER - BC_ASSERT_LOWER(ms, 2600, long, "%li"); + BC_ASSERT_LOWER(ms, 3200, long, "%li"); #else #if __APPLE__ BC_ASSERT_LOWER(ms, 1000, long, "%li"); @@ -369,6 +383,13 @@ static void load_a_lot_of_chatrooms(void) { BC_ASSERT_LOWER(ms, 600, long, "%li"); #endif #endif + +#ifndef _WIN32 + err = setpriority(PRIO_PROCESS, 0, current_priority); + if (err != 0) { + ms_warning("load_a_lot_of_chatrooms(): cannot restore priority to [%i]: %s", current_priority, strerror(errno)); + } +#endif } static void load_chatroom_conference(void) { diff --git a/tester/shared_tester_functions.cpp b/tester/shared_tester_functions.cpp index 7088c5e228945077c1c5edc1d39920d602426bb7..1b0b46cc8573b5af36a3e029b73d957a781cd999 100644 --- a/tester/shared_tester_functions.cpp +++ b/tester/shared_tester_functions.cpp @@ -836,3 +836,56 @@ bool_t check_custom_m_line(LinphoneCall *call, const char *m_line) { remote_stream_type_ok; return ret; } + +bool check_conference_ssrc(LinphoneConference *local_conference, LinphoneConference *remote_conference) { + bool ret = true; + if (!local_conference) ret = false; + if (!remote_conference) ret = false; + if (local_conference && remote_conference) { + bctbx_list_t *local_conference_participants = linphone_conference_get_participant_list(local_conference); + + LinphoneParticipant *remote_conference_me = linphone_conference_get_me(remote_conference); + const LinphoneAddress *remote_me_address = linphone_participant_get_address(remote_conference_me); + for (bctbx_list_t *itp = local_conference_participants; itp; itp = bctbx_list_next(itp)) { + LinphoneParticipant *p = (LinphoneParticipant *)bctbx_list_get_data(itp); + const LinphoneAddress *p_address = linphone_participant_get_address(p); + bctbx_list_t *local_devices = NULL; + LinphoneParticipant *remote_participant = + (linphone_address_equal(p_address, remote_me_address)) + ? linphone_conference_get_me(remote_conference) + : linphone_conference_find_participant(remote_conference, p_address); + if (!remote_participant) ret = false; + if (remote_participant) { + local_devices = linphone_participant_get_devices(p); + for (bctbx_list_t *itd = local_devices; itd; itd = bctbx_list_next(itd)) { + LinphoneParticipantDevice *d = (LinphoneParticipantDevice *)bctbx_list_get_data(itd); + LinphoneParticipantDevice *remote_device = linphone_participant_find_device( + remote_participant, linphone_participant_device_get_address(d)); + if (!remote_device) ret = false; + if (remote_device) { + for (const auto type : + {LinphoneStreamTypeAudio, LinphoneStreamTypeVideo, LinphoneStreamTypeText}) { + for (const auto device : {d, remote_device}) { + if (linphone_participant_device_get_stream_capability(device, type) != + LinphoneMediaDirectionInactive) { + if (linphone_participant_device_get_ssrc(device, type) == 0) { + ret = false; + } + } else { + if (linphone_participant_device_get_ssrc(device, type) != 0) { + ret = false; + } + } + } + } + } + } + } + if (local_devices) { + bctbx_list_free_with_data(local_devices, (void (*)(void *))linphone_participant_device_unref); + } + } + bctbx_list_free_with_data(local_conference_participants, (void (*)(void *))linphone_participant_unref); + } + return ret; +} diff --git a/tester/tester.c b/tester/tester.c index 779af2f7987f29b29e5343ffc6caec81c009d63d..f0ec30c0318f785456990108b37e4aacb51311a6 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -873,87 +873,11 @@ static void check_participant_media_direction(const LinphoneMediaDirection local } } -void check_conference_ssrc(LinphoneConference *local_conference, LinphoneConference *remote_conference) { - BC_ASSERT_PTR_NOT_NULL(local_conference); - BC_ASSERT_PTR_NOT_NULL(remote_conference); - if (local_conference && remote_conference) { - bctbx_list_t *local_conference_participants = linphone_conference_get_participant_list(local_conference); - - LinphoneParticipant *remote_conference_me = linphone_conference_get_me(remote_conference); - const LinphoneAddress *remote_me_address = linphone_participant_get_address(remote_conference_me); - for (bctbx_list_t *itp = local_conference_participants; itp; itp = bctbx_list_next(itp)) { - LinphoneParticipant *p = (LinphoneParticipant *)bctbx_list_get_data(itp); - const LinphoneAddress *p_address = linphone_participant_get_address(p); - bctbx_list_t *local_devices = NULL; - LinphoneParticipant *remote_participant = - (linphone_address_equal(p_address, remote_me_address)) - ? linphone_conference_get_me(remote_conference) - : linphone_conference_find_participant(remote_conference, p_address); - BC_ASSERT_PTR_NOT_NULL(remote_participant); - if (remote_participant) { - local_devices = linphone_participant_get_devices(p); - for (bctbx_list_t *itd = local_devices; itd; itd = bctbx_list_next(itd)) { - LinphoneParticipantDevice *d = (LinphoneParticipantDevice *)bctbx_list_get_data(itd); - LinphoneParticipantDevice *remote_device = linphone_participant_find_device( - remote_participant, linphone_participant_device_get_address(d)); - BC_ASSERT_PTR_NOT_NULL(remote_device); - if (remote_device) { - if (linphone_participant_device_get_stream_capability(d, LinphoneStreamTypeAudio) != - LinphoneMediaDirectionInactive) { - BC_ASSERT_NOT_EQUAL( - (unsigned long)linphone_participant_device_get_ssrc(d, LinphoneStreamTypeAudio), 0, - unsigned long, "%0lu"); - } else { - BC_ASSERT_EQUAL( - (unsigned long)linphone_participant_device_get_ssrc(d, LinphoneStreamTypeAudio), 0, - unsigned long, "%0lu"); - } - if (linphone_participant_device_get_stream_capability(remote_device, LinphoneStreamTypeAudio) != - LinphoneMediaDirectionInactive) { - BC_ASSERT_NOT_EQUAL((unsigned long)linphone_participant_device_get_ssrc( - remote_device, LinphoneStreamTypeAudio), - 0, unsigned long, "%0lu"); - } else { - BC_ASSERT_EQUAL((unsigned long)linphone_participant_device_get_ssrc( - remote_device, LinphoneStreamTypeAudio), - 0, unsigned long, "%0lu"); - } - if (linphone_participant_device_get_stream_capability(d, LinphoneStreamTypeVideo) != - LinphoneMediaDirectionInactive) { - BC_ASSERT_NOT_EQUAL( - (unsigned long)linphone_participant_device_get_ssrc(d, LinphoneStreamTypeVideo), 0, - unsigned long, "%0lu"); - } else { - BC_ASSERT_EQUAL( - (unsigned long)linphone_participant_device_get_ssrc(d, LinphoneStreamTypeVideo), 0, - unsigned long, "%0lu"); - } - if (linphone_participant_device_get_stream_capability(remote_device, LinphoneStreamTypeVideo) != - LinphoneMediaDirectionInactive) { - BC_ASSERT_NOT_EQUAL((unsigned long)linphone_participant_device_get_ssrc( - remote_device, LinphoneStreamTypeVideo), - 0, unsigned long, "%0lu"); - } else { - BC_ASSERT_EQUAL((unsigned long)linphone_participant_device_get_ssrc( - remote_device, LinphoneStreamTypeVideo), - 0, unsigned long, "%0lu"); - } - } - } - } - if (local_devices) { - bctbx_list_free_with_data(local_devices, (void (*)(void *))linphone_participant_device_unref); - } - } - bctbx_list_free_with_data(local_conference_participants, (void (*)(void *))linphone_participant_unref); - } -} - void check_conference_medias(LinphoneConference *local_conference, LinphoneConference *remote_conference) { BC_ASSERT_PTR_NOT_NULL(local_conference); BC_ASSERT_PTR_NOT_NULL(remote_conference); if (local_conference && remote_conference) { - check_conference_ssrc(local_conference, remote_conference); + BC_ASSERT_TRUE(check_conference_ssrc(local_conference, remote_conference)); bctbx_list_t *local_conference_participants = linphone_conference_get_participant_list(local_conference); LinphoneParticipant *remote_conference_me = linphone_conference_get_me(remote_conference);