From c69cdef765643a68c8b845c054a8fd5a463a0909 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini <sylvain.berfini@belledonne-communications.com> Date: Thu, 31 Aug 2023 17:27:25 +0200 Subject: [PATCH] Handling empty reaction as removal --- coreapi/linphonecore.c | 8 ++++ coreapi/private_functions.h | 5 +++ coreapi/vtables.c | 8 ++++ include/linphone/api/c-callbacks.h | 7 +++ include/linphone/api/c-chat-message-cbs.h | 16 +++++++ include/linphone/callbacks.h | 13 ++++++ include/linphone/core.h | 15 +++++++ src/c-wrapper/api/c-chat-message-cbs.cpp | 11 +++++ src/c-wrapper/api/c-chat-message.cpp | 4 ++ .../chat-message/chat-message-reaction.cpp | 23 ++++++++-- src/chat/chat-message/chat-message.cpp | 23 +++++++++- src/core/core.h | 2 + src/db/main-db.cpp | 21 +++++++++ src/db/main-db.h | 2 + tester/group_chat_secure_tester.c | 43 +++++++++++++++++++ tester/liblinphone_tester.h | 5 +++ tester/message_tester.c | 30 ++++++------- tester/tester.c | 12 ++++++ 18 files changed, 226 insertions(+), 22 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 6f45ee3fcd..d3992af132 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -376,6 +376,14 @@ void linphone_core_cbs_set_new_message_reaction(LinphoneCoreCbs *cbs, LinphoneCo cbs->vtable->new_message_reaction = cb; } +LinphoneCoreCbsReactionRemovedCb linphone_core_cbs_get_reaction_removed(LinphoneCoreCbs *cbs) { + return cbs->vtable->reaction_removed; +} + +void linphone_core_cbs_set_reaction_removed(LinphoneCoreCbs *cbs, LinphoneCoreCbsReactionRemovedCb cb) { + cbs->vtable->reaction_removed = cb; +} + LinphoneCoreCbsMessagesReceivedCb linphone_core_cbs_get_messages_received(LinphoneCoreCbs *cbs) { return cbs->vtable->messages_received; } diff --git a/coreapi/private_functions.h b/coreapi/private_functions.h index 042072d362..4020cacddc 100644 --- a/coreapi/private_functions.h +++ b/coreapi/private_functions.h @@ -533,6 +533,7 @@ void _linphone_chat_room_clear_callbacks(LinphoneChatRoom *cr); void _linphone_chat_message_notify_msg_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state); void _linphone_chat_message_notify_new_message_reaction(LinphoneChatMessage *msg, const LinphoneChatMessageReaction *reaction); +void _linphone_chat_message_notify_reaction_removed(LinphoneChatMessage *msg, const LinphoneAddress *address); void _linphone_chat_message_notify_participant_imdn_state_changed(LinphoneChatMessage *msg, const LinphoneParticipantImdnState *state); void _linphone_chat_message_notify_file_transfer_recv(LinphoneChatMessage *msg, @@ -853,6 +854,10 @@ void linphone_core_notify_new_message_reaction(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message, const LinphoneChatMessageReaction *reaction); +void linphone_core_notify_message_reaction_removed(LinphoneCore *lc, + LinphoneChatRoom *room, + LinphoneChatMessage *message, + const LinphoneAddress *address); void linphone_core_notify_messages_received(LinphoneCore *lc, LinphoneChatRoom *room, const bctbx_list_t *messages); void linphone_core_notify_message_sent(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message); void linphone_core_notify_message_received_unable_decrypt(LinphoneCore *lc, diff --git a/coreapi/vtables.c b/coreapi/vtables.c index e2423499c8..41fa7b8dce 100644 --- a/coreapi/vtables.c +++ b/coreapi/vtables.c @@ -252,6 +252,14 @@ void linphone_core_notify_new_message_reaction(LinphoneCore *lc, cleanup_dead_vtable_refs(lc); } +void linphone_core_notify_message_reaction_removed(LinphoneCore *lc, + LinphoneChatRoom *room, + LinphoneChatMessage *message, + const LinphoneAddress *address) { + NOTIFY_IF_EXIST(reaction_removed, lc, room, message, address); + cleanup_dead_vtable_refs(lc); +} + void linphone_core_notify_messages_received(LinphoneCore *lc, LinphoneChatRoom *room, const bctbx_list_t *messages) { NOTIFY_IF_EXIST(messages_received, lc, room, messages); cleanup_dead_vtable_refs(lc); diff --git a/include/linphone/api/c-callbacks.h b/include/linphone/api/c-callbacks.h index 33d6db150f..f6b51fe812 100644 --- a/include/linphone/api/c-callbacks.h +++ b/include/linphone/api/c-callbacks.h @@ -230,6 +230,13 @@ typedef void (*LinphoneChatMessageCbsMsgStateChangedCb)(LinphoneChatMessage *mes typedef void (*LinphoneChatMessageCbsNewMessageReactionCb)(LinphoneChatMessage *message, const LinphoneChatMessageReaction *reaction); +/** + * Callback used to notify a reaction has been removed from a given message + * @param message #LinphoneChatMessage object @notnil + * @param address the #LinphoneAddress of the person that removed it's reaction @notnil + */ +typedef void (*LinphoneChatMessageCbsReactionRemovedCb)(LinphoneChatMessage *message, const LinphoneAddress *address); + /** * Call back used to notify participant IMDN state * @param message #LinphoneChatMessage object @notnil diff --git a/include/linphone/api/c-chat-message-cbs.h b/include/linphone/api/c-chat-message-cbs.h index c00a746770..476de5866a 100644 --- a/include/linphone/api/c-chat-message-cbs.h +++ b/include/linphone/api/c-chat-message-cbs.h @@ -96,6 +96,22 @@ linphone_chat_message_cbs_get_new_message_reaction(const LinphoneChatMessageCbs LINPHONE_PUBLIC void linphone_chat_message_cbs_set_new_message_reaction(LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsNewMessageReactionCb cb); +/** + * Get the removed reaction callback. + * @param cbs #LinphoneChatMessageCbs object. @notnil + * @return The current new reaction callback. + */ +LINPHONE_PUBLIC LinphoneChatMessageCbsReactionRemovedCb +linphone_chat_message_cbs_get_reaction_removed(const LinphoneChatMessageCbs *cbs); + +/** + * Set the removed reaction callback. + * @param cbs LinphoneChatMessageCbs object. @notnil + * @param cb The new reaction callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_message_cbs_set_reaction_removed(LinphoneChatMessageCbs *cbs, + LinphoneChatMessageCbsReactionRemovedCb cb); + /** * Get the file transfer receive callback. * @param cbs LinphoneChatMessageCbs object. @notnil diff --git a/include/linphone/callbacks.h b/include/linphone/callbacks.h index a3a399744e..e9bddaa609 100644 --- a/include/linphone/callbacks.h +++ b/include/linphone/callbacks.h @@ -253,6 +253,19 @@ typedef void (*LinphoneCoreCbsNewMessageReactionCb)(LinphoneCore *core, LinphoneChatMessage *message, const LinphoneChatMessageReaction *reaction); +/** + * Chat message removed reaction callback prototype. + * @param core #LinphoneCore object @notnil + * @param chat_room #LinphoneChatRoom involved in this conversation. Can be created by the framework in case the + * From-URI is not present in any chat room. @notnil + * @param message the #LinphoneChatMessage to which a reaction has been removed from @notnil + * @param address the #LinphoneAddress of the person that removed it's reaction @notnil + */ +typedef void (*LinphoneCoreCbsReactionRemovedCb)(LinphoneCore *core, + LinphoneChatRoom *chat_room, + LinphoneChatMessage *message, + const LinphoneAddress *address); + /** * Chat messages callback prototype. * Only called when aggregation is enabled (aka [sip] chat_messages_aggregation == 1 or using diff --git a/include/linphone/core.h b/include/linphone/core.h index 1e7bafcd68..f659edbc44 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -302,6 +302,7 @@ typedef struct _LinphoneCoreVTable { LinphoneCoreCbsOnAlertCb on_alert; LinphoneCoreCbsPreviewDisplayErrorOccurredCb preview_display_error_occurred; LinphoneCoreCbsNewMessageReactionCb new_message_reaction; + LinphoneCoreCbsReactionRemovedCb reaction_removed; void *user_data; /**<User data associated with the above callbacks */ } LinphoneCoreVTable; @@ -600,6 +601,20 @@ LINPHONE_PUBLIC void linphone_core_cbs_set_new_message_reaction(LinphoneCoreCbs */ LINPHONE_PUBLIC LinphoneCoreCbsNewMessageReactionCb linphone_core_cbs_get_new_message_reaction(LinphoneCoreCbs *cbs); +/** + * Set the #LinphoneCoreCbsReactionRemovedCb callback. + * @param cbs A #LinphoneCoreCbs. @notnil + * @param cb The callback. + */ +LINPHONE_PUBLIC void linphone_core_cbs_set_reaction_removed(LinphoneCoreCbs *cbs, LinphoneCoreCbsReactionRemovedCb cb); + +/** + * Get the #LinphoneCoreCbsReactionRemovedCb callback. + * @param cbs A #LinphoneCoreCbs. @notnil + * @return The callback. + */ +LINPHONE_PUBLIC LinphoneCoreCbsReactionRemovedCb linphone_core_cbs_get_reaction_removed(LinphoneCoreCbs *cbs); + /** * Set the #LinphoneCoreCbsMessagesReceivedCb callback. * @param cbs A #LinphoneCoreCbs. @notnil diff --git a/src/c-wrapper/api/c-chat-message-cbs.cpp b/src/c-wrapper/api/c-chat-message-cbs.cpp index 420a4e7a4b..a0fc399410 100644 --- a/src/c-wrapper/api/c-chat-message-cbs.cpp +++ b/src/c-wrapper/api/c-chat-message-cbs.cpp @@ -36,6 +36,7 @@ struct _LinphoneChatMessageCbs { LinphoneChatMessageCbsEphemeralMessageDeletedCb ephemeral_message_deleted; LinphoneChatMessageCbsFileTransferSendChunkCb file_transfer_send_chunk; LinphoneChatMessageCbsNewMessageReactionCb new_message_reaction; + LinphoneChatMessageCbsReactionRemovedCb reaction_removed; }; BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessageCbs); @@ -160,4 +161,14 @@ linphone_chat_message_cbs_get_new_message_reaction(const LinphoneChatMessageCbs void linphone_chat_message_cbs_set_new_message_reaction(LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsNewMessageReactionCb cb) { cbs->new_message_reaction = cb; +} + +LinphoneChatMessageCbsReactionRemovedCb +linphone_chat_message_cbs_get_reaction_removed(const LinphoneChatMessageCbs *cbs) { + return cbs->reaction_removed; +} + +void linphone_chat_message_cbs_set_reaction_removed(LinphoneChatMessageCbs *cbs, + LinphoneChatMessageCbsReactionRemovedCb cb) { + cbs->reaction_removed = cb; } \ No newline at end of file diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index b248469365..6e2700d4a2 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -152,6 +152,10 @@ void _linphone_chat_message_notify_new_message_reaction(LinphoneChatMessage *msg NOTIFY_IF_EXIST(NewMessageReaction, new_message_reaction, msg, reaction); } +void _linphone_chat_message_notify_reaction_removed(LinphoneChatMessage *msg, const LinphoneAddress *address) { + NOTIFY_IF_EXIST(ReactionRemoved, reaction_removed, msg, address); +} + void _linphone_chat_message_notify_participant_imdn_state_changed(LinphoneChatMessage *msg, const LinphoneParticipantImdnState *state) { NOTIFY_IF_EXIST(ParticipantImdnStateChanged, participant_imdn_state_changed, msg, state); diff --git a/src/chat/chat-message/chat-message-reaction.cpp b/src/chat/chat-message/chat-message-reaction.cpp index 9d97d71e4f..9322fb72bd 100644 --- a/src/chat/chat-message/chat-message-reaction.cpp +++ b/src/chat/chat-message/chat-message-reaction.cpp @@ -21,6 +21,8 @@ #include "chat-message-reaction.h" #include "chat-message-p.h" #include "chat/chat-room/abstract-chat-room.h" +#include "core/core-p.h" +#include "db/main-db-p.h" #include "linphone/utils/utils.h" #include "logger/logger.h" @@ -71,11 +73,24 @@ void ChatMessageReaction::onChatMessageStateChanged(const shared_ptr<ChatMessage } LinphoneChatMessage *msg = L_GET_C_BACK_PTR(originalMessage); - LinphoneChatMessageReaction *reaction = getSharedFromThis()->toC(); - _linphone_chat_message_notify_new_message_reaction(msg, reaction); - + const string &messageId = originalMessage->getImdnMessageId(); LinphoneChatRoom *cr = L_GET_C_BACK_PTR(message->getChatRoom()); - linphone_core_notify_new_message_reaction(message->getCore()->getCCore(), cr, msg, reaction); + + if (reaction.empty()) { + lInfo() << "[Chat Message Reaction] Sending empty reaction to chat message ID [" << messageId + << "] to remove any previously existing reaction"; + const LinphoneAddress *address = fromAddress->toC(); + unique_ptr<MainDb> &mainDb = message->getChatRoom()->getCore()->getPrivate()->mainDb; + mainDb->removeConferenceChatMessageReactionEvent(messageId, fromAddress); + + _linphone_chat_message_notify_reaction_removed(msg, address); + linphone_core_notify_message_reaction_removed(message->getCore()->getCCore(), cr, msg, address); + } else { + LinphoneChatMessageReaction *reaction = getSharedFromThis()->toC(); + _linphone_chat_message_notify_new_message_reaction(msg, reaction); + + linphone_core_notify_new_message_reaction(message->getCore()->getCCore(), cr, msg, reaction); + } message->removeListener(getSharedFromThis()); } else if (state == ChatMessage::State::NotDelivered) { diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index e74ba2724d..0f6450d93a 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -886,7 +886,6 @@ LinphoneReason ChatMessagePrivate::receive() { if (q->isReaction()) { markAsRead(); - storeInDb(); auto messageId = q->getReactionToMessageId(); auto originalMessage = q->getReactionToMessage(); @@ -896,12 +895,32 @@ LinphoneReason ChatMessagePrivate::receive() { return reason; } + shared_ptr<AbstractChatRoom> chatRoom = q->getChatRoom(); + LinphoneChatRoom *cr = L_GET_C_BACK_PTR(chatRoom); + LinphoneChatMessage *msg = L_GET_C_BACK_PTR(originalMessage); + + const string &reactionBody = getUtf8Text(); + if (reactionBody.empty()) { + auto fromAddress = q->getFromAddress(); + lInfo() << "Reaction body for message ID [" << messageId << "] is empty, removing existing reaction from [" + << fromAddress->asStringUriOnly() << "] if any"; + unique_ptr<MainDb> &mainDb = chatRoom->getCore()->getPrivate()->mainDb; + mainDb->removeConferenceChatMessageReactionEvent(messageId, fromAddress); + + const LinphoneAddress *address = q->getFromAddress()->toC(); + _linphone_chat_message_notify_reaction_removed(msg, address); + linphone_core_notify_message_reaction_removed(q->getCore()->getCCore(), cr, msg, address); + + return reason; + } + + storeInDb(); + LinphoneChatMessageReaction *reaction = ChatMessageReaction::createCObject(messageId, getUtf8Text(), q->getFromAddress()); _linphone_chat_message_notify_new_message_reaction(msg, reaction); - LinphoneChatRoom *cr = L_GET_C_BACK_PTR(q->getChatRoom()); linphone_core_notify_new_message_reaction(q->getCore()->getCCore(), cr, msg, reaction); linphone_chat_message_reaction_unref(reaction); diff --git a/src/core/core.h b/src/core/core.h index 01f560ed76..c6e707a54a 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -61,6 +61,7 @@ class ConferenceParams; class CorePrivate; class EncryptionEngine; class ChatMessage; +class ChatMessageReaction; class ChatRoom; class Ldap; class PushNotificationMessage; @@ -83,6 +84,7 @@ class LINPHONE_PUBLIC Core : public Object { friend class CallSession; friend class ChatMessage; friend class ChatMessagePrivate; + friend class ChatMessageReaction; friend class ChatRoom; friend class ChatRoomPrivate; friend class Conference; diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 895dbc4955..6b1dbb471d 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -4575,6 +4575,10 @@ list<shared_ptr<ChatMessageReaction>> MainDb::getChatMessageReactions(const shar soci::rowset<soci::row> rows = (session->prepare << query, soci::use(messageId)); for (const auto &row : rows) { string body = row.get<string>(0); + if (body.empty()) { + lDebug() << "Found empty reaction for message [" << chatMessage << "], skipping"; + continue; + } shared_ptr<Address> fromAddress = make_shared<Address>(row.get<string>(1)); shared_ptr<ChatMessageReaction> reaction = ChatMessageReaction::create(messageId, body, fromAddress); reactions.push_back(reaction); @@ -4584,6 +4588,23 @@ list<shared_ptr<ChatMessageReaction>> MainDb::getChatMessageReactions(const shar return reactions; } +void MainDb::removeConferenceChatMessageReactionEvent(const string &messageId, + const std::shared_ptr<const Address> &from) { +#ifdef HAVE_DB_STORAGE + L_DB_TRANSACTION { + L_D(); + + const long long &fromSipAddressId = d->selectSipAddressId(from->toStringUriOnlyOrdered()); + + *d->dbSession.getBackendSession() + << "DELETE FROM conference_chat_message_reaction_event WHERE" + " from_sip_address_id = :from_sip_address_id AND reaction_to_message_id = :messageId", + soci::use(fromSipAddressId), soci::use(messageId); + tr.commit(); + }; +#endif +} + // ----------------------------------------------------------------------------- void MainDb::disableDeliveryNotificationRequired(const std::shared_ptr<const EventLog> &eventLog) { diff --git a/src/db/main-db.h b/src/db/main-db.h index f133cf0df4..3e8f233e50 100644 --- a/src/db/main-db.h +++ b/src/db/main-db.h @@ -159,6 +159,8 @@ public: void loadChatMessageContents(const std::shared_ptr<ChatMessage> &chatMessage); std::list<std::shared_ptr<ChatMessageReaction>> getChatMessageReactions(const std::shared_ptr<ChatMessage> &chatMessage); + void removeConferenceChatMessageReactionEvent(const std::string &messageId, + const std::shared_ptr<const Address> &from); void disableDeliveryNotificationRequired(const std::shared_ptr<const EventLog> &eventLog); void disableDisplayNotificationRequired(const std::shared_ptr<const EventLog> &eventLog); diff --git a/tester/group_chat_secure_tester.c b/tester/group_chat_secure_tester.c index 6ae3b82b03..862e33d9b9 100644 --- a/tester/group_chat_secure_tester.c +++ b/tester/group_chat_secure_tester.c @@ -1621,6 +1621,49 @@ static void group_chat_lime_x3dh_chat_room_reaction_message_base(const int curve check_reactions(marieSentMessage, 3, expected_reactions, expected_reactions_from); check_reactions(paulineReceivedMessage, 3, expected_reactions, expected_reactions_from); } + } else { + // Marie is sending an empty reaction to remove it's previous reaction + LinphoneChatMessageReaction *marieEmptyReaction = linphone_chat_message_create_reaction(marieSentMessage, ""); + linphone_chat_message_reaction_send(marieEmptyReaction); + + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneReactionRemoved, + initialMarieStats.number_of_LinphoneReactionRemoved + 1, 5000)); + linphone_chat_message_reaction_unref(marieEmptyReaction); + + expected_reactions = bctbx_list_remove(expected_reactions, bctbx_list_last_elem(expected_reactions)); + expected_reactions_from = + bctbx_list_remove(expected_reactions_from, bctbx_list_last_elem(expected_reactions_from)); + check_reactions(marieSentMessage, 2, expected_reactions, expected_reactions_from); + + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneReactionRemoved, + initialLaureStats.number_of_LinphoneReactionRemoved + 1, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneReactionRemoved, + initialPaulineStats.number_of_LinphoneReactionRemoved + 1, 5000)); + + check_reactions(laureReceivedMessage, 2, expected_reactions, expected_reactions_from); + check_reactions(paulineReceivedMessage, 2, expected_reactions, expected_reactions_from); + + // Laure is sending an empty reaction to remove it's previous reaction + LinphoneChatMessageReaction *laureEmptyReaction = + linphone_chat_message_create_reaction(laureReceivedMessage, ""); + linphone_chat_message_reaction_send(laureEmptyReaction); + + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneReactionRemoved, + initialMarieStats.number_of_LinphoneReactionRemoved + 2, 5000)); + linphone_chat_message_reaction_unref(laureEmptyReaction); + + expected_reactions = bctbx_list_remove(expected_reactions, bctbx_list_last_elem(expected_reactions)); + expected_reactions_from = + bctbx_list_remove(expected_reactions_from, bctbx_list_last_elem(expected_reactions_from)); + check_reactions(laureReceivedMessage, 1, expected_reactions, expected_reactions_from); + + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneReactionRemoved, + initialLaureStats.number_of_LinphoneReactionRemoved + 2, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneReactionRemoved, + initialPaulineStats.number_of_LinphoneReactionRemoved + 2, 5000)); + + check_reactions(marieSentMessage, 1, expected_reactions, expected_reactions_from); + check_reactions(paulineReceivedMessage, 1, expected_reactions, expected_reactions_from); } end: diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 99e15a7e97..5a7d9aab9f 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -341,6 +341,7 @@ typedef struct _stats { int progress_of_LinphoneFileTransfer; int number_of_LinphoneFileTransfer; int number_of_LinphoneReactionSentOrReceived; + int number_of_LinphoneReactionRemoved; int number_of_LinphoneChatRoomConferenceJoined; int number_of_LinphoneChatRoomEphemeralLifetimeChanged; @@ -636,6 +637,10 @@ void reaction_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg, const LinphoneChatMessageReaction *reaction); +void reaction_removed(LinphoneCore *lc, + LinphoneChatRoom *room, + LinphoneChatMessage *msg, + const LinphoneAddress *address); void file_transfer_received(LinphoneChatMessage *message, LinphoneContent *content, const LinphoneBuffer *buffer); LinphoneBuffer * tester_file_transfer_send(LinphoneChatMessage *message, LinphoneContent *content, size_t offset, size_t size); diff --git a/tester/message_tester.c b/tester/message_tester.c index d5960286f9..a9daf2d94d 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -422,25 +422,24 @@ void check_reactions(LinphoneChatMessage *message, BC_ASSERT_PTR_NOT_NULL(reactions); if (reactions_it) { - BC_ASSERT_EQUAL(bctbx_list_size(reactions), expected_reactions_count, size_t, "%zu"); - if (bctbx_list_size(reactions) == expected_reactions_count) { - for (size_t i = 0; i < expected_reactions_count; i++) { - const LinphoneChatMessageReaction *reaction = - (const LinphoneChatMessageReaction *)bctbx_list_get_data(reactions_it); - reactions_it = bctbx_list_next(reactions_it); + size_t count = bctbx_list_size(reactions); + BC_ASSERT_EQUAL(count, expected_reactions_count, size_t, "%zu"); + for (size_t i = 0; i < count; i++) { + const LinphoneChatMessageReaction *reaction = + (const LinphoneChatMessageReaction *)bctbx_list_get_data(reactions_it); + reactions_it = bctbx_list_next(reactions_it); - const char *expected_reaction = (const char *)bctbx_list_get_data(expected_reactions_it); - expected_reactions_it = bctbx_list_next(expected_reactions_it); + const char *expected_reaction = (const char *)bctbx_list_get_data(expected_reactions_it); + expected_reactions_it = bctbx_list_next(expected_reactions_it); - const char *expected_reaction_from = (const char *)bctbx_list_get_data(expected_reactions_from_it); - expected_reactions_from_it = bctbx_list_next(expected_reactions_from_it); + const char *expected_reaction_from = (const char *)bctbx_list_get_data(expected_reactions_from_it); + expected_reactions_from_it = bctbx_list_next(expected_reactions_from_it); - const char *reaction_body = linphone_chat_message_reaction_get_body(reaction); - BC_ASSERT_STRING_EQUAL(reaction_body, expected_reaction); + const char *reaction_body = linphone_chat_message_reaction_get_body(reaction); + BC_ASSERT_STRING_EQUAL(reaction_body, expected_reaction); - const LinphoneAddress *from = linphone_chat_message_reaction_get_from_address(reaction); - BC_ASSERT_STRING_EQUAL(linphone_address_as_string_uri_only(from), expected_reaction_from); - } + const LinphoneAddress *from = linphone_chat_message_reaction_get_from_address(reaction); + BC_ASSERT_STRING_EQUAL(linphone_address_as_string_uri_only(from), expected_reaction_from); } } bctbx_list_free_with_data(reactions, (bctbx_list_free_func)linphone_chat_message_reaction_unref); @@ -4101,4 +4100,3 @@ test_suite_t rtt_message_test_suite = {"RTT Message", sizeof(rtt_message_tests) / sizeof(rtt_message_tests[0]), rtt_message_tests, 0}; - diff --git a/tester/tester.c b/tester/tester.c index 185d7fe089..e6d166d9db 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -2477,6 +2477,7 @@ void linphone_core_manager_init2(LinphoneCoreManager *mgr, BCTBX_UNUSED(const ch linphone_core_cbs_set_call_state_changed(mgr->cbs, call_state_changed); linphone_core_cbs_set_message_received(mgr->cbs, message_received); linphone_core_cbs_set_new_message_reaction(mgr->cbs, reaction_received); + linphone_core_cbs_set_reaction_removed(mgr->cbs, reaction_removed); linphone_core_cbs_set_messages_received(mgr->cbs, messages_received); linphone_core_cbs_set_is_composing_received(mgr->cbs, is_composing_received); linphone_core_cbs_set_new_subscription_requested(mgr->cbs, new_subscription_requested); @@ -3218,6 +3219,17 @@ void reaction_received(LinphoneCore *lc, counters->number_of_LinphoneReactionSentOrReceived++; } +void reaction_removed(LinphoneCore *lc, + BCTBX_UNUSED(LinphoneChatRoom *room), + LinphoneChatMessage *msg, + const LinphoneAddress *address) { + char *from = linphone_address_as_string(address); + const char *text = linphone_chat_message_get_text(msg); + ms_message("Reaction sent by [%s] for message [%s] has been removed", from, text); + stats *counters = get_stats(lc); + counters->number_of_LinphoneReactionRemoved++; +} + void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { stats *counters = get_stats(lc); if (linphone_chat_room_is_remote_composing(room)) { -- GitLab