mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-30 01:39:20 +00:00
Added a way to suspend the sending of a ChatMessage (now using this for file transfer)
This commit is contained in:
parent
6beb962517
commit
25371cbfef
6 changed files with 91 additions and 39 deletions
|
|
@ -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);
|
||||
/* 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();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue