Commit 8d39bbe9 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Moved send code from ChatRoom to ChatMessage

parent 33d7a384
......@@ -91,9 +91,7 @@ LinphoneChatMessageCbs *linphone_chat_message_get_callbacks(const LinphoneChatMe
// =============================================================================
LinphoneChatRoom *linphone_chat_message_get_chat_room(const LinphoneChatMessage *msg) {
shared_ptr<const LinphonePrivate::ChatMessage> message = L_GET_CPP_PTR_FROM_C_OBJECT(msg);
shared_ptr<LinphonePrivate::ChatRoom> room = message->getChatRoom();
return L_GET_C_BACK_PTR(room);
return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getChatRoom());
}
const char *linphone_chat_message_get_external_body_url(const LinphoneChatMessage *msg) {
......
......@@ -97,6 +97,8 @@ public:
// -----------------------------------------------------------------------------
void sendImdn(ImdnType imdnType, LinphoneReason reason);
void send();
private:
std::shared_ptr<ChatRoom> chatRoom;
......
......@@ -29,6 +29,8 @@
#include "content/content.h"
#include "chat-room-p.h"
#include "real-time-text-chat-room.h"
#include "modifier/multipart-chat-message-modifier.h"
#include "modifier/cpim-chat-message-modifier.h"
#include "ortp/b64.h"
......@@ -83,7 +85,7 @@ void ChatMessagePrivate::setState(ChatMessage::State s) {
linphone_chat_message_get_message_state_changed_cb(msg)(msg, (LinphoneChatMessageState)state, linphone_chat_message_get_message_state_changed_cb_user_data(msg));
}
LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
if (linphone_chat_message_cbs_get_msg_state_changed(cbs)) {
if (cbs && linphone_chat_message_cbs_get_msg_state_changed(cbs)) {
linphone_chat_message_cbs_get_msg_state_changed(cbs)(msg, linphone_chat_message_get_state(msg));
}
}
......@@ -585,8 +587,7 @@ void ChatMessagePrivate::processResponseFromPostFile(const belle_http_response_e
first_part_header = "form-data; name=\"File\"; filename=\"filename.txt\"";
} else {
// temporary storage for the Content-disposition header value
first_part_header = "form-data; name=\"File\"; filename=\"%s\"";
first_part_header = first_part_header + linphone_content_get_name(cFileTransferInformation);
first_part_header = "form-data; name=\"File\"; filename=\"" +string(linphone_content_get_name(cFileTransferInformation)) + "\"";
}
// create a user body handler to take care of the file and add the content disposition and content-type headers
......@@ -683,7 +684,7 @@ void ChatMessagePrivate::processResponseFromPostFile(const belle_http_response_e
setContentType("application/vnd.gsma.rcs-ft-http+xml");
q->updateState(ChatMessage::State::FileTransferDone);
releaseHttpRequest();
//TODO chatRoom->sendMessage(q);
send();
fileUploadEndBackgroundTask();
} else {
ms_warning("Received empty response from server, file transfer failed");
......@@ -793,7 +794,7 @@ void ChatMessagePrivate::processIoErrorUpload(const belle_sip_io_error_event_t *
ms_error("I/O Error during file upload of msg [%p]", this);
q->updateState(ChatMessage::State::NotDelivered);
releaseHttpRequest();
//TODO chatRoom->getPrivate()->removeTransientMessage(q);
chatRoom->getPrivate()->removeTransientMessage(q->getSharedPtr());
}
static void _chat_message_process_auth_requested_upload(void *data, belle_sip_auth_event *event) {
......@@ -806,7 +807,7 @@ void ChatMessagePrivate::processAuthRequestedUpload(const belle_sip_auth_event *
ms_error("Error during file upload: auth requested for msg [%p]", this);
q->updateState(ChatMessage::State::NotDelivered);
releaseHttpRequest();
//TODO chatRoom->getPrivate()->removeTransientMessage(q);
chatRoom->getPrivate()->removeTransientMessage(q->getSharedPtr());
}
static void _chat_message_process_io_error_download(void *data, const belle_sip_io_error_event_t *event) {
......@@ -886,6 +887,132 @@ void ChatMessagePrivate::releaseHttpRequest() {
}
}
void ChatMessagePrivate::send() {
L_Q();
SalOp *op = salOp;
LinphoneCall *call = NULL;
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) {
if (linphone_call_get_state(call) == LinphoneCallConnected || linphone_call_get_state(call) == LinphoneCallStreamsRunning ||
linphone_call_get_state(call) == LinphoneCallPaused || linphone_call_get_state(call) == LinphoneCallPausing ||
linphone_call_get_state(call) == LinphoneCallPausedByRemote) {
ms_message("send SIP msg through the existing call.");
op = linphone_call_get_op(call);
string identity = linphone_core_find_best_identity(chatRoom->getCore(), linphone_call_get_remote_address(call));
if (identity.empty()) {
LinphoneAddress *addr = linphone_address_new(chatRoom->getPeerAddress().asString().c_str());
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(chatRoom->getCore(), addr);
if (proxy) {
identity = L_GET_CPP_PTR_FROM_C_OBJECT(linphone_proxy_config_get_identity_address(proxy))->asString();
} else {
identity = linphone_core_get_primary_contact(chatRoom->getCore());
}
linphone_address_unref(addr);
}
q->setFromAddress(identity);
}
}
}
if (!op) {
LinphoneAddress *peer = linphone_address_new(chatRoom->getPeerAddress().asString().c_str());
/* Sending out of call */
salOp = op = new SalMessageOp(chatRoom->getCore()->sal);
linphone_configure_op(
chatRoom->getCore(), op, peer, getSalCustomHeaders(),
!!lp_config_get_int(chatRoom->getCore()->config, "sip", "chat_msg_with_contact", 0)
);
op->set_user_pointer(L_GET_C_BACK_PTR(q)); /* If out of call, directly store msg */
linphone_address_unref(peer);
}
// ---------------------------------------
// Start of message modification
// ---------------------------------------
string clearTextMessage;
string clearTextContentType;
if (!getText().empty()) {
clearTextMessage = getText().c_str();
}
if (!getContentType().empty()) {
clearTextContentType = getContentType();
}
int retval = -1;
LinphoneImEncryptionEngine *imee = chatRoom->getCore()->im_encryption_engine;
if (imee) {
LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs);
if (cbProcessOutgoingMessage) {
//TODO retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(chatRoom), L_GET_C_BACK_PTR(this));
if (retval == 0) {
isSecured = true;
}
}
}
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 (contents.size() > 1) {
MultipartChatMessageModifier mcmm;
mcmm.encode(this);
}
if (lp_config_get_int(chatRoom->getCore()->config, "sip", "use_cpim", 0) == 1) {
CpimChatMessageModifier ccmm;
ccmm.encode(this);
}
// ---------------------------------------
// End of message modification
// ---------------------------------------
if (!externalBodyUrl.empty()) {
char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", externalBodyUrl.c_str());
auto msgOp = dynamic_cast<SalMessageOpInterface *>(op);
msgOp->send_message(from.asString().c_str(), chatRoom->getPeerAddress().asString().c_str(), content_type, nullptr, nullptr);
ms_free(content_type);
} else {
auto msgOp = dynamic_cast<SalMessageOpInterface *>(op);
if (!getContentType().empty()) {
msgOp->send_message(from.asString().c_str(), chatRoom->getPeerAddress().asString().c_str(), getContentType().c_str(), getText().c_str(), chatRoom->getPeerAddress().asStringUriOnly().c_str());
} else {
msgOp->send_message(from.asString().c_str(), chatRoom->getPeerAddress().asString().c_str(), getText().c_str());
}
}
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);
}
if (!getContentType().empty() && getContentType() == clearTextContentType) {
/* We replace the encrypted content type by the original one */
setContentType(clearTextContentType);
}
q->setId(op->get_call_id()); /* must be known at that time */
if (call && linphone_call_get_op(call) == op) {
/* In this case, chat delivery status is not notified, so unrefing chat message right now */
/* Might be better fixed by delivering status, but too costly for now */
return;
}
/* If operation failed, we should not change message state */
if (q->isOutgoing()) {
setIsReadOnly(true);
setState(ChatMessage::State::InProgress);
}
}
// -----------------------------------------------------------------------------
// =============================================================================
......@@ -1150,7 +1277,7 @@ void ChatMessage::sendDisplayNotification() {
int ChatMessage::uploadFile() {
L_D();
if (d->httpRequest){
if (d->httpRequest) {
ms_error("linphone_chat_room_upload_file(): there is already an upload in progress.");
return -1;
}
......@@ -1246,4 +1373,8 @@ int ChatMessage::putCharacter(uint32_t character) {
return -1;
}
shared_ptr<ChatMessage> ChatMessage::getSharedPtr() {
return static_pointer_cast<ChatMessage>(shared_from_this());
}
LINPHONE_END_NAMESPACE
......@@ -143,6 +143,7 @@ public:
void removeCustomHeader(const std::string &headerName);
protected:
std::shared_ptr<ChatMessage> getSharedPtr();
explicit ChatMessage(ChatMessagePrivate &p);
private:
......
......@@ -23,8 +23,6 @@
#include "c-wrapper/c-wrapper.h"
#include "chat-room-p.h"
#include "modifier/multipart-chat-message-modifier.h"
#include "modifier/cpim-chat-message-modifier.h"
#include "imdn.h"
#include "content/content.h"
#include "chat-message-p.h"
......@@ -770,150 +768,24 @@ void ChatRoom::sendMessage (shared_ptr<ChatMessage> msg) {
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 {
SalOp *op = msg->getPrivate()->getSalOp();
LinphoneCall *call = nullptr;
string identity;
char *clearTextMessage = nullptr;
char *clearTextContentType = nullptr;
LinphoneAddress *peer = linphone_address_new(d->peerAddress.asString().c_str());
if (!msg->getPrivate()->getText().empty()) {
clearTextMessage = ms_strdup(msg->getPrivate()->getText().c_str());
}
if (!msg->getPrivate()->getContentType().empty()) {
clearTextContentType = ms_strdup(msg->getPrivate()->getContentType().c_str());
}
/* Add to transient list */
d->addTransientMessage(msg);
msg->getPrivate()->setTime(ms_time(0));
if (lp_config_get_int(d->core->config, "sip", "chat_use_call_dialogs", 0) != 0) {
call = linphone_core_get_call_by_remote_address(d->core, d->peerAddress.asString().c_str());
if (call) {
if (linphone_call_get_state(call) == LinphoneCallConnected || linphone_call_get_state(call) == LinphoneCallStreamsRunning ||
linphone_call_get_state(call) == LinphoneCallPaused || linphone_call_get_state(call) == LinphoneCallPausing ||
linphone_call_get_state(call) == LinphoneCallPausedByRemote) {
ms_message("send SIP msg through the existing call.");
op = linphone_call_get_op(call);
identity = linphone_core_find_best_identity(d->core, linphone_call_get_remote_address(call));
}
}
}
if (identity.empty()) {
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(d->core, peer);
if (proxy) {
identity = L_GET_CPP_PTR_FROM_C_OBJECT(linphone_proxy_config_get_identity_address(proxy))->asString();
} else {
identity = linphone_core_get_primary_contact(d->core);
}
}
msg->setFromAddress(identity);
// ---------------------------------------
// Start of message modification
// ---------------------------------------
int retval = -1;
LinphoneImEncryptionEngine *imee = d->core->im_encryption_engine;
if (imee) {
LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs);
if (cbProcessOutgoingMessage) {
retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(this), L_GET_C_BACK_PTR(msg));
if (retval == 0) {
msg->setIsSecured(true);
}
}
}
if (msg->getContents().size() > 1) {
MultipartChatMessageModifier mcmm;
mcmm.encode(msg->getPrivate());
}
if (lp_config_get_int(d->core->config, "sip", "use_cpim", 0) == 1) {
CpimChatMessageModifier ccmm;
ccmm.encode(msg->getPrivate());
}
// ---------------------------------------
// End of message modification
// ---------------------------------------
if (!op) {
/* Sending out of call */
msg->getPrivate()->setSalOp(op = new SalMessageOp(d->core->sal));
linphone_configure_op(
d->core, op, peer, msg->getPrivate()->getSalCustomHeaders(),
!!lp_config_get_int(d->core->config, "sip", "chat_msg_with_contact", 0)
);
op->set_user_pointer(L_GET_C_BACK_PTR(msg)); /* If out of call, directly store msg */
}
if (retval > 0) {
sal_error_info_set((SalErrorInfo *)op->get_error_info(), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", nullptr);
d->storeOrUpdateMessage(msg);
msg->updateState(ChatMessage::State::NotDelivered);
linphone_address_unref(peer);
return;
}
if (!msg->getExternalBodyUrl().empty()) {
char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", msg->getExternalBodyUrl().c_str());
auto msgOp = dynamic_cast<SalMessageOpInterface *>(op);
msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), content_type, nullptr, nullptr);
ms_free(content_type);
} else {
auto msgOp = dynamic_cast<SalMessageOpInterface *>(op);
if (!msg->getPrivate()->getContentType().empty()) {
msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), msg->getPrivate()->getContentType().c_str(), msg->getPrivate()->getText().c_str(), d->peerAddress.asStringUriOnly().c_str());
} else {
msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), msg->getPrivate()->getText().c_str());
}
}
msg->getPrivate()->setTime(ms_time(0));
msg->getPrivate()->send();
if (!msg->getPrivate()->getText().empty() && clearTextMessage && strcmp(msg->getPrivate()->getText().c_str(), clearTextMessage) != 0) {
/* We replace the encrypted message by the original one so it can be correctly stored and displayed by the application */
msg->getPrivate()->setText(clearTextMessage);
}
if (!msg->getPrivate()->getContentType().empty() && clearTextContentType && (strcmp(msg->getPrivate()->getContentType().c_str(), clearTextContentType) != 0)) {
/* We replace the encrypted content type by the original one */
msg->getPrivate()->setContentType(clearTextContentType);
}
msg->setId(op->get_call_id()); /* must be known at that time */
d->storeOrUpdateMessage(msg);
if (d->isComposing)
d->isComposing = false;
d->isComposingHandler.stopIdleTimer();
d->isComposingHandler.stopRefreshTimer();
if (clearTextMessage) {
ms_free(clearTextMessage);
}
if (clearTextContentType) {
ms_free(clearTextContentType);
}
linphone_address_unref(peer);
if (call && linphone_call_get_op(call) == op) {
/* In this case, chat delivery status is not notified, so unrefing chat message right now */
/* Might be better fixed by delivering status, but too costly for now */
d->removeTransientMessage(msg);
return;
}
}
/* If operation failed, we should not change message state */
if (msg->isOutgoing()) {
msg->getPrivate()->setIsReadOnly(true);
msg->getPrivate()->setState(ChatMessage::State::InProgress);
}
}
......
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