mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
Fixed compil broken due to chat message changes
This commit is contained in:
parent
eccde9b8f1
commit
d9d06fa32f
16 changed files with 1805 additions and 1652 deletions
|
|
@ -605,11 +605,11 @@ static void message_delivery_update(SalOp *op, SalMessageDeliveryStatus status){
|
|||
return;
|
||||
}
|
||||
// check that the message does not belong to an already destroyed chat room - if so, do not invoke callbacks
|
||||
if (chat_msg->chat_room != NULL) {
|
||||
if (linphone_chat_message_get_chat_room(chat_msg) != NULL) {
|
||||
linphone_chat_message_update_state(chat_msg, chatStatusSal2Linphone(status));
|
||||
}
|
||||
if (status != SalMessageDeliveryInProgress) { /*only release op if not in progress*/
|
||||
linphone_chat_message_destroy(chat_msg);
|
||||
linphone_chat_message_unref(chat_msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
458
coreapi/chat.c
458
coreapi/chat.c
|
|
@ -42,26 +42,6 @@
|
|||
#include "chat/real-time-text-chat-room-p.h"
|
||||
#include "content/content-type.h"
|
||||
|
||||
void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
|
||||
/* do not invoke callbacks on orphan messages */
|
||||
if (state != msg->state && msg->chat_room != NULL) {
|
||||
if (((msg->state == LinphoneChatMessageStateDisplayed) || (msg->state == LinphoneChatMessageStateDeliveredToUser))
|
||||
&& ((state == LinphoneChatMessageStateDeliveredToUser) || (state == LinphoneChatMessageStateDelivered) || (state == LinphoneChatMessageStateNotDelivered))) {
|
||||
/* If the message has been displayed or delivered to user we must not go back to the delivered or not delivered state. */
|
||||
return;
|
||||
}
|
||||
ms_message("Chat message %p: moving from state %s to %s", msg, linphone_chat_message_state_to_string(msg->state),
|
||||
linphone_chat_message_state_to_string(state));
|
||||
msg->state = state;
|
||||
if (msg->message_state_changed_cb) {
|
||||
msg->message_state_changed_cb(msg, msg->state, msg->message_state_changed_user_data);
|
||||
}
|
||||
if (linphone_chat_message_cbs_get_msg_state_changed(msg->callbacks)) {
|
||||
linphone_chat_message_cbs_get_msg_state_changed(msg->callbacks)(msg, msg->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_disable_chat(LinphoneCore *lc, LinphoneReason deny_reason) {
|
||||
lc->chat_deny_code = deny_reason;
|
||||
}
|
||||
|
|
@ -161,22 +141,14 @@ LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const c
|
|||
return _linphone_core_get_or_create_chat_room(lc, to);
|
||||
}
|
||||
|
||||
void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state) {
|
||||
linphone_chat_message_set_state(msg, new_state);
|
||||
linphone_chat_message_store_state(msg);
|
||||
|
||||
if (msg->state == LinphoneChatMessageStateDelivered || msg->state == LinphoneChatMessageStateNotDelivered) {
|
||||
L_GET_PRIVATE_FROM_C_STRUCT(msg->chat_room, ChatRoom)->moveTransientMessageToWeakMessages(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg) {
|
||||
xmlChar *file_url = NULL;
|
||||
xmlDocPtr xmlMessageBody;
|
||||
xmlNodePtr cur;
|
||||
/* parse the msg body to get all informations from it */
|
||||
xmlMessageBody = xmlParseDoc((const xmlChar *)msg->message);
|
||||
msg->file_transfer_information = linphone_content_new();
|
||||
xmlMessageBody = xmlParseDoc((const xmlChar *)linphone_chat_message_get_text(msg));
|
||||
LinphoneContent *content = linphone_content_new();
|
||||
linphone_chat_message_set_file_transfer_information(msg, content);
|
||||
|
||||
cur = xmlDocGetRootElement(xmlMessageBody);
|
||||
if (cur != NULL) {
|
||||
|
|
@ -190,13 +162,13 @@ void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChat
|
|||
while (cur != NULL) {
|
||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) {
|
||||
xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1);
|
||||
linphone_content_set_size(msg->file_transfer_information, strtol((const char *)fileSizeString, NULL, 10));
|
||||
linphone_content_set_size(content, strtol((const char *)fileSizeString, NULL, 10));
|
||||
xmlFree(fileSizeString);
|
||||
}
|
||||
|
||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-name")) {
|
||||
xmlChar *filename = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1);
|
||||
linphone_content_set_name(msg->file_transfer_information, (char *)filename);
|
||||
linphone_content_set_name(content, (char *)filename);
|
||||
xmlFree(filename);
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"content-type")) {
|
||||
|
|
@ -209,8 +181,8 @@ void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChat
|
|||
}
|
||||
type = ms_strndup((char *)contentType, contentTypeIndex);
|
||||
subtype = ms_strdup(((char *)contentType + contentTypeIndex + 1));
|
||||
linphone_content_set_type(msg->file_transfer_information, type);
|
||||
linphone_content_set_subtype(msg->file_transfer_information, subtype);
|
||||
linphone_content_set_type(content, type);
|
||||
linphone_content_set_subtype(content, subtype);
|
||||
ms_free(subtype);
|
||||
ms_free(type);
|
||||
xmlFree(contentType);
|
||||
|
|
@ -227,7 +199,7 @@ void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChat
|
|||
uint8_t *keyBuffer = (uint8_t *)malloc(keyLength);
|
||||
/* decode the key into local key buffer */
|
||||
b64::b64_decode((char *)keyb64, strlen((char *)keyb64), keyBuffer, keyLength);
|
||||
linphone_content_set_key(msg->file_transfer_information, (char *)keyBuffer, keyLength);
|
||||
linphone_content_set_key(content, (char *)keyBuffer, keyLength);
|
||||
/* duplicate key value into the linphone content private structure */
|
||||
xmlFree(keyb64);
|
||||
free(keyBuffer);
|
||||
|
|
@ -258,155 +230,7 @@ int linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage
|
|||
return reason;
|
||||
}
|
||||
|
||||
void _linphone_chat_message_resend(LinphoneChatMessage *msg, bool_t ref_msg) {
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(msg);
|
||||
LinphoneChatRoom *cr;
|
||||
|
||||
if (state != LinphoneChatMessageStateNotDelivered) {
|
||||
ms_warning("Cannot resend chat message in state %s", linphone_chat_message_state_to_string(state));
|
||||
return;
|
||||
}
|
||||
|
||||
cr = linphone_chat_message_get_chat_room(msg);
|
||||
if (ref_msg) linphone_chat_message_ref(msg);
|
||||
L_GET_CPP_PTR_FROM_C_STRUCT(cr, ChatRoom)->sendMessage(msg);
|
||||
}
|
||||
|
||||
void linphone_chat_message_resend(LinphoneChatMessage *msg) {
|
||||
_linphone_chat_message_resend(msg, FALSE);
|
||||
}
|
||||
|
||||
void linphone_chat_message_resend_2(LinphoneChatMessage *msg) {
|
||||
_linphone_chat_message_resend(msg, TRUE);
|
||||
}
|
||||
|
||||
static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason) {
|
||||
xmlBufferPtr buf;
|
||||
xmlTextWriterPtr writer;
|
||||
int err;
|
||||
char *content = NULL;
|
||||
char *datetime = NULL;
|
||||
const char *message_id;
|
||||
|
||||
/* Check that the chat message has a message id */
|
||||
message_id = linphone_chat_message_get_message_id(cm);
|
||||
if (message_id == NULL) return NULL;
|
||||
|
||||
buf = xmlBufferCreate();
|
||||
if (buf == NULL) {
|
||||
ms_error("Error creating the XML buffer");
|
||||
return content;
|
||||
}
|
||||
writer = xmlNewTextWriterMemory(buf, 0);
|
||||
if (writer == NULL) {
|
||||
ms_error("Error creating the XML writer");
|
||||
return content;
|
||||
}
|
||||
|
||||
datetime = linphone_timestamp_to_rfc3339_string(linphone_chat_message_get_time(cm));
|
||||
err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"imdn",
|
||||
(const xmlChar *)"urn:ietf:params:xml:ns:imdn");
|
||||
}
|
||||
if ((err >= 0) && (reason != LinphoneReasonNone)) {
|
||||
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"linphoneimdn", NULL, (const xmlChar *)"http://www.linphone.org/xsds/imdn.xsd");
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"message-id", (const xmlChar *)message_id);
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"datetime", (const xmlChar *)datetime);
|
||||
}
|
||||
if (err >= 0) {
|
||||
if (imdn_type == ImdnTypeDelivery) {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"delivery-notification");
|
||||
} else {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"display-notification");
|
||||
}
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"status");
|
||||
}
|
||||
if (err >= 0) {
|
||||
if (reason == LinphoneReasonNone) {
|
||||
if (imdn_type == ImdnTypeDelivery) {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"delivered");
|
||||
} else {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"displayed");
|
||||
}
|
||||
} else {
|
||||
err = xmlTextWriterStartElement(writer, (const xmlChar *)"error");
|
||||
}
|
||||
}
|
||||
if (err >= 0) {
|
||||
/* Close the "delivered", "displayed" or "error" element. */
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
if ((err >= 0) && (reason != LinphoneReasonNone)) {
|
||||
err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"linphoneimdn", (const xmlChar *)"reason", NULL);
|
||||
if (err >= 0) {
|
||||
char codestr[16];
|
||||
snprintf(codestr, 16, "%d", linphone_reason_to_error_code(reason));
|
||||
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"code", (const xmlChar *)codestr);
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterWriteString(writer, (const xmlChar *)linphone_reason_to_string(reason));
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
}
|
||||
if (err >= 0) {
|
||||
/* Close the "status" element. */
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
if (err >= 0) {
|
||||
/* Close the "delivery-notification" or "display-notification" element. */
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
if (err >= 0) {
|
||||
/* Close the "imdn" element. */
|
||||
err = xmlTextWriterEndElement(writer);
|
||||
}
|
||||
if (err >= 0) {
|
||||
err = xmlTextWriterEndDocument(writer);
|
||||
}
|
||||
if (err > 0) {
|
||||
/* xmlTextWriterEndDocument returns the size of the content. */
|
||||
content = ms_strdup((char *)buf->content);
|
||||
}
|
||||
xmlFreeTextWriter(writer);
|
||||
xmlBufferFree(buf);
|
||||
ms_free(datetime);
|
||||
return content;
|
||||
}
|
||||
|
||||
void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason) {
|
||||
char *content = linphone_chat_message_create_imdn_xml(cm, imdn_type, reason);
|
||||
if (content) {
|
||||
L_GET_PRIVATE_FROM_C_STRUCT(linphone_chat_message_get_chat_room(cm), ChatRoom)->sendImdn(content, reason);
|
||||
ms_free(content);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason) {
|
||||
LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(cm);
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(cr);
|
||||
LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc);
|
||||
if (linphone_im_notif_policy_get_send_imdn_delivered(policy) == TRUE) {
|
||||
linphone_chat_message_send_imdn(cm, ImdnTypeDelivery, reason);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm) {
|
||||
LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(cm);
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(cr);
|
||||
LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc);
|
||||
if (linphone_im_notif_policy_get_send_imdn_displayed(policy) == TRUE) {
|
||||
linphone_chat_message_send_imdn(cm, ImdnTypeDisplay, LinphoneReasonNone);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call) {
|
||||
if (linphone_core_realtime_text_enabled(lc)) {
|
||||
|
|
@ -416,269 +240,3 @@ void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *c
|
|||
//L_GET_PRIVATE(std::static_pointer_cast<LinphonePrivate::RealTimeTextChatRoom>(L_GET_CPP_PTR_FROM_C_STRUCT(cr, ChatRoom, ChatRoom)))->realtimeTextReceived(character, call);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneStatus linphone_chat_message_put_char(LinphoneChatMessage *msg, uint32_t character) {
|
||||
LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg);
|
||||
if (linphone_core_realtime_text_enabled(linphone_chat_room_get_core(cr))) {
|
||||
std::shared_ptr<LinphonePrivate::RealTimeTextChatRoom> rttcr =
|
||||
std::static_pointer_cast<LinphonePrivate::RealTimeTextChatRoom>(L_GET_CPP_PTR_FROM_C_STRUCT(cr, ChatRoom));
|
||||
LinphoneCall *call = rttcr->getCall();
|
||||
LinphoneCore *lc = rttcr->getCore();
|
||||
const uint32_t new_line = 0x2028;
|
||||
const uint32_t crlf = 0x0D0A;
|
||||
const uint32_t lf = 0x0A;
|
||||
|
||||
if (!call || !linphone_call_get_stream(call, LinphoneStreamTypeText)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (character == new_line || character == crlf || character == lf) {
|
||||
if (lc && lp_config_get_int(lc->config, "misc", "store_rtt_messages", 1) == 1) {
|
||||
ms_debug("New line sent, forge a message with content %s", msg->message);
|
||||
msg->time = ms_time(0);
|
||||
msg->state = LinphoneChatMessageStateDisplayed;
|
||||
msg->dir = LinphoneChatMessageOutgoing;
|
||||
if (msg->from) linphone_address_unref(msg->from);
|
||||
msg->from = linphone_address_new(linphone_core_get_identity(lc));
|
||||
msg->storage_id = linphone_chat_message_store(msg);
|
||||
ms_free(msg->message);
|
||||
msg->message = NULL;
|
||||
}
|
||||
} else {
|
||||
char *value = LinphonePrivate::Utils::utf8ToChar(character);
|
||||
msg->message = ms_strcat_printf(msg->message, value);
|
||||
ms_debug("Sent RTT character: %s (%lu), pending text is %s", value, (unsigned long)character, msg->message);
|
||||
delete value;
|
||||
}
|
||||
|
||||
text_stream_putchar32(reinterpret_cast<TextStream *>(linphone_call_get_stream(call, LinphoneStreamTypeText)), character);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* linphone_chat_message_get_message_id(const LinphoneChatMessage *cm) {
|
||||
return cm->message_id;
|
||||
}
|
||||
|
||||
const char *linphone_chat_message_state_to_string(const LinphoneChatMessageState state) {
|
||||
switch (state) {
|
||||
case LinphoneChatMessageStateIdle:
|
||||
return "LinphoneChatMessageStateIdle";
|
||||
case LinphoneChatMessageStateInProgress:
|
||||
return "LinphoneChatMessageStateInProgress";
|
||||
case LinphoneChatMessageStateDelivered:
|
||||
return "LinphoneChatMessageStateDelivered";
|
||||
case LinphoneChatMessageStateNotDelivered:
|
||||
return "LinphoneChatMessageStateNotDelivered";
|
||||
case LinphoneChatMessageStateFileTransferError:
|
||||
return "LinphoneChatMessageStateFileTransferError";
|
||||
case LinphoneChatMessageStateFileTransferDone:
|
||||
return "LinphoneChatMessageStateFileTransferDone ";
|
||||
case LinphoneChatMessageStateDeliveredToUser:
|
||||
return "LinphoneChatMessageStateDeliveredToUser";
|
||||
case LinphoneChatMessageStateDisplayed:
|
||||
return "LinphoneChatMessageStateDisplayed";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LinphoneChatRoom *linphone_chat_message_get_chat_room(LinphoneChatMessage *msg) {
|
||||
return msg->chat_room;
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_chat_message_get_peer_address(LinphoneChatMessage *msg) {
|
||||
return linphone_chat_room_get_peer_address(msg->chat_room);
|
||||
}
|
||||
|
||||
const char *linphone_chat_message_get_external_body_url(const LinphoneChatMessage *msg) {
|
||||
return msg->external_body_url;
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_external_body_url(LinphoneChatMessage *msg, const char *url) {
|
||||
if (msg->external_body_url) {
|
||||
ms_free(msg->external_body_url);
|
||||
}
|
||||
msg->external_body_url = url ? ms_strdup(url) : NULL;
|
||||
}
|
||||
|
||||
const char * linphone_chat_message_get_content_type(const LinphoneChatMessage *msg) {
|
||||
return msg->content_type;
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_content_type(LinphoneChatMessage *msg, const char *content_type) {
|
||||
if (msg->content_type) {
|
||||
ms_free(msg->content_type);
|
||||
}
|
||||
msg->content_type = content_type ? ms_strdup(content_type) : NULL;
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_is_file_transfer(const LinphoneChatMessage *msg) {
|
||||
return LinphonePrivate::ContentType::isFileTransfer(msg->content_type);
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_is_text(const LinphoneChatMessage *msg) {
|
||||
return LinphonePrivate::ContentType::isText(msg->content_type);
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *msg) {
|
||||
return msg->to_be_stored;
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_to_be_stored(LinphoneChatMessage *msg, bool_t to_be_stored) {
|
||||
msg->to_be_stored = to_be_stored;
|
||||
}
|
||||
|
||||
const char *linphone_chat_message_get_appdata(const LinphoneChatMessage *msg) {
|
||||
return msg->appdata;
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_appdata(LinphoneChatMessage *msg, const char *data) {
|
||||
if (msg->appdata) {
|
||||
ms_free(msg->appdata);
|
||||
}
|
||||
msg->appdata = data ? ms_strdup(data) : NULL;
|
||||
linphone_chat_message_store_appdata(msg);
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_from_address(LinphoneChatMessage *msg, const LinphoneAddress *from) {
|
||||
if (msg->from)
|
||||
linphone_address_unref(msg->from);
|
||||
msg->from = linphone_address_clone(from);
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_chat_message_get_from_address(const LinphoneChatMessage *msg) {
|
||||
return msg->from;
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_to_address(LinphoneChatMessage *msg, const LinphoneAddress *to) {
|
||||
if (msg->to)
|
||||
linphone_address_unref(msg->to);
|
||||
msg->to = linphone_address_clone(to);
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_chat_message_get_to_address(const LinphoneChatMessage *msg) {
|
||||
if (msg->to)
|
||||
return msg->to;
|
||||
if (msg->dir == LinphoneChatMessageOutgoing) {
|
||||
return linphone_chat_room_get_peer_address(msg->chat_room);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_is_secured(LinphoneChatMessage *msg, bool_t secured) {
|
||||
msg->is_secured = secured;
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_is_secured(LinphoneChatMessage *msg) {
|
||||
return msg->is_secured;
|
||||
}
|
||||
|
||||
LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage *msg) {
|
||||
return msg->dir == LinphoneChatMessageOutgoing ? msg->from : msg->to;
|
||||
}
|
||||
|
||||
time_t linphone_chat_message_get_time(const LinphoneChatMessage *msg) {
|
||||
return msg->time;
|
||||
}
|
||||
|
||||
LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage *msg) {
|
||||
return msg->state;
|
||||
}
|
||||
|
||||
const char *linphone_chat_message_get_text(const LinphoneChatMessage *msg) {
|
||||
return msg->message;
|
||||
}
|
||||
|
||||
int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) {
|
||||
if (msg->message)
|
||||
ms_free(msg->message);
|
||||
if (text)
|
||||
msg->message = ms_strdup(text);
|
||||
else
|
||||
msg->message = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void linphone_chat_message_add_custom_header(LinphoneChatMessage *msg, const char *header_name,
|
||||
const char *header_value) {
|
||||
msg->custom_headers = sal_custom_header_append(msg->custom_headers, header_name, header_value);
|
||||
}
|
||||
|
||||
const char *linphone_chat_message_get_custom_header(LinphoneChatMessage *msg, const char *header_name) {
|
||||
return sal_custom_header_find(msg->custom_headers, header_name);
|
||||
}
|
||||
|
||||
void linphone_chat_message_remove_custom_header(LinphoneChatMessage *msg, const char *header_name) {
|
||||
msg->custom_headers = sal_custom_header_remove(msg->custom_headers, header_name);
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_is_read(LinphoneChatMessage *msg) {
|
||||
LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg);
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(cr);
|
||||
LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc);
|
||||
if ((linphone_im_notif_policy_get_recv_imdn_displayed(policy) == TRUE) && (msg->state == LinphoneChatMessageStateDisplayed)) return TRUE;
|
||||
if ((linphone_im_notif_policy_get_recv_imdn_delivered(policy) == TRUE) && (msg->state == LinphoneChatMessageStateDeliveredToUser || msg->state == LinphoneChatMessageStateDisplayed)) return TRUE;
|
||||
return (msg->state == LinphoneChatMessageStateDelivered || msg->state == LinphoneChatMessageStateDisplayed || msg->state == LinphoneChatMessageStateDeliveredToUser);
|
||||
}
|
||||
|
||||
bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage *msg) {
|
||||
return msg->dir == LinphoneChatMessageOutgoing;
|
||||
}
|
||||
|
||||
unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage *msg) {
|
||||
return msg->storage_id;
|
||||
}
|
||||
|
||||
LinphoneChatMessage *linphone_chat_message_clone(const LinphoneChatMessage *msg) {
|
||||
LinphoneChatMessage *new_message = linphone_chat_room_create_message(msg->chat_room, msg->message);
|
||||
if (msg->external_body_url)
|
||||
new_message->external_body_url = ms_strdup(msg->external_body_url);
|
||||
if (msg->appdata)
|
||||
new_message->appdata = ms_strdup(msg->appdata);
|
||||
new_message->message_state_changed_cb = msg->message_state_changed_cb;
|
||||
new_message->message_state_changed_user_data = msg->message_state_changed_user_data;
|
||||
new_message->message_userdata = msg->message_userdata;
|
||||
new_message->time = msg->time;
|
||||
new_message->state = msg->state;
|
||||
new_message->storage_id = msg->storage_id;
|
||||
if (msg->from)
|
||||
new_message->from = linphone_address_clone(msg->from);
|
||||
if (msg->file_transfer_filepath)
|
||||
new_message->file_transfer_filepath = ms_strdup(msg->file_transfer_filepath);
|
||||
if (msg->file_transfer_information)
|
||||
new_message->file_transfer_information = linphone_content_copy(msg->file_transfer_information);
|
||||
return new_message;
|
||||
}
|
||||
|
||||
void linphone_chat_message_destroy(LinphoneChatMessage *msg) {
|
||||
belle_sip_object_unref(msg);
|
||||
}
|
||||
|
||||
void linphone_chat_message_deactivate(LinphoneChatMessage *msg){
|
||||
if (msg->file_transfer_information != NULL) {
|
||||
_linphone_chat_message_cancel_file_transfer(msg, FALSE);
|
||||
}
|
||||
/*mark the chat msg as orphan (it has no chat room anymore)*/
|
||||
msg->chat_room = NULL;
|
||||
}
|
||||
|
||||
void linphone_chat_message_release(LinphoneChatMessage *msg) {
|
||||
linphone_chat_message_deactivate(msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
}
|
||||
|
||||
const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg) {
|
||||
if (!msg->ei) ((LinphoneChatMessage*)msg)->ei = linphone_error_info_new(); /*let's do it mutable*/
|
||||
linphone_error_info_from_sal_op(msg->ei, msg->op);
|
||||
return msg->ei;
|
||||
}
|
||||
|
||||
LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage *msg) {
|
||||
return linphone_error_info_get_reason(linphone_chat_message_get_error_info(msg));
|
||||
}
|
||||
|
||||
LinphoneChatMessageCbs *linphone_chat_message_get_callbacks(const LinphoneChatMessage *msg) {
|
||||
return msg->callbacks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,638 +24,10 @@
|
|||
|
||||
#include "linphone/core.h"
|
||||
#include "private.h"
|
||||
#include "ortp/b64.h"
|
||||
|
||||
#include "c-wrapper/c-tools.h"
|
||||
#include "chat/chat-room.h"
|
||||
|
||||
static bool_t file_transfer_in_progress_and_valid(LinphoneChatMessage* msg) {
|
||||
return (msg->chat_room && linphone_chat_room_get_core(msg->chat_room) && msg->http_request && !belle_http_request_is_cancelled(msg->http_request));
|
||||
}
|
||||
|
||||
static void _release_http_request(LinphoneChatMessage* msg) {
|
||||
if (msg->http_request) {
|
||||
belle_sip_object_unref(msg->http_request);
|
||||
msg->http_request = NULL;
|
||||
if (msg->http_listener){
|
||||
belle_sip_object_unref(msg->http_listener);
|
||||
msg->http_listener = NULL;
|
||||
// unhold the reference that the listener was holding on the message
|
||||
linphone_chat_message_unref(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_chat_message_process_io_error_upload(void *data, const belle_sip_io_error_event_t *event) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
ms_error("I/O Error during file upload of msg [%p]", msg);
|
||||
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
|
||||
_release_http_request(msg);
|
||||
linphone_chat_room_remove_transient_message(msg->chat_room, msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
}
|
||||
|
||||
static void linphone_chat_message_process_auth_requested_upload(void *data, belle_sip_auth_event_t *event) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
ms_error("Error during file upload: auth requested for msg [%p]", msg);
|
||||
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
|
||||
_release_http_request(msg);
|
||||
linphone_chat_room_remove_transient_message(msg->chat_room, msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
}
|
||||
|
||||
static void linphone_chat_message_process_io_error_download(void *data, const belle_sip_io_error_event_t *event) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
ms_error("I/O Error during file download msg [%p]", msg);
|
||||
linphone_chat_message_update_state(msg, LinphoneChatMessageStateFileTransferError);
|
||||
_release_http_request(msg);
|
||||
}
|
||||
|
||||
static void linphone_chat_message_process_auth_requested_download(void *data, belle_sip_auth_event_t *event) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
ms_error("Error during file download : auth requested for msg [%p]", msg);
|
||||
linphone_chat_message_update_state(msg, LinphoneChatMessageStateFileTransferError);
|
||||
_release_http_request(msg);
|
||||
}
|
||||
|
||||
static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handler_t *bh, belle_sip_message_t *m,
|
||||
void *data, size_t offset, size_t total) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
if (!file_transfer_in_progress_and_valid(msg)) {
|
||||
ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__);
|
||||
_release_http_request(msg);
|
||||
return;
|
||||
}
|
||||
if (linphone_chat_message_cbs_get_file_transfer_progress_indication(msg->callbacks)) {
|
||||
linphone_chat_message_cbs_get_file_transfer_progress_indication(msg->callbacks)(
|
||||
msg, msg->file_transfer_information, offset, total);
|
||||
} else {
|
||||
/* Legacy: call back given by application level */
|
||||
linphone_core_notify_file_transfer_progress_indication(linphone_chat_room_get_core(msg->chat_room), msg, msg->file_transfer_information,
|
||||
offset, total);
|
||||
}
|
||||
}
|
||||
|
||||
static int on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *m,
|
||||
void *data, size_t offset, uint8_t *buffer, size_t *size) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
LinphoneCore *lc = NULL;
|
||||
LinphoneImEncryptionEngine *imee = NULL;
|
||||
int retval = -1;
|
||||
|
||||
if (!file_transfer_in_progress_and_valid(msg)) {
|
||||
if (msg->http_request) {
|
||||
ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__);
|
||||
_release_http_request(msg);
|
||||
}
|
||||
return BELLE_SIP_STOP;
|
||||
}
|
||||
|
||||
lc = linphone_chat_room_get_core(msg->chat_room);
|
||||
/* if we've not reach the end of file yet, ask for more data */
|
||||
/* in case of file body handler, won't be called */
|
||||
if (msg->file_transfer_filepath == NULL && offset < linphone_content_get_size(msg->file_transfer_information)) {
|
||||
/* get data from call back */
|
||||
LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb = linphone_chat_message_cbs_get_file_transfer_send(msg->callbacks);
|
||||
if (file_transfer_send_cb) {
|
||||
LinphoneBuffer *lb = file_transfer_send_cb(msg, msg->file_transfer_information, offset, *size);
|
||||
if (lb == NULL) {
|
||||
*size = 0;
|
||||
} else {
|
||||
*size = linphone_buffer_get_size(lb);
|
||||
memcpy(buffer, linphone_buffer_get_content(lb), *size);
|
||||
linphone_buffer_unref(lb);
|
||||
}
|
||||
} else {
|
||||
/* Legacy */
|
||||
linphone_core_notify_file_transfer_send(lc, msg, msg->file_transfer_information, (char *)buffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
imee = linphone_core_get_im_encryption_engine(lc);
|
||||
if (imee) {
|
||||
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsUploadingFileCb cb_process_uploading_file = linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs);
|
||||
if (cb_process_uploading_file) {
|
||||
size_t max_size = *size;
|
||||
uint8_t *encrypted_buffer = (uint8_t *)ms_malloc0(max_size);
|
||||
retval = cb_process_uploading_file(imee, msg, offset, (const uint8_t *)buffer, size, encrypted_buffer);
|
||||
if (retval == 0) {
|
||||
if (*size > max_size) {
|
||||
ms_error("IM encryption engine process upload file callback returned a size bigger than the size of the buffer, so it will be truncated !");
|
||||
*size = max_size;
|
||||
}
|
||||
memcpy(buffer, encrypted_buffer, *size);
|
||||
}
|
||||
ms_free(encrypted_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return retval <= 0 ? BELLE_SIP_CONTINUE : BELLE_SIP_STOP;
|
||||
}
|
||||
|
||||
static void on_send_end(belle_sip_user_body_handler_t *bh, void *data) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room);
|
||||
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc);
|
||||
|
||||
if (imee) {
|
||||
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsUploadingFileCb cb_process_uploading_file = linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs);
|
||||
if (cb_process_uploading_file) {
|
||||
cb_process_uploading_file(imee, msg, 0, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void file_upload_end_background_task(LinphoneChatMessage *obj){
|
||||
if (obj->bg_task_id){
|
||||
ms_message("channel [%p]: ending file upload background task with id=[%lx].",obj,obj->bg_task_id);
|
||||
sal_end_background_task(obj->bg_task_id);
|
||||
obj->bg_task_id=0;
|
||||
}
|
||||
}
|
||||
|
||||
static void file_upload_background_task_ended(LinphoneChatMessage *obj){
|
||||
ms_warning("channel [%p]: file upload background task has to be ended now, but work isn't finished.",obj);
|
||||
file_upload_end_background_task(obj);
|
||||
}
|
||||
|
||||
static void file_upload_begin_background_task(LinphoneChatMessage *obj){
|
||||
if (obj->bg_task_id==0){
|
||||
obj->bg_task_id=sal_begin_background_task("file transfer upload",(void (*)(void*))file_upload_background_task_ended, obj);
|
||||
if (obj->bg_task_id) ms_message("channel [%p]: starting file upload background task with id=[%lx].",obj,obj->bg_task_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_chat_message_process_response_from_post_file(void *data, const belle_http_response_event_t *event) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
|
||||
if (msg->http_request && !file_transfer_in_progress_and_valid(msg)) {
|
||||
ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__);
|
||||
_release_http_request(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check the answer code */
|
||||
if (event->response) {
|
||||
int code = belle_http_response_get_status_code(event->response);
|
||||
if (code == 204) { /* this is the reply to the first post to the server - an empty msg */
|
||||
/* start uploading the file */
|
||||
belle_sip_multipart_body_handler_t *bh;
|
||||
char *first_part_header;
|
||||
belle_sip_body_handler_t *first_part_bh;
|
||||
|
||||
bool_t is_file_encryption_enabled = FALSE;
|
||||
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(linphone_chat_room_get_core(msg->chat_room));
|
||||
if (imee) {
|
||||
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb =
|
||||
linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(imee_cbs);
|
||||
if (is_encryption_enabled_for_file_transfer_cb) {
|
||||
is_file_encryption_enabled = is_encryption_enabled_for_file_transfer_cb(imee, msg->chat_room);
|
||||
}
|
||||
}
|
||||
/* shall we encrypt the file */
|
||||
if (is_file_encryption_enabled) {
|
||||
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb =
|
||||
linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs);
|
||||
if (generate_file_transfer_key_cb) {
|
||||
generate_file_transfer_key_cb(imee, msg->chat_room, msg);
|
||||
}
|
||||
/* temporary storage for the Content-disposition header value : use a generic filename to not leak it
|
||||
* Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg
|
||||
* sended to the */
|
||||
first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"filename.txt\"");
|
||||
} else {
|
||||
/* temporary storage for the Content-disposition header value */
|
||||
first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"",
|
||||
linphone_content_get_name(msg->file_transfer_information));
|
||||
}
|
||||
|
||||
/* create a user body handler to take care of the file and add the content disposition and content-type
|
||||
* headers */
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new(
|
||||
linphone_content_get_size(msg->file_transfer_information),
|
||||
linphone_chat_message_file_transfer_on_progress, NULL, NULL,
|
||||
on_send_body, on_send_end, msg);
|
||||
if (msg->file_transfer_filepath != NULL) {
|
||||
belle_sip_user_body_handler_t *body_handler = (belle_sip_user_body_handler_t *)first_part_bh;
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(msg->file_transfer_filepath,
|
||||
NULL, msg); // No need to add again the callback for progression, otherwise it will be called twice
|
||||
linphone_content_set_size(msg->file_transfer_information, belle_sip_file_body_handler_get_file_size((belle_sip_file_body_handler_t *)first_part_bh));
|
||||
belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)first_part_bh, body_handler);
|
||||
} else if (linphone_content_get_buffer(msg->file_transfer_information) != NULL) {
|
||||
first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer(
|
||||
linphone_content_get_buffer(msg->file_transfer_information),
|
||||
linphone_content_get_size(msg->file_transfer_information), linphone_chat_message_file_transfer_on_progress, msg);
|
||||
}
|
||||
|
||||
belle_sip_body_handler_add_header(first_part_bh,
|
||||
belle_sip_header_create("Content-disposition", first_part_header));
|
||||
belle_sip_free(first_part_header);
|
||||
belle_sip_body_handler_add_header(first_part_bh,
|
||||
(belle_sip_header_t *)belle_sip_header_content_type_create(
|
||||
linphone_content_get_type(msg->file_transfer_information),
|
||||
linphone_content_get_subtype(msg->file_transfer_information)));
|
||||
|
||||
/* insert it in a multipart body handler which will manage the boundaries of multipart msg */
|
||||
bh = belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, first_part_bh, NULL);
|
||||
|
||||
linphone_chat_message_ref(msg);
|
||||
_release_http_request(msg);
|
||||
file_upload_begin_background_task(msg);
|
||||
linphone_chat_room_upload_file(msg);
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(msg->http_request), BELLE_SIP_BODY_HANDLER(bh));
|
||||
linphone_chat_message_unref(msg);
|
||||
} else if (code == 200) { /* file has been uploaded correctly, get server reply and send it */
|
||||
const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
|
||||
if (body && strlen(body) > 0) {
|
||||
/* if we have an encryption key for the file, we must insert it into the msg and restore the correct
|
||||
* filename */
|
||||
const char *content_key = linphone_content_get_key(msg->file_transfer_information);
|
||||
size_t content_key_size = linphone_content_get_key_size(msg->file_transfer_information);
|
||||
if (content_key != NULL) {
|
||||
/* parse the msg body */
|
||||
xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body);
|
||||
|
||||
xmlNodePtr cur = xmlDocGetRootElement(xmlMessageBody);
|
||||
if (cur != NULL) {
|
||||
cur = cur->xmlChildrenNode;
|
||||
while (cur != NULL) {
|
||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { /* we found a file info node, check
|
||||
it has a type="file" attribute */
|
||||
xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type");
|
||||
if (!xmlStrcmp(typeAttribute,
|
||||
(const xmlChar *)"file")) { /* this is the node we are looking for : add a
|
||||
file-key children node */
|
||||
xmlNodePtr fileInfoNodeChildren =
|
||||
cur
|
||||
->xmlChildrenNode; /* need to parse the children node to update the file-name
|
||||
one */
|
||||
/* convert key to base64 */
|
||||
size_t b64Size = b64::b64_encode(NULL, content_key_size, NULL, 0);
|
||||
char *keyb64 = (char *)ms_malloc0(b64Size + 1);
|
||||
int xmlStringLength;
|
||||
|
||||
b64Size = b64::b64_encode(content_key, content_key_size, keyb64, b64Size);
|
||||
keyb64[b64Size] = '\0'; /* libxml need a null terminated string */
|
||||
|
||||
/* add the node containing the key to the file-info node */
|
||||
xmlNewTextChild(cur, NULL, (const xmlChar *)"file-key", (const xmlChar *)keyb64);
|
||||
xmlFree(typeAttribute);
|
||||
ms_free(keyb64);
|
||||
|
||||
/* look for the file-name node and update its content */
|
||||
while (fileInfoNodeChildren != NULL) {
|
||||
if (!xmlStrcmp(
|
||||
fileInfoNodeChildren->name,
|
||||
(const xmlChar *)"file-name")) { /* we found a the file-name node, update
|
||||
its content with the real filename */
|
||||
/* update node content */
|
||||
xmlNodeSetContent(fileInfoNodeChildren,
|
||||
(const xmlChar *)(linphone_content_get_name(
|
||||
msg->file_transfer_information)));
|
||||
break;
|
||||
}
|
||||
fileInfoNodeChildren = fileInfoNodeChildren->next;
|
||||
}
|
||||
|
||||
/* dump the xml into msg->message */
|
||||
xmlDocDumpFormatMemoryEnc(xmlMessageBody, (xmlChar **)&msg->message, &xmlStringLength,
|
||||
"UTF-8", 0);
|
||||
|
||||
break;
|
||||
}
|
||||
xmlFree(typeAttribute);
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
xmlFreeDoc(xmlMessageBody);
|
||||
} else { /* no encryption key, transfer in plain, just copy the msg sent by server */
|
||||
msg->message = ms_strdup(body);
|
||||
}
|
||||
linphone_chat_message_set_content_type(msg, "application/vnd.gsma.rcs-ft-http+xml");
|
||||
linphone_chat_message_ref(msg);
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone);
|
||||
_release_http_request(msg);
|
||||
L_GET_CPP_PTR_FROM_C_STRUCT(msg->chat_room, ChatRoom)->sendMessage(msg);
|
||||
file_upload_end_background_task(msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
} else {
|
||||
ms_warning("Received empty response from server, file transfer failed");
|
||||
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
|
||||
_release_http_request(msg);
|
||||
file_upload_end_background_task(msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
}
|
||||
} else {
|
||||
ms_warning("Unhandled HTTP code response %d for file transfer", code);
|
||||
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
|
||||
_release_http_request(msg);
|
||||
file_upload_end_background_task(msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const LinphoneContent *linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage *msg) {
|
||||
return msg->file_transfer_information;
|
||||
}
|
||||
|
||||
static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, void *data, size_t offset, uint8_t *buffer, size_t size) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
LinphoneCore *lc = NULL;
|
||||
LinphoneImEncryptionEngine *imee = NULL;
|
||||
int retval = -1;
|
||||
uint8_t *decrypted_buffer = NULL;
|
||||
|
||||
if (!msg->chat_room) {
|
||||
linphone_chat_message_cancel_file_transfer(msg);
|
||||
return;
|
||||
}
|
||||
lc = linphone_chat_room_get_core(msg->chat_room);
|
||||
|
||||
if (lc == NULL){
|
||||
return; /*might happen during linphone_core_destroy()*/
|
||||
}
|
||||
|
||||
if (!msg->http_request || belle_http_request_is_cancelled(msg->http_request)) {
|
||||
ms_warning("Cancelled request for msg [%p], ignoring %s", msg, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* first call may be with a zero size, ignore it */
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
decrypted_buffer = (uint8_t *)ms_malloc0(size);
|
||||
imee = linphone_core_get_im_encryption_engine(lc);
|
||||
if (imee) {
|
||||
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs);
|
||||
if (cb_process_downloading_file) {
|
||||
retval = cb_process_downloading_file(imee, msg, offset, (const uint8_t *)buffer, size, decrypted_buffer);
|
||||
if (retval == 0) {
|
||||
memcpy(buffer, decrypted_buffer, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
ms_free(decrypted_buffer);
|
||||
|
||||
if (retval <= 0) {
|
||||
if (msg->file_transfer_filepath == NULL) {
|
||||
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
|
||||
LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size);
|
||||
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb);
|
||||
linphone_buffer_unref(lb);
|
||||
} else {
|
||||
/* Legacy: call back given by application level */
|
||||
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, (const char *)buffer, size);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ms_warning("File transfer decrypt failed with code %d", (int)retval);
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void on_recv_end(belle_sip_user_body_handler_t *bh, void *data) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room);
|
||||
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc);
|
||||
int retval = -1;
|
||||
|
||||
if (imee) {
|
||||
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
|
||||
LinphoneImEncryptionEngineCbsDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs);
|
||||
if (cb_process_downloading_file) {
|
||||
retval = cb_process_downloading_file(imee, msg, 0, NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (retval <= 0) {
|
||||
if (msg->file_transfer_filepath == NULL) {
|
||||
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
|
||||
LinphoneBuffer *lb = linphone_buffer_new();
|
||||
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb);
|
||||
linphone_buffer_unref(lb);
|
||||
} else {
|
||||
/* Legacy: call back given by application level */
|
||||
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retval <= 0 && linphone_chat_message_get_state(msg) != LinphoneChatMessageStateFileTransferError) {
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone);
|
||||
}
|
||||
}
|
||||
|
||||
static LinphoneContent *linphone_chat_create_file_transfer_information_from_headers(const belle_sip_message_t *m) {
|
||||
LinphoneContent *content = linphone_content_new();
|
||||
|
||||
belle_sip_header_content_length_t *content_length_hdr =
|
||||
BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(m, "Content-Length"));
|
||||
belle_sip_header_content_type_t *content_type_hdr =
|
||||
BELLE_SIP_HEADER_CONTENT_TYPE(belle_sip_message_get_header(m, "Content-Type"));
|
||||
const char *type = NULL, *subtype = NULL;
|
||||
|
||||
linphone_content_set_name(content, "");
|
||||
|
||||
if (content_type_hdr) {
|
||||
type = belle_sip_header_content_type_get_type(content_type_hdr);
|
||||
subtype = belle_sip_header_content_type_get_subtype(content_type_hdr);
|
||||
ms_message("Extracted content type %s / %s from header", type ? type : "", subtype ? subtype : "");
|
||||
if (type)
|
||||
linphone_content_set_type(content, type);
|
||||
if (subtype)
|
||||
linphone_content_set_subtype(content, subtype);
|
||||
}
|
||||
|
||||
if (content_length_hdr) {
|
||||
linphone_content_set_size(content, belle_sip_header_content_length_get_content_length(content_length_hdr));
|
||||
ms_message("Extracted content length %i from header", (int)linphone_content_get_size(content));
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
static void linphone_chat_process_response_headers_from_get_file(void *data, const belle_http_response_event_t *event) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
if (event->response) {
|
||||
/*we are receiving a response, set a specific body handler to acquire the response.
|
||||
* if not done, belle-sip will create a memory body handler, the default*/
|
||||
belle_sip_message_t *response = BELLE_SIP_MESSAGE(event->response);
|
||||
belle_sip_body_handler_t *body_handler = NULL;
|
||||
size_t body_size = 0;
|
||||
|
||||
if (msg->file_transfer_information == NULL) {
|
||||
ms_warning("No file transfer information for msg %p: creating...", msg);
|
||||
msg->file_transfer_information = linphone_chat_create_file_transfer_information_from_headers(response);
|
||||
}
|
||||
|
||||
if (msg->file_transfer_information) {
|
||||
body_size = linphone_content_get_size(msg->file_transfer_information);
|
||||
}
|
||||
|
||||
|
||||
body_handler = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new(body_size, linphone_chat_message_file_transfer_on_progress, NULL, on_recv_body, NULL, on_recv_end, msg);
|
||||
if (msg->file_transfer_filepath != NULL) {
|
||||
belle_sip_user_body_handler_t *bh = (belle_sip_user_body_handler_t *)body_handler;
|
||||
body_handler = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(
|
||||
msg->file_transfer_filepath, linphone_chat_message_file_transfer_on_progress, msg);
|
||||
if (belle_sip_body_handler_get_size((belle_sip_body_handler_t *)body_handler) == 0) {
|
||||
/* If the size of the body has not been initialized from the file stat, use the one from the
|
||||
* file_transfer_information. */
|
||||
belle_sip_body_handler_set_size((belle_sip_body_handler_t *)body_handler, body_size);
|
||||
}
|
||||
belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)body_handler, bh);
|
||||
}
|
||||
belle_sip_message_set_body_handler((belle_sip_message_t *)event->response, body_handler);
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_chat_process_response_from_get_file(void *data, const belle_http_response_event_t *event) {
|
||||
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
|
||||
/* check the answer code */
|
||||
if (event->response) {
|
||||
int code = belle_http_response_get_status_code(event->response);
|
||||
if (code >= 400 && code < 500) {
|
||||
ms_warning("File transfer failed with code %d", code);
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError);
|
||||
} else if (code != 200) {
|
||||
ms_warning("Unhandled HTTP code response %d for file transfer", code);
|
||||
}
|
||||
_release_http_request(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int _linphone_chat_room_start_http_transfer(LinphoneChatMessage *msg, const char* url, const char* action, const belle_http_request_listener_callbacks_t *cbs) {
|
||||
belle_generic_uri_t *uri = NULL;
|
||||
const char* ua = linphone_core_get_user_agent(linphone_chat_room_get_core(msg->chat_room));
|
||||
|
||||
if (url == NULL) {
|
||||
ms_warning("Cannot process file transfer msg: no file remote URI configured.");
|
||||
goto error;
|
||||
}
|
||||
uri = belle_generic_uri_parse(url);
|
||||
if (uri == NULL || belle_generic_uri_get_host(uri)==NULL) {
|
||||
ms_warning("Cannot process file transfer msg: incorrect file remote URI configured '%s'.", url);
|
||||
goto error;
|
||||
}
|
||||
|
||||
msg->http_request = belle_http_request_create(action, uri, belle_sip_header_create("User-Agent", ua), NULL);
|
||||
|
||||
if (msg->http_request == NULL) {
|
||||
ms_warning("Could not create http request for uri %s", url);
|
||||
goto error;
|
||||
}
|
||||
/* keep a reference to the http request to be able to cancel it during upload */
|
||||
belle_sip_object_ref(msg->http_request);
|
||||
|
||||
/* give msg to listener to be able to start the actual file upload when server answer a 204 No content */
|
||||
msg->http_listener = belle_http_request_listener_create_from_callbacks(cbs, linphone_chat_message_ref(msg));
|
||||
belle_http_provider_send_request(linphone_chat_room_get_core(msg->chat_room)->http_provider, msg->http_request, msg->http_listener);
|
||||
return 0;
|
||||
error:
|
||||
if (uri) {
|
||||
belle_sip_object_unref(uri);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int linphone_chat_room_upload_file(LinphoneChatMessage *msg) {
|
||||
belle_http_request_listener_callbacks_t cbs = {0};
|
||||
int err;
|
||||
|
||||
if (msg->http_request){
|
||||
ms_error("linphone_chat_room_upload_file(): there is already an upload in progress.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cbs.process_response = linphone_chat_message_process_response_from_post_file;
|
||||
cbs.process_io_error = linphone_chat_message_process_io_error_upload;
|
||||
cbs.process_auth_requested = linphone_chat_message_process_auth_requested_upload;
|
||||
err = _linphone_chat_room_start_http_transfer(msg, linphone_core_get_file_transfer_server(linphone_chat_room_get_core(msg->chat_room)), "POST", &cbs);
|
||||
if (err == -1){
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
LinphoneStatus linphone_chat_message_download_file(LinphoneChatMessage *msg) {
|
||||
belle_http_request_listener_callbacks_t cbs = {0};
|
||||
int err;
|
||||
|
||||
if (msg->http_request){
|
||||
ms_error("linphone_chat_message_download_file(): there is already a download in progress");
|
||||
return -1;
|
||||
}
|
||||
cbs.process_response_headers = linphone_chat_process_response_headers_from_get_file;
|
||||
cbs.process_response = linphone_chat_process_response_from_get_file;
|
||||
cbs.process_io_error = linphone_chat_message_process_io_error_download;
|
||||
cbs.process_auth_requested = linphone_chat_message_process_auth_requested_download;
|
||||
err = _linphone_chat_room_start_http_transfer(msg, msg->external_body_url, "GET", &cbs);
|
||||
if (err == -1) return -1;
|
||||
/* start the download, status is In Progress */
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void linphone_chat_message_start_file_download(LinphoneChatMessage *msg,
|
||||
LinphoneChatMessageStateChangedCb status_cb, void *ud) {
|
||||
msg->message_state_changed_cb = status_cb;
|
||||
msg->message_state_changed_user_data = ud;
|
||||
linphone_chat_message_download_file(msg);
|
||||
}
|
||||
|
||||
void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_t unref) {
|
||||
if (msg->http_request) {
|
||||
if (msg->state == LinphoneChatMessageStateInProgress) {
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
|
||||
}
|
||||
if (!belle_http_request_is_cancelled(msg->http_request)) {
|
||||
if (msg->chat_room) {
|
||||
ms_message("Canceling file transfer %s - msg [%p] chat room[%p]"
|
||||
, (msg->external_body_url == NULL) ? linphone_core_get_file_transfer_server(linphone_chat_room_get_core(msg->chat_room)) : msg->external_body_url
|
||||
, msg
|
||||
, msg->chat_room);
|
||||
belle_http_provider_cancel_request(linphone_chat_room_get_core(msg->chat_room)->http_provider, msg->http_request);
|
||||
if ((msg->dir == LinphoneChatMessageOutgoing) && unref) {
|
||||
// must release it
|
||||
linphone_chat_message_unref(msg);
|
||||
}
|
||||
} else {
|
||||
ms_message("Warning: http request still running for ORPHAN msg [%p]: this is a memory leak", msg);
|
||||
}
|
||||
}
|
||||
_release_http_request(msg);
|
||||
} else {
|
||||
ms_message("No existing file transfer - nothing to cancel");
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg) {
|
||||
_linphone_chat_message_cancel_file_transfer(msg, TRUE);
|
||||
}
|
||||
|
||||
void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath) {
|
||||
if (msg->file_transfer_filepath != NULL) {
|
||||
ms_free(msg->file_transfer_filepath);
|
||||
}
|
||||
msg->file_transfer_filepath = ms_strdup(filepath);
|
||||
}
|
||||
|
||||
const char *linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg) {
|
||||
return msg->file_transfer_filepath;
|
||||
}
|
||||
|
||||
LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent *initial_content) {
|
||||
return L_GET_CPP_PTR_FROM_C_STRUCT(cr, ChatRoom)->createFileTransferMessage(initial_content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ static void stop(int signum){
|
|||
* function invoked to report file transfer progress.
|
||||
* */
|
||||
static void file_transfer_progress_indication(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) {
|
||||
const LinphoneAddress* from_address = linphone_chat_message_get_from(message);
|
||||
const LinphoneAddress* to_address = linphone_chat_message_get_to(message);
|
||||
const LinphoneAddress* from_address = linphone_chat_message_get_from_address(message);
|
||||
const LinphoneAddress* to_address = linphone_chat_message_get_to_address(message);
|
||||
char *address = linphone_chat_message_is_outgoing(message)?linphone_address_as_string(to_address):linphone_address_as_string(from_address);
|
||||
printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)((offset *100)/total)
|
||||
,(linphone_chat_message_is_outgoing(message)?"sent":"received")
|
||||
|
|
@ -70,7 +70,7 @@ static void file_transfer_received(LinphoneChatMessage *message, const LinphoneC
|
|||
file = (FILE*)linphone_chat_message_get_user_data(message);
|
||||
if (linphone_buffer_is_empty(buffer)) {
|
||||
printf("File transfert completed\n");
|
||||
linphone_chat_message_destroy(message);
|
||||
linphone_chat_message_unref(message);
|
||||
fclose(file);
|
||||
running=FALSE;
|
||||
} else { /* store content on a file*/
|
||||
|
|
@ -95,7 +95,7 @@ static LinphoneBuffer * file_transfer_send(LinphoneChatMessage *message, const L
|
|||
* Call back to get delivery status of a message
|
||||
* */
|
||||
static void linphone_file_transfer_state_changed(LinphoneChatMessage* msg,LinphoneChatMessageState state) {
|
||||
const LinphoneAddress* to_address = linphone_chat_message_get_to(msg);
|
||||
const LinphoneAddress* to_address = linphone_chat_message_get_to_address(msg);
|
||||
char *to = linphone_address_as_string(to_address);
|
||||
printf("File transfer sent to [%s] delivery status is [%s] \n" , to
|
||||
, linphone_chat_message_state_to_string(state));
|
||||
|
|
|
|||
|
|
@ -785,7 +785,9 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn
|
|||
LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine);
|
||||
int errcode = -1;
|
||||
/* check if we have a xml/cipher message to be decrypted */
|
||||
if (msg->content_type && (strcmp("xml/cipher", msg->content_type) == 0 || strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0)) {
|
||||
if (linphone_chat_message_get_content_type(msg) &&
|
||||
(strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 ||
|
||||
strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", linphone_chat_message_get_content_type(msg)) == 0)) {
|
||||
errcode = 0;
|
||||
int retval;
|
||||
void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */
|
||||
|
|
@ -800,9 +802,9 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn
|
|||
errcode = 500;
|
||||
return errcode;
|
||||
}
|
||||
peerUri = linphone_address_as_string_uri_only(msg->from);
|
||||
selfUri = linphone_address_as_string_uri_only(msg->to);
|
||||
retval = lime_decryptMultipartMessage(zrtp_cache_db, (uint8_t *)msg->message, selfUri, peerUri, &decrypted_body, &decrypted_content_type,
|
||||
peerUri = linphone_address_as_string_uri_only(linphone_chat_message_get_from_address(msg));
|
||||
selfUri = linphone_address_as_string_uri_only(linphone_chat_message_get_to_address(msg));
|
||||
retval = lime_decryptMultipartMessage(zrtp_cache_db, (uint8_t *)linphone_chat_message_get_text(msg), selfUri, peerUri, &decrypted_body, &decrypted_content_type,
|
||||
bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0")));
|
||||
ms_free(peerUri);
|
||||
ms_free(selfUri);
|
||||
|
|
@ -813,15 +815,12 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn
|
|||
return errcode;
|
||||
} else {
|
||||
/* swap encrypted message with plain text message */
|
||||
if (msg->message) {
|
||||
ms_free(msg->message);
|
||||
}
|
||||
msg->message = (char *)decrypted_body;
|
||||
linphone_chat_message_set_text(msg, (char *)decrypted_body);
|
||||
if (decrypted_content_type != NULL) {
|
||||
linphone_chat_message_set_content_type(msg, decrypted_content_type);
|
||||
ms_free(decrypted_content_type);
|
||||
} else {
|
||||
if (strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0) {
|
||||
if (strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", linphone_chat_message_get_content_type(msg)) == 0) {
|
||||
linphone_chat_message_set_content_type(msg, "application/vnd.gsma.rcs-ft-http+xml");
|
||||
} else {
|
||||
linphone_chat_message_set_content_type(msg, "text/plain");
|
||||
|
|
@ -839,14 +838,14 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn
|
|||
if(linphone_core_lime_enabled(linphone_chat_room_get_core(room))) {
|
||||
if (linphone_chat_room_lime_available(room)) {
|
||||
void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */
|
||||
if (msg->content_type) {
|
||||
if (strcmp(msg->content_type, "application/vnd.gsma.rcs-ft-http+xml") == 0) {
|
||||
if (linphone_chat_message_get_content_type(msg)) {
|
||||
if (strcmp(linphone_chat_message_get_content_type(msg), "application/vnd.gsma.rcs-ft-http+xml") == 0) {
|
||||
/* It's a file transfer, content type shall be set to application/cipher.vnd.gsma.rcs-ft-http+xml
|
||||
TODO: As of january 2017, the content type is now included in the encrypted body, this
|
||||
application/cipher.vnd.gsma.rcs-ft-http+xml is kept for compatibility with previous versions,
|
||||
but may be dropped in the future to use xml/cipher instead. */
|
||||
new_content_type = "application/cipher.vnd.gsma.rcs-ft-http+xml";
|
||||
} else if (strcmp(msg->content_type, "application/im-iscomposing+xml") == 0) {
|
||||
} else if (strcmp(linphone_chat_message_get_content_type(msg), "application/im-iscomposing+xml") == 0) {
|
||||
/* We don't encrypt composing messages */
|
||||
return errcode;
|
||||
}
|
||||
|
|
@ -861,19 +860,16 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn
|
|||
} else {
|
||||
int retval;
|
||||
uint8_t *crypted_body = NULL;
|
||||
char *selfUri = linphone_address_as_string_uri_only(msg->from);
|
||||
char *selfUri = linphone_address_as_string_uri_only(linphone_chat_message_get_from_address(msg));
|
||||
char *peerUri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(room));
|
||||
|
||||
retval = lime_createMultipartMessage(zrtp_cache_db, msg->content_type, (uint8_t *)msg->message, selfUri, peerUri, &crypted_body);
|
||||
retval = lime_createMultipartMessage(zrtp_cache_db, linphone_chat_message_get_content_type(msg), (uint8_t *)linphone_chat_message_get_text(msg), selfUri, peerUri, &crypted_body);
|
||||
if (retval != 0) { /* fail to encrypt */
|
||||
ms_warning("Unable to encrypt message for %s : %s", peerUri, lime_error_code_to_string(retval));
|
||||
if (crypted_body) ms_free(crypted_body);
|
||||
errcode = 488;
|
||||
} else { /* encryption ok, swap plain text message body by encrypted one */
|
||||
if (msg->message) {
|
||||
ms_free(msg->message);
|
||||
}
|
||||
msg->message = (char *)crypted_body;
|
||||
linphone_chat_message_set_text(msg, (char *)crypted_body);
|
||||
linphone_chat_message_set_content_type(msg, new_content_type);
|
||||
}
|
||||
ms_free(peerUri);
|
||||
|
|
@ -890,23 +886,23 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn
|
|||
}
|
||||
|
||||
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneImEncryptionEngine *engine, LinphoneChatMessage *msg, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) {
|
||||
if (linphone_content_get_key(msg->file_transfer_information) == NULL) return -1;
|
||||
if (linphone_content_get_key(linphone_chat_message_get_file_transfer_information(msg)) == NULL) return -1;
|
||||
|
||||
if (buffer == NULL || size == 0) {
|
||||
return lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL);
|
||||
return lime_decryptFile(linphone_content_get_cryptoContext_address(linphone_chat_message_get_file_transfer_information(msg)), NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
return lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
|
||||
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), size, (char *)decrypted_buffer,
|
||||
return lime_decryptFile(linphone_content_get_cryptoContext_address(linphone_chat_message_get_file_transfer_information(msg)),
|
||||
(unsigned char *)linphone_content_get_key(linphone_chat_message_get_file_transfer_information(msg)), size, (char *)decrypted_buffer,
|
||||
(char *)buffer);
|
||||
}
|
||||
|
||||
int lime_im_encryption_engine_process_uploading_file_cb(LinphoneImEncryptionEngine *engine, LinphoneChatMessage *msg, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer) {
|
||||
size_t file_size = linphone_content_get_size(msg->file_transfer_information);
|
||||
if (linphone_content_get_key(msg->file_transfer_information) == NULL) return -1;
|
||||
size_t file_size = linphone_content_get_size(linphone_chat_message_get_file_transfer_information(msg));
|
||||
if (linphone_content_get_key(linphone_chat_message_get_file_transfer_information(msg)) == NULL) return -1;
|
||||
|
||||
if (buffer == NULL || *size == 0) {
|
||||
return lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL);
|
||||
return lime_encryptFile(linphone_content_get_cryptoContext_address(linphone_chat_message_get_file_transfer_information(msg)), NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
if (file_size == 0) {
|
||||
|
|
@ -915,8 +911,8 @@ int lime_im_encryption_engine_process_uploading_file_cb(LinphoneImEncryptionEngi
|
|||
*size -= (*size % 16);
|
||||
}
|
||||
|
||||
return lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
|
||||
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), *size,
|
||||
return lime_encryptFile(linphone_content_get_cryptoContext_address(linphone_chat_message_get_file_transfer_information(msg)),
|
||||
(unsigned char *)linphone_content_get_key(linphone_chat_message_get_file_transfer_information(msg)), *size,
|
||||
(char *)buffer, (char *)encrypted_buffer);
|
||||
}
|
||||
|
||||
|
|
@ -930,7 +926,7 @@ void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneImEncryptio
|
|||
/* generate a random 192 bits key + 64 bits of initial vector and store it into the
|
||||
* file_transfer_information->key field of the msg */
|
||||
sal_get_random_bytes((unsigned char *)keyBuffer, FILE_TRANSFER_KEY_SIZE);
|
||||
linphone_content_set_key(msg->file_transfer_information, keyBuffer, FILE_TRANSFER_KEY_SIZE); /* key is duplicated in the content private structure */
|
||||
linphone_content_set_key(linphone_chat_message_get_file_transfer_information(msg), keyBuffer, FILE_TRANSFER_KEY_SIZE); /* key is duplicated in the content private structure */
|
||||
}
|
||||
|
||||
#else /* HAVE_LIME */
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "private.h"
|
||||
#include "linphone/core.h"
|
||||
|
||||
|
||||
#ifdef SQLITE_STORAGE_ENABLED
|
||||
|
||||
#include "chat/chat-room.h"
|
||||
|
|
@ -133,17 +132,14 @@ int _linphone_sqlite3_open(const char *db_file, sqlite3 **db) {
|
|||
static int callback_content(void *data, int argc, char **argv, char **colName) {
|
||||
LinphoneChatMessage *message = (LinphoneChatMessage *)data;
|
||||
|
||||
if (message->file_transfer_information) {
|
||||
linphone_content_unref(message->file_transfer_information);
|
||||
message->file_transfer_information = NULL;
|
||||
}
|
||||
message->file_transfer_information = linphone_content_new();
|
||||
if (argv[1]) linphone_content_set_type(message->file_transfer_information, argv[1]);
|
||||
if (argv[2]) linphone_content_set_subtype(message->file_transfer_information, argv[2]);
|
||||
if (argv[3]) linphone_content_set_name(message->file_transfer_information, argv[3]);
|
||||
if (argv[4]) linphone_content_set_encoding(message->file_transfer_information, argv[4]);
|
||||
linphone_content_set_size(message->file_transfer_information, (size_t)atoi(argv[5]));
|
||||
if (argv[8]) linphone_content_set_key(message->file_transfer_information, argv[8], (size_t)atol(argv[7]));
|
||||
LinphoneContent *content = linphone_content_new();
|
||||
if (argv[1]) linphone_content_set_type(content, argv[1]);
|
||||
if (argv[2]) linphone_content_set_subtype(content, argv[2]);
|
||||
if (argv[3]) linphone_content_set_name(content, argv[3]);
|
||||
if (argv[4]) linphone_content_set_encoding(content, argv[4]);
|
||||
linphone_content_set_size(content, (size_t)atoi(argv[5]));
|
||||
if (argv[8]) linphone_content_set_key(content, argv[8], (size_t)atol(argv[7]));
|
||||
linphone_chat_message_set_file_transfer_information(message, content);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -197,10 +193,10 @@ void linphone_sql_request_all(sqlite3* db,const char *stmt, LinphoneCore* lc){
|
|||
}
|
||||
|
||||
static int linphone_chat_message_store_content(LinphoneChatMessage *msg) {
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room);
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(linphone_chat_message_get_chat_room(msg));
|
||||
int id = -1;
|
||||
if (lc->db) {
|
||||
LinphoneContent *content = msg->file_transfer_information;
|
||||
LinphoneContent *content = linphone_chat_message_get_file_transfer_information(msg);
|
||||
char *buf = sqlite3_mprintf("INSERT INTO content VALUES(NULL,%Q,%Q,%Q,%Q,%i,%Q,%lld,%Q);",
|
||||
linphone_content_get_type(content),
|
||||
linphone_content_get_subtype(content),
|
||||
|
|
@ -219,7 +215,7 @@ static int linphone_chat_message_store_content(LinphoneChatMessage *msg) {
|
|||
}
|
||||
|
||||
unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
|
||||
LinphoneCore *lc=linphone_chat_room_get_core(msg->chat_room);
|
||||
LinphoneCore *lc=linphone_chat_room_get_core(linphone_chat_message_get_chat_room(msg));
|
||||
int id = 0;
|
||||
|
||||
if (lc->db){
|
||||
|
|
@ -227,27 +223,27 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
|
|||
char *peer;
|
||||
char *local_contact;
|
||||
char *buf;
|
||||
if (msg->file_transfer_information) {
|
||||
if (linphone_chat_message_get_file_transfer_information(msg)) {
|
||||
content_id = linphone_chat_message_store_content(msg);
|
||||
}
|
||||
|
||||
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room));
|
||||
peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(linphone_chat_message_get_chat_room(msg)));
|
||||
local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
|
||||
buf = sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%lld,%Q,%i,%Q,%Q,%i);",
|
||||
local_contact,
|
||||
peer,
|
||||
msg->dir,
|
||||
msg->message,
|
||||
linphone_chat_message_get_direction(msg),
|
||||
linphone_chat_message_get_text(msg),
|
||||
"-1", /* use UTC field now */
|
||||
FALSE, /* use state == LinphoneChatMessageStateDisplayed now */
|
||||
msg->state,
|
||||
msg->external_body_url,
|
||||
(int64_t)msg->time,
|
||||
msg->appdata,
|
||||
linphone_chat_message_get_state(msg),
|
||||
linphone_chat_message_get_external_body_url(msg),
|
||||
(int64_t)linphone_chat_message_get_time(msg),
|
||||
linphone_chat_message_get_appdata(msg),
|
||||
content_id,
|
||||
msg->message_id,
|
||||
msg->content_type,
|
||||
(int)msg->is_secured
|
||||
linphone_chat_message_get_message_id(msg),
|
||||
linphone_chat_message_get_content_type(msg),
|
||||
(int)linphone_chat_message_is_secured(msg)
|
||||
);
|
||||
linphone_sql_request(lc->db,buf);
|
||||
sqlite3_free(buf);
|
||||
|
|
@ -255,18 +251,19 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
|
|||
ms_free(peer);
|
||||
id = (unsigned int) sqlite3_last_insert_rowid (lc->db);
|
||||
}
|
||||
linphone_chat_message_set_storage_id(msg, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
void linphone_chat_message_store_update(LinphoneChatMessage *msg) {
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room);
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(linphone_chat_message_get_chat_room(msg));
|
||||
|
||||
if (lc->db) {
|
||||
char *peer;
|
||||
char *local_contact;
|
||||
char *buf;
|
||||
|
||||
peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room));
|
||||
peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(linphone_chat_message_get_chat_room(msg)));
|
||||
local_contact = linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
|
||||
buf = sqlite3_mprintf("UPDATE history SET"
|
||||
" localContact = %Q,"
|
||||
|
|
@ -279,12 +276,12 @@ void linphone_chat_message_store_update(LinphoneChatMessage *msg) {
|
|||
" WHERE (id = %u);",
|
||||
local_contact,
|
||||
peer,
|
||||
msg->message,
|
||||
msg->state,
|
||||
msg->appdata,
|
||||
msg->message_id,
|
||||
msg->content_type,
|
||||
msg->storage_id
|
||||
linphone_chat_message_get_text(msg),
|
||||
linphone_chat_message_get_state(msg),
|
||||
linphone_chat_message_get_appdata(msg),
|
||||
linphone_chat_message_get_message_id(msg),
|
||||
linphone_chat_message_get_content_type(msg),
|
||||
linphone_chat_message_get_storage_id(msg)
|
||||
);
|
||||
linphone_sql_request(lc->db, buf);
|
||||
sqlite3_free(buf);
|
||||
|
|
@ -294,20 +291,20 @@ void linphone_chat_message_store_update(LinphoneChatMessage *msg) {
|
|||
}
|
||||
|
||||
void linphone_chat_message_store_state(LinphoneChatMessage *msg){
|
||||
LinphoneCore *lc=linphone_chat_room_get_core(msg->chat_room);
|
||||
LinphoneCore *lc=linphone_chat_room_get_core(linphone_chat_message_get_chat_room(msg));
|
||||
if (lc->db){
|
||||
char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %u);",
|
||||
msg->state,msg->storage_id);
|
||||
linphone_chat_message_get_state(msg), linphone_chat_message_get_storage_id(msg));
|
||||
linphone_sql_request(lc->db,buf);
|
||||
sqlite3_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){
|
||||
LinphoneCore *lc=linphone_chat_room_get_core(msg->chat_room);
|
||||
LinphoneCore *lc=linphone_chat_room_get_core(linphone_chat_message_get_chat_room(msg));
|
||||
if (lc->db){
|
||||
char *buf=sqlite3_mprintf("UPDATE history SET appdata=%Q WHERE id=%u;",
|
||||
msg->appdata,msg->storage_id);
|
||||
linphone_chat_message_get_appdata(msg), linphone_chat_message_get_storage_id(msg));
|
||||
linphone_sql_request(lc->db,buf);
|
||||
sqlite3_free(buf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,11 +129,6 @@ extern "C" {
|
|||
#define STRING_TRANSFER(field, newvalue) do{ if (field){bctbx_free(field);field=NULL;}; field=newvalue; }while(0)
|
||||
|
||||
|
||||
typedef enum _ImdnType {
|
||||
ImdnTypeDelivery,
|
||||
ImdnTypeDisplay
|
||||
} ImdnType;
|
||||
|
||||
|
||||
struct _LinphoneQualityReporting{
|
||||
reporting_session_report_t * reports[3]; /**Store information on audio and video media streams (RFC 6035) */
|
||||
|
|
@ -174,14 +169,9 @@ typedef struct _CallCallbackObj
|
|||
void * _user_data;
|
||||
}CallCallbackObj;
|
||||
|
||||
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessageCbs);
|
||||
//BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessageCbs);
|
||||
|
||||
typedef enum _LinphoneChatMessageDir{
|
||||
LinphoneChatMessageIncoming,
|
||||
LinphoneChatMessageOutgoing
|
||||
} LinphoneChatMessageDir;
|
||||
|
||||
struct _LinphoneChatMessage {
|
||||
/*struct _LinphoneChatMessage {
|
||||
belle_sip_object_t base;
|
||||
LinphoneChatRoom* chat_room;
|
||||
LinphoneChatMessageCbs *callbacks;
|
||||
|
|
@ -201,11 +191,11 @@ struct _LinphoneChatMessage {
|
|||
unsigned int storage_id;
|
||||
char *message_id;
|
||||
SalOp *op;
|
||||
LinphoneContent *file_transfer_information; /**< used to store file transfer information when the message is of file transfer type */
|
||||
char *content_type; /**< is used to specified the type of message to be sent, used only for file transfer message */
|
||||
LinphoneContent *file_transfer_information; //< used to store file transfer information when the message is of file transfer type
|
||||
char *content_type; //< is used to specified the type of message to be sent, used only for file transfer message
|
||||
bool_t to_be_stored;
|
||||
belle_http_request_t *http_request; /**< keep a reference to the http_request in case of file transfer in order to be able to cancel the transfer */
|
||||
belle_http_request_listener_t *http_listener; /* our listener, only owned by us*/
|
||||
belle_http_request_t *http_request; //< keep a reference to the http_request in case of file transfer in order to be able to cancel the transfer
|
||||
belle_http_request_listener_t *http_listener; // our listener, only owned by us
|
||||
char *file_transfer_filepath;
|
||||
unsigned long bg_task_id;
|
||||
bool_t is_secured;
|
||||
|
|
@ -223,9 +213,7 @@ struct _LinphoneChatMessage {
|
|||
#if defined(__clang__) || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
};
|
||||
|
||||
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessage);
|
||||
};*/
|
||||
|
||||
typedef struct StunCandidate{
|
||||
char addr[64];
|
||||
|
|
@ -500,22 +488,6 @@ void linphone_chat_room_release(LinphoneChatRoom *cr);
|
|||
void linphone_chat_room_set_call(LinphoneChatRoom *cr, LinphoneCall *call);
|
||||
bctbx_list_t * linphone_chat_room_get_transient_messages(const LinphoneChatRoom *cr);
|
||||
LinphoneChatRoomCbs * linphone_chat_room_cbs_new (void);
|
||||
void linphone_chat_message_destroy(LinphoneChatMessage* msg);
|
||||
void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state);
|
||||
void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state);
|
||||
void linphone_chat_message_set_is_secured(LinphoneChatMessage *msg, bool_t secured);
|
||||
void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason);
|
||||
void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm);
|
||||
void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_t unref);
|
||||
int linphone_chat_room_upload_file(LinphoneChatMessage *msg);
|
||||
LinphoneChatMessageCbs *linphone_chat_message_cbs_new(void);
|
||||
LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call);
|
||||
void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
|
||||
void linphone_chat_message_deactivate(LinphoneChatMessage *msg);
|
||||
void linphone_chat_message_release(LinphoneChatMessage *msg);
|
||||
void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg);
|
||||
void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id);
|
||||
void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason);
|
||||
/**/
|
||||
|
||||
struct _LinphoneProxyConfig
|
||||
|
|
|
|||
|
|
@ -33,6 +33,50 @@
|
|||
* @addtogroup chatroom
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Call back used to notify message delivery status
|
||||
* @param msg #LinphoneChatMessage object
|
||||
* @param status LinphoneChatMessageState
|
||||
* @param ud application user data
|
||||
* @deprecated Use LinphoneChatMessageCbsMsgStateChangedCb instead.
|
||||
* @donotwrap
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageStateChangedCb)(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud);
|
||||
|
||||
/**
|
||||
* Call back used to notify message delivery status
|
||||
* @param msg #LinphoneChatMessage object
|
||||
* @param status LinphoneChatMessageState
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageCbsMsgStateChangedCb)(LinphoneChatMessage* msg, LinphoneChatMessageState state);
|
||||
|
||||
/**
|
||||
* File transfer receive callback prototype. This function is called by the core upon an incoming File transfer is started. This function may be call several time for the same file in case of large file.
|
||||
* @param message #LinphoneChatMessage message from which the body is received.
|
||||
* @param content #LinphoneContent incoming content information
|
||||
* @param buffer #LinphoneBuffer holding the received data. Empty buffer means end of file.
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageCbsFileTransferRecvCb)(LinphoneChatMessage *message, const LinphoneContent* content, const LinphoneBuffer *buffer);
|
||||
|
||||
/**
|
||||
* File transfer send callback prototype. This function is called by the core when an outgoing file transfer is started. This function is called until size is set to 0.
|
||||
* @param message #LinphoneChatMessage message from which the body is received.
|
||||
* @param content #LinphoneContent outgoing content
|
||||
* @param offset the offset in the file from where to get the data to be sent
|
||||
* @param size the number of bytes expected by the framework
|
||||
* @return A LinphoneBuffer object holding the data written by the application. An empty buffer means end of file.
|
||||
*/
|
||||
typedef LinphoneBuffer * (*LinphoneChatMessageCbsFileTransferSendCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t size);
|
||||
|
||||
/**
|
||||
* File transfer progress indication callback prototype.
|
||||
* @param message #LinphoneChatMessage message from which the body is received.
|
||||
* @param content #LinphoneContent incoming content information
|
||||
* @param offset The number of bytes sent/received since the beginning of the transfer.
|
||||
* @param total The total number of bytes to be sent/received.
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageCbsFileTransferProgressIndicationCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total);
|
||||
|
||||
/**
|
||||
* Is composing notification callback prototype.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
* @addtogroup chatroom
|
||||
* @{
|
||||
*/
|
||||
|
||||
LinphoneChatMessageCbs *linphone_chat_message_cbs_new(void);
|
||||
|
||||
/**
|
||||
* Acquire a reference to the chat room callbacks object.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,25 @@
|
|||
#ifndef _C_CHAT_MESSAGE_H_
|
||||
#define _C_CHAT_MESSAGE_H_
|
||||
|
||||
#include "sal/sal.h"
|
||||
#include "linphone/api/c-types.h"
|
||||
#include "linphone/api/c-chat-message-cbs.h"
|
||||
|
||||
#ifdef SQLITE_STORAGE_ENABLED
|
||||
#include <sqlite3.h>
|
||||
#endif
|
||||
|
||||
// =============================================================================
|
||||
|
||||
typedef enum _ImdnType {
|
||||
ImdnTypeDelivery,
|
||||
ImdnTypeDisplay
|
||||
} ImdnType;
|
||||
|
||||
typedef enum _LinphoneChatMessageDir{
|
||||
LinphoneChatMessageIncoming,
|
||||
LinphoneChatMessageOutgoing
|
||||
} LinphoneChatMessageDir;
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -59,6 +77,352 @@ LINPHONE_PUBLIC void *linphone_chat_message_get_user_data(const LinphoneChatMess
|
|||
**/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_user_data(LinphoneChatMessage *msg, void *ud);
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_PUBLIC const char * linphone_chat_message_get_external_body_url(const LinphoneChatMessage *msg);
|
||||
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage *msg, const char *external_body_url);
|
||||
|
||||
/**
|
||||
* Get the time the message was sent.
|
||||
*/
|
||||
LINPHONE_PUBLIC time_t linphone_chat_message_get_time(const LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the message has been sent, returns FALSE if the message has been received.
|
||||
* @param message the message
|
||||
**/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Set origin of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @param[in] from #LinphoneAddress origin of this message (copied)
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_from_address(LinphoneChatMessage* msg, const LinphoneAddress* from);
|
||||
|
||||
/**
|
||||
* Get origin of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @return #LinphoneAddress
|
||||
*/
|
||||
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Set destination of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @param[in] addr #LinphoneAddress destination of this message (copied)
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_to_address(LinphoneChatMessage* msg, const LinphoneAddress* addr);
|
||||
|
||||
/**
|
||||
* Get destination of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @return #LinphoneAddress
|
||||
*/
|
||||
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Get the content type of a chat message.
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Set the content type of a chat message.
|
||||
* This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml.
|
||||
* @param[in] message LinphoneChatMessage object
|
||||
* @param[in] content_type The new content type of the chat message
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_content_type(LinphoneChatMessage *msg, const char *content_type);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Returns the id used to identify this message in the storage database
|
||||
* @param message the message
|
||||
* @return the id
|
||||
*/
|
||||
LINPHONE_PUBLIC unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Get the message identifier.
|
||||
* It is used to identify a message so that it can be notified as delivered and/or displayed.
|
||||
* @param[in] cm LinphoneChatMessage object
|
||||
* @return The message identifier.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_message_id(const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Linphone message has an app-specific field that can store a text. The application might want
|
||||
* to use it for keeping data over restarts, like thumbnail image path.
|
||||
* @param message #LinphoneChatMessage
|
||||
* @return the application-specific data or NULL if none has been stored.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Linphone message has an app-specific field that can store a text. The application might want
|
||||
* to use it for keeping data over restarts, like thumbnail image path.
|
||||
*
|
||||
* Invoking this function will attempt to update the message storage to reflect the changeif it is
|
||||
* enabled.
|
||||
*
|
||||
* @param message #LinphoneChatMessage
|
||||
* @param data the data to store into the message
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data);
|
||||
|
||||
/**
|
||||
* Returns the chatroom this message belongs to.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneChatRoom* linphone_chat_message_get_chat_room(const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Get the path to the file to read from or write to during the file transfer.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @return The path to the file to use for the file transfer.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char * linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg);
|
||||
|
||||
// =============================================================================
|
||||
|
||||
void linphone_chat_message_set_time(LinphoneChatMessage* msg, time_t time);
|
||||
|
||||
void linphone_chat_message_set_incoming(LinphoneChatMessage *msg);
|
||||
|
||||
void linphone_chat_message_set_outgoing(LinphoneChatMessage *msg);
|
||||
|
||||
void linphone_chat_message_set_message_state_changed_cb(LinphoneChatMessage* msg, LinphoneChatMessageStateChangedCb cb);
|
||||
|
||||
void linphone_chat_message_set_message_state_changed_cb_user_data(LinphoneChatMessage* msg, void *user_data);
|
||||
|
||||
void * linphone_chat_message_get_message_state_changed_cb_user_data(LinphoneChatMessage* msg);
|
||||
|
||||
void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state);
|
||||
|
||||
void linphone_chat_message_set_message_id(LinphoneChatMessage *msg, char *id);
|
||||
|
||||
void linphone_chat_message_set_is_read(LinphoneChatMessage *msg, bool_t is_read);
|
||||
|
||||
void linphone_chat_message_set_storage_id(LinphoneChatMessage *msg, unsigned int id);
|
||||
|
||||
SalCustomHeader * linphone_chat_message_get_sal_custom_headers(const LinphoneChatMessage *msg);
|
||||
|
||||
void linphone_chat_message_set_sal_custom_headers(LinphoneChatMessage *msg, SalCustomHeader *header);
|
||||
|
||||
belle_http_request_t * linphone_chat_message_get_http_request(const LinphoneChatMessage *msg);
|
||||
|
||||
void linphone_chat_message_set_http_request(LinphoneChatMessage *msg, belle_http_request_t *request);
|
||||
|
||||
void linphone_chat_message_set_file_transfer_information(LinphoneChatMessage *msg, LinphoneContent *content);
|
||||
|
||||
LinphoneChatMessageDir linphone_chat_message_get_direction(const LinphoneChatMessage *msg);
|
||||
|
||||
SalOp * linphone_chat_message_get_sal_op(const LinphoneChatMessage *msg);
|
||||
|
||||
void linphone_chat_message_set_sal_op(LinphoneChatMessage *msg, SalOp *op);
|
||||
|
||||
void linphone_chat_message_set_chat_room(LinphoneChatMessage *msg, LinphoneChatRoom *room);
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_PUBLIC unsigned int linphone_chat_message_store(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Get the state of the message
|
||||
*@param message #LinphoneChatMessage obj
|
||||
*@return #LinphoneChatMessageState
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Duplicate a LinphoneChatMessage
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Get if the message was encrypted when transfered
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @return whether the message was encrypted when transfered or not
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_secured(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Linphone message can carry external body as defined by rfc2017
|
||||
* @param message #LinphoneChatMessage
|
||||
* @return external body url or NULL if not present.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Linphone message can carry external body as defined by rfc2017
|
||||
*
|
||||
* @param message a LinphoneChatMessage
|
||||
* @param url ex: access-type=URL; URL="http://www.foo.com/file"
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
|
||||
|
||||
/**
|
||||
* Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer)
|
||||
*
|
||||
* @param message #LinphoneChatMessage
|
||||
* @return a pointer to the LinphoneContent structure or NULL if not present.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneContent* linphone_chat_message_get_file_transfer_information(LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Return whether or not a chat message is a file tranfer.
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Get if a chat message is to be stored.
|
||||
* @param[in] message LinphoneChatMessage object
|
||||
* @return Whether or not the message is to be stored
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *message);
|
||||
|
||||
/**
|
||||
* Set if a chat message is to be stored.
|
||||
* This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml.
|
||||
* @param[in] message LinphoneChatMessage object
|
||||
* @param[in] to_be_stored Whether or not the chat message is to be stored
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_to_be_stored(LinphoneChatMessage *message, bool_t to_be_stored);
|
||||
|
||||
/**
|
||||
* Start the download of the file from remote server
|
||||
*
|
||||
* @param message #LinphoneChatMessage
|
||||
* @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when file is downloaded or could not be downloaded
|
||||
* @param ud user data
|
||||
* @deprecated Use linphone_chat_message_download_file() instead.
|
||||
* @donotwrap
|
||||
*/
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb, void* ud);
|
||||
|
||||
/**
|
||||
* Start the download of the file referenced in a LinphoneChatMessage from remote server.
|
||||
* @param[in] message LinphoneChatMessage object.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneStatus linphone_chat_message_download_file(LinphoneChatMessage *message);
|
||||
|
||||
/**
|
||||
* Cancel an ongoing file transfer attached to this message.(upload or download)
|
||||
* @param msg #LinphoneChatMessage
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Resend a chat message if it is in the 'not delivered' state for whatever reason.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @donotwrap
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_resend(LinphoneChatMessage *msg);
|
||||
|
||||
LINPHONE_PUBLIC LinphoneChatRoom * linphone_core_create_client_group_chat_room(LinphoneCore *lc, const bctbx_list_t *addresses);
|
||||
|
||||
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_peer_address(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Returns the origin address of a message if it was a outgoing message, or the destination address if it was an incoming message.
|
||||
*@param message #LinphoneChatMessage obj
|
||||
*@return #LinphoneAddress
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Add custom headers to the message.
|
||||
* @param message the message
|
||||
* @param header_name name of the header
|
||||
* @param header_value header value
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_add_custom_header(LinphoneChatMessage* message, const char *header_name, const char *header_value);
|
||||
|
||||
/**
|
||||
* Retrieve a custom header value given its name.
|
||||
* @param message the message
|
||||
* @param header_name header name searched
|
||||
**/
|
||||
LINPHONE_PUBLIC const char * linphone_chat_message_get_custom_header(LinphoneChatMessage* message, const char *header_name);
|
||||
|
||||
/**
|
||||
* Removes a custom header from the message.
|
||||
* @param msg the message
|
||||
* @param header_name name of the header to remove
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_remove_custom_header(LinphoneChatMessage *msg, const char *header_name);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the message has been read, otherwise returns FALSE.
|
||||
* @param message the message
|
||||
**/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_read(LinphoneChatMessage* message);
|
||||
|
||||
LINPHONE_PUBLIC LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Get full details about delivery error of a chat message.
|
||||
* @param msg a LinphoneChatMessage
|
||||
* @return a LinphoneErrorInfo describing the details.
|
||||
**/
|
||||
LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Set the path to the file to read from or write to during the file transfer.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @param[in] filepath The path to the file to use for the file transfer.
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath);
|
||||
|
||||
/**
|
||||
* Fulfill a chat message char by char. Message linked to a Real Time Text Call send char in realtime following RFC 4103/T.140
|
||||
* To commit a message, use #linphone_chat_room_send_message
|
||||
* @param[in] msg LinphoneChatMessage
|
||||
* @param[in] character T.140 char
|
||||
* @returns 0 if succeed.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneStatus linphone_chat_message_put_char(LinphoneChatMessage *msg,uint32_t character);
|
||||
|
||||
/**
|
||||
* Get the LinphoneChatMessageCbs object associated with the LinphoneChatMessage.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @return The LinphoneChatMessageCbs object associated with the LinphoneChatMessage.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneChatMessageCbs * linphone_chat_message_get_callbacks(const LinphoneChatMessage *msg);
|
||||
|
||||
// =============================================================================
|
||||
|
||||
void linphone_chat_message_destroy(LinphoneChatMessage* msg);
|
||||
void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state);
|
||||
void linphone_chat_message_set_is_secured(LinphoneChatMessage *msg, bool_t secured);
|
||||
void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason);
|
||||
void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm);
|
||||
void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_t unref);
|
||||
int linphone_chat_room_upload_file(LinphoneChatMessage *msg);
|
||||
LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call);
|
||||
void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
|
||||
void linphone_chat_message_deactivate(LinphoneChatMessage *msg);
|
||||
void linphone_chat_message_release(LinphoneChatMessage *msg);
|
||||
void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg);
|
||||
void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id);
|
||||
void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -30,50 +30,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Call back used to notify message delivery status
|
||||
* @param msg #LinphoneChatMessage object
|
||||
* @param status LinphoneChatMessageState
|
||||
* @param ud application user data
|
||||
* @deprecated Use LinphoneChatMessageCbsMsgStateChangedCb instead.
|
||||
* @donotwrap
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageStateChangedCb)(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud);
|
||||
|
||||
/**
|
||||
* Call back used to notify message delivery status
|
||||
* @param msg #LinphoneChatMessage object
|
||||
* @param status LinphoneChatMessageState
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageCbsMsgStateChangedCb)(LinphoneChatMessage* msg, LinphoneChatMessageState state);
|
||||
|
||||
/**
|
||||
* File transfer receive callback prototype. This function is called by the core upon an incoming File transfer is started. This function may be call several time for the same file in case of large file.
|
||||
* @param message #LinphoneChatMessage message from which the body is received.
|
||||
* @param content #LinphoneContent incoming content information
|
||||
* @param buffer #LinphoneBuffer holding the received data. Empty buffer means end of file.
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageCbsFileTransferRecvCb)(LinphoneChatMessage *message, const LinphoneContent* content, const LinphoneBuffer *buffer);
|
||||
|
||||
/**
|
||||
* File transfer send callback prototype. This function is called by the core when an outgoing file transfer is started. This function is called until size is set to 0.
|
||||
* @param message #LinphoneChatMessage message from which the body is received.
|
||||
* @param content #LinphoneContent outgoing content
|
||||
* @param offset the offset in the file from where to get the data to be sent
|
||||
* @param size the number of bytes expected by the framework
|
||||
* @return A LinphoneBuffer object holding the data written by the application. An empty buffer means end of file.
|
||||
*/
|
||||
typedef LinphoneBuffer * (*LinphoneChatMessageCbsFileTransferSendCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t size);
|
||||
|
||||
/**
|
||||
* File transfer progress indication callback prototype.
|
||||
* @param message #LinphoneChatMessage message from which the body is received.
|
||||
* @param content #LinphoneContent incoming content information
|
||||
* @param offset The number of bytes sent/received since the beginning of the transfer.
|
||||
* @param total The total number of bytes to be sent/received.
|
||||
*/
|
||||
typedef void (*LinphoneChatMessageCbsFileTransferProgressIndicationCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total);
|
||||
|
||||
/**
|
||||
* @}
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -46,302 +46,7 @@ extern "C" {
|
|||
**/
|
||||
LINPHONE_PUBLIC const bctbx_list_t* linphone_core_get_chat_rooms(LinphoneCore *lc);
|
||||
|
||||
LINPHONE_PUBLIC unsigned int linphone_chat_message_store(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Get the state of the message
|
||||
*@param message #LinphoneChatMessage obj
|
||||
*@return #LinphoneChatMessageState
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Duplicate a LinphoneChatMessage
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Destroys a LinphoneChatMessage.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_destroy(LinphoneChatMessage* msg);
|
||||
|
||||
/** @deprecated Use linphone_chat_message_set_from_address() instead. */
|
||||
#define linphone_chat_message_set_from(msg, addr) linphone_chat_message_set_from_address(msg, addr)
|
||||
|
||||
/**
|
||||
* Set origin of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @param[in] from #LinphoneAddress origin of this message (copied)
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_from_address(LinphoneChatMessage* message, const LinphoneAddress* from);
|
||||
|
||||
/** @deprecated Use linphone_chat_message_get_from_address() instead. */
|
||||
#define linphone_chat_message_get_from(msg) linphone_chat_message_get_from_address(msg)
|
||||
|
||||
/**
|
||||
* Get origin of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @return #LinphoneAddress
|
||||
*/
|
||||
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* message);
|
||||
|
||||
#define linphone_chat_message_set_to(msg, addr) linphone_chat_message_set_to_address(msg, addr)
|
||||
|
||||
/**
|
||||
* Set destination of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @param[in] addr #LinphoneAddress destination of this message (copied)
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_to_address(LinphoneChatMessage* message, const LinphoneAddress* addr);
|
||||
|
||||
/** @deprecated Use linphone_chat_message_get_to_address() instead. */
|
||||
#define linphone_chat_message_get_to(msg) linphone_chat_message_get_to_address(msg)
|
||||
|
||||
/**
|
||||
* Get destination of the message
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @return #LinphoneAddress
|
||||
*/
|
||||
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Get if the message was encrypted when transfered
|
||||
* @param[in] message #LinphoneChatMessage obj
|
||||
* @return whether the message was encrypted when transfered or not
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_secured(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Linphone message can carry external body as defined by rfc2017
|
||||
* @param message #LinphoneChatMessage
|
||||
* @return external body url or NULL if not present.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Linphone message can carry external body as defined by rfc2017
|
||||
*
|
||||
* @param message a LinphoneChatMessage
|
||||
* @param url ex: access-type=URL; URL="http://www.foo.com/file"
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
|
||||
|
||||
/**
|
||||
* Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer)
|
||||
*
|
||||
* @param message #LinphoneChatMessage
|
||||
* @return a pointer to the LinphoneContent structure or NULL if not present.
|
||||
*/
|
||||
LINPHONE_PUBLIC const LinphoneContent* linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Get the content type of a chat message.
|
||||
* @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 *message);
|
||||
|
||||
/**
|
||||
* Set the content type of a chat message.
|
||||
* This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml.
|
||||
* @param[in] message LinphoneChatMessage object
|
||||
* @param[in] content_type The new content type of the chat message
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_content_type(LinphoneChatMessage *message, const char *content_type);
|
||||
|
||||
/**
|
||||
* Return whether or not a chat message is a file tranfer.
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Get if a chat message is to be stored.
|
||||
* @param[in] message LinphoneChatMessage object
|
||||
* @return Whether or not the message is to be stored
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *message);
|
||||
|
||||
/**
|
||||
* Set if a chat message is to be stored.
|
||||
* This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml.
|
||||
* @param[in] message LinphoneChatMessage object
|
||||
* @param[in] to_be_stored Whether or not the chat message is to be stored
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_to_be_stored(LinphoneChatMessage *message, bool_t to_be_stored);
|
||||
|
||||
/**
|
||||
* Start the download of the file from remote server
|
||||
*
|
||||
* @param message #LinphoneChatMessage
|
||||
* @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when file is downloaded or could not be downloaded
|
||||
* @param ud user data
|
||||
* @deprecated Use linphone_chat_message_download_file() instead.
|
||||
* @donotwrap
|
||||
*/
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb, void* ud);
|
||||
|
||||
/**
|
||||
* Start the download of the file referenced in a LinphoneChatMessage from remote server.
|
||||
* @param[in] message LinphoneChatMessage object.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneStatus linphone_chat_message_download_file(LinphoneChatMessage *message);
|
||||
|
||||
/**
|
||||
* Cancel an ongoing file transfer attached to this message.(upload or download)
|
||||
* @param msg #LinphoneChatMessage
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Resend a chat message if it is in the 'not delivered' state for whatever reason.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @donotwrap
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_resend(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Linphone message has an app-specific field that can store a text. The application might want
|
||||
* to use it for keeping data over restarts, like thumbnail image path.
|
||||
* @param message #LinphoneChatMessage
|
||||
* @return the application-specific data or NULL if none has been stored.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Linphone message has an app-specific field that can store a text. The application might want
|
||||
* to use it for keeping data over restarts, like thumbnail image path.
|
||||
*
|
||||
* Invoking this function will attempt to update the message storage to reflect the changeif it is
|
||||
* enabled.
|
||||
*
|
||||
* @param message #LinphoneChatMessage
|
||||
* @param data the data to store into the message
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data);
|
||||
|
||||
/**
|
||||
* Get text part of this message
|
||||
* @return text or NULL if no text.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_text(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Get the time the message was sent.
|
||||
*/
|
||||
LINPHONE_PUBLIC time_t linphone_chat_message_get_time(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Returns the chatroom this message belongs to.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneChatRoom* linphone_chat_message_get_chat_room(LinphoneChatMessage *msg);
|
||||
|
||||
LINPHONE_PUBLIC LinphoneChatRoom * linphone_core_create_client_group_chat_room(LinphoneCore *lc, const bctbx_list_t *addresses);
|
||||
|
||||
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_peer_address(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Returns the origin address of a message if it was a outgoing message, or the destination address if it was an incoming message.
|
||||
*@param message #LinphoneChatMessage obj
|
||||
*@return #LinphoneAddress
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Add custom headers to the message.
|
||||
* @param message the message
|
||||
* @param header_name name of the header
|
||||
* @param header_value header value
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_add_custom_header(LinphoneChatMessage* message, const char *header_name, const char *header_value);
|
||||
|
||||
/**
|
||||
* Retrieve a custom header value given its name.
|
||||
* @param message the message
|
||||
* @param header_name header name searched
|
||||
**/
|
||||
LINPHONE_PUBLIC const char * linphone_chat_message_get_custom_header(LinphoneChatMessage* message, const char *header_name);
|
||||
|
||||
/**
|
||||
* Removes a custom header from the message.
|
||||
* @param msg the message
|
||||
* @param header_name name of the header to remove
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_remove_custom_header(LinphoneChatMessage *msg, const char *header_name);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the message has been read, otherwise returns FALSE.
|
||||
* @param message the message
|
||||
**/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_read(LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the message has been sent, returns FALSE if the message has been received.
|
||||
* @param message the message
|
||||
**/
|
||||
LINPHONE_PUBLIC bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage* message);
|
||||
|
||||
/**
|
||||
* Returns the id used to identify this message in the storage database
|
||||
* @param message the message
|
||||
* @return the id
|
||||
*/
|
||||
LINPHONE_PUBLIC unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage* message);
|
||||
|
||||
LINPHONE_PUBLIC LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg);
|
||||
|
||||
/**
|
||||
* Get full details about delivery error of a chat message.
|
||||
* @param msg a LinphoneChatMessage
|
||||
* @return a LinphoneErrorInfo describing the details.
|
||||
**/
|
||||
LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Set the path to the file to read from or write to during the file transfer.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @param[in] filepath The path to the file to use for the file transfer.
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath);
|
||||
|
||||
/**
|
||||
* Get the path to the file to read from or write to during the file transfer.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @return The path to the file to use for the file transfer.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char * linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Fulfill a chat message char by char. Message linked to a Real Time Text Call send char in realtime following RFC 4103/T.140
|
||||
* To commit a message, use #linphone_chat_room_send_message
|
||||
* @param[in] msg LinphoneChatMessage
|
||||
* @param[in] character T.140 char
|
||||
* @returns 0 if succeed.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneStatus linphone_chat_message_put_char(LinphoneChatMessage *msg,uint32_t character);
|
||||
|
||||
/**
|
||||
* Get the message identifier.
|
||||
* It is used to identify a message so that it can be notified as delivered and/or displayed.
|
||||
* @param[in] cm LinphoneChatMessage object
|
||||
* @return The message identifier.
|
||||
*/
|
||||
LINPHONE_PUBLIC const char* linphone_chat_message_get_message_id(const LinphoneChatMessage *cm);
|
||||
|
||||
/**
|
||||
* Get the LinphoneChatMessageCbs object associated with the LinphoneChatMessage.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @return The LinphoneChatMessageCbs object associated with the LinphoneChatMessage.
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneChatMessageCbs * linphone_chat_message_get_callbacks(const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -113,18 +113,18 @@ LinphoneChatMessage *linphone_chat_room_create_message_2 (
|
|||
) {
|
||||
LinphoneChatMessage *msg = linphone_chat_room_create_message(cr, message);
|
||||
LinphoneCore *lc = linphone_chat_room_get_core(cr);
|
||||
msg->external_body_url = external_body_url ? ms_strdup(external_body_url) : NULL;
|
||||
msg->time = time;
|
||||
msg->is_secured = FALSE;
|
||||
linphone_chat_message_set_external_body_url(msg, external_body_url ? ms_strdup(external_body_url) : NULL);
|
||||
linphone_chat_message_set_time(msg, time);
|
||||
linphone_chat_message_set_is_secured(msg, FALSE);
|
||||
linphone_chat_message_set_state(msg, state);
|
||||
if (is_incoming) {
|
||||
msg->dir = LinphoneChatMessageIncoming;
|
||||
linphone_chat_message_set_from(msg, linphone_chat_room_get_peer_address(cr));
|
||||
msg->to = linphone_address_new(linphone_core_get_identity(lc)); /*direct assignment*/
|
||||
linphone_chat_message_set_incoming(msg);
|
||||
linphone_chat_message_set_from_address(msg, linphone_chat_room_get_peer_address(cr));
|
||||
linphone_chat_message_set_to_address(msg, linphone_address_new(linphone_core_get_identity(lc)));
|
||||
} else {
|
||||
msg->dir = LinphoneChatMessageOutgoing;
|
||||
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
|
||||
msg->from = linphone_address_new(linphone_core_get_identity(lc)); /*direct assignment*/
|
||||
linphone_chat_message_set_outgoing(msg);
|
||||
linphone_chat_message_set_to_address(msg, linphone_chat_room_get_peer_address(cr));
|
||||
linphone_chat_message_set_from_address(msg, linphone_address_new(linphone_core_get_identity(lc)));
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
|
@ -135,8 +135,8 @@ void linphone_chat_room_send_message2 (
|
|||
LinphoneChatMessageStateChangedCb status_cb,
|
||||
void *ud
|
||||
) {
|
||||
msg->message_state_changed_cb = status_cb;
|
||||
msg->message_state_changed_user_data = ud;
|
||||
linphone_chat_message_set_message_state_changed_cb(msg, status_cb);
|
||||
linphone_chat_message_set_message_state_changed_cb_user_data(msg, ud);
|
||||
GET_CPP_PTR(cr)->sendMessage(msg);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "linphone/utils/utils.h"
|
||||
|
||||
#include "linphone/api/c-chat-message.h"
|
||||
#include "c-wrapper/c-tools.h"
|
||||
#include "chat-room-p.h"
|
||||
#include "content/content-type.h"
|
||||
|
|
@ -44,7 +45,7 @@ ChatRoomPrivate::~ChatRoomPrivate () {
|
|||
for (auto &message : transientMessages)
|
||||
linphone_chat_message_release(message);
|
||||
if (pendingMessage)
|
||||
linphone_chat_message_destroy(pendingMessage);
|
||||
linphone_chat_message_unref(pendingMessage);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -140,7 +141,7 @@ void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) {
|
|||
}
|
||||
|
||||
if (retval <= 0) {
|
||||
sal_message_send(op, identity, peerAddress.asString().c_str(), msg->content_type, msg->message, nullptr);
|
||||
sal_message_send(op, identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr);
|
||||
}
|
||||
|
||||
linphone_chat_message_unref(msg);
|
||||
|
|
@ -226,7 +227,7 @@ void ChatRoomPrivate::sendIsComposingNotification () {
|
|||
}
|
||||
|
||||
if (retval <= 0) {
|
||||
sal_message_send(op, identity, peerAddress.asString().c_str(), msg->content_type, msg->message, nullptr);
|
||||
sal_message_send(op, identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr);
|
||||
}
|
||||
|
||||
linphone_chat_message_unref(msg);
|
||||
|
|
@ -273,25 +274,25 @@ int ChatRoomPrivate::createChatMessageFromDb (int argc, char **argv, char **colN
|
|||
|
||||
LinphoneAddress *peer = linphone_address_new(peerAddress.asString().c_str());
|
||||
if (atoi(argv[3]) == LinphoneChatMessageIncoming) {
|
||||
newMessage->dir = LinphoneChatMessageIncoming;
|
||||
linphone_chat_message_set_from(newMessage, peer);
|
||||
newMessage->to = nullptr; /* Will be filled at the end */
|
||||
linphone_chat_message_set_incoming(newMessage);
|
||||
linphone_chat_message_set_from_address(newMessage, peer);
|
||||
linphone_chat_message_set_to_address(newMessage, NULL);
|
||||
} else {
|
||||
newMessage->dir = LinphoneChatMessageOutgoing;
|
||||
newMessage->from = nullptr; /* Will be filled at the end */
|
||||
linphone_chat_message_set_to(newMessage, peer);
|
||||
linphone_chat_message_set_outgoing(newMessage);
|
||||
linphone_chat_message_set_from_address(newMessage, NULL);
|
||||
linphone_chat_message_set_to_address(newMessage, peer);
|
||||
}
|
||||
linphone_address_unref(peer);
|
||||
|
||||
newMessage->time = (time_t)atol(argv[9]);
|
||||
newMessage->is_read = !!atoi(argv[6]);
|
||||
newMessage->state = static_cast<LinphoneChatMessageState>(atoi(argv[7]));
|
||||
newMessage->storage_id = storageId;
|
||||
newMessage->external_body_url = ms_strdup(argv[8]);
|
||||
newMessage->appdata = ms_strdup(argv[10]);
|
||||
newMessage->message_id = ms_strdup(argv[12]);
|
||||
linphone_chat_message_set_time(newMessage, (time_t)atol(argv[9]));
|
||||
linphone_chat_message_set_is_read(newMessage, !!atoi(argv[6]));
|
||||
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]);
|
||||
newMessage->is_secured = (bool_t)atoi(argv[14]);
|
||||
linphone_chat_message_set_is_secured(newMessage, (bool_t)atoi(argv[14]));
|
||||
|
||||
if (argv[11]) {
|
||||
int id = atoi(argv[11]);
|
||||
|
|
@ -300,13 +301,13 @@ int ChatRoomPrivate::createChatMessageFromDb (int argc, char **argv, char **colN
|
|||
}
|
||||
|
||||
/* Fix content type for old messages that were stored without it */
|
||||
if (!newMessage->content_type) {
|
||||
if (newMessage->file_transfer_information) {
|
||||
newMessage->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml");
|
||||
} else if (newMessage->external_body_url) {
|
||||
newMessage->content_type = ms_strdup("message/external-body");
|
||||
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"));
|
||||
} else if (linphone_chat_message_get_external_body_url(newMessage)) {
|
||||
linphone_chat_message_set_content_type(newMessage, ms_strdup("message/external-body"));
|
||||
} else {
|
||||
newMessage->content_type = ms_strdup("text/plain");
|
||||
linphone_chat_message_set_content_type(newMessage, ms_strdup("text/plain"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -375,12 +376,12 @@ list<LinphoneChatMessage *> ChatRoomPrivate::findMessages (const string &message
|
|||
* TODO: Should be handled directly by the LinphoneChatMessage object!
|
||||
*/
|
||||
void ChatRoomPrivate::storeOrUpdateMessage (LinphoneChatMessage *msg) {
|
||||
if (msg->storage_id != 0) {
|
||||
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 */
|
||||
msg->storage_id = linphone_chat_message_store(msg);
|
||||
linphone_chat_message_store(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -404,19 +405,19 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
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(msg, peer);
|
||||
linphone_chat_message_set_from_address(msg, peer);
|
||||
linphone_address_unref(peer);
|
||||
|
||||
LinphoneAddress *to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(core));
|
||||
msg->to = to;
|
||||
msg->time = salMsg->time;
|
||||
msg->state = LinphoneChatMessageStateDelivered;
|
||||
msg->dir = LinphoneChatMessageIncoming;
|
||||
msg->message_id = ms_strdup(sal_op_get_call_id(op));
|
||||
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(sal_op_get_call_id(op)));
|
||||
|
||||
const SalCustomHeader *ch = sal_op_get_recv_custom_header(op);
|
||||
if (ch)
|
||||
msg->custom_headers = sal_custom_header_clone(ch);
|
||||
linphone_chat_message_set_sal_custom_headers(msg, sal_custom_header_clone(ch));
|
||||
if (salMsg->url)
|
||||
linphone_chat_message_set_external_body_url(msg, salMsg->url);
|
||||
|
||||
|
|
@ -428,7 +429,7 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
if (cbProcessIncomingMessage) {
|
||||
retval = cbProcessIncomingMessage(imee, GET_BACK_PTR(q), msg);
|
||||
if (retval == 0) {
|
||||
msg->is_secured = TRUE;
|
||||
linphone_chat_message_set_is_secured(msg, TRUE);
|
||||
} else if (retval > 0) {
|
||||
/* Unable to decrypt message */
|
||||
notifyUndecryptableMessageReceived(msg);
|
||||
|
|
@ -441,9 +442,9 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
}
|
||||
}
|
||||
|
||||
if ((retval <= 0) && (linphone_core_is_content_type_supported(core, msg->content_type) == FALSE)) {
|
||||
if ((retval <= 0) && (linphone_core_is_content_type_supported(core, linphone_chat_message_get_content_type(msg)) == FALSE)) {
|
||||
retval = 415;
|
||||
lError() << "Unsupported MESSAGE (content-type " << msg->content_type << " not recognized)";
|
||||
lError() << "Unsupported MESSAGE (content-type " << linphone_chat_message_get_content_type(msg) << " not recognized)";
|
||||
}
|
||||
|
||||
if (retval > 0) {
|
||||
|
|
@ -452,24 +453,24 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (ContentType::isFileTransfer(msg->content_type)) {
|
||||
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(msg->content_type)) {
|
||||
isComposingReceived(msg->message);
|
||||
} 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);
|
||||
increaseMsgCount = FALSE;
|
||||
if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) {
|
||||
goto end;
|
||||
}
|
||||
} else if (ContentType::isImdn(msg->content_type)) {
|
||||
imdnReceived(msg->message);
|
||||
} 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);
|
||||
increaseMsgCount = FALSE;
|
||||
if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) {
|
||||
goto end;
|
||||
}
|
||||
} else if (ContentType::isText(msg->content_type)) {
|
||||
} else if (ContentType::isText(linphone_chat_message_get_content_type(msg))) {
|
||||
linphone_chat_message_set_to_be_stored(msg, TRUE);
|
||||
}
|
||||
|
||||
|
|
@ -487,7 +488,7 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa
|
|||
chatMessageReceived(msg);
|
||||
|
||||
if (linphone_chat_message_get_to_be_stored(msg)) {
|
||||
msg->storage_id = linphone_chat_message_store(msg);
|
||||
linphone_chat_message_store(msg);
|
||||
}
|
||||
|
||||
pendingMessage = nullptr;
|
||||
|
|
@ -502,7 +503,7 @@ end:
|
|||
|
||||
void ChatRoomPrivate::chatMessageReceived (LinphoneChatMessage *msg) {
|
||||
L_Q(ChatRoom);
|
||||
if (!ContentType::isImdn(msg->content_type) && !ContentType::isImIsComposing(msg->content_type)) {
|
||||
if (!ContentType::isImdn(linphone_chat_message_get_content_type(msg)) && !ContentType::isImIsComposing(linphone_chat_message_get_content_type(msg))) {
|
||||
notifyChatMessageReceived(msg);
|
||||
remoteIsComposing = false;
|
||||
linphone_core_notify_is_composing_received(core, GET_BACK_PTR(q));
|
||||
|
|
@ -524,9 +525,9 @@ void ChatRoomPrivate::isComposingReceived (const string &text) {
|
|||
void ChatRoomPrivate::notifyChatMessageReceived (LinphoneChatMessage *msg) {
|
||||
L_Q(ChatRoom);
|
||||
LinphoneChatRoom *cr = GET_BACK_PTR(q);
|
||||
if (msg->message) {
|
||||
if (linphone_chat_message_get_text(msg)) {
|
||||
/* Legacy API */
|
||||
linphone_core_notify_text_message_received(core, cr, msg->from, msg->message);
|
||||
linphone_core_notify_text_message_received(core, cr, linphone_chat_message_get_from_address(msg), linphone_chat_message_get_text(msg));
|
||||
}
|
||||
LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(cr);
|
||||
LinphoneChatRoomCbsMessageReceivedCb cb = linphone_chat_room_cbs_get_message_received(cbs);
|
||||
|
|
@ -591,36 +592,33 @@ void ChatRoom::compose () {
|
|||
|
||||
LinphoneChatMessage *ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) {
|
||||
L_D(ChatRoom);
|
||||
LinphoneChatMessage *cm = belle_sip_object_new(LinphoneChatMessage);
|
||||
cm->callbacks = linphone_chat_message_cbs_new();
|
||||
cm->chat_room = GET_BACK_PTR(this);
|
||||
cm->message = nullptr;
|
||||
cm->file_transfer_information = linphone_content_copy(initialContent);
|
||||
cm->dir = LinphoneChatMessageOutgoing;
|
||||
LinphoneChatMessage *msg = createMessage("");
|
||||
linphone_chat_message_set_chat_room(msg, GET_BACK_PTR(this));
|
||||
linphone_chat_message_set_text(msg, NULL);
|
||||
linphone_chat_message_set_file_transfer_information(msg, linphone_content_copy(initialContent));
|
||||
linphone_chat_message_set_outgoing(msg);
|
||||
LinphoneAddress *peer = linphone_address_new(d->peerAddress.asString().c_str());
|
||||
linphone_chat_message_set_to(cm, peer);
|
||||
linphone_chat_message_set_to_address(msg, peer);
|
||||
linphone_address_unref(peer);
|
||||
cm->from = linphone_address_new(linphone_core_get_identity(d->core));
|
||||
linphone_chat_message_set_from_address(msg, linphone_address_new(linphone_core_get_identity(d->core)));
|
||||
/* This will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */
|
||||
cm->content_type = nullptr;
|
||||
linphone_chat_message_set_content_type(msg, NULL);
|
||||
/* This will store the http request during file upload to the server */
|
||||
cm->http_request = nullptr;
|
||||
cm->time = ms_time(0);
|
||||
return cm;
|
||||
linphone_chat_message_set_http_request(msg, NULL);
|
||||
linphone_chat_message_set_time(msg, ms_time(0));
|
||||
return msg;
|
||||
}
|
||||
|
||||
LinphoneChatMessage *ChatRoom::createMessage (const string &msg) {
|
||||
LinphoneChatMessage *cm = belle_sip_object_new(LinphoneChatMessage);
|
||||
cm->state = LinphoneChatMessageStateIdle;
|
||||
cm->callbacks = linphone_chat_message_cbs_new();
|
||||
cm->chat_room = GET_BACK_PTR(this);
|
||||
cm->message = msg.empty() ? nullptr : ms_strdup(msg.c_str());
|
||||
cm->content_type = ms_strdup("text/plain");
|
||||
cm->file_transfer_information = nullptr; /* this property is used only when transfering file */
|
||||
cm->http_request = nullptr;
|
||||
cm->time = ms_time(0);
|
||||
cm->is_secured = FALSE;
|
||||
return cm;
|
||||
LinphoneChatMessage *ChatRoom::createMessage (const string &message) {
|
||||
LinphoneChatMessage *msg = createMessage("");
|
||||
linphone_chat_message_set_chat_room(msg, GET_BACK_PTR(this));
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateIdle);
|
||||
linphone_chat_message_set_text(msg, message.empty() ? nullptr : ms_strdup(message.c_str()));
|
||||
linphone_chat_message_set_content_type(msg, ms_strdup("text/plain"));
|
||||
linphone_chat_message_set_file_transfer_information(msg, nullptr);
|
||||
linphone_chat_message_set_http_request(msg, NULL);
|
||||
linphone_chat_message_set_time(msg, ms_time(0));
|
||||
return msg;
|
||||
}
|
||||
|
||||
void ChatRoom::deleteHistory () {
|
||||
|
|
@ -636,7 +634,7 @@ void ChatRoom::deleteHistory () {
|
|||
void ChatRoom::deleteMessage (LinphoneChatMessage *msg) {
|
||||
L_D(ChatRoom);
|
||||
if (!d->core->db) return;
|
||||
char *buf = sqlite3_mprintf("DELETE FROM history WHERE id = %u;", msg->storage_id);
|
||||
char *buf = sqlite3_mprintf("DELETE FROM history WHERE id = %u;", linphone_chat_message_get_storage_id(msg));
|
||||
d->sqlRequest(d->core->db, buf);
|
||||
sqlite3_free(buf);
|
||||
|
||||
|
|
@ -663,7 +661,7 @@ LinphoneChatMessage * ChatRoom::findMessageWithDirection (const string &messageI
|
|||
LinphoneChatMessage *ret = nullptr;
|
||||
list<LinphoneChatMessage *> l = d->findMessages(messageId);
|
||||
for (auto &message : l) {
|
||||
if (message->dir == direction) {
|
||||
if (linphone_chat_message_get_direction(message) == direction) {
|
||||
linphone_chat_message_ref(message);
|
||||
ret = message;
|
||||
break;
|
||||
|
|
@ -727,11 +725,10 @@ list<LinphoneChatMessage *> ChatRoom::getHistoryRange (int startm, int endm) {
|
|||
/* 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 (message->dir == LinphoneChatMessageOutgoing) {
|
||||
if (message->from != NULL) linphone_address_unref(message->from);
|
||||
message->from = linphone_address_ref(localAddr);
|
||||
if (linphone_chat_message_is_outgoing(message)) {
|
||||
linphone_chat_message_set_from_address(message, linphone_address_ref(localAddr));
|
||||
} else {
|
||||
message->to = linphone_address_ref(localAddr);
|
||||
linphone_chat_message_set_to_address(message, linphone_address_ref(localAddr));
|
||||
}
|
||||
}
|
||||
linphone_address_unref(localAddr);
|
||||
|
|
@ -784,10 +781,10 @@ void ChatRoom::markAsRead () {
|
|||
void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
||||
L_D(ChatRoom);
|
||||
|
||||
msg->dir = LinphoneChatMessageOutgoing;
|
||||
linphone_chat_message_set_outgoing(msg);
|
||||
|
||||
/* Check if we shall upload a file to a server */
|
||||
if (msg->file_transfer_information && !msg->content_type) {
|
||||
if (linphone_chat_message_get_file_transfer_information(msg) && !linphone_chat_message_get_content_type(msg)) {
|
||||
/* 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) {
|
||||
/* Add to transient list only if message is going out */
|
||||
|
|
@ -799,23 +796,23 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
SalOp *op = msg->op;
|
||||
SalOp *op = linphone_chat_message_get_sal_op(msg);
|
||||
LinphoneCall *call = nullptr;
|
||||
string identity;
|
||||
char *clearTextMessage = nullptr;
|
||||
char *clearTextContentType = nullptr;
|
||||
LinphoneAddress *peer = linphone_address_new(d->peerAddress.asString().c_str());
|
||||
|
||||
if (msg->message) {
|
||||
clearTextMessage = ms_strdup(msg->message);
|
||||
if (linphone_chat_message_get_text(msg)) {
|
||||
clearTextMessage = ms_strdup(linphone_chat_message_get_text(msg));
|
||||
}
|
||||
if (msg->content_type) {
|
||||
clearTextContentType = ms_strdup(msg->content_type);
|
||||
if (linphone_chat_message_get_content_type(msg)) {
|
||||
clearTextContentType = ms_strdup(linphone_chat_message_get_content_type(msg));
|
||||
}
|
||||
|
||||
/* Add to transient list */
|
||||
d->addTransientMessage(msg);
|
||||
msg->time = ms_time(0);
|
||||
linphone_chat_message_set_time(msg, 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) {
|
||||
|
|
@ -837,11 +834,7 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
|||
identity = linphone_core_get_primary_contact(d->core);
|
||||
}
|
||||
}
|
||||
if (msg->from) {
|
||||
/* BUG: the file transfer message constructor sets the from, but doesn't do it as well as here */
|
||||
linphone_address_unref(msg->from);
|
||||
}
|
||||
msg->from = linphone_address_new(identity.c_str());
|
||||
linphone_chat_message_set_from_address(msg, linphone_address_new(identity.c_str()));
|
||||
|
||||
int retval = -1;
|
||||
LinphoneImEncryptionEngine *imee = d->core->im_encryption_engine;
|
||||
|
|
@ -851,16 +844,16 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
|||
if (cbProcessOutgoingMessage) {
|
||||
retval = cbProcessOutgoingMessage(imee, GET_BACK_PTR(this), msg);
|
||||
if (retval == 0) {
|
||||
msg->is_secured = TRUE;
|
||||
linphone_chat_message_set_is_secured(msg, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!op) {
|
||||
/* Sending out of call */
|
||||
msg->op = op = sal_op_new(d->core->sal);
|
||||
linphone_chat_message_set_sal_op(msg, op = sal_op_new(d->core->sal));
|
||||
linphone_configure_op(
|
||||
d->core, op, peer, msg->custom_headers,
|
||||
d->core, op, peer, linphone_chat_message_get_sal_custom_headers(msg),
|
||||
!!lp_config_get_int(d->core->config, "sip", "chat_msg_with_contact", 0)
|
||||
);
|
||||
sal_op_set_user_pointer(op, msg); /* If out of call, directly store msg */
|
||||
|
|
@ -875,29 +868,27 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (msg->external_body_url) {
|
||||
char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", msg->external_body_url);
|
||||
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));
|
||||
sal_message_send(op, identity.c_str(), d->peerAddress.asString().c_str(), content_type, nullptr, nullptr);
|
||||
ms_free(content_type);
|
||||
} else {
|
||||
if (msg->content_type) {
|
||||
sal_message_send(op, identity.c_str(), d->peerAddress.asString().c_str(), msg->content_type, msg->message, d->peerAddress.asStringUriOnly().c_str());
|
||||
if (linphone_chat_message_get_content_type(msg)) {
|
||||
sal_message_send(op, 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());
|
||||
} else {
|
||||
sal_text_send(op, identity.c_str(), d->peerAddress.asString().c_str(), msg->message);
|
||||
sal_text_send(op, identity.c_str(), d->peerAddress.asString().c_str(), linphone_chat_message_get_text(msg));
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->message && clearTextMessage && strcmp(msg->message, clearTextMessage) != 0) {
|
||||
if (linphone_chat_message_get_text(msg) && clearTextMessage && strcmp(linphone_chat_message_get_text(msg), clearTextMessage) != 0) {
|
||||
/* We replace the encrypted message by the original one so it can be correctly stored and displayed by the application */
|
||||
ms_free(msg->message);
|
||||
msg->message = ms_strdup(clearTextMessage);
|
||||
linphone_chat_message_set_text(msg, ms_strdup(clearTextMessage));
|
||||
}
|
||||
if (msg->content_type && clearTextContentType && (strcmp(msg->content_type, clearTextContentType) != 0)) {
|
||||
if (linphone_chat_message_get_content_type(msg) && clearTextContentType && (strcmp(linphone_chat_message_get_content_type(msg), clearTextContentType) != 0)) {
|
||||
/* We replace the encrypted content type by the original one */
|
||||
ms_free(msg->content_type);
|
||||
msg->content_type = ms_strdup(clearTextContentType);
|
||||
linphone_chat_message_set_content_type(msg, ms_strdup(clearTextContentType));
|
||||
}
|
||||
msg->message_id = ms_strdup(sal_op_get_call_id(op)); /* must be known at that time */
|
||||
linphone_chat_message_set_message_id(msg, ms_strdup(sal_op_get_call_id(op))); /* must be known at that time */
|
||||
d->storeOrUpdateMessage(msg);
|
||||
|
||||
if (d->isComposing)
|
||||
|
|
@ -916,14 +907,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(msg->chat_room, msg);
|
||||
linphone_chat_room_remove_transient_message(linphone_chat_message_get_chat_room(msg), msg);
|
||||
linphone_chat_message_unref(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If operation failed, we should not change message state */
|
||||
if (msg->dir == LinphoneChatMessageOutgoing) {
|
||||
if (linphone_chat_message_is_outgoing(msg)) {
|
||||
linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ RealTimeTextChatRoomPrivate::~RealTimeTextChatRoomPrivate () {
|
|||
bctbx_free(rttChars);
|
||||
}
|
||||
if (pendingMessage)
|
||||
linphone_chat_message_destroy(pendingMessage);
|
||||
linphone_chat_message_unref(pendingMessage);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -70,18 +70,16 @@ 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 " << pendingMessage->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(pendingMessage, peer);
|
||||
linphone_chat_message_set_from_address(pendingMessage, peer);
|
||||
linphone_address_unref(peer);
|
||||
if (pendingMessage->to)
|
||||
linphone_address_unref(pendingMessage->to);
|
||||
pendingMessage->to = linphone_call_get_dest_proxy(call)
|
||||
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));
|
||||
pendingMessage->time = ms_time(0);
|
||||
pendingMessage->state = LinphoneChatMessageStateDelivered;
|
||||
pendingMessage->dir = LinphoneChatMessageIncoming;
|
||||
: 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);
|
||||
|
||||
if (lp_config_get_int(core->config, "misc", "store_rtt_messages", 1) == 1)
|
||||
storeOrUpdateMessage(pendingMessage);
|
||||
|
|
@ -97,8 +95,9 @@ void RealTimeTextChatRoomPrivate::realtimeTextReceived (uint32_t character, Linp
|
|||
receivedRttCharacters.clear();
|
||||
} else {
|
||||
char *value = Utils::utf8ToChar(character);
|
||||
pendingMessage->message = ms_strcat_printf(pendingMessage->message, value);
|
||||
lDebug() << "Received RTT character: " << value << " (" << character << "), pending text is " << pendingMessage->message;
|
||||
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);
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue