mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-03 20:46:28 +00:00
Moved most of exisiting code from LinphoneChatMessage* to shared_ptr<ChatMessage>
This commit is contained in:
parent
e7f7abd7ae
commit
72bc4fec53
18 changed files with 370 additions and 350 deletions
|
|
@ -29,5 +29,5 @@
|
|||
#include "chat/chat-room.h"
|
||||
|
||||
LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent *initial_content) {
|
||||
return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(initial_content);
|
||||
return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(initial_content));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to_address(Linp
|
|||
* @param[in] message LinphoneChatMessage object
|
||||
* @return The content type of the chat message
|
||||
*/
|
||||
LINPHONE_PUBLIC const char * linphone_chat_message_get_content_type(const LinphoneChatMessage *msg);
|
||||
LINPHONE_PUBLIC const char * linphone_chat_message_get_content_type(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Set the content type of a chat message.
|
||||
|
|
@ -140,7 +140,7 @@ LINPHONE_PUBLIC void linphone_chat_message_set_content_type(LinphoneChatMessage
|
|||
* Get text part of this message
|
||||
* @return text or NULL if no text.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_text(const LinphoneChatMessage* msg);
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_text(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Returns the id used to identify this message in the storage database
|
||||
|
|
@ -235,14 +235,14 @@ LINPHONE_PUBLIC LinphoneContent* linphone_chat_message_get_file_transfer_informa
|
|||
* @param[in] message LinphoneChatMessage object
|
||||
* @return Whether or not the message is a file tranfer
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer(const LinphoneChatMessage *message);
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer(LinphoneChatMessage *message);
|
||||
|
||||
/**
|
||||
* Return whether or not a chat message is a text.
|
||||
* @param[in] message LinphoneChatMessage object
|
||||
* @return Whether or not the message is a text
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_text(const LinphoneChatMessage *message);
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_text(LinphoneChatMessage *message);
|
||||
|
||||
/**
|
||||
* Get if a chat message is to be stored.
|
||||
|
|
|
|||
|
|
@ -173,26 +173,28 @@ void linphone_chat_message_set_appdata(LinphoneChatMessage *msg, const char *dat
|
|||
}
|
||||
|
||||
void linphone_chat_message_set_from_address(LinphoneChatMessage *msg, const LinphoneAddress *from) {
|
||||
if (!from) L_GET_CPP_PTR_FROM_C_OBJECT(msg)->setFromAddress(nullptr);
|
||||
else L_GET_CPP_PTR_FROM_C_OBJECT(msg)->setFromAddress(make_shared<LinphonePrivate::Address>(linphone_address_as_string(from)));
|
||||
LinphonePrivate::Address addr;
|
||||
if (from) addr = LinphonePrivate::Address(linphone_address_as_string(from));
|
||||
else L_GET_CPP_PTR_FROM_C_OBJECT(msg)->setFromAddress(addr);
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_chat_message_get_from_address(LinphoneChatMessage *msg) {
|
||||
if (msg->from)
|
||||
linphone_address_unref(msg->from);
|
||||
msg->from = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getFromAddress()->asString().c_str());
|
||||
msg->from = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getFromAddress().asString().c_str());
|
||||
return msg->from;
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_to_address(LinphoneChatMessage *msg, const LinphoneAddress *to) {
|
||||
if (!to) L_GET_CPP_PTR_FROM_C_OBJECT(msg)->setToAddress(nullptr);
|
||||
else L_GET_CPP_PTR_FROM_C_OBJECT(msg)->setToAddress(make_shared<LinphonePrivate::Address>(linphone_address_as_string(to)));
|
||||
LinphonePrivate::Address addr;
|
||||
if (to) addr = LinphonePrivate::Address(linphone_address_as_string(to));
|
||||
else L_GET_CPP_PTR_FROM_C_OBJECT(msg)->setToAddress(addr);
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_chat_message_get_to_address(LinphoneChatMessage *msg) {
|
||||
if (msg->to)
|
||||
linphone_address_unref(msg->to);
|
||||
msg->to = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getToAddress()->asString().c_str());
|
||||
msg->to = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getToAddress().asString().c_str());
|
||||
return msg->to;
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +327,7 @@ void * linphone_chat_message_get_message_state_changed_cb_user_data(LinphoneChat
|
|||
// Structure has changed, hard to keep the behavior
|
||||
// =============================================================================
|
||||
|
||||
const char * linphone_chat_message_get_content_type(const LinphoneChatMessage *msg) {
|
||||
const char * linphone_chat_message_get_content_type(LinphoneChatMessage *msg) {
|
||||
return L_STRING_TO_C(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getContentType());
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +335,7 @@ void linphone_chat_message_set_content_type(LinphoneChatMessage *msg, const char
|
|||
L_GET_PRIVATE_FROM_C_OBJECT(msg)->setContentType(L_C_TO_STRING(content_type));
|
||||
}
|
||||
|
||||
const char *linphone_chat_message_get_text(const LinphoneChatMessage *msg) {
|
||||
const char *linphone_chat_message_get_text(LinphoneChatMessage *msg) {
|
||||
return L_STRING_TO_C(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getText());
|
||||
}
|
||||
|
||||
|
|
@ -369,11 +371,11 @@ LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage *msg) {
|
|||
return linphone_error_info_get_reason(linphone_chat_message_get_error_info(msg));
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_is_file_transfer(const LinphoneChatMessage *msg) {
|
||||
bool_t linphone_chat_message_is_file_transfer(LinphoneChatMessage *msg) {
|
||||
return LinphonePrivate::ContentType::isFileTransfer(linphone_chat_message_get_content_type(msg));
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_is_text(const LinphoneChatMessage *msg) {
|
||||
bool_t linphone_chat_message_is_text(LinphoneChatMessage *msg) {
|
||||
return LinphonePrivate::ContentType::isText(linphone_chat_message_get_content_type(msg));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,12 +68,11 @@ void linphone_chat_room_release (LinphoneChatRoom *cr) {
|
|||
}
|
||||
|
||||
void linphone_chat_room_remove_transient_message (LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
L_GET_PRIVATE_FROM_C_OBJECT(cr)->removeTransientMessage(msg);
|
||||
L_GET_PRIVATE_FROM_C_OBJECT(cr)->removeTransientMessage(L_GET_CPP_PTR_FROM_C_OBJECT(msg));
|
||||
}
|
||||
|
||||
void linphone_chat_room_send_message (LinphoneChatRoom *cr, const char *msg) {
|
||||
LinphoneChatMessage *message = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createMessage(msg);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(message);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createMessage(msg));
|
||||
}
|
||||
|
||||
bool_t linphone_chat_room_is_remote_composing (const LinphoneChatRoom *cr) {
|
||||
|
|
@ -97,7 +96,7 @@ const LinphoneAddress *linphone_chat_room_get_peer_address (LinphoneChatRoom *cr
|
|||
}
|
||||
|
||||
LinphoneChatMessage *linphone_chat_room_create_message (LinphoneChatRoom *cr, const char *message) {
|
||||
return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createMessage(L_C_TO_STRING(message));
|
||||
return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createMessage(L_C_TO_STRING(message)));
|
||||
}
|
||||
|
||||
LinphoneChatMessage *linphone_chat_room_create_message_2 (
|
||||
|
|
@ -135,16 +134,16 @@ void linphone_chat_room_send_message2 (
|
|||
) {
|
||||
linphone_chat_message_set_message_state_changed_cb(msg, status_cb);
|
||||
linphone_chat_message_set_message_state_changed_cb_user_data(msg, ud);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(msg);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(L_GET_CPP_PTR_FROM_C_OBJECT(msg));
|
||||
}
|
||||
|
||||
void linphone_chat_room_send_chat_message_2 (LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
linphone_chat_message_ref(msg);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(msg);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(L_GET_CPP_PTR_FROM_C_OBJECT(msg));
|
||||
}
|
||||
|
||||
void linphone_chat_room_send_chat_message (LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(msg);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->sendMessage(L_GET_CPP_PTR_FROM_C_OBJECT(msg));
|
||||
}
|
||||
|
||||
uint32_t linphone_chat_room_get_char (const LinphoneChatRoom *cr) {
|
||||
|
|
@ -169,7 +168,7 @@ void linphone_chat_room_set_call (LinphoneChatRoom *cr, LinphoneCall *call) {
|
|||
}
|
||||
|
||||
bctbx_list_t *linphone_chat_room_get_transient_messages (const LinphoneChatRoom *cr) {
|
||||
return L_GET_C_LIST_FROM_CPP_LIST(L_GET_PRIVATE_FROM_C_OBJECT(cr)->getTransientMessages());
|
||||
return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_PRIVATE_FROM_C_OBJECT(cr)->getTransientMessages());
|
||||
}
|
||||
|
||||
void linphone_chat_room_mark_as_read (LinphoneChatRoom *cr) {
|
||||
|
|
@ -185,7 +184,7 @@ int linphone_chat_room_get_history_size (LinphoneChatRoom *cr) {
|
|||
}
|
||||
|
||||
void linphone_chat_room_delete_message (LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->deleteMessage(msg);
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->deleteMessage(L_GET_CPP_PTR_FROM_C_OBJECT(msg));
|
||||
}
|
||||
|
||||
void linphone_chat_room_delete_history (LinphoneChatRoom *cr) {
|
||||
|
|
@ -193,15 +192,15 @@ void linphone_chat_room_delete_history (LinphoneChatRoom *cr) {
|
|||
}
|
||||
|
||||
bctbx_list_t *linphone_chat_room_get_history_range (LinphoneChatRoom *cr, int startm, int endm) {
|
||||
return L_GET_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getHistoryRange(startm, endm));
|
||||
return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getHistoryRange(startm, endm));
|
||||
}
|
||||
|
||||
bctbx_list_t *linphone_chat_room_get_history (LinphoneChatRoom *cr, int nb_message) {
|
||||
return L_GET_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getHistory(nb_message));
|
||||
return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getHistory(nb_message));
|
||||
}
|
||||
|
||||
LinphoneChatMessage *linphone_chat_room_find_message (LinphoneChatRoom *cr, const char *message_id) {
|
||||
return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findMessage(message_id);
|
||||
return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findMessage(message_id));
|
||||
}
|
||||
|
||||
LinphoneChatRoomCbs *linphone_chat_room_get_callbacks (const LinphoneChatRoom *cr) {
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ public:
|
|||
// Methods only used for C wrapper
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const std::string& getContentType() const;
|
||||
const std::string& getContentType();
|
||||
void setContentType(const std::string& contentType);
|
||||
|
||||
const std::string& getText() const;
|
||||
const std::string& getText();
|
||||
void setText(const std::string& text);
|
||||
|
||||
LinphoneContent * getFileTransferInformation() const;
|
||||
|
|
@ -98,11 +98,11 @@ public:
|
|||
|
||||
private:
|
||||
std::shared_ptr<ChatRoom> chatRoom;
|
||||
ChatMessage::Direction direction = ChatMessage::Incoming;
|
||||
ChatMessage::State state = ChatMessage::Idle;
|
||||
ChatMessage::Direction direction = ChatMessage::Direction::Incoming;
|
||||
ChatMessage::State state = ChatMessage::State::Idle;
|
||||
unsigned int storageId = 0;
|
||||
std::shared_ptr<Address> from;
|
||||
std::shared_ptr<Address> to;
|
||||
Address from;
|
||||
Address to;
|
||||
time_t time = 0;
|
||||
std::string id = "";
|
||||
std::string appData = "";
|
||||
|
|
@ -122,9 +122,10 @@ private:
|
|||
SalOp *salOp = NULL;
|
||||
SalCustomHeader *salCustomHeaders = NULL;
|
||||
unsigned long backgroundTaskId;
|
||||
// Used for compatibility with previous C API
|
||||
// Cache for returned values, used for compatibility with previous C API
|
||||
std::string cContentType = "";
|
||||
std::string cText = "";
|
||||
// Used for compatibility with previous C API
|
||||
LinphoneContent *cFileTransferInformation = NULL;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@
|
|||
#include "linphone/core.h"
|
||||
#include "linphone/lpconfig.h"
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
#include "address/address.h"
|
||||
|
||||
#include "chat-message-p.h"
|
||||
#include "chat-message.h"
|
||||
#include "content/content.h"
|
||||
|
||||
#include "content/content.h"
|
||||
#include "modifier/multipart-chat-message-modifier.h"
|
||||
#include "modifier/cpim-chat-message-modifier.h"
|
||||
#include "chat-room-p.h"
|
||||
|
|
@ -133,20 +133,33 @@ string ChatMessagePrivate::getSalCustomHeaderValue(const string& name) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const string& ChatMessagePrivate::getContentType() const {
|
||||
const string& ChatMessagePrivate::getContentType() {
|
||||
if (internalContent) {
|
||||
ContentType contentType = internalContent->getContentType();
|
||||
cContentType = contentType.asString();
|
||||
}
|
||||
return cContentType;
|
||||
}
|
||||
|
||||
void ChatMessagePrivate::setContentType(const string& contentType) {
|
||||
cContentType = contentType;
|
||||
if (!internalContent) {
|
||||
internalContent = make_shared<Content>();
|
||||
}
|
||||
internalContent->setContentType(contentType);
|
||||
}
|
||||
|
||||
const string& ChatMessagePrivate::getText() const {
|
||||
const string& ChatMessagePrivate::getText() {
|
||||
if (internalContent) {
|
||||
cText = internalContent->getBodyAsString();
|
||||
}
|
||||
return cText;
|
||||
}
|
||||
|
||||
void ChatMessagePrivate::setText(const string& text) {
|
||||
cText = text;
|
||||
if (!internalContent) {
|
||||
internalContent = make_shared<Content>();
|
||||
}
|
||||
internalContent->setBody(text);
|
||||
}
|
||||
|
||||
LinphoneContent * ChatMessagePrivate::getFileTransferInformation() const {
|
||||
|
|
@ -464,7 +477,7 @@ void ChatMessagePrivate::onRecvBody(belle_sip_user_body_handler_t *bh, belle_sip
|
|||
}
|
||||
} else {
|
||||
ms_warning("File transfer decrypt failed with code %d", (int)retval);
|
||||
setState(ChatMessage::FileTransferError);
|
||||
setState(ChatMessage::State::FileTransferError);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -654,22 +667,22 @@ void ChatMessagePrivate::processResponseFromPostFile(const belle_http_response_e
|
|||
}
|
||||
xmlFreeDoc(xmlMessageBody);
|
||||
} else { // no encryption key, transfer in plain, just copy the msg sent by server
|
||||
cText = ms_strdup(body);
|
||||
setText(body);
|
||||
}
|
||||
cContentType = "application/vnd.gsma.rcs-ft-http+xml";
|
||||
q->updateState(ChatMessage::FileTransferDone);
|
||||
setContentType("application/vnd.gsma.rcs-ft-http+xml");
|
||||
q->updateState(ChatMessage::State::FileTransferDone);
|
||||
releaseHttpRequest();
|
||||
chatRoom->sendMessage(L_GET_C_BACK_PTR(q));
|
||||
//TODO chatRoom->sendMessage(q);
|
||||
fileUploadEndBackgroundTask();
|
||||
} else {
|
||||
ms_warning("Received empty response from server, file transfer failed");
|
||||
q->updateState(ChatMessage::NotDelivered);
|
||||
q->updateState(ChatMessage::State::NotDelivered);
|
||||
releaseHttpRequest();
|
||||
fileUploadEndBackgroundTask();
|
||||
}
|
||||
} else {
|
||||
ms_warning("Unhandled HTTP code response %d for file transfer", code);
|
||||
q->updateState(ChatMessage::NotDelivered);
|
||||
q->updateState(ChatMessage::State::NotDelivered);
|
||||
releaseHttpRequest();
|
||||
fileUploadEndBackgroundTask();
|
||||
}
|
||||
|
|
@ -755,7 +768,7 @@ void ChatMessagePrivate::processAuthRequestedDownload(const belle_sip_auth_event
|
|||
L_Q();
|
||||
|
||||
ms_error("Error during file download : auth requested for msg [%p]", this);
|
||||
q->updateState(ChatMessage::FileTransferError);
|
||||
q->updateState(ChatMessage::State::FileTransferError);
|
||||
releaseHttpRequest();
|
||||
}
|
||||
|
||||
|
|
@ -767,9 +780,9 @@ static void _chat_message_process_io_error_upload(void *data, const belle_sip_io
|
|||
void ChatMessagePrivate::processIoErrorUpload(const belle_sip_io_error_event_t *event) {
|
||||
L_Q();
|
||||
ms_error("I/O Error during file upload of msg [%p]", this);
|
||||
q->updateState(ChatMessage::NotDelivered);
|
||||
q->updateState(ChatMessage::State::NotDelivered);
|
||||
releaseHttpRequest();
|
||||
chatRoom->getPrivate()->removeTransientMessage(L_GET_C_BACK_PTR(q));
|
||||
//TODO chatRoom->getPrivate()->removeTransientMessage(q);
|
||||
}
|
||||
|
||||
static void _chat_message_process_auth_requested_upload(void *data, belle_sip_auth_event *event) {
|
||||
|
|
@ -780,9 +793,9 @@ static void _chat_message_process_auth_requested_upload(void *data, belle_sip_au
|
|||
void ChatMessagePrivate::processAuthRequestedUpload(const belle_sip_auth_event *event) {
|
||||
L_Q();
|
||||
ms_error("Error during file upload: auth requested for msg [%p]", this);
|
||||
q->updateState(ChatMessage::NotDelivered);
|
||||
q->updateState(ChatMessage::State::NotDelivered);
|
||||
releaseHttpRequest();
|
||||
chatRoom->getPrivate()->removeTransientMessage(L_GET_C_BACK_PTR(q));
|
||||
//TODO chatRoom->getPrivate()->removeTransientMessage(q);
|
||||
}
|
||||
|
||||
static void _chat_message_process_io_error_download(void *data, const belle_sip_io_error_event_t *event) {
|
||||
|
|
@ -794,7 +807,7 @@ void ChatMessagePrivate::processIoErrorDownload(const belle_sip_io_error_event_t
|
|||
L_Q();
|
||||
|
||||
ms_error("I/O Error during file download msg [%p]", this);
|
||||
q->updateState(ChatMessage::FileTransferError);
|
||||
q->updateState(ChatMessage::State::FileTransferError);
|
||||
releaseHttpRequest();
|
||||
}
|
||||
|
||||
|
|
@ -809,7 +822,7 @@ void ChatMessagePrivate::processResponseFromGetFile(const belle_http_response_ev
|
|||
int code = belle_http_response_get_status_code(event->response);
|
||||
if (code >= 400 && code < 500) {
|
||||
ms_warning("File transfer failed with code %d", code);
|
||||
setState(ChatMessage::FileTransferError);
|
||||
setState(ChatMessage::State::FileTransferError);
|
||||
} else if (code != 200) {
|
||||
ms_warning("Unhandled HTTP code response %d for file transfer", code);
|
||||
}
|
||||
|
|
@ -959,26 +972,36 @@ void ChatMessage::setAppdata (const string &appData) {
|
|||
linphone_chat_message_store_appdata(L_GET_C_BACK_PTR(this));
|
||||
}
|
||||
|
||||
shared_ptr<Address> ChatMessage::getFromAddress () const {
|
||||
const Address& ChatMessage::getFromAddress () const {
|
||||
L_D();
|
||||
return d->from;
|
||||
}
|
||||
|
||||
void ChatMessage::setFromAddress(shared_ptr<Address> from) {
|
||||
void ChatMessage::setFromAddress(Address from) {
|
||||
L_D();
|
||||
d->from = from;
|
||||
}
|
||||
|
||||
shared_ptr<Address> ChatMessage::getToAddress () const {
|
||||
void ChatMessage::setFromAddress(const string& from) {
|
||||
L_D();
|
||||
d->from = Address(from);
|
||||
}
|
||||
|
||||
const Address& ChatMessage::getToAddress () const {
|
||||
L_D();
|
||||
return d->to;
|
||||
}
|
||||
|
||||
void ChatMessage::setToAddress(shared_ptr<Address> to) {
|
||||
void ChatMessage::setToAddress(Address to) {
|
||||
L_D();
|
||||
d->to = to;
|
||||
}
|
||||
|
||||
void ChatMessage::setToAddress(const string& to) {
|
||||
L_D();
|
||||
d->to = Address(to);
|
||||
}
|
||||
|
||||
const string& ChatMessage::getFileTransferFilepath() const {
|
||||
L_D();
|
||||
return d->fileTransferFilePath;
|
||||
|
|
@ -1061,6 +1084,18 @@ void ChatMessage::removeCustomHeader (const string &headerName) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatMessage::store() {
|
||||
L_D();
|
||||
|
||||
if (d->storageId != 0) {
|
||||
/* The message has already been stored (probably because of file transfer), update it */
|
||||
linphone_chat_message_store_update(L_GET_C_BACK_PTR(this));
|
||||
} else {
|
||||
/* Store the new message */
|
||||
linphone_chat_message_store(L_GET_C_BACK_PTR(this));
|
||||
}
|
||||
}
|
||||
|
||||
void ChatMessage::updateState(State state) {
|
||||
L_D();
|
||||
|
||||
|
|
@ -1068,7 +1103,7 @@ void ChatMessage::updateState(State state) {
|
|||
linphone_chat_message_store_state(L_GET_C_BACK_PTR(this));
|
||||
|
||||
if (state == Delivered || state == NotDelivered) {
|
||||
d->chatRoom->getPrivate()->moveTransientMessageToWeakMessages(L_GET_C_BACK_PTR(this));
|
||||
d->chatRoom->getPrivate()->moveTransientMessageToWeakMessages(static_pointer_cast<ChatMessage>(shared_from_this()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1098,7 +1133,7 @@ void ChatMessage::reSend() {
|
|||
return;
|
||||
}
|
||||
|
||||
d->chatRoom->sendMessage(L_GET_C_BACK_PTR(this));
|
||||
d->chatRoom->sendMessage(static_pointer_cast<ChatMessage>(shared_from_this()));
|
||||
}
|
||||
|
||||
void ChatMessage::sendDeliveryNotification(LinphoneReason reason) {
|
||||
|
|
@ -1201,7 +1236,7 @@ int ChatMessage::putCharacter(uint32_t character) {
|
|||
d->setTime(ms_time(0));
|
||||
d->state = Displayed;
|
||||
d->direction = Outgoing;
|
||||
setFromAddress(make_shared<LinphonePrivate::Address>(linphone_address_as_string(linphone_address_new(linphone_core_get_identity(lc)))));
|
||||
setFromAddress(LinphonePrivate::Address(linphone_address_as_string(linphone_address_new(linphone_core_get_identity(lc)))));
|
||||
linphone_chat_message_store(L_GET_C_BACK_PTR(this));
|
||||
d->rttMessage = "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include "imdn.h"
|
||||
#include "enums.h"
|
||||
#include "linphone/api/c-types.h"
|
||||
#include "linphone/api/c-chat-message.h"
|
||||
|
||||
|
|
@ -34,19 +34,22 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
|
||||
class Address;
|
||||
class ChatRoom;
|
||||
class ChatRoomPrivate;
|
||||
class Content;
|
||||
class ErrorInfo;
|
||||
class ChatMessagePrivate;
|
||||
|
||||
class LINPHONE_PUBLIC ChatMessage : public Object {
|
||||
friend class ChatRoom;
|
||||
friend class ChatRoomPrivate;
|
||||
friend class RealTimeTextChatRoomPrivate;
|
||||
|
||||
public:
|
||||
public:
|
||||
enum Direction {
|
||||
Incoming,
|
||||
Outgoing
|
||||
};
|
||||
|
||||
|
||||
enum State {
|
||||
Idle,
|
||||
InProgress,
|
||||
|
|
@ -69,6 +72,7 @@ public:
|
|||
// Methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void store();
|
||||
void updateState(State state);
|
||||
void send();
|
||||
void reSend();
|
||||
|
|
@ -105,11 +109,13 @@ public:
|
|||
const std::string& getAppdata () const;
|
||||
void setAppdata (const std::string &appData);
|
||||
|
||||
std::shared_ptr<Address> getFromAddress () const;
|
||||
void setFromAddress(std::shared_ptr<Address> from);
|
||||
const Address& getFromAddress () const;
|
||||
void setFromAddress(Address from);
|
||||
void setFromAddress(const std::string& from);
|
||||
|
||||
std::shared_ptr<Address> getToAddress () const;
|
||||
void setToAddress(std::shared_ptr<Address> to);
|
||||
const Address& getToAddress () const;
|
||||
void setToAddress(Address to);
|
||||
void setToAddress(const std::string& to);
|
||||
|
||||
const std::string& getFileTransferFilepath() const;
|
||||
void setFileTransferFilepath(const std::string &path);
|
||||
|
|
|
|||
|
|
@ -41,16 +41,15 @@ public:
|
|||
|
||||
private:
|
||||
static int createChatMessageFromDb (void *data, int argc, char **argv, char **colName);
|
||||
static void onWeakMessageDestroyed (void *obj, belle_sip_object_t *messageBeingDestroyed);
|
||||
|
||||
public:
|
||||
void addTransientMessage (LinphoneChatMessage *msg);
|
||||
void addWeakMessage (LinphoneChatMessage *msg);
|
||||
std::list<LinphoneChatMessage *> getTransientMessages () const {
|
||||
void addTransientMessage (std::shared_ptr<ChatMessage> msg);
|
||||
void addWeakMessage (std::shared_ptr<ChatMessage> msg);
|
||||
std::list<std::shared_ptr<ChatMessage> > getTransientMessages () const {
|
||||
return transientMessages;
|
||||
}
|
||||
void moveTransientMessageToWeakMessages (LinphoneChatMessage *msg);
|
||||
void removeTransientMessage (LinphoneChatMessage *msg);
|
||||
void moveTransientMessageToWeakMessages (std::shared_ptr<ChatMessage> msg);
|
||||
void removeTransientMessage (std::shared_ptr<ChatMessage> msg);
|
||||
|
||||
void release ();
|
||||
void sendImdn (const std::string &content, LinphoneReason reason);
|
||||
|
|
@ -62,27 +61,26 @@ protected:
|
|||
void sendIsComposingNotification ();
|
||||
|
||||
int createChatMessageFromDb (int argc, char **argv, char **colName);
|
||||
void onWeakMessageDestroyed (LinphoneChatMessage *messageBeingDestroyed);
|
||||
LinphoneChatMessage *getTransientMessage (unsigned int storageId) const;
|
||||
LinphoneChatMessage *getWeakMessage (unsigned int storageId) const;
|
||||
std::shared_ptr<ChatMessage> getTransientMessage (unsigned int storageId) const;
|
||||
std::shared_ptr<ChatMessage> getWeakMessage (unsigned int storageId) const;
|
||||
int sqlRequest (sqlite3 *db, const std::string &stmt);
|
||||
void sqlRequestMessage (sqlite3 *db, const std::string &stmt);
|
||||
std::list<LinphoneChatMessage *> findMessages (const std::string &messageId);
|
||||
void storeOrUpdateMessage (LinphoneChatMessage *msg);
|
||||
std::list<std::shared_ptr<ChatMessage> > findMessages (const std::string &messageId);
|
||||
void storeOrUpdateMessage (std::shared_ptr<ChatMessage> msg);
|
||||
|
||||
public:
|
||||
LinphoneReason messageReceived (SalOp *op, const SalMessage *msg);
|
||||
void realtimeTextReceived (uint32_t character, LinphoneCall *call);
|
||||
|
||||
protected:
|
||||
void chatMessageReceived (LinphoneChatMessage *msg);
|
||||
void chatMessageReceived (std::shared_ptr<ChatMessage> msg);
|
||||
void imdnReceived (const std::string &text);
|
||||
void isComposingReceived (const std::string &text);
|
||||
|
||||
private:
|
||||
void notifyChatMessageReceived (LinphoneChatMessage *msg);
|
||||
void notifyChatMessageReceived (std::shared_ptr<ChatMessage> msg);
|
||||
void notifyStateChanged ();
|
||||
void notifyUndecryptableMessageReceived (LinphoneChatMessage *msg);
|
||||
void notifyUndecryptableMessageReceived (std::shared_ptr<ChatMessage> msg);
|
||||
|
||||
private:
|
||||
/* IsComposingListener */
|
||||
|
|
@ -98,11 +96,11 @@ public:
|
|||
int unreadCount = -1;
|
||||
bool isComposing = false;
|
||||
bool remoteIsComposing = false;
|
||||
std::list<LinphoneChatMessage *> messages;
|
||||
std::list<LinphoneChatMessage *> transientMessages;
|
||||
std::list<LinphoneChatMessage *> weakMessages;
|
||||
std::list<std::shared_ptr<ChatMessage> > messages;
|
||||
std::list<std::shared_ptr<ChatMessage> > transientMessages;
|
||||
std::list<std::weak_ptr<ChatMessage> > weakMessages;
|
||||
std::list<LinphoneChatMessageCharacter *> receivedRttCharacters;
|
||||
LinphoneChatMessage *pendingMessage = nullptr;
|
||||
std::shared_ptr<ChatMessage> pendingMessage = nullptr;
|
||||
IsComposing isComposingHandler;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -23,13 +23,12 @@
|
|||
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
#include "chat-room-p.h"
|
||||
#include "content/content-type.h"
|
||||
#include "imdn.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
#include "content/content.h"
|
||||
#include "chat-message-p.h"
|
||||
#include "chat-room.h"
|
||||
#include "sal/message_op.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -41,10 +40,10 @@ ChatRoomPrivate::ChatRoomPrivate (LinphoneCore *core)
|
|||
: core(core), isComposingHandler(core, this) {}
|
||||
|
||||
ChatRoomPrivate::~ChatRoomPrivate () {
|
||||
for (auto &message : transientMessages)
|
||||
/*for (auto &message : transientMessages)
|
||||
linphone_chat_message_release(message);
|
||||
if (pendingMessage)
|
||||
linphone_chat_message_unref(pendingMessage);
|
||||
linphone_chat_message_unref(pendingMessage);*/
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -54,26 +53,20 @@ int ChatRoomPrivate::createChatMessageFromDb (void *data, int argc, char **argv,
|
|||
return d->createChatMessageFromDb(argc, argv, colName);
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::onWeakMessageDestroyed (void *obj, belle_sip_object_t *messageBeingDestroyed) {
|
||||
ChatRoomPrivate *d = reinterpret_cast<ChatRoomPrivate *>(obj);
|
||||
d->onWeakMessageDestroyed(reinterpret_cast<LinphoneChatMessage *>(messageBeingDestroyed));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatRoomPrivate::addTransientMessage (LinphoneChatMessage *msg) {
|
||||
void ChatRoomPrivate::addTransientMessage (shared_ptr<ChatMessage> msg) {
|
||||
auto iter = find(transientMessages.begin(), transientMessages.end(), msg);
|
||||
if (iter == transientMessages.end())
|
||||
transientMessages.push_back(linphone_chat_message_ref(msg));
|
||||
transientMessages.push_back(msg);
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::addWeakMessage (LinphoneChatMessage *msg) {
|
||||
auto iter = find(weakMessages.begin(), weakMessages.end(), msg);
|
||||
if (iter == weakMessages.end())
|
||||
weakMessages.push_back(reinterpret_cast<LinphoneChatMessage *>(belle_sip_object_weak_ref(msg, onWeakMessageDestroyed, this)));
|
||||
void ChatRoomPrivate::addWeakMessage (shared_ptr<ChatMessage> msg) {
|
||||
weak_ptr<ChatMessage> weakptr(msg);
|
||||
weakMessages.push_back(weakptr);
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::moveTransientMessageToWeakMessages (LinphoneChatMessage *msg) {
|
||||
void ChatRoomPrivate::moveTransientMessageToWeakMessages (shared_ptr<ChatMessage> msg) {
|
||||
auto iter = find(transientMessages.begin(), transientMessages.end(), msg);
|
||||
if (iter != transientMessages.end()) {
|
||||
/* msg is not transient anymore, we can remove it from our transient list and unref it */
|
||||
|
|
@ -84,10 +77,9 @@ void ChatRoomPrivate::moveTransientMessageToWeakMessages (LinphoneChatMessage *m
|
|||
}
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::removeTransientMessage (LinphoneChatMessage *msg) {
|
||||
void ChatRoomPrivate::removeTransientMessage (shared_ptr<ChatMessage> msg) {
|
||||
auto iter = find(transientMessages.begin(), transientMessages.end(), msg);
|
||||
if (iter != transientMessages.end()) {
|
||||
linphone_chat_message_unref(*iter);
|
||||
transientMessages.erase(iter);
|
||||
}
|
||||
}
|
||||
|
|
@ -98,16 +90,16 @@ void ChatRoomPrivate::release () {
|
|||
L_Q();
|
||||
isComposingHandler.stopTimers();
|
||||
|
||||
for (auto &message : weakMessages)
|
||||
/*for (auto &message : weakMessages)
|
||||
linphone_chat_message_deactivate(message);
|
||||
for (auto &message : transientMessages)
|
||||
linphone_chat_message_deactivate(message);
|
||||
linphone_chat_message_deactivate(message);*/
|
||||
|
||||
core = nullptr;
|
||||
linphone_chat_room_unref(L_GET_C_BACK_PTR(q));
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) {
|
||||
void ChatRoomPrivate::sendImdn (const string &payload, LinphoneReason reason) {
|
||||
L_Q();
|
||||
|
||||
const char *identity = nullptr;
|
||||
|
|
@ -121,12 +113,15 @@ void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) {
|
|||
/* Sending out of call */
|
||||
SalMessageOp *op = new SalMessageOp(core->sal);
|
||||
linphone_configure_op(core, op, peer, nullptr, !!lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0));
|
||||
LinphoneChatMessage *msg = q->createMessage(content);
|
||||
LinphoneAddress *fromAddr = linphone_address_new(identity);
|
||||
linphone_chat_message_set_from_address(msg, fromAddr);
|
||||
LinphoneAddress *toAddr = linphone_address_new(peerAddress.asString().c_str());
|
||||
linphone_chat_message_set_to_address(msg, toAddr);
|
||||
linphone_chat_message_set_content_type(msg, "message/imdn+xml");
|
||||
|
||||
shared_ptr<ChatMessage> msg = q->createMessage();
|
||||
msg->setFromAddress(identity);
|
||||
msg->setToAddress(peerAddress.asString());
|
||||
|
||||
shared_ptr<Content> content = make_shared<Content>();
|
||||
content->setContentType("message/imdn+xml");
|
||||
content->setBody(payload);
|
||||
msg->addContent(content);
|
||||
|
||||
/* Do not try to encrypt the notification when it is reporting an error (maybe it should be bypassed only for some reasons). */
|
||||
int retval = -1;
|
||||
|
|
@ -135,17 +130,14 @@ void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) {
|
|||
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(q), msg);
|
||||
retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(q), L_GET_C_BACK_PTR(msg));
|
||||
}
|
||||
}
|
||||
|
||||
if (retval <= 0) {
|
||||
op->send_message(identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr);
|
||||
op->send_message(identity, peerAddress.asString().c_str(), msg->getPrivate()->getContentType().c_str(), msg->getPrivate()->getText().c_str(), nullptr);
|
||||
}
|
||||
|
||||
linphone_chat_message_unref(msg);
|
||||
linphone_address_unref(fromAddr);
|
||||
linphone_address_unref(toAddr);
|
||||
linphone_address_unref(peer);
|
||||
op->unref();
|
||||
}
|
||||
|
|
@ -210,30 +202,31 @@ void ChatRoomPrivate::sendIsComposingNotification () {
|
|||
/* Sending out of call */
|
||||
SalMessageOp *op = new SalMessageOp(core->sal);
|
||||
linphone_configure_op(core, op, peer, nullptr, !!lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0));
|
||||
string content = isComposingHandler.marshal(isComposing);
|
||||
if (!content.empty()) {
|
||||
string payload = isComposingHandler.marshal(isComposing);
|
||||
if (!payload.empty()) {
|
||||
int retval = -1;
|
||||
LinphoneAddress *fromAddr = linphone_address_new(identity);
|
||||
LinphoneChatMessage *msg = q->createMessage(content);
|
||||
linphone_chat_message_set_from_address(msg, fromAddr);
|
||||
linphone_chat_message_set_to_address(msg, peer);
|
||||
linphone_chat_message_set_content_type(msg, "application/im-iscomposing+xml");
|
||||
|
||||
shared_ptr<ChatMessage> msg = q->createMessage();
|
||||
msg->setFromAddress(identity);
|
||||
msg->setToAddress(peerAddress.asString());
|
||||
|
||||
shared_ptr<Content> content = make_shared<Content>();
|
||||
content->setContentType("application/im-iscomposing+xml");
|
||||
content->setBody(payload);
|
||||
msg->addContent(content);
|
||||
|
||||
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(core);
|
||||
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(q), msg);
|
||||
retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(q), L_GET_C_BACK_PTR(msg));
|
||||
}
|
||||
}
|
||||
|
||||
if (retval <= 0) {
|
||||
op->send_message(identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr);
|
||||
op->send_message(identity, peerAddress.asString().c_str(), msg->getPrivate()->getContentType().c_str(), msg->getPrivate()->getText().c_str(), nullptr);
|
||||
}
|
||||
|
||||
linphone_chat_message_unref(msg);
|
||||
linphone_address_unref(fromAddr);
|
||||
op->unref();
|
||||
}
|
||||
linphone_address_unref(peer);
|
||||
|
|
@ -266,40 +259,53 @@ int ChatRoomPrivate::createChatMessageFromDb (int argc, char **argv, char **colN
|
|||
unsigned int storageId = (unsigned int)atoi(argv[0]);
|
||||
|
||||
/* Check if the message exists in the weak messages list, in which case we should return that one. */
|
||||
LinphoneChatMessage *newMessage = getWeakMessage(storageId);
|
||||
if (!newMessage) {
|
||||
shared_ptr<ChatMessage> message = getWeakMessage(storageId);
|
||||
if (!message) {
|
||||
/* Check if the message exists in the transient list, in which case we should return that one. */
|
||||
newMessage = getTransientMessage(storageId);
|
||||
message = getTransientMessage(storageId);
|
||||
}
|
||||
if (!newMessage) {
|
||||
newMessage = q->createMessage(argv[4] ? argv[4] : "");
|
||||
if (!message) {
|
||||
message = q->createMessage();
|
||||
|
||||
LinphoneAddress *peer = linphone_address_new(peerAddress.asString().c_str());
|
||||
if (atoi(argv[3]) == LinphoneChatMessageIncoming) {
|
||||
linphone_chat_message_set_incoming(newMessage);
|
||||
linphone_chat_message_set_from_address(newMessage, peer);
|
||||
} else {
|
||||
linphone_chat_message_set_outgoing(newMessage);
|
||||
linphone_chat_message_set_to_address(newMessage, peer);
|
||||
shared_ptr<Content> content = make_shared<Content>();
|
||||
message->addContent(content);
|
||||
|
||||
if (argv[4]) {
|
||||
content->setBody(argv[4]);
|
||||
}
|
||||
linphone_address_unref(peer);
|
||||
if (argv[13]) {
|
||||
content->setContentType(argv[13]);
|
||||
}
|
||||
|
||||
linphone_chat_message_set_time(newMessage, (time_t)atol(argv[9]));
|
||||
linphone_chat_message_set_state(newMessage, static_cast<LinphoneChatMessageState>(atoi(argv[7])));
|
||||
linphone_chat_message_set_storage_id(newMessage, storageId);
|
||||
linphone_chat_message_set_external_body_url(newMessage, ms_strdup(argv[8]));
|
||||
linphone_chat_message_set_appdata(newMessage, ms_strdup(argv[10]));
|
||||
linphone_chat_message_set_message_id(newMessage, ms_strdup(argv[12]));
|
||||
linphone_chat_message_set_content_type(newMessage, argv[13]);
|
||||
linphone_chat_message_set_is_secured(newMessage, (bool_t)atoi(argv[14]));
|
||||
Address peer(peerAddress.asString());
|
||||
if (atoi(argv[3]) == ChatMessage::Direction::Incoming) {
|
||||
message->getPrivate()->setDirection(ChatMessage::Direction::Incoming);
|
||||
message->setFromAddress(peer);
|
||||
} else {
|
||||
message->getPrivate()->setDirection(ChatMessage::Direction::Outgoing);
|
||||
message->setToAddress(peer);
|
||||
}
|
||||
|
||||
message->getPrivate()->setTime((time_t)atol(argv[9]));
|
||||
message->getPrivate()->setState((ChatMessage::State)atoi(argv[7]));
|
||||
message->getPrivate()->setStorageId(storageId);
|
||||
if (argv[8]) {
|
||||
message->setExternalBodyUrl(argv[8]);
|
||||
}
|
||||
if (argv[10]) {
|
||||
message->setAppdata(argv[10]);
|
||||
}
|
||||
message->setId(argv[12]);
|
||||
message->setIsSecured((bool)atoi(argv[14]));
|
||||
|
||||
if (argv[11]) {
|
||||
int id = atoi(argv[11]);
|
||||
if (id >= 0)
|
||||
linphone_chat_message_fetch_content_from_database(core->db, newMessage, id);
|
||||
linphone_chat_message_fetch_content_from_database(core->db, L_GET_C_BACK_PTR(message), id);
|
||||
}
|
||||
|
||||
/* Fix content type for old messages that were stored without it */
|
||||
/* To keep ?
|
||||
if (!linphone_chat_message_get_content_type(newMessage)) {
|
||||
if (linphone_chat_message_get_file_transfer_information(newMessage)) {
|
||||
linphone_chat_message_set_content_type(newMessage, ms_strdup("application/vnd.gsma.rcs-ft-http+xml"));
|
||||
|
|
@ -308,33 +314,28 @@ int ChatRoomPrivate::createChatMessageFromDb (int argc, char **argv, char **colN
|
|||
} else {
|
||||
linphone_chat_message_set_content_type(newMessage, ms_strdup("text/plain"));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/* Add the new message to the weak messages list. */
|
||||
addWeakMessage(newMessage);
|
||||
addWeakMessage(message);
|
||||
}
|
||||
messages.push_front(newMessage);
|
||||
messages.push_front(message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::onWeakMessageDestroyed (LinphoneChatMessage *messageBeingDestroyed) {
|
||||
auto iter = find(weakMessages.begin(), weakMessages.end(), messageBeingDestroyed);
|
||||
if (iter != transientMessages.end())
|
||||
weakMessages.erase(iter);
|
||||
}
|
||||
|
||||
LinphoneChatMessage *ChatRoomPrivate::getTransientMessage (unsigned int storageId) const {
|
||||
shared_ptr<ChatMessage> ChatRoomPrivate::getTransientMessage (unsigned int storageId) const {
|
||||
for (auto &message : transientMessages) {
|
||||
if (linphone_chat_message_get_storage_id(message) == storageId)
|
||||
return linphone_chat_message_ref(message);
|
||||
if (message->getPrivate()->getStorageId() == storageId)
|
||||
return message;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinphoneChatMessage *ChatRoomPrivate::getWeakMessage (unsigned int storageId) const {
|
||||
std::shared_ptr<ChatMessage> ChatRoomPrivate::getWeakMessage (unsigned int storageId) const {
|
||||
for (auto &message : weakMessages) {
|
||||
if (linphone_chat_message_get_storage_id(message) == storageId)
|
||||
return linphone_chat_message_ref(message);
|
||||
shared_ptr<ChatMessage> msg(message);
|
||||
if (msg->getPrivate()->getStorageId() == storageId)
|
||||
return msg;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -358,30 +359,21 @@ void ChatRoomPrivate::sqlRequestMessage (sqlite3 *db, const string &stmt) {
|
|||
}
|
||||
}
|
||||
|
||||
list<LinphoneChatMessage *> ChatRoomPrivate::findMessages (const string &messageId) {
|
||||
list<shared_ptr<ChatMessage> > ChatRoomPrivate::findMessages (const string &messageId) {
|
||||
if (!core->db)
|
||||
return list<LinphoneChatMessage *>();
|
||||
return list<shared_ptr<ChatMessage> >();
|
||||
string peer = peerAddress.asStringUriOnly();
|
||||
char *buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND messageId = %Q", peer.c_str(), messageId.c_str());
|
||||
messages.clear();
|
||||
sqlRequestMessage(core->db, buf);
|
||||
sqlite3_free(buf);
|
||||
list<LinphoneChatMessage *> result = messages;
|
||||
list<shared_ptr<ChatMessage> > result = messages;
|
||||
messages.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Should be handled directly by the LinphoneChatMessage object!
|
||||
*/
|
||||
void ChatRoomPrivate::storeOrUpdateMessage (LinphoneChatMessage *msg) {
|
||||
if (linphone_chat_message_get_storage_id(msg) != 0) {
|
||||
/* The message has already been stored (probably because of file transfer), update it */
|
||||
linphone_chat_message_store_update(msg);
|
||||
} else {
|
||||
/* Store the new message */
|
||||
linphone_chat_message_store(msg);
|
||||
}
|
||||
void ChatRoomPrivate::storeOrUpdateMessage (shared_ptr<ChatMessage> msg) {
|
||||
msg->store();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -391,34 +383,32 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
|
||||
bool increaseMsgCount = true;
|
||||
LinphoneReason reason = LinphoneReasonNone;
|
||||
LinphoneChatMessage *msg;
|
||||
shared_ptr<ChatMessage> msg;
|
||||
|
||||
/* Check if this is a duplicate message */
|
||||
if ((msg = q->findMessageWithDirection(op->get_call_id(), LinphoneChatMessageIncoming))) {
|
||||
if ((msg = q->findMessageWithDirection(op->get_call_id(), ChatMessage::Direction::Incoming))) {
|
||||
reason = core->chat_deny_code;
|
||||
if (msg)
|
||||
linphone_chat_message_unref(msg);
|
||||
return reason;
|
||||
}
|
||||
|
||||
msg = q->createMessage(salMsg->text ? salMsg->text : "");
|
||||
linphone_chat_message_set_content_type(msg, salMsg->content_type);
|
||||
LinphoneAddress *peer = linphone_address_new(peerAddress.asString().c_str());
|
||||
linphone_chat_message_set_from_address(msg, peer);
|
||||
linphone_address_unref(peer);
|
||||
msg = q->createMessage();
|
||||
|
||||
LinphoneAddress *to = op->get_to() ? linphone_address_new(op->get_to()) : linphone_address_new(linphone_core_get_identity(core));
|
||||
linphone_chat_message_set_to_address(msg, to);
|
||||
linphone_chat_message_set_time(msg, salMsg->time);
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateDelivered);
|
||||
linphone_chat_message_set_incoming(msg);
|
||||
linphone_chat_message_set_message_id(msg, ms_strdup(op->get_call_id()));
|
||||
shared_ptr<Content> content = make_shared<Content>();
|
||||
content->setContentType(salMsg->content_type);
|
||||
content->setBody(salMsg->text ? salMsg->text : "");
|
||||
msg->addContent(content);
|
||||
|
||||
msg->setToAddress( op->get_to() ? op->get_to() : linphone_core_get_identity(core));
|
||||
msg->getPrivate()->setTime(salMsg->time);
|
||||
msg->getPrivate()->setState(ChatMessage::State::Delivered);
|
||||
msg->getPrivate()->setDirection(ChatMessage::Direction::Incoming);
|
||||
msg->setId(op->get_call_id());
|
||||
|
||||
const SalCustomHeader *ch = op->get_recv_custom_header();
|
||||
if (ch)
|
||||
linphone_chat_message_set_sal_custom_headers(msg, sal_custom_header_clone(ch));
|
||||
msg->getPrivate()->setSalCustomHeaders(sal_custom_header_clone(ch));
|
||||
if (salMsg->url)
|
||||
linphone_chat_message_set_external_body_url(msg, salMsg->url);
|
||||
msg->setExternalBodyUrl(salMsg->url);
|
||||
|
||||
int retval = -1;
|
||||
LinphoneImEncryptionEngine *imee = core->im_encryption_engine;
|
||||
|
|
@ -426,14 +416,14 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsIncomingMessageCb cbProcessIncomingMessage = linphone_im_encryption_engine_cbs_get_process_incoming_message(imeeCbs);
|
||||
if (cbProcessIncomingMessage) {
|
||||
retval = cbProcessIncomingMessage(imee, L_GET_C_BACK_PTR(q), msg);
|
||||
retval = cbProcessIncomingMessage(imee, L_GET_C_BACK_PTR(q), L_GET_C_BACK_PTR(msg));
|
||||
if (retval == 0) {
|
||||
linphone_chat_message_set_is_secured(msg, TRUE);
|
||||
msg->setIsSecured(true);
|
||||
} else if (retval > 0) {
|
||||
/* Unable to decrypt message */
|
||||
notifyUndecryptableMessageReceived(msg);
|
||||
reason = linphone_error_code_to_reason(retval);
|
||||
linphone_chat_message_send_delivery_notification(msg, reason);
|
||||
msg->sendDeliveryNotification(reason);
|
||||
/* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */
|
||||
reason = LinphoneReasonNone;
|
||||
goto end;
|
||||
|
|
@ -441,36 +431,36 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
}
|
||||
}
|
||||
|
||||
if ((retval <= 0) && (linphone_core_is_content_type_supported(core, linphone_chat_message_get_content_type(msg)) == FALSE)) {
|
||||
if ((retval <= 0) && (linphone_core_is_content_type_supported(core, msg->getPrivate()->getContentType().c_str()) == FALSE)) {
|
||||
retval = 415;
|
||||
lError() << "Unsupported MESSAGE (content-type " << linphone_chat_message_get_content_type(msg) << " not recognized)";
|
||||
lError() << "Unsupported MESSAGE (content-type " << msg->getPrivate()->getContentType() << " not recognized)";
|
||||
}
|
||||
|
||||
if (retval > 0) {
|
||||
reason = linphone_error_code_to_reason(retval);
|
||||
linphone_chat_message_send_delivery_notification(msg, reason);
|
||||
msg->sendDeliveryNotification(reason);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ContentType::isFileTransfer(linphone_chat_message_get_content_type(msg))) {
|
||||
create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(msg);
|
||||
linphone_chat_message_set_to_be_stored(msg, TRUE);
|
||||
} else if (ContentType::isImIsComposing(linphone_chat_message_get_content_type(msg))) {
|
||||
isComposingReceived(linphone_chat_message_get_text(msg));
|
||||
linphone_chat_message_set_to_be_stored(msg, FALSE);
|
||||
if (ContentType::isFileTransfer(msg->getPrivate()->getContentType())) {
|
||||
create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(L_GET_C_BACK_PTR(msg));
|
||||
msg->setIsToBeStored(true);
|
||||
} else if (ContentType::isImIsComposing(msg->getPrivate()->getContentType())) {
|
||||
isComposingReceived(msg->getPrivate()->getText());
|
||||
msg->setIsToBeStored(false);
|
||||
increaseMsgCount = FALSE;
|
||||
if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) {
|
||||
goto end;
|
||||
}
|
||||
} else if (ContentType::isImdn(linphone_chat_message_get_content_type(msg))) {
|
||||
imdnReceived(linphone_chat_message_get_text(msg));
|
||||
linphone_chat_message_set_to_be_stored(msg, FALSE);
|
||||
} else if (ContentType::isImdn(msg->getPrivate()->getContentType())) {
|
||||
imdnReceived(msg->getPrivate()->getText());
|
||||
msg->setIsToBeStored(false);
|
||||
increaseMsgCount = FALSE;
|
||||
if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) {
|
||||
goto end;
|
||||
}
|
||||
} else if (ContentType::isText(linphone_chat_message_get_content_type(msg))) {
|
||||
linphone_chat_message_set_to_be_stored(msg, TRUE);
|
||||
} else if (ContentType::isText(msg->getPrivate()->getContentType())) {
|
||||
msg->setIsToBeStored(true);
|
||||
}
|
||||
|
||||
if (increaseMsgCount) {
|
||||
|
|
@ -486,27 +476,25 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
|
||||
chatMessageReceived(msg);
|
||||
|
||||
if (linphone_chat_message_get_to_be_stored(msg)) {
|
||||
linphone_chat_message_store(msg);
|
||||
if (msg->isToBeStored()) {
|
||||
msg->store();
|
||||
}
|
||||
|
||||
pendingMessage = nullptr;
|
||||
|
||||
end:
|
||||
if (msg)
|
||||
linphone_chat_message_unref(msg);
|
||||
return reason;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatRoomPrivate::chatMessageReceived (LinphoneChatMessage *msg) {
|
||||
void ChatRoomPrivate::chatMessageReceived (shared_ptr<ChatMessage> msg) {
|
||||
L_Q();
|
||||
if (!ContentType::isImdn(linphone_chat_message_get_content_type(msg)) && !ContentType::isImIsComposing(linphone_chat_message_get_content_type(msg))) {
|
||||
if (!ContentType::isImdn(msg->getPrivate()->getContentType()) && !ContentType::isImIsComposing(msg->getPrivate()->getContentType())) {
|
||||
notifyChatMessageReceived(msg);
|
||||
remoteIsComposing = false;
|
||||
linphone_core_notify_is_composing_received(core, L_GET_C_BACK_PTR(q));
|
||||
linphone_chat_message_send_delivery_notification(msg, LinphoneReasonNone);
|
||||
msg->sendDeliveryNotification(LinphoneReasonNone);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -521,18 +509,18 @@ void ChatRoomPrivate::isComposingReceived (const string &text) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatRoomPrivate::notifyChatMessageReceived (LinphoneChatMessage *msg) {
|
||||
void ChatRoomPrivate::notifyChatMessageReceived (shared_ptr<ChatMessage> msg) {
|
||||
L_Q();
|
||||
LinphoneChatRoom *cr = L_GET_C_BACK_PTR(q);
|
||||
if (linphone_chat_message_get_text(msg)) {
|
||||
if (!msg->getPrivate()->getText().empty()) {
|
||||
/* Legacy API */
|
||||
linphone_core_notify_text_message_received(core, cr, linphone_chat_message_get_from_address(msg), linphone_chat_message_get_text(msg));
|
||||
linphone_core_notify_text_message_received(core, cr, L_GET_C_BACK_PTR(&msg->getFromAddress()), msg->getPrivate()->getText().c_str());
|
||||
}
|
||||
LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(cr);
|
||||
LinphoneChatRoomCbsMessageReceivedCb cb = linphone_chat_room_cbs_get_message_received(cbs);
|
||||
if (cb)
|
||||
cb(cr, msg);
|
||||
linphone_core_notify_message_received(core, cr, msg);
|
||||
cb(cr, L_GET_C_BACK_PTR(msg));
|
||||
linphone_core_notify_message_received(core, cr, L_GET_C_BACK_PTR(msg));
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::notifyStateChanged () {
|
||||
|
|
@ -544,14 +532,14 @@ void ChatRoomPrivate::notifyStateChanged () {
|
|||
cb(cr, (LinphoneChatRoomState)state);
|
||||
}
|
||||
|
||||
void ChatRoomPrivate::notifyUndecryptableMessageReceived (LinphoneChatMessage *msg) {
|
||||
void ChatRoomPrivate::notifyUndecryptableMessageReceived (shared_ptr<ChatMessage> msg) {
|
||||
L_Q();
|
||||
LinphoneChatRoom *cr = L_GET_C_BACK_PTR(q);
|
||||
LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(cr);
|
||||
LinphoneChatRoomCbsUndecryptableMessageReceivedCb cb = linphone_chat_room_cbs_get_undecryptable_message_received(cbs);
|
||||
if (cb)
|
||||
cb(cr, msg);
|
||||
linphone_core_notify_message_received_unable_decrypt(core, cr, msg);
|
||||
cb(cr, L_GET_C_BACK_PTR(msg));
|
||||
linphone_core_notify_message_received_unable_decrypt(core, cr, L_GET_C_BACK_PTR(msg));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -589,30 +577,34 @@ void ChatRoom::compose () {
|
|||
d->isComposingHandler.startIdleTimer();
|
||||
}
|
||||
|
||||
LinphoneChatMessage *ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) {
|
||||
shared_ptr<ChatMessage> ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) {
|
||||
L_D();
|
||||
|
||||
shared_ptr<ChatMessage> chatMessage = make_shared<ChatMessage>(static_pointer_cast<ChatRoom>(shared_from_this()));
|
||||
shared_ptr<ChatMessage> chatMessage = createMessage();
|
||||
|
||||
chatMessage->getPrivate()->setTime(ms_time(0));
|
||||
chatMessage->getPrivate()->setDirection(ChatMessage::Direction::Outgoing);
|
||||
chatMessage->getPrivate()->setFileTransferInformation(linphone_content_copy(initialContent));
|
||||
chatMessage->setToAddress(make_shared<Address>(d->peerAddress.asString().c_str()));
|
||||
chatMessage->setFromAddress(make_shared<Address>(linphone_core_get_identity(d->core)));
|
||||
chatMessage->setToAddress(d->peerAddress);
|
||||
chatMessage->setFromAddress(linphone_core_get_identity(d->core));
|
||||
|
||||
LinphoneChatMessage *msg = chatMessage->getBackPtr();
|
||||
return msg;
|
||||
return chatMessage;
|
||||
}
|
||||
|
||||
LinphoneChatMessage *ChatRoom::createMessage (const string &message) {
|
||||
shared_ptr<ChatMessage> ChatRoom::createMessage (const string &message) {
|
||||
shared_ptr<ChatMessage> chatMessage = createMessage();
|
||||
|
||||
shared_ptr<Content> content = make_shared<Content>();
|
||||
content->setContentType("text/plain");
|
||||
content->setBody(message);
|
||||
chatMessage->addContent(content);
|
||||
|
||||
return chatMessage;
|
||||
}
|
||||
|
||||
shared_ptr<ChatMessage> ChatRoom::createMessage () {
|
||||
shared_ptr<ChatMessage> chatMessage = make_shared<ChatMessage>(static_pointer_cast<ChatRoom>(shared_from_this()));
|
||||
|
||||
chatMessage->getPrivate()->setTime(ms_time(0));
|
||||
chatMessage->getPrivate()->setContentType("text/plain");
|
||||
chatMessage->getPrivate()->setText(message);
|
||||
|
||||
LinphoneChatMessage *msg = chatMessage->getBackPtr();
|
||||
return msg;
|
||||
return chatMessage;
|
||||
}
|
||||
|
||||
void ChatRoom::deleteHistory () {
|
||||
|
|
@ -625,10 +617,10 @@ void ChatRoom::deleteHistory () {
|
|||
if (d->unreadCount > 0) d->unreadCount = 0;
|
||||
}
|
||||
|
||||
void ChatRoom::deleteMessage (LinphoneChatMessage *msg) {
|
||||
void ChatRoom::deleteMessage (shared_ptr<ChatMessage> msg) {
|
||||
L_D();
|
||||
if (!d->core->db) return;
|
||||
char *buf = sqlite3_mprintf("DELETE FROM history WHERE id = %u;", linphone_chat_message_get_storage_id(msg));
|
||||
char *buf = sqlite3_mprintf("DELETE FROM history WHERE id = %u;", msg->getPrivate()->getStorageId());
|
||||
d->sqlRequest(d->core->db, buf);
|
||||
sqlite3_free(buf);
|
||||
|
||||
|
|
@ -637,38 +629,30 @@ void ChatRoom::deleteMessage (LinphoneChatMessage *msg) {
|
|||
d->unreadCount = -1;
|
||||
}
|
||||
|
||||
LinphoneChatMessage *ChatRoom::findMessage (const string &messageId) {
|
||||
shared_ptr<ChatMessage> ChatRoom::findMessage (const string &messageId) {
|
||||
L_D();
|
||||
LinphoneChatMessage *cm = nullptr;
|
||||
list<LinphoneChatMessage *> l = d->findMessages(messageId);
|
||||
shared_ptr<ChatMessage> cm = nullptr;
|
||||
list<shared_ptr<ChatMessage> > l = d->findMessages(messageId);
|
||||
if (!l.empty()) {
|
||||
cm = l.front();
|
||||
linphone_chat_message_ref(cm);
|
||||
for (auto &message : l)
|
||||
linphone_chat_message_unref(message);
|
||||
}
|
||||
return cm;
|
||||
}
|
||||
|
||||
LinphoneChatMessage * ChatRoom::findMessageWithDirection (const string &messageId, LinphoneChatMessageDir direction) {
|
||||
shared_ptr<ChatMessage> ChatRoom::findMessageWithDirection (const string &messageId, ChatMessage::Direction direction) {
|
||||
L_D();
|
||||
LinphoneChatMessage *ret = nullptr;
|
||||
list<LinphoneChatMessage *> l = d->findMessages(messageId);
|
||||
shared_ptr<ChatMessage> ret = nullptr;
|
||||
list<shared_ptr<ChatMessage> > l = d->findMessages(messageId);
|
||||
for (auto &message : l) {
|
||||
if (linphone_chat_message_get_direction(message) == direction) {
|
||||
linphone_chat_message_ref(message);
|
||||
if (message->getDirection() == direction) {
|
||||
ret = message;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!l.empty()) {
|
||||
for (auto &message : l)
|
||||
linphone_chat_message_unref(message);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
list<LinphoneChatMessage *> ChatRoom::getHistory (int nbMessages) {
|
||||
list<shared_ptr<ChatMessage> > ChatRoom::getHistory (int nbMessages) {
|
||||
return getHistoryRange(0, nbMessages - 1);
|
||||
}
|
||||
|
||||
|
|
@ -677,9 +661,9 @@ int ChatRoom::getHistorySize () {
|
|||
return d->getMessagesCount(false);
|
||||
}
|
||||
|
||||
list<LinphoneChatMessage *> ChatRoom::getHistoryRange (int startm, int endm) {
|
||||
list<shared_ptr<ChatMessage> > ChatRoom::getHistoryRange (int startm, int endm) {
|
||||
L_D();
|
||||
if (!d->core->db) return list<LinphoneChatMessage *>();
|
||||
if (!d->core->db) return list<shared_ptr<ChatMessage> >();
|
||||
string peer = d->peerAddress.asStringUriOnly();
|
||||
d->messages.clear();
|
||||
|
||||
|
|
@ -717,18 +701,16 @@ list<LinphoneChatMessage *> ChatRoom::getHistoryRange (int startm, int endm) {
|
|||
|
||||
if (!d->messages.empty()) {
|
||||
/* Fill local addr with core identity instead of per message */
|
||||
LinphoneAddress *localAddr = linphone_address_new(linphone_core_get_identity(d->core));
|
||||
for (auto &message : d->messages) {
|
||||
if (linphone_chat_message_is_outgoing(message)) {
|
||||
linphone_chat_message_set_from_address(message, linphone_address_ref(localAddr));
|
||||
if (message->isOutgoing()) {
|
||||
message->setFromAddress(linphone_core_get_identity(d->core));
|
||||
} else {
|
||||
linphone_chat_message_set_to_address(message, linphone_address_ref(localAddr));
|
||||
message->setToAddress(linphone_core_get_identity(d->core));
|
||||
}
|
||||
}
|
||||
linphone_address_unref(localAddr);
|
||||
}
|
||||
|
||||
list<LinphoneChatMessage *> result = d->messages;
|
||||
list<shared_ptr<ChatMessage> > result = d->messages;
|
||||
d->messages.clear();
|
||||
return result;
|
||||
}
|
||||
|
|
@ -752,61 +734,60 @@ void ChatRoom::markAsRead () {
|
|||
if (getUnreadMessagesCount() == 0) return;
|
||||
|
||||
string peer = d->peerAddress.asStringUriOnly();
|
||||
char *buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND direction = %i AND status != %i", peer.c_str(), LinphoneChatMessageIncoming, LinphoneChatMessageStateDisplayed);
|
||||
char *buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND direction = %i AND status != %i", peer.c_str(), ChatMessage::Direction::Incoming, ChatMessage::State::Displayed);
|
||||
d->sqlRequestMessage(d->core->db, buf);
|
||||
sqlite3_free(buf);
|
||||
for (auto &message : d->messages) {
|
||||
linphone_chat_message_send_display_notification(message);
|
||||
linphone_chat_message_unref(message);
|
||||
message->sendDisplayNotification();
|
||||
}
|
||||
d->messages.clear();
|
||||
buf = sqlite3_mprintf("UPDATE history SET status=%i WHERE remoteContact=%Q AND direction=%i;", LinphoneChatMessageStateDisplayed, peer.c_str(), LinphoneChatMessageIncoming);
|
||||
buf = sqlite3_mprintf("UPDATE history SET status=%i WHERE remoteContact=%Q AND direction=%i;", ChatMessage::State::Displayed, peer.c_str(), ChatMessage::Direction::Incoming);
|
||||
d->sqlRequest(d->core->db, buf);
|
||||
sqlite3_free(buf);
|
||||
|
||||
if (d->pendingMessage) {
|
||||
linphone_chat_message_set_state(d->pendingMessage, LinphoneChatMessageStateDisplayed);
|
||||
linphone_chat_message_send_display_notification(d->pendingMessage);
|
||||
d->pendingMessage->getPrivate()->setState(ChatMessage::State::Displayed);
|
||||
d->pendingMessage->sendDisplayNotification();
|
||||
}
|
||||
|
||||
d->unreadCount = 0;
|
||||
}
|
||||
|
||||
void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
||||
void ChatRoom::sendMessage (shared_ptr<ChatMessage> msg) {
|
||||
L_D();
|
||||
|
||||
linphone_chat_message_set_outgoing(msg);
|
||||
msg->getPrivate()->setDirection(ChatMessage::Direction::Outgoing);
|
||||
|
||||
/* Check if we shall upload a file to a server */
|
||||
if (linphone_chat_message_get_file_transfer_information(msg) && !linphone_chat_message_get_content_type(msg)) {
|
||||
if (msg->getPrivate()->getFileTransferInformation() && msg->getPrivate()->getContentType().empty()) {
|
||||
/* Open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */
|
||||
if (linphone_chat_room_upload_file(msg) == 0) {
|
||||
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);
|
||||
} else {
|
||||
linphone_chat_message_unref(msg);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
SalOp *op = linphone_chat_message_get_sal_op(msg);
|
||||
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 (linphone_chat_message_get_text(msg)) {
|
||||
clearTextMessage = ms_strdup(linphone_chat_message_get_text(msg));
|
||||
if (!msg->getPrivate()->getText().empty()) {
|
||||
clearTextMessage = ms_strdup(msg->getPrivate()->getText().c_str());
|
||||
}
|
||||
if (linphone_chat_message_get_content_type(msg)) {
|
||||
clearTextContentType = ms_strdup(linphone_chat_message_get_content_type(msg));
|
||||
if (!msg->getPrivate()->getContentType().empty()) {
|
||||
clearTextContentType = ms_strdup(msg->getPrivate()->getContentType().c_str());
|
||||
}
|
||||
|
||||
/* Add to transient list */
|
||||
d->addTransientMessage(msg);
|
||||
linphone_chat_message_set_time(msg, ms_time(0));
|
||||
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) {
|
||||
|
|
@ -828,7 +809,7 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
|||
identity = linphone_core_get_primary_contact(d->core);
|
||||
}
|
||||
}
|
||||
linphone_chat_message_set_from_address(msg, linphone_address_new(identity.c_str()));
|
||||
msg->setFromAddress(identity);
|
||||
|
||||
int retval = -1;
|
||||
LinphoneImEncryptionEngine *imee = d->core->im_encryption_engine;
|
||||
|
|
@ -836,55 +817,54 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
|||
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), msg);
|
||||
retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(this), L_GET_C_BACK_PTR(msg));
|
||||
if (retval == 0) {
|
||||
linphone_chat_message_set_is_secured(msg, TRUE);
|
||||
msg->setIsSecured(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!op) {
|
||||
/* Sending out of call */
|
||||
linphone_chat_message_set_sal_op(msg, op = new SalMessageOp(d->core->sal));
|
||||
msg->getPrivate()->setSalOp(op = new SalMessageOp(d->core->sal));
|
||||
linphone_configure_op(
|
||||
d->core, op, peer, linphone_chat_message_get_sal_custom_headers(msg),
|
||||
d->core, op, peer, msg->getPrivate()->getSalCustomHeaders(),
|
||||
!!lp_config_get_int(d->core->config, "sip", "chat_msg_with_contact", 0)
|
||||
);
|
||||
op->set_user_pointer(msg); /* If out of call, directly store msg */
|
||||
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);
|
||||
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
|
||||
linphone_chat_message_unref(msg);
|
||||
msg->updateState(ChatMessage::State::NotDelivered);
|
||||
linphone_address_unref(peer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (linphone_chat_message_get_external_body_url(msg)) {
|
||||
char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", linphone_chat_message_get_external_body_url(msg));
|
||||
if (!msg->getExternalBodyUrl().empty()) {
|
||||
char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"",msg->getExternalBodyUrl().empty());
|
||||
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 (linphone_chat_message_get_content_type(msg)) {
|
||||
msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), d->peerAddress.asStringUriOnly().c_str());
|
||||
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(), linphone_chat_message_get_text(msg));
|
||||
msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), msg->getPrivate()->getText().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (linphone_chat_message_get_text(msg) && clearTextMessage && strcmp(linphone_chat_message_get_text(msg), clearTextMessage) != 0) {
|
||||
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 */
|
||||
linphone_chat_message_set_text(msg, ms_strdup(clearTextMessage));
|
||||
msg->getPrivate()->setText(clearTextMessage);
|
||||
}
|
||||
if (linphone_chat_message_get_content_type(msg) && clearTextContentType && (strcmp(linphone_chat_message_get_content_type(msg), clearTextContentType) != 0)) {
|
||||
if (!msg->getPrivate()->getContentType().empty() && clearTextContentType && (strcmp(msg->getPrivate()->getContentType().c_str(), clearTextContentType) != 0)) {
|
||||
/* We replace the encrypted content type by the original one */
|
||||
linphone_chat_message_set_content_type(msg, ms_strdup(clearTextContentType));
|
||||
msg->getPrivate()->setContentType(clearTextContentType);
|
||||
}
|
||||
linphone_chat_message_set_message_id(msg, ms_strdup(op->get_call_id())); /* must be known at that time */
|
||||
msg->setId(op->get_call_id()); /* must be known at that time */
|
||||
d->storeOrUpdateMessage(msg);
|
||||
|
||||
if (d->isComposing)
|
||||
|
|
@ -903,15 +883,14 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
|||
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 */
|
||||
linphone_chat_room_remove_transient_message(linphone_chat_message_get_chat_room(msg), msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
d->removeTransientMessage(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If operation failed, we should not change message state */
|
||||
if (linphone_chat_message_is_outgoing(msg)) {
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress);
|
||||
if (msg->isOutgoing()) {
|
||||
msg->getPrivate()->setState(ChatMessage::State::InProgress);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "object/object.h"
|
||||
#include "conference/conference-interface.h"
|
||||
|
||||
#include "chat-message.h"
|
||||
|
||||
#include "linphone/types.h"
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -47,19 +49,20 @@ public:
|
|||
virtual ~ChatRoom () = default;
|
||||
|
||||
void compose ();
|
||||
LinphoneChatMessage *createFileTransferMessage (const LinphoneContent *initialContent);
|
||||
LinphoneChatMessage *createMessage (const std::string &msg);
|
||||
std::shared_ptr<ChatMessage> createFileTransferMessage (const LinphoneContent *initialContent);
|
||||
std::shared_ptr<ChatMessage> createMessage (const std::string &msg);
|
||||
std::shared_ptr<ChatMessage> createMessage ();
|
||||
void deleteHistory ();
|
||||
void deleteMessage (LinphoneChatMessage *msg);
|
||||
LinphoneChatMessage * findMessage (const std::string& messageId);
|
||||
LinphoneChatMessage * findMessageWithDirection (const std::string &messageId, LinphoneChatMessageDir direction);
|
||||
std::list<LinphoneChatMessage *> getHistory (int nbMessages);
|
||||
void deleteMessage (std::shared_ptr<ChatMessage> msg);
|
||||
std::shared_ptr<ChatMessage> findMessage (const std::string& messageId);
|
||||
std::shared_ptr<ChatMessage> findMessageWithDirection (const std::string &messageId, ChatMessage::Direction direction);
|
||||
std::list<std::shared_ptr<ChatMessage> > getHistory (int nbMessages);
|
||||
int getHistorySize ();
|
||||
std::list<LinphoneChatMessage *> getHistoryRange (int startm, int endm);
|
||||
std::list<std::shared_ptr<ChatMessage> > getHistoryRange (int startm, int endm);
|
||||
int getUnreadMessagesCount ();
|
||||
bool isRemoteComposing () const;
|
||||
void markAsRead ();
|
||||
virtual void sendMessage (LinphoneChatMessage *msg);
|
||||
virtual void sendMessage (std::shared_ptr<ChatMessage> msg);
|
||||
|
||||
LinphoneCore *getCore () const;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#include "logger/logger.h"
|
||||
|
||||
#include "imdn.h"
|
||||
#include "chat/chat-room.h"
|
||||
#include "chat/chat-message.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -59,7 +61,7 @@ void Imdn::parse (ChatRoom &cr, xmlparsing_context_t *xmlCtx) {
|
|||
}
|
||||
|
||||
if (messageIdStr && datetimeStr) {
|
||||
LinphoneChatMessage *cm = cr.findMessageWithDirection(messageIdStr, LinphoneChatMessageOutgoing);
|
||||
shared_ptr<ChatMessage> cm = cr.findMessageWithDirection(messageIdStr, ChatMessage::Direction::Outgoing);
|
||||
if (!cm) {
|
||||
lWarning() << "Received IMDN for unknown message " << messageIdStr;
|
||||
} else {
|
||||
|
|
@ -73,9 +75,9 @@ void Imdn::parse (ChatRoom &cr, xmlparsing_context_t *xmlCtx) {
|
|||
xmlNodePtr node = deliveryStatusObject->nodesetval->nodeTab[0];
|
||||
if (node->children && node->children->name) {
|
||||
if (strcmp((const char *)node->children->name, "delivered") == 0) {
|
||||
linphone_chat_message_update_state(cm, LinphoneChatMessageStateDeliveredToUser);
|
||||
cm->updateState(ChatMessage::State::DeliveredToUser);
|
||||
} else if (strcmp((const char *)node->children->name, "error") == 0) {
|
||||
linphone_chat_message_update_state(cm, LinphoneChatMessageStateNotDelivered);
|
||||
cm->updateState(ChatMessage::State::NotDelivered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -86,13 +88,12 @@ void Imdn::parse (ChatRoom &cr, xmlparsing_context_t *xmlCtx) {
|
|||
xmlNodePtr node = displayStatusObject->nodesetval->nodeTab[0];
|
||||
if (node->children && node->children->name) {
|
||||
if (strcmp((const char *)node->children->name, "displayed") == 0) {
|
||||
linphone_chat_message_update_state(cm, LinphoneChatMessageStateDisplayed);
|
||||
cm->updateState(ChatMessage::State::Displayed);
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(displayStatusObject);
|
||||
}
|
||||
linphone_chat_message_unref(cm);
|
||||
}
|
||||
}
|
||||
if (messageIdStr)
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@
|
|||
|
||||
#include "linphone/utils/general.h"
|
||||
|
||||
#include "chat-room.h"
|
||||
|
||||
#include "private.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class ChatRoom;
|
||||
|
||||
class Imdn {
|
||||
public:
|
||||
static void parse (ChatRoom &cr, const std::string &content);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "linphone/utils/general.h"
|
||||
|
||||
#include "private.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -16,12 +16,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "chat/chat-message-p.h"
|
||||
#include "cpim-chat-message-modifier.h"
|
||||
|
||||
#include "chat/cpim/cpim.h"
|
||||
#include "content/content-type.h"
|
||||
#include "content/content.h"
|
||||
|
||||
#include "cpim-chat-message-modifier.h"
|
||||
#include "address/address.h"
|
||||
#include "chat/chat-message-p.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "chat/chat-message-p.h"
|
||||
#include "multipart-chat-message-modifier.h"
|
||||
#include "address/address.h"
|
||||
#include "chat/chat-message-p.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public:
|
|||
public:
|
||||
LinphoneCall *call = nullptr;
|
||||
std::list<LinphoneChatMessageCharacter *> receivedRttCharacters;
|
||||
LinphoneChatMessage *pendingMessage = nullptr;
|
||||
std::shared_ptr<ChatMessage> pendingMessage = nullptr;
|
||||
|
||||
private:
|
||||
L_DECLARE_PUBLIC(RealTimeTextChatRoom);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "linphone/utils/utils.h"
|
||||
|
||||
#include "real-time-text-chat-room-p.h"
|
||||
#include "chat-message-p.h"
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
|
|
@ -40,8 +41,6 @@ RealTimeTextChatRoomPrivate::~RealTimeTextChatRoomPrivate () {
|
|||
for (auto &rttChars : receivedRttCharacters)
|
||||
bctbx_free(rttChars);
|
||||
}
|
||||
if (pendingMessage)
|
||||
linphone_chat_message_unref(pendingMessage);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -67,16 +66,11 @@ void RealTimeTextChatRoomPrivate::realtimeTextReceived (uint32_t character, Linp
|
|||
|
||||
if ((character == new_line) || (character == crlf) || (character == lf)) {
|
||||
/* End of message */
|
||||
lDebug() << "New line received, forge a message with content " << linphone_chat_message_get_text(pendingMessage);
|
||||
LinphoneAddress *peer = linphone_address_new(peerAddress.asString().c_str());
|
||||
linphone_chat_message_set_from_address(pendingMessage, peer);
|
||||
linphone_address_unref(peer);
|
||||
linphone_chat_message_set_to_address(pendingMessage, linphone_call_get_dest_proxy(call)
|
||||
? linphone_address_clone(linphone_call_get_dest_proxy(call)->identity_address)
|
||||
: linphone_address_new(linphone_core_get_identity(core)));
|
||||
linphone_chat_message_set_time(pendingMessage, ms_time(0));
|
||||
linphone_chat_message_set_state(pendingMessage, LinphoneChatMessageStateDelivered);
|
||||
linphone_chat_message_set_incoming(pendingMessage);
|
||||
lDebug() << "New line received, forge a message with content " << pendingMessage->getPrivate()->getText().c_str();
|
||||
pendingMessage->setFromAddress(peerAddress);
|
||||
pendingMessage->setToAddress(linphone_call_get_dest_proxy(call) ? linphone_address_as_string(linphone_call_get_dest_proxy(call)->identity_address) : linphone_core_get_identity(core));
|
||||
pendingMessage->getPrivate()->setState(ChatMessage::State::Delivered);
|
||||
pendingMessage->getPrivate()->setDirection(ChatMessage::Direction::Incoming);
|
||||
|
||||
if (lp_config_get_int(core->config, "misc", "store_rtt_messages", 1) == 1)
|
||||
storeOrUpdateMessage(pendingMessage);
|
||||
|
|
@ -85,16 +79,15 @@ void RealTimeTextChatRoomPrivate::realtimeTextReceived (uint32_t character, Linp
|
|||
else unreadCount++;
|
||||
|
||||
chatMessageReceived(pendingMessage);
|
||||
linphone_chat_message_unref(pendingMessage);
|
||||
pendingMessage = nullptr;
|
||||
for (auto &rttChars : receivedRttCharacters)
|
||||
ms_free(rttChars);
|
||||
receivedRttCharacters.clear();
|
||||
} else {
|
||||
char *value = Utils::utf8ToChar(character);
|
||||
char *text = (char *)linphone_chat_message_get_text(pendingMessage);
|
||||
linphone_chat_message_set_text(pendingMessage, ms_strcat_printf(text, value));
|
||||
lDebug() << "Received RTT character: " << value << " (" << character << "), pending text is " << linphone_chat_message_get_text(pendingMessage);
|
||||
char *text = (char *)pendingMessage->getPrivate()->getText().c_str();
|
||||
pendingMessage->getPrivate()->setText(ms_strcat_printf(text, value));
|
||||
lDebug() << "Received RTT character: " << value << " (" << character << "), pending text is " << pendingMessage->getPrivate()->getText();
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
|
|
@ -106,12 +99,11 @@ RealTimeTextChatRoom::RealTimeTextChatRoom (LinphoneCore *core, const Address &p
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void RealTimeTextChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
||||
void RealTimeTextChatRoom::sendMessage (std::shared_ptr<ChatMessage> msg) {
|
||||
L_D();
|
||||
if (d->call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(d->call))) {
|
||||
uint32_t new_line = 0x2028;
|
||||
linphone_chat_message_put_char(msg, new_line);
|
||||
linphone_chat_message_unref(msg);
|
||||
msg->putCharacter(new_line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public:
|
|||
RealTimeTextChatRoom (LinphoneCore *core, const Address &peerAddress);
|
||||
virtual ~RealTimeTextChatRoom () = default;
|
||||
|
||||
void sendMessage (LinphoneChatMessage *msg) override;
|
||||
void sendMessage (std::shared_ptr<ChatMessage> msg) override;
|
||||
|
||||
uint32_t getChar () const;
|
||||
LinphoneCall *getCall () const;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue