Commit 50f4e529 authored by Ghislain MARY's avatar Ghislain MARY

Store chat message in database before file upload so that if the file upload...

Store chat message in database before file upload so that if the file upload fails we can try sending the chat message an other time.
parent 01e99025
......@@ -329,7 +329,7 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t,
#ifdef SQLITE_STORAGE_ENABLED
static void linphone_create_table(sqlite3* db) {
static void linphone_create_call_log_table(sqlite3* db) {
char* errmsg=NULL;
int ret;
ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS call_history ("
......@@ -386,7 +386,7 @@ void linphone_core_call_log_storage_init(LinphoneCore *lc) {
return;
}
linphone_create_table(db);
linphone_create_call_log_table(db);
linphone_update_call_log_table(db);
lc->logs_db = db;
......
......@@ -343,6 +343,29 @@ void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) {
cr->user_data = ud;
}
void linphone_chat_room_add_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
if (bctbx_list_find(msg->chat_room->transient_messages, msg) == NULL) {
cr->transient_messages = bctbx_list_append(cr->transient_messages, linphone_chat_message_ref(msg));
}
}
void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
if (bctbx_list_find(msg->chat_room->transient_messages, msg) != NULL) {
cr->transient_messages = bctbx_list_remove(cr->transient_messages, msg);
linphone_chat_message_unref(msg);
}
}
static void store_or_update_chat_message(LinphoneChatMessage *msg) {
if (msg->storage_id != 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);
}
}
void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
int retval = -1;
LinphoneCore *lc = cr->lc;
......@@ -363,8 +386,10 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
if (msg->file_transfer_information != NULL && msg->content_type == NULL) {
/* 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
cr->transient_messages = bctbx_list_append(cr->transient_messages, linphone_chat_message_ref(msg));
/* Add to transient list only if message is going out */
linphone_chat_room_add_transient_message(cr, msg);
/* Store the message so that even if the upload is stopped, it can be done again */
msg->storage_id = linphone_chat_message_store(msg);
} else {
linphone_chat_message_unref(msg);
return;
......@@ -380,8 +405,8 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
message_not_encrypted = ms_strdup(msg->message);
}
// add to transient list
cr->transient_messages = bctbx_list_append(cr->transient_messages, linphone_chat_message_ref(msg));
/* Add to transient list */
linphone_chat_room_add_transient_message(cr, msg);
msg->time = ms_time(0);
if (lp_config_get_int(cr->lc->config, "sip", "chat_use_call_dialogs", 0) != 0) {
if ((call = linphone_core_get_call_by_remote_address(cr->lc, cr->peer)) != NULL) {
......@@ -433,6 +458,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
if (retval > 0) {
sal_error_info_set((SalErrorInfo *)sal_op_get_error_info(op), SalReasonNotAcceptable, retval, "Unable to encrypt IM", NULL);
store_or_update_chat_message(msg);
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
linphone_chat_message_unref(msg);
return;
......@@ -459,7 +485,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
msg->message = ms_strdup(message_not_encrypted);
}
msg->message_id = ms_strdup(sal_op_get_call_id(op)); /* must be known at that time */
msg->storage_id = linphone_chat_message_store(msg);
store_or_update_chat_message(msg);
if (cr->is_composing == LinphoneIsComposingActive) {
cr->is_composing = LinphoneIsComposingIdle;
......@@ -474,8 +500,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
if (call && call->op == 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*/
msg->chat_room->transient_messages = bctbx_list_remove(msg->chat_room->transient_messages, msg);
linphone_chat_message_unref(msg);
linphone_chat_room_remove_transient_message(msg->chat_room, msg);
linphone_chat_message_unref(msg);
return;
}
......@@ -493,9 +518,8 @@ void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMe
if (msg->state == LinphoneChatMessageStateDelivered || msg->state == LinphoneChatMessageStateNotDelivered) {
if (bctbx_list_find(msg->chat_room->transient_messages, msg) != NULL) {
// msg is not transient anymore, we can remove it from our transient list and unref it
msg->chat_room->transient_messages = bctbx_list_remove(msg->chat_room->transient_messages, msg);
linphone_chat_room_add_weak_message(msg->chat_room, msg);
linphone_chat_message_unref(msg);
linphone_chat_room_remove_transient_message(msg->chat_room, msg);
} else {
// msg has already been removed from the transient messages, do nothing. */
}
......
......@@ -48,6 +48,7 @@ static void linphone_chat_message_process_io_error_upload(void *data, const bell
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);
}
......@@ -56,6 +57,7 @@ static void linphone_chat_message_process_auth_requested_upload(void *data, bell
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);
}
......@@ -260,7 +262,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data,
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 uplaoded 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
......
......@@ -1152,7 +1152,7 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriend, belle_sip_object_t,
#ifdef SQLITE_STORAGE_ENABLED
static void linphone_create_table(sqlite3* db) {
static void linphone_create_friends_table(sqlite3* db) {
char* errmsg = NULL;
int ret;
ret = sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS friends ("
......@@ -1187,7 +1187,7 @@ static void linphone_create_table(sqlite3* db) {
}
}
static bool_t linphone_update_table(sqlite3* db) {
static bool_t linphone_update_friends_table(sqlite3* db) {
static sqlite3_stmt *stmt_version;
int database_user_version = -1;
char *errmsg = NULL;
......@@ -1246,8 +1246,8 @@ void linphone_core_friends_storage_init(LinphoneCore *lc) {
return;
}
linphone_create_table(db);
if (linphone_update_table(db)) {
linphone_create_friends_table(db);
if (linphone_update_friends_table(db)) {
// After updating schema, database need to be closed/reopenned
sqlite3_close(db);
_linphone_sqlite3_open(lc->friends_db_file, &db);
......
......@@ -247,7 +247,7 @@ static int create_chat_message(void *data, int argc, char **argv, char **colName
new_message->external_body_url= ms_strdup(argv[8]);
new_message->appdata = ms_strdup(argv[10]);
new_message->message_id = ms_strdup(argv[12]);
new_message->content_type = ms_strdup(argv[13]);
linphone_chat_message_set_content_type(new_message, argv[13]);
new_message->is_secured = (bool_t)atoi(argv[14]);
if (argv[11] != NULL) {
......@@ -370,6 +370,41 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){
return id;
}
void linphone_chat_message_store_update(LinphoneChatMessage *msg) {
LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room);
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));
local_contact = linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
buf = sqlite3_mprintf("UPDATE history SET"
" localContact = %Q,"
" remoteContact = %Q,"
" message = %Q,"
" status = %i,"
" appdata = %Q,"
" messageId = %Q,"
" content_type = %Q"
" WHERE (id = %u);",
local_contact,
peer,
msg->message,
msg->state,
msg->appdata,
msg->message_id,
msg->content_type,
msg->storage_id
);
linphone_sql_request(lc->db, buf);
sqlite3_free(buf);
ms_free(local_contact);
ms_free(peer);
}
}
void linphone_chat_message_store_state(LinphoneChatMessage *msg){
LinphoneCore *lc=msg->chat_room->lc;
if (lc->db){
......@@ -563,6 +598,7 @@ bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int sta
while (it) {
LinphoneChatMessage* msg = it->data;
if (msg->dir == LinphoneChatMessageOutgoing) {
if (msg->from != NULL) linphone_address_unref(msg->from);
msg->from = linphone_address_ref(local_addr);
} else {
msg->to = linphone_address_ref(local_addr);
......@@ -604,7 +640,7 @@ LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, cons
return cm;
}
void linphone_create_table(sqlite3* db){
static void linphone_create_history_table(sqlite3* db){
char* errmsg=NULL;
int ret;
ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS history ("
......@@ -686,7 +722,7 @@ static void linphone_migrate_timestamps(sqlite3* db){
}
}
void linphone_update_table(sqlite3* db) {
static void linphone_update_history_table(sqlite3* db) {
char* errmsg=NULL;
char *buf;
int ret;
......@@ -764,6 +800,7 @@ void linphone_update_table(sqlite3* db) {
ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN messageId TEXT;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
ms_message("Table already up to date: %s", errmsg);
sqlite3_free(errmsg);
} else {
ms_message("Table history updated successfully for messageId data.");
}
......@@ -777,6 +814,7 @@ void linphone_update_table(sqlite3* db) {
ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN content_type TEXT;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
ms_message("Table already up to date: %s", errmsg);
sqlite3_free(errmsg);
} else {
ms_message("Table history updated successfully for content_type data.");
}
......@@ -785,11 +823,20 @@ void linphone_update_table(sqlite3* db) {
ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN is_secured INTEGER DEFAULT 0;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
ms_message("Table already up to date: %s", errmsg);
sqlite3_free(errmsg);
} else {
ms_message("Table history updated successfully for is_secured data.");
}
}
static void linphone_fix_outgoing_messages_state(sqlite3* db) {
/* Convert Idle and InProgress states of outgoing messages to NotDelivered */
char *buf = sqlite3_mprintf("UPDATE history SET status=%i WHERE direction=%i AND (status=%i OR status=%i);",
LinphoneChatMessageStateNotDelivered, LinphoneChatMessageOutgoing, LinphoneChatMessageStateIdle, LinphoneChatMessageStateInProgress);
linphone_sql_request(db, buf);
sqlite3_free(buf);
}
void linphone_message_storage_init_chat_rooms(LinphoneCore *lc) {
char *buf;
......@@ -837,8 +884,9 @@ void linphone_core_message_storage_init(LinphoneCore *lc){
linphone_message_storage_activate_debug(db, lc->debug_storage);
linphone_create_table(db);
linphone_update_table(db);
linphone_create_history_table(db);
linphone_update_history_table(db);
linphone_fix_outgoing_messages_state(db);
lc->db=db;
// Create a chatroom for each contact in the chat history
......
......@@ -621,6 +621,8 @@ int linphone_chat_room_upload_file(LinphoneChatMessage *msg);
void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
LinphoneChatMessageCbs *linphone_chat_message_cbs_new(void);
LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call);
void linphone_chat_room_add_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
/**/
struct _LinphoneProxyConfig
......@@ -1238,6 +1240,7 @@ int _linphone_sqlite3_open(const char *db_file, sqlite3 **db);
sqlite3 * linphone_message_storage_init(void);
void linphone_message_storage_init_chat_rooms(LinphoneCore *lc);
#endif
void linphone_chat_message_store_update(LinphoneChatMessage *msg);
void linphone_chat_message_store_state(LinphoneChatMessage *msg);
void linphone_chat_message_store_appdata(LinphoneChatMessage* msg);
void linphone_core_message_storage_init(LinphoneCore *lc);
......
This diff is collapsed.
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