Commit 735ab95f authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Added FileTransferInProgress state for ChatMessage + only set Displayed state...

Added FileTransferInProgress state for ChatMessage + only set Displayed state when displayed IMDN has been sent (do not set it when using MarkAsRead if there is a file transfer not yet downloaded)
parent 84f937e2
......@@ -30,7 +30,8 @@
F(FileTransferError /**< Message was received and acknowledged but cannot get file from server */) \
F(FileTransferDone /**< File transfer has been completed successfully */) \
F(DeliveredToUser /**< Message successfully delivered an acknowledged by the remote user */) \
F(Displayed /**< Message successfully displayed to the remote user */)
F(Displayed /**< Message successfully displayed to the remote user */) \
F(FileTransferInProgress /** <File transfer is in progress. If message is incoming it's a download, otherwise it's an upload. */)
#define L_ENUM_VALUES_CHAT_MESSAGE_DIRECTION(F) \
F(Incoming /**< Incoming message */) \
......
......@@ -457,6 +457,8 @@ const char *linphone_chat_message_state_to_string (const LinphoneChatMessageStat
return "LinphoneChatMessageStateDeliveredToUser";
case LinphoneChatMessageStateDisplayed:
return "LinphoneChatMessageStateDisplayed";
case LinphoneChatMessageStateFileTransferInProgress:
return "LinphoneChatMessageStateFileTransferInProgress";
}
return NULL;
}
......
......@@ -75,6 +75,10 @@ public:
void setIsReadOnly (bool readOnly);
void markAsRead ();
bool isMarkedAsRead () const;
void setImdnMessageId (const std::string &imdnMessageId);
void setAuthenticatedFromAddress (const IdentityAddress &authenticatedFromAddress) {
......@@ -214,6 +218,7 @@ private:
std::string externalBodyUrl;
bool isSecured = false;
mutable bool isReadOnly = false;
bool markedAsRead = false;
Content internalContent;
bool isAutoDownloadAttachedFilesHappened = false;
......
......@@ -71,6 +71,14 @@ void ChatMessagePrivate::setIsReadOnly (bool readOnly) {
isReadOnly = readOnly;
}
void ChatMessagePrivate::markAsRead () {
markedAsRead = true;
}
bool ChatMessagePrivate::isMarkedAsRead () const {
return markedAsRead;
}
void ChatMessagePrivate::setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState, time_t stateChangeTime) {
L_Q();
......@@ -174,26 +182,32 @@ void ChatMessagePrivate::setState (ChatMessage::State newState) {
linphone_chat_message_cbs_get_msg_state_changed(cbs)(msg, (LinphoneChatMessageState)state);
_linphone_chat_message_notify_msg_state_changed(msg, (LinphoneChatMessageState)state);
// 3. Specific case, change to displayed after transfer.
// 3. Specific case, change to displayed once all file transfers haven been downloaded.
if (state == ChatMessage::State::FileTransferDone && direction == ChatMessage::Direction::Incoming) {
setState(ChatMessage::State::Displayed);
if (!hasFileTransferContent()) {
setState(ChatMessage::State::Displayed);
return;
}
}
// 4. Specific case, upon reception do not attempt to store in db before asking the user if he wants to do so or not
if (state == ChatMessage::State::Delivered && oldState == ChatMessage::State::Idle
&& direction == ChatMessage::Direction::Incoming && !dbKey.isValid()) {
// If we're here it's because message is because we're in the middle of the receive() method and
// we won't have a valid dbKey until the chat room callback asking if message should be store will be called
// and that's happen in the notifyReceiving() called at the of the receive() method we're in.
// This prevents the error log: Invalid db key [%p] associated to message [%p]
return;
}
// 4. Send notification and update in database if necessary.
if (state != ChatMessage::State::FileTransferError && state != ChatMessage::State::InProgress) {
if ((state == ChatMessage::State::Displayed) && (direction == ChatMessage::Direction::Incoming) && (!hasFileTransferContent())) {
// Wait until all files are downloaded before sending displayed IMDN
static_cast<ChatRoomPrivate *>(q->getChatRoom()->getPrivate())->sendDisplayNotification(q->getSharedFromThis());
}
if (state == ChatMessage::State::Delivered && oldState == ChatMessage::State::Idle
&& direction == ChatMessage::Direction::Incoming && !dbKey.isValid()) {
// If we're here it's because message is because we're in the middle of the receive() method and
// we won't have a valid dbKey until the chat room callback asking if message should be store will be called
// and that's happen in the notifyReceiving() called at the of the receive() method we're in.
// This prevents the error log: Invalid db key [%p] associated to message [%p]
return;
}
// 5. Send notification
if ((state == ChatMessage::State::Displayed) && (direction == ChatMessage::Direction::Incoming)) {
// Wait until all files are downloaded before sending displayed IMDN
static_cast<ChatRoomPrivate *>(q->getChatRoom()->getPrivate())->sendDisplayNotification(q->getSharedFromThis());
}
// 6. Update in database if necessary.
if (state != ChatMessage::State::InProgress && state != ChatMessage::State::FileTransferError && state != ChatMessage::State::FileTransferInProgress) {
updateInDb();
}
}
......@@ -726,6 +740,7 @@ void ChatMessagePrivate::send () {
shared_ptr<AbstractChatRoom> chatRoom(q->getChatRoom());
if (!chatRoom) return;
markAsRead();
SalOp *op = salOp;
LinphoneCall *lcall = nullptr;
int errorCode = 0;
......@@ -750,7 +765,7 @@ void ChatMessagePrivate::send () {
return;
}
if (result == ChatMessageModifier::Result::Suspended) {
setState(ChatMessage::State::InProgress);
setState(ChatMessage::State::FileTransferInProgress);
return;
}
currentSendStep |= ChatMessagePrivate::Step::FileUpload;
......@@ -1215,7 +1230,7 @@ void ChatMessage::send () {
// Do not allow sending a message that is already being sent or that has been correctly delivered/displayed
if ((d->state == State::InProgress) || (d->state == State::Delivered) || (d->state == State::FileTransferDone) ||
(d->state == State::DeliveredToUser) || (d->state == State::Displayed)) {
(d->state == State::DeliveredToUser) || (d->state == State::Displayed)|| (d->state == State::FileTransferInProgress)) {
lWarning() << "Cannot send chat message in state " << Utils::toString(d->state);
return;
}
......@@ -1242,7 +1257,7 @@ bool ChatMessage::isFileTransferInProgress () const {
void ChatMessage::cancelFileTransfer () {
L_D();
if (d->fileTransferChatMessageModifier.isFileTransferInProgressAndValid()) {
if (d->state == State::InProgress) {
if (d->state == State::FileTransferInProgress) {
d->setState(State::NotDelivered);
}
d->fileTransferChatMessageModifier.cancelFileTransfer();
......
......@@ -542,8 +542,13 @@ void ChatRoom::markAsRead () {
L_D();
CorePrivate *dCore = getCore()->getPrivate();
for (auto &chatMessage : dCore->mainDb->getUnreadChatMessages(d->conferenceId))
chatMessage->getPrivate()->setState(ChatMessage::State::Displayed);
for (auto &chatMessage : dCore->mainDb->getUnreadChatMessages(d->conferenceId)) {
chatMessage->getPrivate()->markAsRead();
// Do not set the message state has displayed if it contains a file transfer (to prevent imdn sending)
if (!chatMessage->getPrivate()->hasFileTransferContent()) {
chatMessage->getPrivate()->setState(ChatMessage::State::Displayed);
}
}
dCore->mainDb->markChatMessagesAsRead(d->conferenceId);
}
......
......@@ -993,7 +993,7 @@ bool FileTransferChatMessageModifier::downloadFile (
if (err == -1)
return false;
// start the download, status is In Progress
message->getPrivate()->setState(ChatMessage::State::InProgress);
message->getPrivate()->setState(ChatMessage::State::FileTransferInProgress);
return true;
}
......
......@@ -87,7 +87,7 @@ namespace Statements {
)",
/* SelectConferenceEvent */ R"(
SELECT conference_event_view.id AS event_id, type, conference_event_view.creation_time, from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured, notify_id, device_sip_address.value, participant_sip_address.value, conference_event_view.subject, delivery_notification_required, display_notification_required, peer_sip_address.value, local_sip_address.value
SELECT conference_event_view.id AS event_id, type, conference_event_view.creation_time, from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured, notify_id, device_sip_address.value, participant_sip_address.value, conference_event_view.subject, delivery_notification_required, display_notification_required, peer_sip_address.value, local_sip_address.value, marked_as_read
FROM conference_event_view
JOIN chat_room ON chat_room.id = chat_room_id
JOIN sip_address AS peer_sip_address ON peer_sip_address.id = peer_sip_address_id
......@@ -100,7 +100,7 @@ namespace Statements {
)",
/* SelectConferenceEvents */ R"(
SELECT conference_event_view.id AS event_id, type, creation_time, from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured, notify_id, device_sip_address.value, participant_sip_address.value, subject, delivery_notification_required, display_notification_required, security_alert, faulty_device
SELECT conference_event_view.id AS event_id, type, creation_time, from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured, notify_id, device_sip_address.value, participant_sip_address.value, subject, delivery_notification_required, display_notification_required, security_alert, faulty_device, marked_as_read
FROM conference_event_view
LEFT JOIN sip_address AS from_sip_address ON from_sip_address.id = from_sip_address_id
LEFT JOIN sip_address AS to_sip_address ON to_sip_address.id = to_sip_address_id
......
This diff is collapsed.
......@@ -253,6 +253,7 @@ void _receive_file(bctbx_list_t *coresList, LinphoneCoreManager *lcm, stats *rec
BC_ASSERT_TRUE(linphone_content_is_file_transfer(fileTransferContent));
linphone_content_set_file_path(fileTransferContent, receive_filepath);
linphone_chat_message_download_content(msg, fileTransferContent);
BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), LinphoneChatMessageStateFileTransferInProgress, int, "%d");
if (BC_ASSERT_TRUE(wait_for_list(coresList, &lcm->stat.number_of_LinphoneFileTransferDownloadSuccessful,receiverStats->number_of_LinphoneFileTransferDownloadSuccessful + 1, 20000))) {
compare_files(sendFilepath, receive_filepath);
......@@ -277,6 +278,7 @@ void _receive_file_plus_text(bctbx_list_t *coresList, LinphoneCoreManager *lcm,
BC_ASSERT_TRUE(linphone_content_is_file_transfer(fileTransferContent));
linphone_content_set_file_path(fileTransferContent, receive_filepath);
linphone_chat_message_download_content(msg, fileTransferContent);
BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), LinphoneChatMessageStateFileTransferInProgress, int, "%d");
if (BC_ASSERT_TRUE(wait_for_list(coresList, &lcm->stat.number_of_LinphoneFileTransferDownloadSuccessful,receiverStats->number_of_LinphoneFileTransferDownloadSuccessful + 1, 20000))) {
compare_files(sendFilepath, receive_filepath);
......
......@@ -193,6 +193,7 @@ typedef struct _stats {
int number_of_LinphoneMessageUndecryptable;
int number_of_LinphoneMessageFileTransferDone;
int number_of_LinphoneMessageFileTransferError;
int number_of_LinphoneMessageFileTransferInProgress;
int number_of_LinphoneMessageDeliveredToUser;
int number_of_LinphoneMessageDisplayed;
int number_of_LinphoneIsComposingActiveReceived;
......
......@@ -323,7 +323,7 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau
if (chat_room_size == 1) {
history = linphone_chat_room_get_history(chat_room, 0);
LinphoneChatMessage *sent_msg = (LinphoneChatMessage *)bctbx_list_get_data(history);
BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateInProgress, int, "%d");
BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateFileTransferInProgress, int, "%d");
bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref);
}
sal_set_send_error(linphone_core_get_sal(pauline->lc), -1);
......@@ -373,6 +373,7 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau
linphone_chat_message_set_file_transfer_filepath(recv_msg, receive_filepath);
}
linphone_chat_message_download_file(recv_msg);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageFileTransferInProgress, 1, int, "%d");
if (download_error) {
/* wait for file to be 50% downloaded */
......@@ -399,8 +400,9 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau
compare_files(send_filepath, linphone_content_get_file_path(content));
}
}
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); //sent twice because of file transfer
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageFileTransferInProgress, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered, 1, int, "%d");
}
end:
linphone_chat_message_unref(msg);
......@@ -493,10 +495,10 @@ static void transfer_message_upload_cancelled(void) {
BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 25, 60000));
linphone_chat_message_cancel_file_transfer(msg);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered, 1));
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered, 1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful, 0, int, "%d");
linphone_chat_message_unref(msg);
linphone_core_manager_destroy(pauline);
......@@ -531,10 +533,11 @@ static void transfer_message_download_cancelled(void) {
linphone_chat_message_cancel_file_transfer(marie->stat.last_received_chat_message);
}
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageFileTransferInProgress, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered, 1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful, 0, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered, 1, int, "%d");
linphone_chat_message_unref(msg);
linphone_core_manager_destroy(marie);
......@@ -570,9 +573,9 @@ static void file_transfer_2_messages_simultaneously(void) {
if (bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)) == 0) {
linphone_chat_message_send(msg);
linphone_chat_message_send(msg2);
if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000))) {
if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile, 1, 60000))) {
LinphoneChatMessage *recvMsg = linphone_chat_message_ref(marie->stat.last_received_chat_message);
BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,2, 60000));
BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile, 2, 60000));
LinphoneChatMessage *recvMsg2 = marie->stat.last_received_chat_message;
BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)), 1, unsigned int, "%u");
if (bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)) != 1) {
......@@ -600,8 +603,9 @@ static void file_transfer_2_messages_simultaneously(void) {
BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,2,50000));
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,4, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,2, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageFileTransferInProgress, 2, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress, 2, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered, 2, int, "%d");
compare_files(send_filepath, receive_filepath);
linphone_chat_message_unref(recvMsg);
......@@ -1557,7 +1561,7 @@ void file_transfer_io_error_base(char *server_url) {
linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
linphone_core_set_file_transfer_server(marie->lc, server_url);
linphone_chat_message_send(msg);
BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageInProgress, 1, 1000));
BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageFileTransferInProgress, 1, 1000));
BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 3000));
linphone_chat_message_unref(msg);
linphone_core_manager_destroy(marie);
......@@ -1581,7 +1585,7 @@ static void file_transfer_success_after_destroying_chatroom(void) {
);
linphone_core_set_file_transfer_server(marie->lc, "https://www.linphone.org:444/lft.php");
linphone_chat_message_send(msg);
BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageInProgress, 1, 1000));
BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageFileTransferInProgress, 1, 1000));
linphone_core_delete_chat_room(marie->lc, chatroom);
//As of today (2019/02/07), chat message can no longer be sent without chatroom
BC_ASSERT_FALSE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageDisplayed, 1, 1000));
......
......@@ -1466,6 +1466,9 @@ void liblinphone_tester_chat_message_msg_state_changed(LinphoneChatMessage *msg,
case LinphoneChatMessageStateDisplayed:
counters->number_of_LinphoneMessageDisplayed++;
return;
case LinphoneChatMessageStateFileTransferInProgress:
counters->number_of_LinphoneMessageFileTransferInProgress++;
return;
}
ms_error("Unexpected state [%s] for msg [%p]",linphone_chat_message_state_to_string(state), msg);
}
......@@ -1482,6 +1485,7 @@ LinphoneBuffer * tester_file_transfer_send(LinphoneChatMessage *msg, const Linph
// If a file path is set, we should NOT call the on_send callback !
BC_ASSERT_PTR_NULL(linphone_chat_message_get_file_transfer_filepath(msg));
BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), LinphoneChatMessageStateFileTransferInProgress, int, "%d");
BC_ASSERT_PTR_NOT_NULL(file_to_send);
if (file_to_send == NULL){
......@@ -1513,6 +1517,7 @@ void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneC
stats *counters = get_stats(lc);
char *address = linphone_address_as_string(linphone_chat_message_is_outgoing(msg) ? to_address : from_address);
BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), LinphoneChatMessageStateFileTransferInProgress, int, "%d");
bctbx_message(
"File transfer [%d%%] %s of type [%s/%s] %s [%s] \n",
progress,
......@@ -1538,6 +1543,7 @@ void file_transfer_received(LinphoneChatMessage *msg, const LinphoneContent* con
// If a file path is set, we should NOT call the on_recv callback !
BC_ASSERT_PTR_NULL(linphone_chat_message_get_file_transfer_filepath(msg));
BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), LinphoneChatMessageStateFileTransferInProgress, int, "%d");
receive_file = bc_tester_file("receive_file.dump");
if (!linphone_chat_message_get_user_data(msg)) {
......
......@@ -62,6 +62,7 @@ static void on_msg_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageSt
case LinphoneChatMessageStateFileTransferDone:
case LinphoneChatMessageStateFileTransferError:
case LinphoneChatMessageStateIdle:
case LinphoneChatMessageStateFileTransferInProgress:
break;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment