diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 0827aae8121f621a801199790fbc275087f23edf..decbdedfdcb650d42d9b78a322d42e010e31acb6 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -6368,12 +6368,13 @@ void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *pat CoreLogContextualizer logContextualizer(lc); if (!linphone_core_conference_server_enabled(lc)) { auto &mainDb = L_GET_PRIVATE_FROM_C_OBJECT(lc)->mainDb; - if (mainDb) { + if (mainDb && mainDb->isInitialized()) { mainDb->import(LinphonePrivate::MainDb::Sqlite3, path); linphone_core_migrate_logs_from_rc_to_db(lc); } else { - ms_warning("linphone_core_set_call_logs_database_path() needs to be called once linphone_core_start() has " - "been called"); + ms_warning("%s() needs to be called once linphone_core_start() has been called or Database has not been " + "initialized, therefore it is not possible to import call log database at %s", + __func__, path); } } } @@ -8922,12 +8923,13 @@ void linphone_core_set_chat_database_path(LinphoneCore *lc, const char *path) { CoreLogContextualizer logContextualizer(lc); if (!linphone_core_conference_server_enabled(lc)) { auto &mainDb = L_GET_PRIVATE_FROM_C_OBJECT(lc)->mainDb; - if (mainDb) { + if (mainDb && mainDb->isInitialized()) { mainDb->import(LinphonePrivate::MainDb::Sqlite3, path); L_GET_PRIVATE_FROM_C_OBJECT(lc)->loadChatRooms(); } else { - ms_warning("linphone_core_set_chat_database_path() needs to be called once linphone_core_start() has " - "been called"); + ms_warning("%s() needs to be called once linphone_core_start() has been called or Database has not been " + "initialized, therefore it is not possible to import chat database at %s", + __func__, path); } } } diff --git a/src/c-wrapper/api/c-friend.cpp b/src/c-wrapper/api/c-friend.cpp index bb240074e505a38b17f2035778db5e8148773139..dce4d693be45d703a3a9a051f7b804d4d33a4e45 100644 --- a/src/c-wrapper/api/c-friend.cpp +++ b/src/c-wrapper/api/c-friend.cpp @@ -898,9 +898,14 @@ void linphone_core_set_friends_database_path(LinphoneCore *lc, const char *path) lc->friends_db_file = ms_strdup(path); } - if (L_GET_PRIVATE(lc->cppPtr)->mainDb) { - if (L_GET_PRIVATE(lc->cppPtr)->mainDb->import(LinphonePrivate::MainDb::Sqlite3, path)) + auto &mainDb = L_GET_PRIVATE(lc->cppPtr)->mainDb; + if (mainDb && mainDb->isInitialized()) { + if (mainDb->import(LinphonePrivate::MainDb::Sqlite3, path)) linphone_core_friends_storage_resync_friends_lists(lc); + } else { + ms_warning( + "Database has not been initialized, therefore it is not possible to import friends database at path %s", + path); } } } diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 7152e1a4d09e1971f6f215e4aa686b3a0dd659c5..fc5dd10c2be729a5b34c5630efd82ec31782b235 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -816,8 +816,8 @@ void ChatMessagePrivate::setChatRoom(const shared_ptr<AbstractChatRoom> &chatRoo if (isBasicChatRoom) { localAddress = account->getAccountParams()->getIdentityAddress(); lInfo() << *chatRoom << " with ID " << conferenceId - << " is a basic chatroom therefore set the local address of message [" << q - << "] to the account identity address " << *localAddress; + << " is a basic chatroom therefore set the local address of message [" << q << "] to the account [" + << account << "]'s identity address " << *localAddress; } else { localAddress = account->getContactAddress(); if (localAddress) { @@ -828,10 +828,14 @@ void ChatMessagePrivate::setChatRoom(const shared_ptr<AbstractChatRoom> &chatRoo } } if (!localAddress) { - lInfo() << *chatRoom << " with ID " << conferenceId - << " has no account associated to or the contact or the identity address is not available yet, setting " - "conference ID's local address as message local address"; localAddress = conferenceId.getLocalAddress(); + if (localAddress) { + lInfo() + << *chatRoom << " with ID " << conferenceId + << " has no account associated to or the contact or the identity address is not available yet, setting " + "conference ID's local address as message local address " + << *localAddress; + } } if (localAddress) { @@ -840,6 +844,8 @@ void ChatMessagePrivate::setChatRoom(const shared_ptr<AbstractChatRoom> &chatRoo } else { localAddress = localAddress->clone()->toSharedPtr(); } + } else { + lError() << "Unable to set local address of message [" << q << "] in " << *chatRoom; } auto peerAddress = conferenceId.getPeerAddress()->clone()->toSharedPtr(); diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index eae6947e9e6dbc331f05b4e59d9ff0a8eda7f433..b7f37db5dc4daea7a721a8f84ccd5300d1151c22 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -724,10 +724,12 @@ void ChatRoom::notifyAggregatedChatMessages() { bctbx_list_t *cEvents = L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(eventsList); _linphone_chat_room_notify_chat_messages_received(cChatRoom, cEvents); - // Notify delivery + // Notify delivery - do the same things as when chat messages are not aggregated: send the delivery notification + // when the message is in the Delivered state for (auto &chatMessage : aggregatedMessages) { - chatMessage->getPrivate()->setParticipantState(getMe()->getAddress(), ChatMessage::State::DeliveredToUser, + chatMessage->getPrivate()->setParticipantState(getMe()->getAddress(), ChatMessage::State::Delivered, ::ms_time(nullptr)); + sendDeliveryNotification(chatMessage); } bctbx_list_free_with_data(cMessages, (bctbx_list_free_func)linphone_chat_message_unref); diff --git a/src/core/core.cpp b/src/core/core.cpp index 242f4df012bb6a11d021d351ff5e3c1c8ecb0569..cc7ac2dac21f0071e4be9a47951de28f3f34fb97 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -231,6 +231,8 @@ void CorePrivate::init() { linphone_core_set_friends_database_path(lc, friendsDbPath.c_str()); } else lWarning() << "Friends database explicitely not requested"; } + } else { + lInfo() << "The Core was explicitely requested not to use any database"; } createConferenceCleanupTimer(); diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 1855e4df8a6bf0a730dc6d0ab1519c411b3f0be6..b58e258193ae5127a96a48e653d955965217d980 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -148,6 +148,7 @@ set(RC_FILES rcfiles/chloe_dual_proxy_rc rcfiles/conference_focus_rc rcfiles/empty_rc + rcfiles/empty_with_some_db_rc rcfiles/friends_rc rcfiles/groupchat_rc rcfiles/invalid_friends_rc diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c index 25e4e5bf01fc519db2d6d3791f4d921551a8ca9d..68ca6b1c160e1ad870206ff47785a07538087b59 100644 --- a/tester/group_chat_tester.c +++ b/tester/group_chat_tester.c @@ -61,9 +61,7 @@ static bool_t wait_for_chat_room_participants(bctbx_list_t *lcs, LinphoneChatRoo linphone_core_iterate((LinphoneCore *)(iterator->data)); } #ifdef LINPHONE_WINDOWS_UWP - { - bc_tester_process_events(); - } + { bc_tester_process_events(); } #elif defined(LINPHONE_WINDOWS_DESKTOP) { MSG msg; @@ -6201,7 +6199,7 @@ end: linphone_core_manager_destroy(chloe); } -static void basic_chat_room_with_cpim_base(bool_t use_gruu) { +static void basic_chat_room_with_cpim_base(bool_t use_gruu, bool_t enable_imdn) { LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); bctbx_list_t *coresManagerList = NULL; @@ -6213,6 +6211,15 @@ static void basic_chat_room_with_cpim_base(bool_t use_gruu) { bctbx_list_t *coresList = init_core_for_conference(coresManagerList); start_core_for_conference(coresManagerList); + if (enable_imdn) { + // Enable IMDN + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); + } + + linphone_core_set_chat_messages_aggregation_enabled(marie->lc, TRUE); + linphone_config_set_int(linphone_core_get_config(marie->lc), "sip", "chat_messages_aggregation_delay", 10); + // Enable CPIM LinphoneAccount *marie_account = linphone_core_get_default_account(marie->lc); const LinphoneAccountParams *marie_account_params = linphone_account_get_params(marie_account); @@ -6247,19 +6254,27 @@ static void basic_chat_room_with_cpim_base(bool_t use_gruu) { // Marie sends a message in a basic chatroom const char *marie_text = "This is a basic chat room"; + LinphoneChatMessage *marie_msg = NULL; if (marieCr) { const LinphoneAddress *peer_address = linphone_chat_room_get_peer_address(marieCr); BC_ASSERT_TRUE(linphone_address_has_uri_param(peer_address, "gr")); - LinphoneChatMessage *sent_msg = _send_message(marieCr, marie_text); + linphone_chat_room_compose(marieCr); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, 1)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, 1, 2000)); + marie_msg = _send_message(marieCr, marie_text); BC_ASSERT_TRUE( wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageSent, 1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, 1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, 1, liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, 1, - liblinphone_tester_sip_timeout)); - linphone_chat_message_unref(sent_msg); + if (enable_imdn) { + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDeliveredToUser, 1, + liblinphone_tester_sip_timeout)); + } else { + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, 1, + liblinphone_tester_sip_timeout)); + } } LinphoneConferenceParams *pauline_params = linphone_core_create_conference_params(pauline->lc); @@ -6275,7 +6290,23 @@ static void basic_chat_room_with_cpim_base(bool_t use_gruu) { linphone_chat_room_params_unref(pauline_params); const char *pauline_text = "Yes Madam"; + LinphoneChatMessage *pauline_msg = NULL; if (paulineCr) { + linphone_chat_room_compose(paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, 2, 2000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, 1, 2000)); + if (enable_imdn) { + linphone_chat_room_mark_as_read(paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDisplayed, 1, + liblinphone_tester_sip_timeout)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDisplayed, 1, + liblinphone_tester_sip_timeout)); + } + if (marie_msg) { + linphone_chat_message_unref(marie_msg); + } LinphoneChatMessage *msg = linphone_chat_room_get_last_message_in_history(paulineCr); if (BC_ASSERT_PTR_NOT_NULL(msg)) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), marie_text); @@ -6283,27 +6314,60 @@ static void basic_chat_room_with_cpim_base(bool_t use_gruu) { } const LinphoneAddress *local_address = linphone_chat_room_get_local_address(paulineCr); BC_ASSERT_TRUE(linphone_address_has_uri_param(local_address, "gr")); - LinphoneChatMessage *sent_msg = _send_message(paulineCr, pauline_text); + pauline_msg = _send_message(paulineCr, pauline_text); BC_ASSERT_TRUE( wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageSent, 1, liblinphone_tester_sip_timeout)); BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, 2, 2000)); - BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, 1, - liblinphone_tester_sip_timeout)); - BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDelivered, 1, + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneAggregatedMessagesReceived, 1, liblinphone_tester_sip_timeout)); - linphone_chat_message_unref(sent_msg); + if (enable_imdn) { + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1, + liblinphone_tester_sip_timeout)); + } else { + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDelivered, 1, + liblinphone_tester_sip_timeout)); + } } + LinphoneChatMessageState expected_msg_state = + (enable_imdn) ? LinphoneChatMessageStateDisplayed : LinphoneChatMessageStateDelivered; if (marieCr) { + if (enable_imdn) { + linphone_chat_room_mark_as_read(marieCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDisplayed, 2, + liblinphone_tester_sip_timeout)); + // As Marie enables chat message aggregation, the message state changed is not called + BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDisplayed, 2, 1000)); + } + if (pauline_msg) { + linphone_chat_message_unref(pauline_msg); + } + LinphoneChatMessage *msg = linphone_chat_room_get_last_message_in_history(marieCr); if (BC_ASSERT_PTR_NOT_NULL(msg)) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), pauline_text); linphone_chat_message_unref(msg); } + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 2, int, "%d"); + bctbx_list_t *marie_history = linphone_chat_room_get_history(marieCr, 3); + for (bctbx_list_t *item = marie_history; item; item = bctbx_list_next(item)) { + LinphoneChatMessage *msg = (LinphoneChatMessage *)bctbx_list_get_data(item); + BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), expected_msg_state, int, "%d"); + } + bctbx_list_free_with_data(marie_history, (bctbx_list_free_func)linphone_chat_message_unref); linphone_core_manager_delete_chat_room(marie, marieCr, coresList); linphone_chat_room_unref(marieCr); } - if (paulineCr) linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + if (paulineCr) { + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 2, int, "%d"); + bctbx_list_t *pauline_history = linphone_chat_room_get_history(paulineCr, 3); + for (bctbx_list_t *item = pauline_history; item; item = bctbx_list_next(item)) { + LinphoneChatMessage *msg = (LinphoneChatMessage *)bctbx_list_get_data(item); + BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), expected_msg_state, int, "%d"); + } + bctbx_list_free_with_data(pauline_history, (bctbx_list_free_func)linphone_chat_message_unref); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + } bctbx_list_free(coresList); bctbx_list_free(coresManagerList); @@ -6313,11 +6377,15 @@ static void basic_chat_room_with_cpim_base(bool_t use_gruu) { } static void basic_chat_room_with_cpim_gruu(void) { - basic_chat_room_with_cpim_base(TRUE); + basic_chat_room_with_cpim_base(TRUE, FALSE); +} + +static void basic_chat_room_with_cpim_gruu_imdn(void) { + basic_chat_room_with_cpim_base(TRUE, TRUE); } static void basic_chat_room_with_cpim_without_gruu(void) { - basic_chat_room_with_cpim_base(FALSE); + basic_chat_room_with_cpim_base(FALSE, FALSE); } static void find_one_to_one_chat_room(void) { @@ -9629,6 +9697,7 @@ test_t group_chat2_tests[] = { TEST_NO_TAG("IMDN updated for group chat room with one participant offline", imdn_updated_for_group_chat_room_with_one_participant_offline), TEST_NO_TAG("Basic chat room with CPIM and GRUU", basic_chat_room_with_cpim_gruu), + TEST_NO_TAG("Basic chat room with CPIM, GRUU and IMDN", basic_chat_room_with_cpim_gruu_imdn), TEST_NO_TAG("Basic chat room with CPIM and without GRUU", basic_chat_room_with_cpim_without_gruu), TEST_NO_TAG("Find one-to-one chat room", find_one_to_one_chat_room), TEST_NO_TAG("Exhumed one-to-one chat room 1", exhume_one_to_one_chat_room_1), diff --git a/tester/rcfiles/empty_with_some_db_rc b/tester/rcfiles/empty_with_some_db_rc new file mode 100644 index 0000000000000000000000000000000000000000..01ffeb09e09029c12055e1c298e6320c89183cc9 --- /dev/null +++ b/tester/rcfiles/empty_with_some_db_rc @@ -0,0 +1,15 @@ + +[sip] +# Request no port to be bound. +# By default, liblinphone binds on port 5060. This is a problem as multiple bindings for UDP is allowed and liblinphone_tester suite usually runs on parallel +# which cause port conflicts that are undetected. +sip_port=-2 +sip_tcp_port=-2 +sip_tls_port=-2 + +[storage] +# Disable main database only +uri=null + +[tester] +test_env=1 diff --git a/tester/setup_tester.c b/tester/setup_tester.c index 506352c24a73dd246533e8a67311dc7b23b52895..09e271ce7a8996877b643dcf4f2e92b4f674bf0c 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -177,19 +177,25 @@ static void linphone_version_update_test(void) { linphone_core_manager_destroy(lcm); } -static void core_init_test(void) { +static void core_init_test_base(bool_t use_database, bool_t disable_main_db_only) { LinphoneCore *lc; FILE *in; - lc = - linphone_factory_create_core_3(linphone_factory_get(), NULL, liblinphone_tester_get_empty_rc(), system_context); + char *empty_with_some_db_rc_path = bc_tester_res("rcfiles/empty_with_some_db_rc"); + lc = linphone_factory_create_core_3( + linphone_factory_get(), NULL, + (disable_main_db_only) ? empty_with_some_db_rc_path : liblinphone_tester_get_empty_rc(), system_context); if (BC_ASSERT_PTR_NOT_NULL(lc)) { linphone_config_set_int(linphone_core_get_config(lc), "lime", "enabled", 0); + linphone_core_enable_database(lc, use_database); linphone_core_start(lc); - const char *uri = linphone_config_get_string(linphone_core_get_config(lc), "storage", "uri", NULL); - BC_ASSERT_STRING_EQUAL(uri, "null"); - in = fopen(uri, "rb"); - if (!BC_ASSERT_PTR_NULL(in)) // "null" file should not exists - fclose(in); + if (use_database) { + const char *uri = linphone_config_get_string(linphone_core_get_config(lc), "storage", "uri", NULL); + BC_ASSERT_STRING_EQUAL(uri, "null"); + in = fopen(uri, "rb"); + if (!BC_ASSERT_PTR_NULL(in)) // "null" file should not exists + fclose(in); + } + BC_ASSERT_TRUE(linphone_core_database_enabled(lc) == use_database); /* until we have good certificates on our test server... */ linphone_core_verify_server_certificates(lc, FALSE); BC_ASSERT_EQUAL(linphone_core_get_global_state(lc), LinphoneGlobalOn, int, "%i"); @@ -237,6 +243,19 @@ static void core_init_test(void) { linphone_core_stop(lc); linphone_core_unref(lc); } + ms_free(empty_with_some_db_rc_path); +} + +static void core_init_test(void) { + core_init_test_base(TRUE, FALSE); +} + +static void core_init_test_some_database(void) { + core_init_test_base(TRUE, TRUE); +} + +static void core_init_test_no_database(void) { + core_init_test_base(FALSE, FALSE); } static void core_init_test_2(void) { @@ -3860,6 +3879,8 @@ test_t setup_tests[] = { TEST_NO_TAG("Linphone proxy config server address change (internal api)", linphone_proxy_config_is_server_config_changed_test), TEST_NO_TAG("Linphone core init/uninit", core_init_test), + TEST_NO_TAG("Linphone core init/uninit with some database", core_init_test_some_database), + TEST_NO_TAG("Linphone core init/uninit without database", core_init_test_no_database), TEST_NO_TAG("Linphone core init/uninit from existing factory rc", core_init_test_2), TEST_NO_TAG("Linphone core init/uninit withtout any rc", core_init_test_3), TEST_NO_TAG("Linphone core init/uninit from existing default rc", core_init_test_4), diff --git a/tester/tester.c b/tester/tester.c index 4467d6909b0378f79e6f465cbfe55a3ccabe3adc..1c255e5a495851b3605873cd319d759c113345ba 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -3461,6 +3461,7 @@ void messages_received(LinphoneCore *lc, BCTBX_UNUSED(LinphoneChatRoom *room), c counters = get_stats(lc); int count = (int)bctbx_list_size(messages); counters->number_of_LinphoneAggregatedMessagesReceived += count; + ms_message("Received %0d aggregated messages", count); } void message_received(LinphoneCore *lc, BCTBX_UNUSED(LinphoneChatRoom *room), LinphoneChatMessage *msg) {