From a29a93cd765e405472e2344a337ae57a08375aac Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Mon, 2 Jun 2014 14:05:30 +0200 Subject: [PATCH] Add an API to set and retrieve chat messages "app data". This allows clients to store resilient data for each messages --- coreapi/chat.c | 32 +++++++++++++++++++++++ coreapi/linphonecore.h | 8 +++--- coreapi/message_storage.c | 53 +++++++++++++++++++++++++++++++++------ coreapi/private.h | 2 ++ 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/coreapi/chat.c b/coreapi/chat.c index fb2a34159..2ea196b47 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -668,6 +668,36 @@ void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,co message->external_body_url=url?ms_strdup(url):NULL; } + +/** + * 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. + */ +const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message){ + return message->appdata; +} + +/** + * 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 + */ +void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data){ + if( message->appdata ){ + ms_free(message->appdata); + } + message->appdata = data? ms_strdup(data) : NULL; + linphone_chat_message_store_appdata(message); +} + + /** * Set origin of the message *@param message #LinphoneChatMessage obj @@ -805,6 +835,7 @@ 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->cb=msg->cb; new_message->cb_ud=msg->cb_ud; new_message->message_userdata=msg->message_userdata; @@ -831,6 +862,7 @@ static void _linphone_chat_message_destroy(LinphoneChatMessage* msg) { if (msg->op) sal_op_release(msg->op); if (msg->message) ms_free(msg->message); if (msg->external_body_url) ms_free(msg->external_body_url); + if (msg->appdata) ms_free(msg->appdata); if (msg->from) linphone_address_destroy(msg->from); if (msg->to) linphone_address_destroy(msg->to); if (msg->custom_headers) sal_custom_header_free(msg->custom_headers); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index b21ebc7ca..c2d565695 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1130,7 +1130,9 @@ LINPHONE_PUBLIC void linphone_chat_message_set_to(LinphoneChatMessage* message, LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message); LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message); LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url); -LINPHONE_PUBLIC const char * linphone_chat_message_get_text(const LinphoneChatMessage* message); +LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message); +LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data); +LINPHONE_PUBLIC const char* linphone_chat_message_get_text(const LinphoneChatMessage* message); LINPHONE_PUBLIC time_t linphone_chat_message_get_time(const LinphoneChatMessage* message); LINPHONE_PUBLIC void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message); LINPHONE_PUBLIC void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*); @@ -1622,7 +1624,7 @@ LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const * @param[in] lc the #LinphoneCore object * @param[in] pt the #PayloadType to modify. * @param[in] bitrate the IP bitrate in kbit/s. - * @ingroup media_parameters + * @ingroup media_parameters **/ LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate); @@ -1631,7 +1633,7 @@ LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, Pa * @param[in] lc the #LinphoneCore object * @param[in] pt the #PayloadType to modify. * @return bitrate the IP bitrate in kbit/s, or -1 if an error occured. - * @ingroup media_parameters + * @ingroup media_parameters **/ LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt); diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 81d076fc5..7caf4536b 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -37,6 +37,20 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u return NULL; } + +/* DB layout: + * | 0 | storage_id + * | 1 | localContact + * | 2 | remoteContact + * | 3 | direction flag + * | 4 | message + * | 5 | time (unused now, used to be string-based timestamp) + * | 6 | read flag + * | 7 | status + * | 8 | external body url + * | 9 | utc timestamp + * | 10 | app data text + */ static void create_chat_message(char **argv, void *data){ LinphoneChatRoom *cr = (LinphoneChatRoom *)data; LinphoneAddress *from; @@ -67,7 +81,8 @@ static void create_chat_message(char **argv, void *data){ new_message->is_read=atoi(argv[6]); new_message->state=atoi(argv[7]); new_message->storage_id=storage_id; - new_message->external_body_url=argv[8]?ms_strdup(argv[8]):NULL; + new_message->external_body_url= argv[8] ? ms_strdup(argv[8]) : NULL; + new_message->appdata = argv[10]? ms_strdup(argv[10]) : NULL; } cr->messages_hist=ms_list_prepend(cr->messages_hist,new_message); } @@ -95,7 +110,7 @@ void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom } } -void linphone_sql_request(sqlite3* db,const char *stmt){ +int linphone_sql_request(sqlite3* db,const char *stmt){ char* errmsg=NULL; int ret; ret=sqlite3_exec(db,stmt,NULL,NULL,&errmsg); @@ -103,6 +118,7 @@ void linphone_sql_request(sqlite3* db,const char *stmt){ ms_error("linphone_sql_request: error sqlite3_exec(): %s.\n", errmsg); sqlite3_free(errmsg); } + return ret; } // Process the request to fetch all chat contacts @@ -123,7 +139,7 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){ if (lc->db){ char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room)); char *local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg)); - char *buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i);", + char *buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i,%Q);", local_contact, peer, msg->dir, @@ -132,7 +148,8 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){ msg->is_read, msg->state, msg->external_body_url, - msg->time); + msg->time, + msg->appdata); linphone_sql_request(lc->db,buf); sqlite3_free(buf); ms_free(local_contact); @@ -159,6 +176,16 @@ void linphone_chat_message_store_state(LinphoneChatMessage *msg){ } } +void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){ + LinphoneCore *lc=msg->chat_room->lc; + if (lc->db){ + char *buf=sqlite3_mprintf("UPDATE history SET appdata=%Q WHERE id=%i;", + msg->appdata,msg->storage_id); + linphone_sql_request(lc->db,buf); + sqlite3_free(buf); + } +} + void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); int read=1; @@ -302,11 +329,11 @@ static time_t parse_time_from_db( const char* time ){ } -static int migrate_messages(void* data,int argc, char** argv, char** column_names) { +static int migrate_messages_timestamp(void* data,int argc, char** argv, char** column_names) { time_t new_time = parse_time_from_db(argv[1]); if( new_time ){ /* replace 'time' by -1 and set 'utc' to the timestamp */ - char *buf = sqlite3_mprintf("UPDATE history SET utc=%i,time='-1' WHERE id=%i", new_time, atoi(argv[0])); + char *buf = sqlite3_mprintf("UPDATE history SET utc=%i,time='-1' WHERE id=%i;", new_time, atoi(argv[0])); if( buf) { linphone_sql_request((sqlite3*)data, buf); sqlite3_free(buf); @@ -324,7 +351,7 @@ static void linphone_migrate_timestamps(sqlite3* db){ linphone_sql_request(db,"BEGIN TRANSACTION"); - ret = sqlite3_exec(db,"SELECT id,time,direction FROM history WHERE time != '-1'", migrate_messages, db, &errmsg); + ret = sqlite3_exec(db,"SELECT id,time,direction FROM history WHERE time != '-1';", migrate_messages_timestamp, db, &errmsg); if( ret != SQLITE_OK ){ ms_warning("Error migrating outgoing messages: %s.\n", errmsg); sqlite3_free(errmsg); @@ -359,6 +386,15 @@ void linphone_update_table(sqlite3* db) { // migrate from old text-based timestamps to unix time-based timestamps linphone_migrate_timestamps(db); } + + // new field for app-specific storage + ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN appdata TEXT;",NULL,NULL,&errmsg); + if(ret != SQLITE_OK) { + ms_message("Table already up to date: %s.", errmsg); + sqlite3_free(errmsg); + } else { + ms_debug("Table updated successfully for app-specific data."); + } } void linphone_message_storage_init_chat_rooms(LinphoneCore *lc) { @@ -431,6 +467,9 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *cr){ void linphone_chat_message_store_state(LinphoneChatMessage *cr){ } +void linphone_chat_message_store_appdata(LinphoneChatMessage *msg){ +} + void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ } diff --git a/coreapi/private.h b/coreapi/private.h index 589297849..ac93f41b9 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -144,6 +144,7 @@ struct _LinphoneChatMessage { LinphoneChatMessageStateChangedCb cb; void* cb_ud; void* message_userdata; + char* appdata; char* external_body_url; LinphoneAddress *from; LinphoneAddress *to; @@ -821,6 +822,7 @@ sqlite3 * linphone_message_storage_init(); void linphone_message_storage_init_chat_rooms(LinphoneCore *lc); #endif void linphone_chat_message_store_state(LinphoneChatMessage *msg); +void linphone_chat_message_store_appdata(LinphoneChatMessage* msg); void linphone_core_message_storage_init(LinphoneCore *lc); void linphone_core_message_storage_close(LinphoneCore *lc); void linphone_core_message_storage_set_debug(LinphoneCore *lc, bool_t debug);