Commit 7f68c561 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩
Browse files

Fixed FileContent side by side with FileTransferContent during upload + added chatSending callback

parent c5196e3b
......@@ -345,6 +345,7 @@ void _linphone_chat_room_notify_ephemeral_message_timer_started(LinphoneChatRoom
void _linphone_chat_room_notify_ephemeral_message_deleted(LinphoneChatRoom *cr, const LinphoneEventLog *event_log);
void _linphone_chat_room_notify_undecryptable_message_received(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
void _linphone_chat_room_notify_chat_message_received(LinphoneChatRoom *cr, const LinphoneEventLog *event_log);
void _linphone_chat_room_notify_chat_message_sending(LinphoneChatRoom *cr, const LinphoneEventLog *event_log);
void _linphone_chat_room_notify_chat_message_sent(LinphoneChatRoom *cr, const LinphoneEventLog *event_log);
void _linphone_chat_room_notify_conference_address_generation(LinphoneChatRoom *cr);
void _linphone_chat_room_notify_participant_device_fetch_requested(LinphoneChatRoom *cr, const LinphoneAddress *participantAddr);
......
......@@ -238,6 +238,13 @@ typedef void (*LinphoneChatRoomCbsChatMessageReceivedCb) (LinphoneChatRoom *chat
* @param chat_room #LinphoneChatRoom object @notnil
* @param event_log #LinphoneEventLog The event to be notified @notnil
*/
typedef void (*LinphoneChatRoomCbsChatMessageSendingCb) (LinphoneChatRoom *chat_room, const LinphoneEventLog *event_log);
/**
* Callback used to notify a chat room that a chat message has been sent.
* @param chat_room #LinphoneChatRoom object @notnil
* @param event_log #LinphoneEventLog The event to be notified @notnil
*/
typedef void (*LinphoneChatRoomCbsChatMessageSentCb) (LinphoneChatRoom *chat_room, const LinphoneEventLog *event_log);
/**
......
......@@ -119,6 +119,20 @@ LINPHONE_PUBLIC LinphoneChatRoomCbsChatMessageReceivedCb linphone_chat_room_cbs_
*/
LINPHONE_PUBLIC void linphone_chat_room_cbs_set_chat_message_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsChatMessageReceivedCb cb);
/**
* Get the chat message sending callback.
* @param cbs #LinphoneChatRoomCbs object. @notnil
* @return The current chat message being sent callback.
*/
LINPHONE_PUBLIC LinphoneChatRoomCbsChatMessageSendingCb linphone_chat_room_cbs_get_chat_message_sending (const LinphoneChatRoomCbs *cbs);
/**
* Set the chat message sending callback.
* @param cbs #LinphoneChatRoomCbs object. @notnil
* @param cb The chat message being sent callback to be used.
*/
LINPHONE_PUBLIC void linphone_chat_room_cbs_set_chat_message_sending (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsChatMessageSendingCb cb);
/**
* Get the chat message sent callback.
* @param cbs #LinphoneChatRoomCbs object. @notnil
......
......@@ -40,6 +40,7 @@ struct _LinphoneChatRoomCbs {
LinphoneChatRoomCbsConferenceLeftCb conferenceLeftCb;
LinphoneChatRoomCbsUndecryptableMessageReceivedCb undecryptableMessageReceivedCb;
LinphoneChatRoomCbsChatMessageReceivedCb chatMessageReceivedCb;
LinphoneChatRoomCbsChatMessageSendingCb chatMessageSendingCb;
LinphoneChatRoomCbsChatMessageSentCb chatMessageSentCb;
LinphoneChatRoomCbsConferenceAddressGenerationCb conferenceAddressGenerationCb;
LinphoneChatRoomCbsParticipantRegistrationSubscriptionRequestedCb participantRegistrationSubscriptionRequestedCb;
......@@ -118,6 +119,14 @@ void linphone_chat_room_cbs_set_chat_message_received (LinphoneChatRoomCbs *cbs,
cbs->chatMessageReceivedCb = cb;
}
LinphoneChatRoomCbsChatMessageSendingCb linphone_chat_room_cbs_get_chat_message_sending (const LinphoneChatRoomCbs *cbs) {
return cbs->chatMessageSendingCb;
}
void linphone_chat_room_cbs_set_chat_message_sending (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsChatMessageSendingCb cb) {
cbs->chatMessageSendingCb = cb;
}
LinphoneChatRoomCbsChatMessageSentCb linphone_chat_room_cbs_get_chat_message_sent (const LinphoneChatRoomCbs *cbs) {
return cbs->chatMessageSentCb;
}
......
......@@ -599,6 +599,11 @@ void _linphone_chat_room_notify_chat_message_received(LinphoneChatRoom *cr, cons
NOTIFY_IF_EXIST(ChatMessageReceived, chat_message_received, cr, event_log)
}
void _linphone_chat_room_notify_chat_message_sending(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) {
_linphone_chat_room_notify_new_event(cr, event_log);
NOTIFY_IF_EXIST(ChatMessageSending, chat_message_sending, cr, event_log)
}
void _linphone_chat_room_notify_chat_message_sent(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) {
_linphone_chat_room_notify_new_event(cr, event_log);
NOTIFY_IF_EXIST(ChatMessageSent, chat_message_sent, cr, event_log)
......
......@@ -57,6 +57,7 @@ public:
FileDownload = 1 << 6,
AutoFileDownload = 1 << 7,
Sent = 1 << 8,
Sending = 1 << 9
};
void setApplyModifiers (bool value) { applyModifiers = value; }
......
......@@ -866,6 +866,16 @@ void ChatMessagePrivate::send () {
if (toBeStored && currentSendStep == (ChatMessagePrivate::Step::Started | ChatMessagePrivate::Step::None)) {
storeInDb();
if (!isResend && getContentType() != ContentType::Imdn && getContentType() != ContentType::ImIsComposing) {
if ((currentSendStep & ChatMessagePrivate::Step::Sending) != ChatMessagePrivate::Step::Sending) {
LinphoneChatRoom *cr = L_GET_C_BACK_PTR(q->getChatRoom());
unique_ptr<MainDb> &mainDb = q->getCore()->getPrivate()->mainDb;
shared_ptr<EventLog> eventLog = mainDb->getEvent(mainDb, q->getStorageId());
_linphone_chat_room_notify_chat_message_sending(cr, L_GET_C_BACK_PTR(eventLog));
currentSendStep |= ChatMessagePrivate::Step::Sending;
}
}
}
if ((currentSendStep & ChatMessagePrivate::Step::FileUpload) == ChatMessagePrivate::Step::FileUpload) {
......@@ -878,6 +888,7 @@ void ChatMessagePrivate::send () {
currentSendStep = ChatMessagePrivate::Step::None;
return;
}
if (result == ChatMessageModifier::Result::Suspended) {
setState(ChatMessage::State::FileTransferInProgress);
return;
......
......@@ -231,79 +231,82 @@ static void _chat_message_process_response_from_post_file (void *data, const bel
}
belle_sip_body_handler_t *FileTransferChatMessageModifier::prepare_upload_body_handler(shared_ptr<ChatMessage> message) {
// start uploading the file
string first_part_header;
belle_sip_body_handler_t *first_part_bh;
bool isFileEncryptionEnabled = false;
EncryptionEngine *imee = message->getCore()->getEncryptionEngine();
if (imee)
isFileEncryptionEnabled = imee->isEncryptionEnabledForFileTransfer(message->getChatRoom());
FileTransferContent *fileTransferContent = new FileTransferContent();
fileTransferContent->setContentType(ContentType::FileTransfer);
fileTransferContent->setFileSize(currentFileContentToTransfer->getFileSize()); // Copy file size information
fileTransferContent->setFilePath(currentFileContentToTransfer->getFilePath()); // Copy file path information
message->getPrivate()->addContent(fileTransferContent);
currentFileTransferContent = fileTransferContent;
// shall we encrypt the file
if (isFileEncryptionEnabled && message->getChatRoom()) {
// 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
first_part_header = "form-data; name=\"File\"; filename=\"filename.txt\"";
imee->generateFileTransferKey(message->getChatRoom(), message, currentFileTransferContent);
} else {
first_part_header = "form-data; name=\"File\"; filename=\"" + currentFileContentToTransfer->getFileName() + "\"";
}
// start uploading the file
string first_part_header;
belle_sip_body_handler_t *first_part_bh;
// 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(currentFileContentToTransfer->getFileSize(),
_chat_message_file_transfer_on_progress, nullptr, nullptr,
_chat_message_on_send_body, _chat_message_on_send_end, this);
if (!currentFileContentToTransfer->getFilePath().empty()) {
belle_sip_user_body_handler_t *body_handler = (belle_sip_user_body_handler_t *)first_part_bh;
// No need to add again the callback for progression, otherwise it will be called twice
first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(currentFileContentToTransfer->getFilePath().c_str(), nullptr, this);
belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)first_part_bh, body_handler);
// Ensure the file size has been set to the correct value
currentFileTransferContent->setFileSize(belle_sip_file_body_handler_get_file_size((belle_sip_file_body_handler_t *)first_part_bh));
} else if (!currentFileContentToTransfer->isEmpty()) {
size_t buf_size = currentFileContentToTransfer->getSize();
uint8_t *buf = (uint8_t *)ms_malloc(buf_size);
memcpy(buf, currentFileContentToTransfer->getBody().data(), buf_size);
EncryptionEngine *imee = message->getCore()->getEncryptionEngine();
if (imee) {
size_t max_size = buf_size;
uint8_t *encrypted_buffer = (uint8_t *)ms_malloc0(max_size);
int retval = imee->uploadingFile(message, 0, buf, &max_size, encrypted_buffer, currentFileTransferContent);
if (retval == 0) {
if (max_size > buf_size) {
lError() << "IM encryption engine process upload file callback returned a size bigger than the size of the buffer, so it will be truncated !";
max_size = buf_size;
}
memcpy(buf, encrypted_buffer, buf_size);
// Call it once more to compute the authentication tag
imee->uploadingFile(message, 0, nullptr, 0, nullptr, currentFileTransferContent);
}
ms_free(encrypted_buffer);
}
bool isFileEncryptionEnabled = false;
EncryptionEngine *imee = message->getCore()->getEncryptionEngine();
if (imee)
isFileEncryptionEnabled = imee->isEncryptionEnabledForFileTransfer(message->getChatRoom());
FileTransferContent *fileTransferContent = new FileTransferContent();
fileTransferContent->setContentType(ContentType::FileTransfer);
fileTransferContent->setFileSize(currentFileContentToTransfer->getFileSize()); // Copy file size information
fileTransferContent->setFilePath(currentFileContentToTransfer->getFilePath()); // Copy file path information
message->getPrivate()->addContent(fileTransferContent);
currentFileTransferContent = fileTransferContent;
currentFileTransferContent->setFileContent(currentFileContentToTransfer);
message->getPrivate()->removeContent(currentFileContentToTransfer);
// shall we encrypt the file
if (isFileEncryptionEnabled && message->getChatRoom()) {
// 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
first_part_header = "form-data; name=\"File\"; filename=\"filename.txt\"";
first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer(
buf, buf_size, _chat_message_file_transfer_on_progress, this);
imee->generateFileTransferKey(message->getChatRoom(), message, currentFileTransferContent);
} else {
first_part_header = "form-data; name=\"File\"; filename=\"" + currentFileContentToTransfer->getFileName() + "\"";
}
// 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(currentFileContentToTransfer->getFileSize(),
_chat_message_file_transfer_on_progress, nullptr, nullptr,
_chat_message_on_send_body, _chat_message_on_send_end, this);
if (!currentFileContentToTransfer->getFilePath().empty()) {
belle_sip_user_body_handler_t *body_handler = (belle_sip_user_body_handler_t *)first_part_bh;
// No need to add again the callback for progression, otherwise it will be called twice
first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(currentFileContentToTransfer->getFilePath().c_str(), nullptr, this);
belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)first_part_bh, body_handler);
// Ensure the file size has been set to the correct value
currentFileTransferContent->setFileSize(belle_sip_file_body_handler_get_file_size((belle_sip_file_body_handler_t *)first_part_bh));
} else if (!currentFileContentToTransfer->isEmpty()) {
size_t buf_size = currentFileContentToTransfer->getSize();
uint8_t *buf = (uint8_t *)ms_malloc(buf_size);
memcpy(buf, currentFileContentToTransfer->getBody().data(), buf_size);
EncryptionEngine *imee = message->getCore()->getEncryptionEngine();
if (imee) {
size_t max_size = buf_size;
uint8_t *encrypted_buffer = (uint8_t *)ms_malloc0(max_size);
int retval = imee->uploadingFile(message, 0, buf, &max_size, encrypted_buffer, currentFileTransferContent);
if (retval == 0) {
if (max_size > buf_size) {
lError() << "IM encryption engine process upload file callback returned a size bigger than the size of the buffer, so it will be truncated !";
max_size = buf_size;
}
memcpy(buf, encrypted_buffer, buf_size);
// Call it once more to compute the authentication tag
imee->uploadingFile(message, 0, nullptr, 0, nullptr, currentFileTransferContent);
}
ms_free(encrypted_buffer);
}
first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer(
buf, buf_size, _chat_message_file_transfer_on_progress, this);
}
belle_sip_body_handler_add_header(first_part_bh,
belle_sip_header_create("Content-disposition", first_part_header.c_str()));
belle_sip_body_handler_add_header(first_part_bh,
(belle_sip_header_t *)belle_sip_header_content_type_create(
currentFileContentToTransfer->getContentType().getType().c_str(),
currentFileContentToTransfer->getContentType().getSubType().c_str()));
belle_sip_body_handler_add_header(first_part_bh,
belle_sip_header_create("Content-disposition", first_part_header.c_str()));
belle_sip_body_handler_add_header(first_part_bh,
(belle_sip_header_t *)belle_sip_header_content_type_create(
currentFileContentToTransfer->getContentType().getType().c_str(),
currentFileContentToTransfer->getContentType().getSubType().c_str()));
// insert it in a multipart body handler which will manage the boundaries of multipart msg
return (BELLE_SIP_BODY_HANDLER(belle_sip_multipart_body_handler_new(_chat_message_file_transfer_on_progress, this, first_part_bh, nullptr)));
// insert it in a multipart body handler which will manage the boundaries of multipart msg
return (BELLE_SIP_BODY_HANDLER(belle_sip_multipart_body_handler_new(_chat_message_file_transfer_on_progress, this, first_part_bh, nullptr)));
}
void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_http_response_event_t *event) {
......@@ -324,7 +327,7 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h
releaseHttpRequest();
fileUploadBeginBackgroundTask();
uploadFile(bh);
} else if (code == 200) { // file has been uploaded correctly, get server reply and send it
} 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
......@@ -407,9 +410,6 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h
} else { // no encryption key, transfer in plain, just copy the msg sent by server
currentFileTransferContent->setBodyFromUtf8(body);
}
currentFileTransferContent->setFileContent(currentFileContentToTransfer);
message->getPrivate()->removeContent(currentFileContentToTransfer);
currentFileTransferContent = nullptr;
message->getPrivate()->setState(ChatMessage::State::FileTransferDone);
......@@ -614,8 +614,8 @@ static void fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml (FileTran
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) {
/* we found a file info node, check if 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 */
cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */
if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */
cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */
while (cur) {
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) {
xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1);
......@@ -728,8 +728,8 @@ static void createFileTransferInformationsFromVndGsmaRcsFtHttpXml (FileTransferC
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) {
/* we found a file info node, check if 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 */
cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */
if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */
cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */
while (cur) {
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) {
xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment