diff --git a/src/chat/chat-message-p.h b/src/chat/chat-message-p.h index bd5b5cbe7..f31ffc0b9 100644 --- a/src/chat/chat-message-p.h +++ b/src/chat/chat-message-p.h @@ -33,6 +33,14 @@ class ChatMessagePrivate : public ObjectPrivate { friend class MultipartChatMessageModifier; public: + enum Step { + None = 1 << 0, + FileUpload = 1 << 1, + Multipart = 1 << 2, + Encryption = 1 << 3, + Cpim = 1 << 4 + }; + ChatMessagePrivate (const std::shared_ptr &room); virtual ~ChatMessagePrivate (); @@ -127,6 +135,7 @@ private: SalOp *salOp = NULL; SalCustomHeader *salCustomHeaders = NULL; unsigned long backgroundTaskId; + unsigned char currentSendStep = Step::None; // Cache for returned values, used for compatibility with previous C API ContentType cContentType; std::string cText = ""; diff --git a/src/chat/chat-message.cpp b/src/chat/chat-message.cpp index dc543a760..99cb87839 100644 --- a/src/chat/chat-message.cpp +++ b/src/chat/chat-message.cpp @@ -1030,6 +1030,19 @@ void ChatMessagePrivate::send() { SalOp *op = salOp; LinphoneCall *call = NULL; + if ((currentSendStep & ChatMessagePrivate::Step::FileUpload) == ChatMessagePrivate::Step::FileUpload) { + lInfo() << "File upload step already done, skipping"; + } else { + if (getFileTransferInformation()) { + /* Open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ + if (q->uploadFile() == 0) { + setState(ChatMessage::State::InProgress); + currentSendStep |= ChatMessagePrivate::Step::FileUpload; + } + return; + } + } + if (lp_config_get_int(chatRoom->getCore()->config, "sip", "chat_use_call_dialogs", 0) != 0) { call = linphone_core_get_call_by_remote_address(chatRoom->getCore(), chatRoom->getPeerAddress().asString().c_str()); if (call) { @@ -1070,33 +1083,52 @@ void ChatMessagePrivate::send() { // Start of message modification // --------------------------------------- + //TODO Remove : This won't be necessary once we store the contentsList string clearTextMessage; ContentType clearTextContentType; - + if (!getText().empty()) { clearTextMessage = getText().c_str(); } if (getContentType().isValid()) { clearTextContentType = getContentType(); } + //End of TODO Remove - if (contents.size() > 1) { - MultipartChatMessageModifier mcmm; - mcmm.encode(this); + if ((currentSendStep & ChatMessagePrivate::Step::Multipart) == ChatMessagePrivate::Step::Multipart) { + lInfo() << "Multipart step already done, skipping"; + } else { + if (contents.size() > 1) { + MultipartChatMessageModifier mcmm; + mcmm.encode(this); + } + currentSendStep |= ChatMessagePrivate::Step::Multipart; } - EncryptionChatMessageModifier ecmm; - int retval = ecmm.encode(this); - if (retval > 0) { - sal_error_info_set((SalErrorInfo *)op->get_error_info(), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", nullptr); - q->updateState(ChatMessage::State::NotDelivered); - q->store(); - return; + if ((currentSendStep & ChatMessagePrivate::Step::Encryption) == ChatMessagePrivate::Step::Encryption) { + lInfo() << "Encryption step already done, skipping"; + } else { + EncryptionChatMessageModifier ecmm; + int retval = ecmm.encode(this); + if (retval > 0) { + if (retval > 1) { + sal_error_info_set((SalErrorInfo *)op->get_error_info(), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", nullptr); + q->updateState(ChatMessage::State::NotDelivered); + q->store(); + } + return; + } + currentSendStep |= ChatMessagePrivate::Step::Encryption; } - if (lp_config_get_int(chatRoom->getCore()->config, "sip", "use_cpim", 0) == 1) { - CpimChatMessageModifier ccmm; - ccmm.encode(this); + if ((currentSendStep & ChatMessagePrivate::Step::Cpim) == ChatMessagePrivate::Step::Cpim) { + lInfo() << "Cpim step already done, skipping"; + } else { + if (lp_config_get_int(chatRoom->getCore()->config, "sip", "use_cpim", 0) == 1) { + CpimChatMessageModifier ccmm; + ccmm.encode(this); + } + currentSendStep |= ChatMessagePrivate::Step::Cpim; } // --------------------------------------- @@ -1117,6 +1149,7 @@ void ChatMessagePrivate::send() { } } + //TODO Remove : This won't be necessary once we store the contentsList if (!getText().empty() && getText() == clearTextMessage) { /* We replace the encrypted message by the original one so it can be correctly stored and displayed by the application */ setText(clearTextMessage); @@ -1125,6 +1158,8 @@ void ChatMessagePrivate::send() { /* We replace the encrypted content type by the original one */ setContentType(clearTextContentType); } + //End of TODO Remove + q->setId(op->get_call_id()); /* must be known at that time */ if (call && linphone_call_get_op(call) == op) { diff --git a/src/chat/chat-room.cpp b/src/chat/chat-room.cpp index 3bc88a1d5..150e19bf2 100644 --- a/src/chat/chat-room.cpp +++ b/src/chat/chat-room.cpp @@ -732,33 +732,18 @@ void ChatRoom::sendMessage (shared_ptr msg) { msg->getPrivate()->setDirection(ChatMessage::Direction::Outgoing); - /* Check if we shall upload a file to a server */ - if (msg->getPrivate()->getFileTransferInformation() && !msg->getPrivate()->getContentType().isValid()) { - /* Open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ - if (msg->uploadFile() == 0) { - /* Add to transient list only if message is going out */ - d->addTransientMessage(msg); - /* Store the message so that even if the upload is stopped, it can be done again */ - d->storeOrUpdateMessage(msg); + /* Add to transient list */ + d->addTransientMessage(msg); - msg->getPrivate()->setState(ChatMessage::State::InProgress); - } else { - return; - } - } else { - /* Add to transient list */ - d->addTransientMessage(msg); + msg->getPrivate()->setTime(ms_time(0)); + msg->getPrivate()->send(); - msg->getPrivate()->setTime(ms_time(0)); - msg->getPrivate()->send(); + d->storeOrUpdateMessage(msg); - d->storeOrUpdateMessage(msg); - - if (d->isComposing) - d->isComposing = false; - d->isComposingHandler.stopIdleTimer(); - d->isComposingHandler.stopRefreshTimer(); - } + if (d->isComposing) + d->isComposing = false; + d->isComposingHandler.stopIdleTimer(); + d->isComposingHandler.stopRefreshTimer(); } // ----------------------------------------------------------------------------- diff --git a/src/chat/modifier/chat-message-modifier.h b/src/chat/modifier/chat-message-modifier.h index ed4741de4..3d98de617 100644 --- a/src/chat/modifier/chat-message-modifier.h +++ b/src/chat/modifier/chat-message-modifier.h @@ -32,7 +32,24 @@ class ChatMessageModifier { public: virtual ~ChatMessageModifier () = default; + /** + * This method will be called when the message is about to be sent. + * It should check first if the internalContent is filled. + * If so, it should apply it's changes to it, otherwise it should use the contentsList. + * If it returns 0, it means everything went well. + * If it returns -1, it means it didn't change anything. + * If it returns 1, it means to abort the sending process and it will be resumed later. + * If it returns any other value > 1, it's an error code. + */ virtual int encode (ChatMessagePrivate *messagePrivate) = 0; + + /** + * This method will be called when the message is about to be received. + * It should apply it's changes to the internal content, the last modifier will take care of filling the contentsList. + * If it returns 0, it means everything went well. + * If it returns -1, it means it didn't change anything. + * If it returns any other value > 0, it's an error code. + */ virtual int decode (ChatMessagePrivate *messagePrivate) = 0; }; diff --git a/src/chat/modifier/encryption-chat-message-modifier.cpp b/src/chat/modifier/encryption-chat-message-modifier.cpp index af5b24c91..45735553d 100644 --- a/src/chat/modifier/encryption-chat-message-modifier.cpp +++ b/src/chat/modifier/encryption-chat-message-modifier.cpp @@ -41,7 +41,7 @@ int EncryptionChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs); if (cbProcessOutgoingMessage) { retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(messagePrivate->chatRoom), L_GET_C_BACK_PTR(messagePrivate->getPublic()->getSharedFromThis())); - if (retval == 0) { + if (retval == 0 || retval == 1) { messagePrivate->isSecured = true; } } diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index cdad3fc02..cf2e7dad6 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -35,6 +35,12 @@ int MultipartChatMessageModifier::encode (ChatMessagePrivate *messagePrivate) { int MultipartChatMessageModifier::decode (ChatMessagePrivate *messagePrivate) { //TODO + if (false) { // Multipart required + + } else if (messagePrivate->contents.size() == 0) { + // All previous modifiers only altered the internal content, let's fill the content list because we're the last modifier to be called + messagePrivate->contents.push_back(messagePrivate->internalContent); + } return 0; }