From cabf15f1f5a8cbbca4960adede61d113d21b0722 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 02:45:32 +0200 Subject: [PATCH 01/13] Store call logs in sql database + new method to get all call logs related to a linphone address --- configure.ac | 38 ++++- coreapi/call_log.c | 313 ++++++++++++++++++++++++++++++++++++++ coreapi/linphonecall.c | 6 +- coreapi/linphonecore.c | 37 ++++- coreapi/linphonecore.h | 17 +++ coreapi/message_storage.c | 5 - coreapi/private.h | 12 ++ gtk/calllogs.c | 28 ++++ gtk/linphone.h | 1 + gtk/main.c | 17 ++- 10 files changed, 457 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index 191c7fd7d..c69661a8d 100644 --- a/configure.ac +++ b/configure.ac @@ -894,7 +894,7 @@ if test x$enable_msg_storage != xfalse; then AC_CHECK_LIB(sqlite3, sqlite3_open, [SQLITE3_LIBS+=" -lsqlite3 "; found_sqlite=yes], [foo=bar]) fi if test "$found_sqlite" = "yes"; then - SQLITE3_CFLAGS+="-DMSG_STORAGE_ENABLED" + SQLITE3_CFLAGS+=" -DMSG_STORAGE_ENABLED" if test "$build_macos" = "yes" -o "$ios_found" = "yes"; then SQLITE3_LIBS+=" -liconv" fi @@ -912,6 +912,41 @@ fi AM_CONDITIONAL(BUILD_MSG_STORAGE, test x$enable_msg_storage = xtrue) +AC_ARG_ENABLE(call-logs-storage, + [AS_HELP_STRING([--enable-call-logs-storage=[yes/no]], [Turn on compilation of call logs storage (default=auto)])], + [case "${enableval}" in + yes) enable_call_logs_storage=true ;; + no) enable_call_logs_storage=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-call-logs-storage) ;; + esac], + [enable_call_logs_storage=auto] +) + +if test x$enable_call_logs_storage != xfalse; then + PKG_CHECK_MODULES(SQLITE3,[sqlite3 >= 3.6.0],[found_sqlite=yes],[found_sqlite=no]) + if test "$found_sqlite" = "no"; then + dnl Check the lib presence in case the PKG-CONFIG version is not found + AC_CHECK_LIB(sqlite3, sqlite3_open, [SQLITE3_LIBS+=" -lsqlite3 "; found_sqlite=yes], [foo=bar]) + fi + if test "$found_sqlite" = "yes"; then + SQLITE3_CFLAGS+=" -DCALL_LOGS_STORAGE_ENABLED" + if test "$build_macos" = "yes" -o "$ios_found" = "yes"; then + SQLITE3_LIBS+=" -liconv" + fi + enable_call_logs_storage=true + else + if test x$enable_call_logs_storage = xtrue; then + AC_MSG_ERROR([sqlite3, required for call logs storage, not found]) + fi + enable_call_logs_storage=false + fi + + AC_SUBST(SQLITE3_CFLAGS) + AC_SUBST(SQLITE3_LIBS) +fi + +AM_CONDITIONAL(BUILD_CALL_LOGS_STORAGE, test x$enable_call_logs_storage = xtrue) + PKG_CHECK_MODULES(BELLESIP, [belle-sip >= 1.4.0]) SIPSTACK_CFLAGS="$BELLESIP_CFLAGS" @@ -1065,6 +1100,7 @@ printf "* %-30s %s\n" "Account assistant" $build_wizard printf "* %-30s %s\n" "Console interface" $console_ui printf "* %-30s %s\n" "Tools" $build_tools printf "* %-30s %s\n" "Message storage" $enable_msg_storage +printf "* %-30s %s\n" "Call logs storage" $enable_call_logs_storage printf "* %-30s %s\n" "IM encryption" $lime printf "* %-30s %s\n" "uPnP support" $build_upnp printf "* %-30s %s\n" "LDAP support" $enable_ldap diff --git a/coreapi/call_log.c b/coreapi/call_log.c index 9d16e8511..2cd94d9d8 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -22,6 +22,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include "private.h" +#ifdef CALL_LOGS_STORAGE_ENABLED +#ifndef _WIN32 +#if !defined(ANDROID) && !defined(__QNXNTO__) +# include +# include +# include +#endif +#else +#include +#endif + +#define MAX_PATH_SIZE 1024 +#include "sqlite3.h" +#endif /******************************************************************************* * Internal functions * @@ -278,6 +292,7 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *fr cl->to=to; cl->status=LinphoneCallAborted; /*default status*/ cl->quality=-1; + cl->storage_id=0; cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); @@ -298,3 +313,301 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t, NULL, // marshal FALSE ); + + +/******************************************************************************* + * SQL storage related functions * + ******************************************************************************/ + +#ifdef CALL_LOGS_STORAGE_ENABLED + +static void linphone_create_table(sqlite3* db){ + char* errmsg=NULL; + int ret; + ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS call_history (" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "caller TEXT NOT NULL," // Can't name a field "from"... + "callee TEXT NOT NULL," + "direction INTEGER," + "duration INTEGER," + "start_time TEXT NOT NULL," + "connected_time TEXT NOT NULL," + "status INTEGER," + "videoEnabled INTEGER," + "quality REAL" + ");", + 0,0,&errmsg); + if(ret != SQLITE_OK) { + ms_error("Error in creation: %s.\n", errmsg); + sqlite3_free(errmsg); + } +} + +static int _linphone_sqlite3_open(const char *db_file, sqlite3 **db) { +#if defined(ANDROID) || defined(__QNXNTO__) + return sqlite3_open(db_file, db); +#elif defined(_WIN32) + int ret; + wchar_t db_file_utf16[MAX_PATH_SIZE]; + ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, db_file, -1, db_file_utf16, MAX_PATH_SIZE); + if(ret == 0) db_file_utf16[0] = '\0'; + return sqlite3_open16(db_file_utf16, db); +#else + char db_file_locale[MAX_PATH_SIZE] = {'\0'}; + char db_file_utf8[MAX_PATH_SIZE] = ""; + char *inbuf=db_file_locale, *outbuf=db_file_utf8; + size_t inbyteleft = MAX_PATH_SIZE, outbyteleft = MAX_PATH_SIZE; + iconv_t cb; + + strncpy(db_file_locale, db_file, MAX_PATH_SIZE-1); + cb = iconv_open("UTF-8", nl_langinfo(CODESET)); + if(cb != (iconv_t)-1) { + int ret; + ret = iconv(cb, &inbuf, &inbyteleft, &outbuf, &outbyteleft); + if(ret == -1) db_file_utf8[0] = '\0'; + iconv_close(cb); + } + return sqlite3_open(db_file_utf8, db); +#endif +} + +void linphone_core_call_log_storage_init(LinphoneCore *lc) { + int ret; + const char *errmsg; + sqlite3 *db; + + linphone_core_message_storage_close(lc); + + ret=_linphone_sqlite3_open(lc->logs_db_file, &db); + if(ret != SQLITE_OK) { + errmsg = sqlite3_errmsg(db); + ms_error("Error in the opening: %s.\n", errmsg); + sqlite3_close(db); + return; + } + + linphone_create_table(db); + lc->logs_db = db; + + // Load the existing call logs + linphone_call_log_get_history(lc); +} + +void linphone_core_call_log_storage_close(LinphoneCore *lc) { + if (lc->logs_db){ + sqlite3_close(lc->logs_db); + lc->logs_db = NULL; + } +} + +/* DB layout: + * | 0 | storage_id + * | 1 | from + * | 2 | to + * | 3 | direction flag + * | 4 | duration + * | 5 | start date time (time_t) + * | 6 | connected date time (time_t) + * | 7 | status + * | 8 | video enabled (1 or 0) + * | 9 | quality + */ +static int create_call_log(void *data, int argc, char **argv, char **colName) { + LinphoneCore *lc = (LinphoneCore *)data; + LinphoneAddress *from; + LinphoneAddress *to; + LinphoneCallDir dir; + LinphoneCallLog *log; + + unsigned int storage_id = atoi(argv[0]); + from = linphone_address_new(argv[1]); + to = linphone_address_new(argv[2]); + dir = (LinphoneCallDir) atoi(argv[3]); + log = linphone_call_log_new(dir, from, to); + + log->storage_id = storage_id; + log->duration = atoi(argv[4]); + log->start_date_time = (time_t)atol(argv[5]); + log->connected_date_time = (time_t)atol(argv[6]); + log->status = (LinphoneCallStatus) atoi(argv[7]); + log->video_enabled = atoi(argv[8]) == 1; + log->quality = atof(argv[9]); + + lc->call_logs = ms_list_prepend(lc->call_logs, linphone_call_log_ref(log)); + + return 0; +} + +void linphone_sql_request_call_log(sqlite3 *db, const char *stmt, LinphoneCore *lc){ + char* errmsg = NULL; + int ret; + ret = sqlite3_exec(db, stmt, create_call_log, lc, &errmsg); + if (ret != SQLITE_OK) { + ms_error("Error in creation: %s.", errmsg); + sqlite3_free(errmsg); + } +} + +int linphone_sql_request_generic(sqlite3* db, const char *stmt){ + char* errmsg = NULL; + int ret; + ret = sqlite3_exec(db, stmt, NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg); + sqlite3_free(errmsg); + } + return ret; +} + +void linphone_call_log_store(LinphoneCore *lc, LinphoneCallLog *log) { + if (lc && lc->logs_db){ + char *from, *to; + char *buf; + + from = linphone_address_as_string(log->from); + to = linphone_address_as_string(log->to); + buf = sqlite3_mprintf("INSERT INTO call_history VALUES(NULL,%Q,%Q,%i,%i,%lld,%lld,%i,%i,%f);", + from, + to, + log->dir, + log->duration, + (int64_t)log->start_date_time, + (int64_t)log->connected_date_time, + log->status, + log->video_enabled ? 1 : 0, + log->quality + ); + linphone_sql_request_generic(lc->logs_db, buf); + sqlite3_free(buf); + ms_free(from); + ms_free(to); + sqlite3_last_insert_rowid(lc->logs_db); + } + + if (lc) { + lc->call_logs = ms_list_prepend(lc->call_logs, linphone_call_log_ref(log)); + } +} + +MSList *linphone_call_log_get_history(LinphoneCore *lc) { + char *buf; + uint64_t begin,end; + + if (!lc || lc->logs_db == NULL) return NULL; + + ms_list_for_each(lc->call_logs, (void (*)(void*))linphone_call_log_unref); + lc->call_logs = ms_list_free(lc->call_logs); + + buf = sqlite3_mprintf("SELECT * FROM call_history ORDER BY id ASC LIMIT %i", lc->max_call_logs); + + begin = ortp_get_cur_time_ms(); + linphone_sql_request_call_log(lc->logs_db, buf, lc); + end = ortp_get_cur_time_ms(); + ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); + sqlite3_free(buf); + + return lc->call_logs; +} + +void linphone_call_log_delete_history(LinphoneCore *lc) { + char *buf; + + if (!lc || lc->logs_db == NULL) return ; + + buf = sqlite3_mprintf("DELETE FROM call_history"); + linphone_sql_request_generic(lc->logs_db, buf); + sqlite3_free(buf); +} + +void linphone_call_log_delete_log(LinphoneCore *lc, LinphoneCallLog *log) { + char *buf; + + if (!lc || lc->logs_db == NULL) return ; + + buf = sqlite3_mprintf("DELETE FROM call_history WHERE id = %i", log->storage_id); + linphone_sql_request_generic(lc->logs_db, buf); + sqlite3_free(buf); + + lc->call_logs = ms_list_remove(lc->call_logs, log); + linphone_call_log_unref(log); +} + +int linphone_call_log_get_history_size(LinphoneCore *lc) { + int numrows = 0; + char *buf; + sqlite3_stmt *selectStatement; + int returnValue; + + if (!lc || lc->logs_db == NULL) return 0; + + buf = sqlite3_mprintf("SELECT count(*) FROM call_history"); + returnValue = sqlite3_prepare_v2(lc->logs_db, buf, -1, &selectStatement, NULL); + if (returnValue == SQLITE_OK){ + if(sqlite3_step(selectStatement) == SQLITE_ROW){ + numrows = sqlite3_column_int(selectStatement, 0); + } + } + sqlite3_finalize(selectStatement); + sqlite3_free(buf); + + return numrows; +} + +const MSList * linphone_core_get_call_logs_for_address(LinphoneCore *lc, LinphoneAddress *addr) { + char *buf; + char *sipAddress; + uint64_t begin,end; + MSList *result, *tmp; + + if (!lc || lc->logs_db == NULL || addr == NULL) return NULL; + + tmp = lc->call_logs; + lc->call_logs = NULL; + + /*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/ + sipAddress = linphone_address_as_string_uri_only(addr); + buf = sqlite3_mprintf("SELECT * FROM call_history WHERE caller LIKE '%%%q%%' OR callee LIKE '%%%q%%' ORDER BY id ASC", sipAddress, sipAddress); // The '%%%q%%' takes care of the eventual presence of a display name + + begin = ortp_get_cur_time_ms(); + linphone_sql_request_call_log(lc->logs_db, buf, lc); + end = ortp_get_cur_time_ms(); + ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); + sqlite3_free(buf); + ms_free(sipAddress); + + result = lc->call_logs; + lc->call_logs = tmp; + tmp = NULL; + return result; +} + +#else + +void linphone_core_call_log_storage_init(LinphoneCore *lc) { +} + +void linphone_core_call_log_storage_close(LinphoneCore *lc) { +} + +void linphone_call_log_store(LinphoneCore *lc, LinphoneCallLog *log) { +} + +MSList *linphone_call_log_get_history(LinphoneCore *lc) { + return NULL; +} + +void linphone_call_log_delete_history(LinphoneCore *lc) { +} + +void linphone_call_log_delete_log(LinphoneCore *lc, LinphoneCallLog *log) { +} + +int linphone_call_log_get_history_size(LinphoneCore *lc) { + return 0; +} + +const MSList * linphone_core_get_call_logs_for_address(LinphoneCore *lc, LinphoneAddress *addr) { + return NULL; +} + +#endif \ No newline at end of file diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index b5e8d62b9..56164bf96 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -3945,6 +3945,9 @@ void linphone_call_log_completed(LinphoneCall *call){ linphone_core_notify_display_status(lc,info); ms_free(info); } +#ifdef CALL_LOGS_STORAGE_ENABLED + linphone_call_log_store(lc, call->log); +#else lc->call_logs=ms_list_prepend(lc->call_logs,linphone_call_log_ref(call->log)); if (ms_list_size(lc->call_logs)>lc->max_call_logs){ MSList *elem,*prevelem=NULL; @@ -3956,8 +3959,9 @@ void linphone_call_log_completed(LinphoneCall *call){ linphone_call_log_unref((LinphoneCallLog*)elem->data); lc->call_logs=ms_list_remove_link(lc->call_logs,elem); } - linphone_core_notify_call_log_updated(lc,call->log); call_logs_write_to_config_file(lc); +#endif + linphone_core_notify_call_log_updated(lc,call->log); } /** diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 1c238a4aa..f94358d6d 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1294,7 +1294,10 @@ static void ui_config_read(LinphoneCore *lc) linphone_core_add_friend(lc,lf); linphone_friend_unref(lf); } + +#ifndef CALL_LOGS_STORAGE_ENABLED call_logs_read_from_config_file(lc); +#endif } /* @@ -4929,15 +4932,33 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) * Call log related functions * ******************************************************************************/ -const MSList * linphone_core_get_call_logs(LinphoneCore *lc){ +void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *path){ + if (lc->logs_db_file){ + ms_free(lc->logs_db_file); + lc->logs_db_file = NULL; + } + if (path) { + lc->logs_db_file = ms_strdup(path); + linphone_core_call_log_storage_init(lc); + } +} + +const MSList* linphone_core_get_call_logs(LinphoneCore *lc) { +#ifdef CALL_LOGS_STORAGE_ENABLED + linphone_call_log_get_history(lc); +#endif return lc->call_logs; } -void linphone_core_clear_call_logs(LinphoneCore *lc){ +void linphone_core_clear_call_logs(LinphoneCore *lc) { lc->missed_calls=0; - ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref); - lc->call_logs=ms_list_free(lc->call_logs); +#ifdef CALL_LOGS_STORAGE_ENABLED + linphone_call_log_delete_history(lc); +#else + ms_list_for_each(lc->call_logs, (void (*)(void*))linphone_call_log_unref); + lc->call_logs = ms_list_free(lc->call_logs); call_logs_write_to_config_file(lc); +#endif } int linphone_core_get_missed_calls_count(LinphoneCore *lc) { @@ -4949,12 +4970,19 @@ void linphone_core_reset_missed_calls_count(LinphoneCore *lc) { } void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){ +#ifdef CALL_LOGS_STORAGE_ENABLED + linphone_call_log_delete_log(lc, cl); +#else lc->call_logs = ms_list_remove(lc->call_logs, cl); call_logs_write_to_config_file(lc); linphone_call_log_unref(cl); +#endif } +/******************************************************************************* + * Video related functions * + ******************************************************************************/ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ @@ -6170,6 +6198,7 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_free_payload_types(lc); if (lc->supported_formats) ms_free(lc->supported_formats); linphone_core_message_storage_close(lc); + linphone_core_call_log_storage_close(lc); ms_exit(); linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); linphone_core_deactivate_log_serialization_if_needed(); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index c6d05152e..6e3f84cd5 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -3170,6 +3170,14 @@ LINPHONE_PUBLIC void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *l **/ LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); +/** + * Get the list of call logs (past calls) that matches the given #LinphoneAddress. + * At the contrary of linphone_core_get_call_logs, it is your responsability to unref the logs and free this list once you are done using it. + * @param[in] lc LinphoneCore object + * @return \mslist{LinphoneCallLog} +**/ +LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs_for_address(LinphoneCore *lc, LinphoneAddress *addr); + /** * Erase the call log. * @param[in] lc LinphoneCore object @@ -3198,6 +3206,15 @@ LINPHONE_PUBLIC void linphone_core_reset_missed_calls_count(LinphoneCore *lc); **/ LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *call_log); +/** + * Sets the database filename where call logs will be stored. + * If the file does not exist, it will be created. + * @ingroup initializing + * @param lc the linphone core + * @param path filesystem path +**/ +LINPHONE_PUBLIC void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *path); + /** * @} **/ diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 25d37a1b8..56f8402c3 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -433,11 +433,6 @@ MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ return linphone_chat_room_get_history_range(cr, 0, nb_message-1); } - -void linphone_close_storage(sqlite3* db){ - sqlite3_close(db); -} - void linphone_create_table(sqlite3* db){ char* errmsg=NULL; int ret; diff --git a/coreapi/private.h b/coreapi/private.h index 6d5bc08d3..045606e9f 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -171,6 +171,7 @@ struct _LinphoneCallLog{ char* call_id; /**unique id of a call*/ struct _LinphoneQualityReporting reporting; bool_t video_enabled; + unsigned int storage_id; }; BELLE_SIP_DECLARE_VPTR(LinphoneCallLog); @@ -846,6 +847,10 @@ struct _LinphoneCore #ifdef MSG_STORAGE_ENABLED sqlite3 *db; bool_t debug_storage; +#endif + char *logs_db_file; +#ifdef CALL_LOGS_STORAGE_ENABLED + sqlite3 *logs_db; #endif #ifdef BUILD_UPNP UpnpContext *upnp; @@ -962,6 +967,13 @@ void _linphone_core_codec_config_write(LinphoneCore *lc); #endif void call_logs_read_from_config_file(LinphoneCore *lc); void call_logs_write_to_config_file(LinphoneCore *lc); +void linphone_core_call_log_storage_init(LinphoneCore *lc); +void linphone_core_call_log_storage_close(LinphoneCore *lc); +void linphone_call_log_store(LinphoneCore *lc, LinphoneCallLog *log); +MSList *linphone_call_log_get_history(LinphoneCore *lc); +void linphone_call_log_delete_history(LinphoneCore *lc); +void linphone_call_log_delete_log(LinphoneCore *lc, LinphoneCallLog *log); +int linphone_call_log_get_history_size(LinphoneCore *lc); int linphone_core_get_edge_bw(LinphoneCore *lc); int linphone_core_get_edge_ptime(LinphoneCore *lc); diff --git a/gtk/calllogs.c b/gtk/calllogs.c index 4d91c38bd..733d4fc1e 100644 --- a/gtk/calllogs.c +++ b/gtk/calllogs.c @@ -19,6 +19,34 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphone.h" +#define CONFIG_FILE ".linphone-call-history.db" + +char *linphone_gtk_call_logs_storage_get_db_file(const char *filename){ + const int path_max=1024; + char *db_file=NULL; + + db_file=(char *)g_malloc(path_max*sizeof(char)); + if (filename==NULL) filename=CONFIG_FILE; + /*try accessing a local file first if exists*/ + if (access(CONFIG_FILE,F_OK)==0){ + snprintf(db_file,path_max,"%s",filename); + }else{ +#ifdef WIN32 + const char *appdata=getenv("APPDATA"); + if (appdata){ + snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); + CreateDirectory(db_file,NULL); + snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); + } +#else + const char *home=getenv("HOME"); + if (home==NULL) home="."; + snprintf(db_file,path_max,"%s/%s",home,filename); +#endif + } + return db_file; +} + static void fill_renderers(GtkTreeView *v){ GtkTreeViewColumn *c; GtkCellRenderer *r; diff --git a/gtk/linphone.h b/gtk/linphone.h index 618f1590e..4349abd43 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -101,6 +101,7 @@ LINPHONE_PUBLIC GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char LINPHONE_PUBLIC GtkWidget *linphone_gtk_create_widget(const char* widget_name); char *linphone_gtk_message_storage_get_db_file(const char *filename); +char *linphone_gtk_call_logs_storage_get_db_file(const char *filename); LINPHONE_PUBLIC void linphone_gtk_show_assistant(GtkWidget* parent); LINPHONE_PUBLIC void linphone_gtk_close_assistant(void); diff --git a/gtk/main.c b/gtk/main.c index 5e967242b..c4c332bb3 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -259,7 +259,7 @@ gboolean linphone_gtk_get_audio_assistant_option(void){ } static void linphone_gtk_init_liblinphone(const char *config_file, - const char *factory_config_file, const char *db_file) { + const char *factory_config_file, const char *chat_messages_db_file, const char *call_logs_db_file) { LinphoneCoreVTable vtable={0}; gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE); gchar *user_certificates_dir=linphone_gtk_get_config_file(CERTIFICATES_PATH); @@ -309,7 +309,8 @@ static void linphone_gtk_init_liblinphone(const char *config_file, _linphone_gtk_enable_video(FALSE); linphone_gtk_set_ui_config_int("videoselfview",0); } - if (db_file) linphone_core_set_chat_database_path(the_core,db_file); + if (chat_messages_db_file) linphone_core_set_chat_database_path(the_core,chat_messages_db_file); + if (call_logs_db_file) linphone_core_set_call_logs_database_path(the_core, call_logs_db_file); } LinphoneCore *linphone_gtk_get_core(void){ @@ -2063,7 +2064,7 @@ int main(int argc, char *argv[]){ GdkPixbuf *pbuf; const char *app_name="Linphone"; LpConfig *factory; - char *db_file; + char *chat_messages_db_file, *call_logs_db_file; GError *error=NULL; const char *tmp; @@ -2213,9 +2214,13 @@ core_start: linphone_gtk_create_log_window(); linphone_core_enable_logs_with_cb(linphone_gtk_log_handler); - db_file=linphone_gtk_message_storage_get_db_file(NULL); - linphone_gtk_init_liblinphone(config_file, factory_config_file, db_file); - g_free(db_file); + chat_messages_db_file=linphone_gtk_message_storage_get_db_file(NULL); + call_logs_db_file = linphone_gtk_call_logs_storage_get_db_file(NULL); + linphone_gtk_init_liblinphone(config_file, factory_config_file, chat_messages_db_file, call_logs_db_file); + g_free(chat_messages_db_file); + g_free(call_logs_db_file); + + linphone_gtk_call_log_update(the_ui); /* do not lower timeouts under 30 ms because it exhibits a bug on gtk+/win32, with cpu running 20% all the time...*/ gtk_timeout_add(30,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core()); From 6d9af5fa543c563e855a04d63f2ea18e62c4f4d5 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 14:53:40 +0200 Subject: [PATCH 02/13] Fix ref leak + renamed some functions + improved MSList handling --- coreapi/call_log.c | 59 +++++++++++++++++++----------------------- coreapi/linphonecall.c | 2 +- coreapi/linphonecore.c | 6 ++--- coreapi/linphonecore.h | 2 +- coreapi/private.h | 10 +++---- 5 files changed, 36 insertions(+), 43 deletions(-) diff --git a/coreapi/call_log.c b/coreapi/call_log.c index 2cd94d9d8..d40260166 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -274,7 +274,7 @@ void linphone_call_log_unref(LinphoneCallLog *cl) { * Constructor and destructor functions * ******************************************************************************/ -static void _linphone_call_log_destroy(LinphoneCallLog *cl){ +static void _linphone_call_log_destroy(LinphoneCallLog *cl) { if (cl->from!=NULL) linphone_address_destroy(cl->from); if (cl->to!=NULL) linphone_address_destroy(cl->to); if (cl->refkey!=NULL) ms_free(cl->refkey); @@ -283,7 +283,7 @@ static void _linphone_call_log_destroy(LinphoneCallLog *cl){ if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]); } -LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to){ +LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to) { LinphoneCallLog *cl=belle_sip_object_new(LinphoneCallLog); cl->dir=dir; cl->start_date_time=time(NULL); @@ -321,7 +321,7 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t, #ifdef CALL_LOGS_STORAGE_ENABLED -static void linphone_create_table(sqlite3* db){ +static void linphone_create_table(sqlite3* db) { char* errmsg=NULL; int ret; ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS call_history (" @@ -390,7 +390,7 @@ void linphone_core_call_log_storage_init(LinphoneCore *lc) { lc->logs_db = db; // Load the existing call logs - linphone_call_log_get_history(lc); + linphone_core_get_call_history(lc); } void linphone_core_call_log_storage_close(LinphoneCore *lc) { @@ -413,7 +413,7 @@ void linphone_core_call_log_storage_close(LinphoneCore *lc) { * | 9 | quality */ static int create_call_log(void *data, int argc, char **argv, char **colName) { - LinphoneCore *lc = (LinphoneCore *)data; + MSList **list = (MSList **)data; LinphoneAddress *from; LinphoneAddress *to; LinphoneCallDir dir; @@ -433,22 +433,22 @@ static int create_call_log(void *data, int argc, char **argv, char **colName) { log->video_enabled = atoi(argv[8]) == 1; log->quality = atof(argv[9]); - lc->call_logs = ms_list_prepend(lc->call_logs, linphone_call_log_ref(log)); + *list = ms_list_prepend(*list, log); return 0; } -void linphone_sql_request_call_log(sqlite3 *db, const char *stmt, LinphoneCore *lc){ +void linphone_sql_request_call_log(sqlite3 *db, const char *stmt, MSList **list) { char* errmsg = NULL; int ret; - ret = sqlite3_exec(db, stmt, create_call_log, lc, &errmsg); + ret = sqlite3_exec(db, stmt, create_call_log, list, &errmsg); if (ret != SQLITE_OK) { ms_error("Error in creation: %s.", errmsg); sqlite3_free(errmsg); } } -int linphone_sql_request_generic(sqlite3* db, const char *stmt){ +int linphone_sql_request_generic(sqlite3* db, const char *stmt) { char* errmsg = NULL; int ret; ret = sqlite3_exec(db, stmt, NULL, NULL, &errmsg); @@ -459,7 +459,7 @@ int linphone_sql_request_generic(sqlite3* db, const char *stmt){ return ret; } -void linphone_call_log_store(LinphoneCore *lc, LinphoneCallLog *log) { +void linphone_core_store_call_log(LinphoneCore *lc, LinphoneCallLog *log) { if (lc && lc->logs_db){ char *from, *to; char *buf; @@ -489,19 +489,18 @@ void linphone_call_log_store(LinphoneCore *lc, LinphoneCallLog *log) { } } -MSList *linphone_call_log_get_history(LinphoneCore *lc) { +const MSList *linphone_core_get_call_history(LinphoneCore *lc) { char *buf; uint64_t begin,end; if (!lc || lc->logs_db == NULL) return NULL; - ms_list_for_each(lc->call_logs, (void (*)(void*))linphone_call_log_unref); - lc->call_logs = ms_list_free(lc->call_logs); + lc->call_logs = ms_list_free_with_data(lc->call_logs, (void (*)(void*))linphone_call_log_unref); buf = sqlite3_mprintf("SELECT * FROM call_history ORDER BY id ASC LIMIT %i", lc->max_call_logs); begin = ortp_get_cur_time_ms(); - linphone_sql_request_call_log(lc->logs_db, buf, lc); + linphone_sql_request_call_log(lc->logs_db, buf, &lc->call_logs); end = ortp_get_cur_time_ms(); ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); sqlite3_free(buf); @@ -509,7 +508,7 @@ MSList *linphone_call_log_get_history(LinphoneCore *lc) { return lc->call_logs; } -void linphone_call_log_delete_history(LinphoneCore *lc) { +void linphone_core_delete_call_history(LinphoneCore *lc) { char *buf; if (!lc || lc->logs_db == NULL) return ; @@ -519,7 +518,7 @@ void linphone_call_log_delete_history(LinphoneCore *lc) { sqlite3_free(buf); } -void linphone_call_log_delete_log(LinphoneCore *lc, LinphoneCallLog *log) { +void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log) { char *buf; if (!lc || lc->logs_db == NULL) return ; @@ -532,7 +531,7 @@ void linphone_call_log_delete_log(LinphoneCore *lc, LinphoneCallLog *log) { linphone_call_log_unref(log); } -int linphone_call_log_get_history_size(LinphoneCore *lc) { +int linphone_core_get_call_history_size(LinphoneCore *lc) { int numrows = 0; char *buf; sqlite3_stmt *selectStatement; @@ -553,60 +552,54 @@ int linphone_call_log_get_history_size(LinphoneCore *lc) { return numrows; } -const MSList * linphone_core_get_call_logs_for_address(LinphoneCore *lc, LinphoneAddress *addr) { +const MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { char *buf; char *sipAddress; uint64_t begin,end; - MSList *result, *tmp; + MSList *result = NULL; if (!lc || lc->logs_db == NULL || addr == NULL) return NULL; - tmp = lc->call_logs; - lc->call_logs = NULL; - /*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/ sipAddress = linphone_address_as_string_uri_only(addr); buf = sqlite3_mprintf("SELECT * FROM call_history WHERE caller LIKE '%%%q%%' OR callee LIKE '%%%q%%' ORDER BY id ASC", sipAddress, sipAddress); // The '%%%q%%' takes care of the eventual presence of a display name begin = ortp_get_cur_time_ms(); - linphone_sql_request_call_log(lc->logs_db, buf, lc); + linphone_sql_request_call_log(lc->logs_db, buf, &result); end = ortp_get_cur_time_ms(); ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); sqlite3_free(buf); ms_free(sipAddress); - result = lc->call_logs; - lc->call_logs = tmp; - tmp = NULL; return result; } #else -void linphone_core_call_log_storage_init(LinphoneCore *lc) { +void linphone_core_call_log_storage_init(LinphoneCore *lc) { } void linphone_core_call_log_storage_close(LinphoneCore *lc) { } -void linphone_call_log_store(LinphoneCore *lc, LinphoneCallLog *log) { +void linphone_core_store_call_log(LinphoneCore *lc, LinphoneCallLog *log) { } -MSList *linphone_call_log_get_history(LinphoneCore *lc) { +const MSList *linphone_core_get_call_history(LinphoneCore *lc) { return NULL; } -void linphone_call_log_delete_history(LinphoneCore *lc) { +void linphone_core_delete_call_history(LinphoneCore *lc) { } -void linphone_call_log_delete_log(LinphoneCore *lc, LinphoneCallLog *log) { +void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log) { } -int linphone_call_log_get_history_size(LinphoneCore *lc) { +int linphone_core_get_call_history_size(LinphoneCore *lc) { return 0; } -const MSList * linphone_core_get_call_logs_for_address(LinphoneCore *lc, LinphoneAddress *addr) { +const MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { return NULL; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 56164bf96..c8d3d458f 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -3946,7 +3946,7 @@ void linphone_call_log_completed(LinphoneCall *call){ ms_free(info); } #ifdef CALL_LOGS_STORAGE_ENABLED - linphone_call_log_store(lc, call->log); + linphone_core_store_call_log(lc, call->log); #else lc->call_logs=ms_list_prepend(lc->call_logs,linphone_call_log_ref(call->log)); if (ms_list_size(lc->call_logs)>lc->max_call_logs){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index f94358d6d..89634e511 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -4945,7 +4945,7 @@ void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *pat const MSList* linphone_core_get_call_logs(LinphoneCore *lc) { #ifdef CALL_LOGS_STORAGE_ENABLED - linphone_call_log_get_history(lc); + linphone_core_get_call_history(lc); #endif return lc->call_logs; } @@ -4953,7 +4953,7 @@ const MSList* linphone_core_get_call_logs(LinphoneCore *lc) { void linphone_core_clear_call_logs(LinphoneCore *lc) { lc->missed_calls=0; #ifdef CALL_LOGS_STORAGE_ENABLED - linphone_call_log_delete_history(lc); + linphone_core_delete_call_history(lc); #else ms_list_for_each(lc->call_logs, (void (*)(void*))linphone_call_log_unref); lc->call_logs = ms_list_free(lc->call_logs); @@ -4971,7 +4971,7 @@ void linphone_core_reset_missed_calls_count(LinphoneCore *lc) { void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){ #ifdef CALL_LOGS_STORAGE_ENABLED - linphone_call_log_delete_log(lc, cl); + linphone_core_delete_call_log(lc, cl); #else lc->call_logs = ms_list_remove(lc->call_logs, cl); call_logs_write_to_config_file(lc); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 6e3f84cd5..9a0e215bb 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -3176,7 +3176,7 @@ LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); * @param[in] lc LinphoneCore object * @return \mslist{LinphoneCallLog} **/ -LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs_for_address(LinphoneCore *lc, LinphoneAddress *addr); +LINPHONE_PUBLIC const MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr); /** * Erase the call log. diff --git a/coreapi/private.h b/coreapi/private.h index 045606e9f..55d7402f8 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -969,11 +969,11 @@ void call_logs_read_from_config_file(LinphoneCore *lc); void call_logs_write_to_config_file(LinphoneCore *lc); void linphone_core_call_log_storage_init(LinphoneCore *lc); void linphone_core_call_log_storage_close(LinphoneCore *lc); -void linphone_call_log_store(LinphoneCore *lc, LinphoneCallLog *log); -MSList *linphone_call_log_get_history(LinphoneCore *lc); -void linphone_call_log_delete_history(LinphoneCore *lc); -void linphone_call_log_delete_log(LinphoneCore *lc, LinphoneCallLog *log); -int linphone_call_log_get_history_size(LinphoneCore *lc); +void linphone_core_store_call_log(LinphoneCore *lc, LinphoneCallLog *log); +const MSList *linphone_core_get_call_history(LinphoneCore *lc); +void linphone_core_delete_call_history(LinphoneCore *lc); +void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log); +int linphone_core_get_call_history_size(LinphoneCore *lc); int linphone_core_get_edge_bw(LinphoneCore *lc); int linphone_core_get_edge_ptime(LinphoneCore *lc); From e35ac5dc77110bc6d6df9f673682bdaa9f44d153 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 15:26:35 +0200 Subject: [PATCH 03/13] Fix API + added test for call log sql storage --- coreapi/call_log.c | 4 ++-- coreapi/linphonecore.h | 2 +- tester/call_tester.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/coreapi/call_log.c b/coreapi/call_log.c index d40260166..1bdc13148 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -552,7 +552,7 @@ int linphone_core_get_call_history_size(LinphoneCore *lc) { return numrows; } -const MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { +MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { char *buf; char *sipAddress; uint64_t begin,end; @@ -599,7 +599,7 @@ int linphone_core_get_call_history_size(LinphoneCore *lc) { return 0; } -const MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { +MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { return NULL; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 9a0e215bb..71e6402d3 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -3176,7 +3176,7 @@ LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); * @param[in] lc LinphoneCore object * @return \mslist{LinphoneCallLog} **/ -LINPHONE_PUBLIC const MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr); +LINPHONE_PUBLIC MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr); /** * Erase the call log. diff --git a/tester/call_tester.c b/tester/call_tester.c index 953632bb7..a962844e5 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4901,6 +4901,37 @@ static void call_record_with_custom_rtp_modifier(void) { custom_rtp_modifier(FALSE, TRUE); } +static void call_logs_sqlite_storage() { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + char *logs_db = bc_tester_file("logs.db"); + MSList *logs = NULL; + LinphoneAddress *pauline = NULL; + LinphoneAddress *laure = NULL; + + linphone_core_set_call_logs_database_path(marie->lc, logs_db); + + BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); + + simple_call_base(FALSE); + + BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); + + pauline = linphone_address_new("\"Pauline\" "); + logs = linphone_core_get_call_history_for_address(marie->lc, pauline); + BC_ASSERT_TRUE(ms_list_size(logs) == 1); + ms_list_free_with_data(logs, (void (*)(void*))linphone_call_log_unref); + ms_free(pauline); + + pauline = linphone_address_new("\"Laure\" "); + logs = linphone_core_get_call_history_for_address(marie->lc, laure); + BC_ASSERT_TRUE(ms_list_size(logs) == 0); + ms_free(laure); + + linphone_core_manager_destroy(marie); + remove(logs_db); + ms_free(logs_db); +} + test_t call_tests[] = { { "Early declined call", early_declined_call }, { "Call declined", call_declined }, @@ -5031,6 +5062,9 @@ test_t call_tests[] = { { "Call with RTP IO mode", call_with_rtp_io_mode }, { "Call with generic NACK RTCP feedback", call_with_generic_nack_rtcp_feedback }, { "Call with complex late offering", call_with_complex_late_offering }, +#ifdef CALL_LOGS_STORAGE_ENABLED + { "Call log storage in sqlite database", call_logs_sqlite_storage }, +#endif { "Call with custom RTP Modifier", call_with_custom_rtp_modifier }, { "Call paused resumed with custom RTP Modifier", call_paused_resumed_with_custom_rtp_modifier }, { "Call record with custom RTP Modifier", call_record_with_custom_rtp_modifier } From d3416ec49504cbecf37c2d7ac143372fe9a17b8e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 15:41:48 +0200 Subject: [PATCH 04/13] Fix previous test + fix compil when sqlite is disabled --- tester/call_tester.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tester/call_tester.c b/tester/call_tester.c index a962844e5..e10e26a15 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4901,8 +4901,11 @@ static void call_record_with_custom_rtp_modifier(void) { custom_rtp_modifier(FALSE, TRUE); } +#ifdef CALL_LOGS_STORAGE_ENABLED + static void call_logs_sqlite_storage() { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); char *logs_db = bc_tester_file("logs.db"); MSList *logs = NULL; LinphoneAddress *pauline = NULL; @@ -4912,7 +4915,7 @@ static void call_logs_sqlite_storage() { BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); - simple_call_base(FALSE); + BC_ASSERT_TRUE((call_ok=call(pauline,marie))); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); @@ -4932,6 +4935,8 @@ static void call_logs_sqlite_storage() { ms_free(logs_db); } +#endif + test_t call_tests[] = { { "Early declined call", early_declined_call }, { "Call declined", call_declined }, From 6863508cb9a1d1dcb1472ab4f3fb1dfa66afa31f Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 15:45:39 +0200 Subject: [PATCH 05/13] Fix mistake in tester preventing compilation --- tester/call_tester.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tester/call_tester.c b/tester/call_tester.c index e10e26a15..4ae2d7784 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4908,24 +4908,24 @@ static void call_logs_sqlite_storage() { LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); char *logs_db = bc_tester_file("logs.db"); MSList *logs = NULL; - LinphoneAddress *pauline = NULL; + LinphoneAddress *pauline_addr = NULL; LinphoneAddress *laure = NULL; linphone_core_set_call_logs_database_path(marie->lc, logs_db); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); - BC_ASSERT_TRUE((call_ok=call(pauline,marie))); + BC_ASSERT_TRUE(call(pauline,marie)); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); - pauline = linphone_address_new("\"Pauline\" "); - logs = linphone_core_get_call_history_for_address(marie->lc, pauline); + pauline_addr = linphone_address_new("\"Pauline\" "); + logs = linphone_core_get_call_history_for_address(marie->lc, pauline_addr); BC_ASSERT_TRUE(ms_list_size(logs) == 1); ms_list_free_with_data(logs, (void (*)(void*))linphone_call_log_unref); - ms_free(pauline); + ms_free(pauline_addr); - pauline = linphone_address_new("\"Laure\" "); + laure = linphone_address_new("\"Laure\" "); logs = linphone_core_get_call_history_for_address(marie->lc, laure); BC_ASSERT_TRUE(ms_list_size(logs) == 0); ms_free(laure); From c42efa7ff0a55f58cde41ee9fe81e0ed6d48c3c7 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 15:50:09 +0200 Subject: [PATCH 06/13] Wait for call to end before checking call log db --- tester/call_tester.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tester/call_tester.c b/tester/call_tester.c index 4ae2d7784..412f6b60e 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4916,6 +4916,8 @@ static void call_logs_sqlite_storage() { BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); BC_ASSERT_TRUE(call(pauline,marie)); + wait_for_until(pauline->lc, marie->lc, NULL, 5, 3000); + end_call(pauline, marie); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); From a1352737714dd8d0c7d5222c7a7e799df9d83c30 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 16:12:44 +0200 Subject: [PATCH 07/13] Small improvement of call log storage API + forgot to free pauline lc in tester + fix test --- coreapi/call_log.c | 4 ++-- coreapi/linphonecore.h | 2 +- tester/call_tester.c | 10 ++++------ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/coreapi/call_log.c b/coreapi/call_log.c index 1bdc13148..cc378d879 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -552,7 +552,7 @@ int linphone_core_get_call_history_size(LinphoneCore *lc) { return numrows; } -MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { +MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, const LinphoneAddress *addr) { char *buf; char *sipAddress; uint64_t begin,end; @@ -599,7 +599,7 @@ int linphone_core_get_call_history_size(LinphoneCore *lc) { return 0; } -MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr) { +MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, const LinphoneAddress *addr) { return NULL; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 71e6402d3..f7ef79394 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -3176,7 +3176,7 @@ LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); * @param[in] lc LinphoneCore object * @return \mslist{LinphoneCallLog} **/ -LINPHONE_PUBLIC MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, LinphoneAddress *addr); +LINPHONE_PUBLIC MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, const LinphoneAddress *addr); /** * Erase the call log. diff --git a/tester/call_tester.c b/tester/call_tester.c index 412f6b60e..06747df06 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4906,9 +4906,8 @@ static void call_record_with_custom_rtp_modifier(void) { static void call_logs_sqlite_storage() { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); - char *logs_db = bc_tester_file("logs.db"); + char *logs_db = create_filepath(bc_tester_get_writable_dir_prefix(), "call_logs", "db"); MSList *logs = NULL; - LinphoneAddress *pauline_addr = NULL; LinphoneAddress *laure = NULL; linphone_core_set_call_logs_database_path(marie->lc, logs_db); @@ -4916,16 +4915,14 @@ static void call_logs_sqlite_storage() { BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); BC_ASSERT_TRUE(call(pauline,marie)); - wait_for_until(pauline->lc, marie->lc, NULL, 5, 3000); + wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000); end_call(pauline, marie); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); - pauline_addr = linphone_address_new("\"Pauline\" "); - logs = linphone_core_get_call_history_for_address(marie->lc, pauline_addr); + logs = linphone_core_get_call_history_for_address(marie->lc, linphone_proxy_config_get_identity_address(linphone_core_get_default_proxy_config(pauline->lc))); BC_ASSERT_TRUE(ms_list_size(logs) == 1); ms_list_free_with_data(logs, (void (*)(void*))linphone_call_log_unref); - ms_free(pauline_addr); laure = linphone_address_new("\"Laure\" "); logs = linphone_core_get_call_history_for_address(marie->lc, laure); @@ -4933,6 +4930,7 @@ static void call_logs_sqlite_storage() { ms_free(laure); linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); remove(logs_db); ms_free(logs_db); } From e47839c3e4f022851d958b39c706afb3833465e7 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 16:21:03 +0200 Subject: [PATCH 08/13] Added test for delete log and delete log history functions --- tester/call_tester.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tester/call_tester.c b/tester/call_tester.c index 06747df06..1b0f3b1a0 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4911,13 +4911,11 @@ static void call_logs_sqlite_storage() { LinphoneAddress *laure = NULL; linphone_core_set_call_logs_database_path(marie->lc, logs_db); - BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); BC_ASSERT_TRUE(call(pauline,marie)); wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000); end_call(pauline, marie); - BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); logs = linphone_core_get_call_history_for_address(marie->lc, linphone_proxy_config_get_identity_address(linphone_core_get_default_proxy_config(pauline->lc))); @@ -4928,6 +4926,23 @@ static void call_logs_sqlite_storage() { logs = linphone_core_get_call_history_for_address(marie->lc, laure); BC_ASSERT_TRUE(ms_list_size(logs) == 0); ms_free(laure); + + logs = linphone_core_get_call_history_for_address(marie->lc, linphone_proxy_config_get_identity_address(linphone_core_get_default_proxy_config(pauline->lc))); + BC_ASSERT_TRUE(ms_list_size(logs) == 1); + linphone_core_delete_call_log(marie->lc, (LinphoneCallLog *)ms_list_nth_data(logs, 0)); + ms_list_free_with_data(logs, (void (*)(void*))linphone_call_log_unref); + BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); + + BC_ASSERT_TRUE(call(pauline,marie)); + wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000); + end_call(pauline, marie); + BC_ASSERT_TRUE(call(pauline,marie)); + wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000); + end_call(pauline, marie); + BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 2); + + linphone_core_delete_call_history(marie->lc); + BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); From d77e344d325753a9210f13042a7b7624e877b49e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 16:33:31 +0200 Subject: [PATCH 09/13] Fix call log sqlite storage test --- tester/call_tester.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tester/call_tester.c b/tester/call_tester.c index 1b0f3b1a0..9b95b1b25 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4913,9 +4913,9 @@ static void call_logs_sqlite_storage() { linphone_core_set_call_logs_database_path(marie->lc, logs_db); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); - BC_ASSERT_TRUE(call(pauline,marie)); - wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000); - end_call(pauline, marie); + BC_ASSERT_TRUE(call(marie, pauline)); + wait_for_until(marie->lc, pauline->lc, NULL, 5, 1000); + end_call(marie, pauline); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); logs = linphone_core_get_call_history_for_address(marie->lc, linphone_proxy_config_get_identity_address(linphone_core_get_default_proxy_config(pauline->lc))); @@ -4933,12 +4933,12 @@ static void call_logs_sqlite_storage() { ms_list_free_with_data(logs, (void (*)(void*))linphone_call_log_unref); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 0); - BC_ASSERT_TRUE(call(pauline,marie)); - wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000); - end_call(pauline, marie); - BC_ASSERT_TRUE(call(pauline,marie)); - wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000); - end_call(pauline, marie); + BC_ASSERT_TRUE(call(marie, pauline)); + wait_for_until(marie->lc, pauline->lc, NULL, 5, 1000); + end_call(marie, pauline); + BC_ASSERT_TRUE(call(marie, pauline)); + wait_for_until(marie->lc, pauline->lc, NULL, 5, 1000); + end_call(marie, pauline); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 2); linphone_core_delete_call_history(marie->lc); From 1617069f6a5fea9e974a5414dc80508908871455 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 21:44:50 +0200 Subject: [PATCH 10/13] Few fixes + added migrate method from rc store logs --- coreapi/call_log.c | 13 ++++----- coreapi/linphonecore.c | 66 ++++++++++++++++++++++++++++++++++++++++-- coreapi/linphonecore.h | 7 +++++ gtk/main.c | 4 +++ 4 files changed, 80 insertions(+), 10 deletions(-) diff --git a/coreapi/call_log.c b/coreapi/call_log.c index cc378d879..b3d9cbb75 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -376,7 +376,7 @@ void linphone_core_call_log_storage_init(LinphoneCore *lc) { const char *errmsg; sqlite3 *db; - linphone_core_message_storage_close(lc); + linphone_core_call_log_storage_close(lc); ret=_linphone_sqlite3_open(lc->logs_db_file, &db); if(ret != SQLITE_OK) { @@ -433,7 +433,7 @@ static int create_call_log(void *data, int argc, char **argv, char **colName) { log->video_enabled = atoi(argv[8]) == 1; log->quality = atof(argv[9]); - *list = ms_list_prepend(*list, log); + *list = ms_list_append(*list, log); return 0; } @@ -443,7 +443,7 @@ void linphone_sql_request_call_log(sqlite3 *db, const char *stmt, MSList **list) int ret; ret = sqlite3_exec(db, stmt, create_call_log, list, &errmsg); if (ret != SQLITE_OK) { - ms_error("Error in creation: %s.", errmsg); + ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg); sqlite3_free(errmsg); } } @@ -497,7 +497,7 @@ const MSList *linphone_core_get_call_history(LinphoneCore *lc) { lc->call_logs = ms_list_free_with_data(lc->call_logs, (void (*)(void*))linphone_call_log_unref); - buf = sqlite3_mprintf("SELECT * FROM call_history ORDER BY id ASC LIMIT %i", lc->max_call_logs); + buf = sqlite3_mprintf("SELECT * FROM call_history ORDER BY id DESC LIMIT %i", lc->max_call_logs); begin = ortp_get_cur_time_ms(); linphone_sql_request_call_log(lc->logs_db, buf, &lc->call_logs); @@ -526,9 +526,6 @@ void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log) { buf = sqlite3_mprintf("DELETE FROM call_history WHERE id = %i", log->storage_id); linphone_sql_request_generic(lc->logs_db, buf); sqlite3_free(buf); - - lc->call_logs = ms_list_remove(lc->call_logs, log); - linphone_call_log_unref(log); } int linphone_core_get_call_history_size(LinphoneCore *lc) { @@ -562,7 +559,7 @@ MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, const Linp /*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/ sipAddress = linphone_address_as_string_uri_only(addr); - buf = sqlite3_mprintf("SELECT * FROM call_history WHERE caller LIKE '%%%q%%' OR callee LIKE '%%%q%%' ORDER BY id ASC", sipAddress, sipAddress); // The '%%%q%%' takes care of the eventual presence of a display name + buf = sqlite3_mprintf("SELECT * FROM call_history WHERE caller LIKE '%%%q%%' OR callee LIKE '%%%q%%' ORDER BY id DESC", sipAddress, sipAddress); // The '%%%q%%' takes care of the eventual presence of a display name begin = ortp_get_cur_time_ms(); linphone_sql_request_call_log(lc->logs_db, buf, &result); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 89634e511..a82f98f00 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -4932,7 +4932,7 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) * Call log related functions * ******************************************************************************/ -void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *path){ +void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *path) { if (lc->logs_db_file){ ms_free(lc->logs_db_file); lc->logs_db_file = NULL; @@ -4940,6 +4940,8 @@ void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *pat if (path) { lc->logs_db_file = ms_strdup(path); linphone_core_call_log_storage_init(lc); + + linphone_core_migrate_logs_from_rc_to_db(lc); } } @@ -4969,7 +4971,7 @@ void linphone_core_reset_missed_calls_count(LinphoneCore *lc) { lc->missed_calls=0; } -void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){ +void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl) { #ifdef CALL_LOGS_STORAGE_ENABLED linphone_core_delete_call_log(lc, cl); #else @@ -4979,6 +4981,66 @@ void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){ #endif } +void linphone_core_migrate_logs_from_rc_to_db(LinphoneCore *lc) { + MSList *logs_to_migrate = NULL; + LpConfig *lpc = NULL; + int original_logs_count, migrated_logs_count; + int i; + +#ifndef CALL_LOGS_STORAGE_ENABLED + ms_warning("linphone has been compiled without sqlite, can't migrate call logs"); + return; +#endif + if (!lc) { + return; + } + + lpc = linphone_core_get_config(lc); + if (!lpc) { + ms_warning("this core has been started without a rc file, nothing to migrate"); + return; + } + if (lp_config_get_int(lpc, "misc", "call_logs_migration_done", 0) == 1) { + ms_warning("the call logs migration has already been done, skipping..."); + return; + } + + // This is because there must have been a call previously to linphone_core_call_log_storage_init + lc->call_logs = ms_list_free_with_data(lc->call_logs, (void (*)(void*))linphone_call_log_unref); + + call_logs_read_from_config_file(lc); + if (!lc->call_logs) { + ms_warning("nothing to migrate, skipping..."); + return; + } + + logs_to_migrate = lc->call_logs; + lc->call_logs = NULL; + // We can't use ms_list_for_each because logs_to_migrate are listed in the wrong order (latest first), and we want to store the logs latest last + for (i = ms_list_size(logs_to_migrate) - 1; i >= 0; i--) { + LinphoneCallLog *log = (LinphoneCallLog *) ms_list_nth_data(logs_to_migrate, i); + linphone_core_store_call_log(lc, log); + } + + original_logs_count = ms_list_size(logs_to_migrate); + migrated_logs_count = ms_list_size(lc->call_logs); + if (original_logs_count == migrated_logs_count) { + int i = 0; + ms_debug("call logs migration successful: %i logs migrated", ms_list_size(lc->call_logs)); + lp_config_set_int(lpc, "misc", "call_logs_migration_done", 1); + + for (; i < original_logs_count; i++) { + char logsection[32]; + snprintf(logsection, sizeof(logsection), "call_log_%i", i); + lp_config_clean_section(lpc, logsection); + } + } else { + ms_error("not as many logs saved in db has logs read from rc (%i in rc against %i in db)!", original_logs_count, migrated_logs_count); + } + + ms_list_free_with_data(logs_to_migrate, (void (*)(void*))linphone_call_log_unref); +} + /******************************************************************************* * Video related functions * diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index f7ef79394..b31909941 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -3215,6 +3215,13 @@ LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCal **/ LINPHONE_PUBLIC void linphone_core_set_call_logs_database_path(LinphoneCore *lc, const char *path); +/** + * Migrates the call logs from the linphonerc to the database if not done yet + * @ingroup initializing + * @param lc the linphone core +**/ +LINPHONE_PUBLIC void linphone_core_migrate_logs_from_rc_to_db(LinphoneCore *lc); + /** * @} **/ diff --git a/gtk/main.c b/gtk/main.c index c4c332bb3..8c9ebac24 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1900,7 +1900,9 @@ static void linphone_gtk_init_main_window(){ linphone_gtk_show_friends(); linphone_core_reset_missed_calls_count(linphone_gtk_get_core()); main_window=linphone_gtk_get_main_window(); +#ifndef CALL_LOGS_STORAGE_ENABLED linphone_gtk_call_log_update(main_window); +#endif linphone_gtk_update_call_buttons (NULL); g_object_set_data(G_OBJECT(main_window),"keypad",NULL); @@ -2220,7 +2222,9 @@ core_start: g_free(chat_messages_db_file); g_free(call_logs_db_file); +#ifdef CALL_LOGS_STORAGE_ENABLED linphone_gtk_call_log_update(the_ui); +#endif /* do not lower timeouts under 30 ms because it exhibits a bug on gtk+/win32, with cpu running 20% all the time...*/ gtk_timeout_add(30,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core()); From 88e1d8d872c0cff178d4303892be48f529fb12b6 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 8 Sep 2015 22:09:16 +0200 Subject: [PATCH 11/13] Added test to check call log migration --- tester/call_tester.c | 44 ++++++++++++++++ tester/rcfiles/laure_call_logs_rc | 87 +++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 tester/rcfiles/laure_call_logs_rc diff --git a/tester/call_tester.c b/tester/call_tester.c index 9b95b1b25..d92654672 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4903,6 +4903,49 @@ static void call_record_with_custom_rtp_modifier(void) { #ifdef CALL_LOGS_STORAGE_ENABLED +static void call_logs_migrate() { + LinphoneCoreManager* laure = linphone_core_manager_new("laure_call_logs_rc"); + char *logs_db = create_filepath(bc_tester_get_writable_dir_prefix(), "call_logs", "db"); + int i = 0; + int incoming_count = 0, outgoing_count = 0, missed_count = 0, aborted_count = 0, decline_count = 0, video_enabled_count = 0; + + linphone_core_set_call_logs_database_path(laure->lc, logs_db); + BC_ASSERT_TRUE(linphone_core_get_call_history_size(laure->lc) == 8); + + for (; i < ms_list_size(laure->lc->call_logs); i++) { + LinphoneCallLog *log = ms_list_nth_data(laure->lc->call_logs, i); + LinphoneCallStatus state = linphone_call_log_get_status(log); + LinphoneCallDir direction = linphone_call_log_get_dir(log); + + if (state == LinphoneCallAborted) { + aborted_count += 1; + } else if (state == LinphoneCallMissed) { + missed_count += 1; + } else if (state == LinphoneCallDeclined) { + decline_count += 1; + } + + if (direction == LinphoneCallOutgoing) { + outgoing_count += 1; + } else { + incoming_count += 1; + } + + if (linphone_call_log_video_enabled(log)) { + video_enabled_count += 1; + } + } + BC_ASSERT_TRUE(incoming_count == 4); + BC_ASSERT_TRUE(outgoing_count == 4); + BC_ASSERT_TRUE(missed_count == 1); + BC_ASSERT_TRUE(aborted_count == 3); + BC_ASSERT_TRUE(decline_count == 0); + BC_ASSERT_TRUE(video_enabled_count == 3); + + remove(logs_db); + ms_free(logs_db); +} + static void call_logs_sqlite_storage() { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -5083,6 +5126,7 @@ test_t call_tests[] = { { "Call with generic NACK RTCP feedback", call_with_generic_nack_rtcp_feedback }, { "Call with complex late offering", call_with_complex_late_offering }, #ifdef CALL_LOGS_STORAGE_ENABLED + { "Call log storage migration from rc to db", call_logs_migrate }, { "Call log storage in sqlite database", call_logs_sqlite_storage }, #endif { "Call with custom RTP Modifier", call_with_custom_rtp_modifier }, diff --git a/tester/rcfiles/laure_call_logs_rc b/tester/rcfiles/laure_call_logs_rc new file mode 100644 index 000000000..ca13605b7 --- /dev/null +++ b/tester/rcfiles/laure_call_logs_rc @@ -0,0 +1,87 @@ +[call_log_0] +dir=0 +status=0 +from=sip:pauline@sip.linphone.org +to=sip:laure@sip.linphone.org +start_date_time=1441738272 +duration=3 +quality=5.000000 +video_enabled=0 +call_id=o6mx-QSdKJ + +[call_log_1] +dir=0 +status=1 +from=sip:pauline@sip.linphone.org +to=sip:laure@sip.linphone.org +start_date_time=1441738266 +duration=0 +quality=-1.000000 +video_enabled=0 +call_id=wnXDtOhURa + +[call_log_2] +dir=1 +status=2 +from=sip:laure@sip.linphone.org +to=sip:pauline@sip.linphone.org +start_date_time=1441738258 +duration=0 +quality=-1.000000 +video_enabled=0 +call_id=81ZldO6dlk + +[call_log_3] +dir=1 +status=1 +from=sip:laure@sip.linphone.org +to=sip:pauline@sip.linphone.org +start_date_time=1441738250 +duration=0 +quality=-1.000000 +video_enabled=0 +call_id=3yq7TlwS8Q + +[call_log_4] +dir=1 +status=0 +from=sip:laure@sip.linphone.org +to=sip:pauline@sip.linphone.org +start_date_time=1441738243 +duration=0 +quality=-1.000000 +video_enabled=1 +call_id=EmoqEyeLbZ + +[call_log_5] +dir=0 +status=1 +from=sip:pauline@sip.linphone.org +to=sip:laure@sip.linphone.org +start_date_time=1441738234 +duration=0 +quality=-1.000000 +video_enabled=0 +call_id=xl29jqHZ2N + +[call_log_6] +dir=1 +status=0 +from=sip:laure@sip.linphone.org +to=sip:pauline@sip.linphone.org +start_date_time=1441738215 +duration=6 +quality=4.898808 +video_enabled=1 +call_id=2JNrT43eji + +[call_log_7] +dir=0 +status=0 +from=sip:pauline@sip.linphone.org +to=sip:laure@sip.linphone.org +start_date_time=1441738200 +duration=5 +quality=4.715808 +video_enabled=1 +call_id=joyRwGhk-2 From d3685c38fa051562f26bb4635d823537722b65af Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 9 Sep 2015 09:41:05 +0200 Subject: [PATCH 12/13] Improved call logs migration tester --- tester/call_tester.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tester/call_tester.c b/tester/call_tester.c index d92654672..c1d6aab3a 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4909,6 +4909,9 @@ static void call_logs_migrate() { int i = 0; int incoming_count = 0, outgoing_count = 0, missed_count = 0, aborted_count = 0, decline_count = 0, video_enabled_count = 0; + call_logs_read_from_config_file(laure->lc); + BC_ASSERT_TRUE(ms_list_size(laure->lc->call_logs) == 8); + linphone_core_set_call_logs_database_path(laure->lc, logs_db); BC_ASSERT_TRUE(linphone_core_get_call_history_size(laure->lc) == 8); @@ -4942,8 +4945,13 @@ static void call_logs_migrate() { BC_ASSERT_TRUE(decline_count == 0); BC_ASSERT_TRUE(video_enabled_count == 3); + laure->lc->call_logs = ms_list_free_with_data(laure->lc->call_logs, (void (*)(void*))linphone_call_log_unref); + call_logs_read_from_config_file(laure->lc); + BC_ASSERT_TRUE(ms_list_size(laure->lc->call_logs) == 0); + remove(logs_db); ms_free(logs_db); + linphone_core_manager_destroy(laure); } static void call_logs_sqlite_storage() { From 312dd45ede3441a44920ace0848584e62822ba05 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 10 Sep 2015 10:58:50 +0200 Subject: [PATCH 13/13] Added test for declined call logs --- tester/call_tester.c | 10 +++++----- tester/rcfiles/laure_call_logs_rc | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/tester/call_tester.c b/tester/call_tester.c index c1d6aab3a..6ff72da79 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -4910,10 +4910,10 @@ static void call_logs_migrate() { int incoming_count = 0, outgoing_count = 0, missed_count = 0, aborted_count = 0, decline_count = 0, video_enabled_count = 0; call_logs_read_from_config_file(laure->lc); - BC_ASSERT_TRUE(ms_list_size(laure->lc->call_logs) == 8); + BC_ASSERT_TRUE(ms_list_size(laure->lc->call_logs) == 10); linphone_core_set_call_logs_database_path(laure->lc, logs_db); - BC_ASSERT_TRUE(linphone_core_get_call_history_size(laure->lc) == 8); + BC_ASSERT_TRUE(linphone_core_get_call_history_size(laure->lc) == 10); for (; i < ms_list_size(laure->lc->call_logs); i++) { LinphoneCallLog *log = ms_list_nth_data(laure->lc->call_logs, i); @@ -4938,11 +4938,11 @@ static void call_logs_migrate() { video_enabled_count += 1; } } - BC_ASSERT_TRUE(incoming_count == 4); - BC_ASSERT_TRUE(outgoing_count == 4); + BC_ASSERT_TRUE(incoming_count == 5); + BC_ASSERT_TRUE(outgoing_count == 5); BC_ASSERT_TRUE(missed_count == 1); BC_ASSERT_TRUE(aborted_count == 3); - BC_ASSERT_TRUE(decline_count == 0); + BC_ASSERT_TRUE(decline_count == 2); BC_ASSERT_TRUE(video_enabled_count == 3); laure->lc->call_logs = ms_list_free_with_data(laure->lc->call_logs, (void (*)(void*))linphone_call_log_unref); diff --git a/tester/rcfiles/laure_call_logs_rc b/tester/rcfiles/laure_call_logs_rc index ca13605b7..c1ad0f492 100644 --- a/tester/rcfiles/laure_call_logs_rc +++ b/tester/rcfiles/laure_call_logs_rc @@ -85,3 +85,25 @@ duration=5 quality=4.715808 video_enabled=1 call_id=joyRwGhk-2 + +[call_log_8] +dir=1 +status=3 +from=sip:laure@sip.linphone.org +to=sip:pauline@sip.linphone.org +start_date_time=1441738122 +duration=0 +quality=-1.000000 +video_enabled=0 +call_id=az01erTY2U + +[call_log_9] +dir=0 +status=3 +from=sip:pauline@sip.linphone.org +to=sip:laure@sip.linphone.org +start_date_time=1441738031 +duration=0 +quality=-1.000000 +video_enabled=0 +call_id=jk39dfZP0L