Commit 25371cbf authored by Sylvain Berfini's avatar Sylvain Berfini 🎩
Browse files

Added a way to suspend the sending of a ChatMessage (now using this for file transfer)

parent 6beb9625
......@@ -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<ChatRoom> &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 = "";
......
......@@ -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) {
......
......@@ -732,33 +732,18 @@ void ChatRoom::sendMessage (shared_ptr<ChatMessage> 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);
msg->getPrivate()->setState(ChatMessage::State::InProgress);
} else {
return;
}
} else {
/* Add to transient list */
d->addTransientMessage(msg);
/* 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();
}
// -----------------------------------------------------------------------------
......
......@@ -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;
};
......
......@@ -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;
}
}
......
......@@ -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;
}
......
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