Moved most of exisiting code from LinphoneChatMessage* to shared_ptr<ChatMessage>

This commit is contained in:
Sylvain Berfini 2017-09-29 18:01:47 +02:00
parent e7f7abd7ae
commit 72bc4fec53
18 changed files with 370 additions and 350 deletions

View file

@ -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));
}

View file

@ -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.

View file

@ -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));
}

View file

@ -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) {

View file

@ -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;
// -----------------------------------------------------------------------------

View file

@ -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 = "";
}

View file

@ -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);

View file

@ -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:

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -21,6 +21,8 @@
#include "linphone/utils/general.h"
#include "private.h"
// =============================================================================
LINPHONE_BEGIN_NAMESPACE

View file

@ -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"
// =============================================================================

View file

@ -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"
// =============================================================================

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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;