Commit d1f7e4d7 authored by Benjamin REIS's avatar Benjamin REIS

Add friends_map_uri to LinphoneFriendList

parent 97600a4b
......@@ -288,45 +288,65 @@ const LinphoneAddress * linphone_friend_get_address(const LinphoneFriend *lf) {
int linphone_friend_set_address(LinphoneFriend *lf, const LinphoneAddress *addr) {
LinphoneAddress *fr = linphone_address_clone(addr);
char *address;
LinphoneAddress *mAddr = linphone_friend_get_address(lf);
if(mAddr && lf->friend_list) {
char *mainAddress = linphone_address_as_string_uri_only(mAddr);
bctbx_iterator_t *it = bctbx_map_cchar_find_key(lf->friend_list->friends_map_uri, mainAddress);
if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(lf->friend_list->friends_map_uri))){
linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it)));
bctbx_map_cchar_erase(lf->friend_list->friends_map_uri, it);
}
bctbx_iterator_cchar_delete(it);
}
linphone_address_clean(fr);
address = linphone_address_as_string_uri_only(fr);
if(lf->friend_list) {
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(address, linphone_friend_ref(lf));
ms_message("inserting %s in map with friend [%p]", address, lf);
bctbx_map_cchar_insert_and_delete(lf->friend_list->friends_map_uri, pair);
}
if (linphone_core_vcard_supported()) {
char *address;
if (!lf->vcard) {
const char *dpname = linphone_address_get_display_name(fr) ? linphone_address_get_display_name(fr) : linphone_address_get_username(fr);
linphone_friend_create_vcard(lf, dpname);
}
address = linphone_address_as_string_uri_only(fr);
linphone_vcard_edit_main_sip_address(lf->vcard, address);
ms_free(address);
linphone_address_unref(fr);
} else {
if (lf->uri != NULL) linphone_address_unref(lf->uri);
lf->uri = fr;
}
ms_free(address);
return 0;
}
void linphone_friend_add_address(LinphoneFriend *lf, const LinphoneAddress *addr) {
LinphoneAddress *fr;
const char *uri;
if (!lf || !addr) return;
fr = linphone_address_clone(addr);
linphone_address_clean(fr);
uri = linphone_address_as_string_uri_only(fr);
if(lf->friend_list) {
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(uri, linphone_friend_ref(lf));
ms_message("inserting %s in map with friend [%p]", uri, lf);
bctbx_map_cchar_insert_and_delete(lf->friend_list->friends_map_uri, pair);
}
if (linphone_core_vcard_supported()) {
if (lf->vcard) {
char *address = linphone_address_as_string_uri_only(fr);
linphone_vcard_add_sip_address(lf->vcard, address);
ms_free(address);
linphone_vcard_add_sip_address(lf->vcard, uri);
linphone_address_unref(fr);
}
} else {
if (lf->uri == NULL) lf->uri = fr;
else linphone_address_unref(fr);
}
ms_free(uri);
}
const bctbx_list_t* linphone_friend_get_addresses(const LinphoneFriend *lf) {
......@@ -342,18 +362,37 @@ const bctbx_list_t* linphone_friend_get_addresses(const LinphoneFriend *lf) {
}
void linphone_friend_remove_address(LinphoneFriend *lf, const LinphoneAddress *addr) {
char *address ;
if (!lf || !addr || !lf->vcard) return;
address = linphone_address_as_string_uri_only(addr);
if(lf->friend_list) {
bctbx_iterator_t *it = bctbx_map_cchar_find_key(lf->friend_list->friends_map_uri, address);
if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(lf->friend_list->friends_map_uri))){
linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it)));
bctbx_map_cchar_erase(lf->friend_list->friends_map_uri, it);
}
bctbx_iterator_cchar_delete(it);
}
if (linphone_core_vcard_supported()) {
char *address = linphone_address_as_string_uri_only(addr);
linphone_vcard_remove_sip_address(lf->vcard, address);
ms_free(address);
}
ms_free(address);
}
void linphone_friend_add_phone_number(LinphoneFriend *lf, const char *phone) {
if (!lf || !phone) return;
if(lf->friend_list) {
const char *uri = linphone_friend_phone_number_to_sip_uri(lf, phone);
if(uri) {
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(uri, linphone_friend_ref(lf));
bctbx_map_cchar_insert_and_delete(lf->friend_list->friends_map_uri, pair);
ms_free(uri);
}
}
if (linphone_core_vcard_supported()) {
if (!lf->vcard) {
linphone_friend_create_vcard(lf, phone);
......@@ -374,6 +413,19 @@ bctbx_list_t* linphone_friend_get_phone_numbers(LinphoneFriend *lf) {
void linphone_friend_remove_phone_number(LinphoneFriend *lf, const char *phone) {
if (!lf || !phone || !lf->vcard) return;
if(lf->friend_list) {
const char *uri = linphone_friend_phone_number_to_sip_uri(lf, phone);
if(uri) {
bctbx_iterator_t *it = bctbx_map_cchar_find_key(lf->friend_list->friends_map_uri, uri);
if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(lf->friend_list->friends_map_uri))){
linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it)));
bctbx_map_cchar_erase(lf->friend_list->friends_map_uri, it);
}
bctbx_iterator_cchar_delete(it);
ms_free(uri);
}
}
if (linphone_core_vcard_supported()) {
linphone_vcard_remove_phone_number(lf->vcard, phone);
}
......@@ -1539,6 +1591,9 @@ bctbx_list_t* linphone_core_fetch_friends_from_db(LinphoneCore *lc, LinphoneFrie
sqlite3_free(buf);
for(elem = result; elem != NULL; elem = bctbx_list_next(elem)) {
bctbx_list_t *iterator;
bctbx_list_t *phone_numbers;
const bctbx_list_t *addresses;
LinphoneFriend *lf = (LinphoneFriend *)bctbx_list_get_data(elem);
lf->lc = lc;
lf->friend_list = list;
......@@ -1546,6 +1601,33 @@ bctbx_list_t* linphone_core_fetch_friends_from_db(LinphoneCore *lc, LinphoneFrie
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(lf->refkey, linphone_friend_ref(lf));
bctbx_map_cchar_insert_and_delete(list->friends_map, pair);
}
phone_numbers = linphone_friend_get_phone_numbers(lf);
iterator = phone_numbers;
while (iterator) {
const char *number = (const char *)bctbx_list_get_data(iterator);
const char *uri = linphone_friend_phone_number_to_sip_uri(lf, number);
if(uri) {
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(uri, linphone_friend_ref(lf));
bctbx_map_cchar_insert_and_delete(list->friends_map_uri, pair);
ms_free(uri);
}
iterator = bctbx_list_next(iterator);
}
addresses = linphone_friend_get_addresses(lf);
iterator = (bctbx_list_t *)addresses;
while (iterator) {
LinphoneAddress *lfaddr = (LinphoneAddress *)bctbx_list_get_data(iterator);
char *uri = linphone_address_as_string_uri_only(lfaddr);
if(uri) {
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(uri, linphone_friend_ref(lf));
bctbx_map_cchar_insert_and_delete(list->friends_map_uri, pair);
ms_free(uri);
}
iterator = bctbx_list_next(iterator);
}
linphone_friend_save(lf, lc); /* required if we freshly created vcard but core was not set at this time */
}
linphone_vcard_context_set_user_data(lc->vcard_context, NULL);
......@@ -1702,7 +1784,7 @@ const char * linphone_friend_phone_number_to_sip_uri(LinphoneFriend *lf, const c
lfpnsu = (LinphoneFriendPhoneNumberSipUri *)bctbx_list_get_data(iterator);
if (strcmp(lfpnsu->number, phone_number) == 0) {
/*force sip uri computation because proxy config may have changed, specially, ccc could have been added since last computation*/
free_phone_number_sip_uri(lfpnsu);
//free_phone_number_sip_uri(lfpnsu);
if (lf->phone_number_sip_uri_map == iterator) {
/*change list head if head is removed*/
iterator = lf->phone_number_sip_uri_map = bctbx_list_erase_link(lf->phone_number_sip_uri_map, iterator);
......@@ -1720,6 +1802,25 @@ const char * linphone_friend_phone_number_to_sip_uri(LinphoneFriend *lf, const c
normalized_number = linphone_proxy_config_normalize_phone_number(proxy_config, phone_number);
if (!normalized_number) return NULL;
full_uri = ms_strdup_printf("sip:%s@%s;user=phone", normalized_number, linphone_proxy_config_get_domain(proxy_config));
if(strcmp(normalized_number, phone_number) != 0) {
char *old_uri = ms_strdup_printf("sip:%s@%s;user=phone", phone_number, linphone_proxy_config_get_domain(proxy_config));
if(linphone_friend_list_find_friend_by_uri(lf->friend_list, old_uri)) {
bctbx_iterator_t *it = bctbx_map_cchar_find_key(lf->friend_list->friends_map_uri, old_uri);
if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(lf->friend_list->friends_map_uri))){
linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it)));
bctbx_map_cchar_erase(lf->friend_list->friends_map_uri, it);
}
bctbx_iterator_cchar_delete(it);
}
ms_free(old_uri);
}
if(!linphone_friend_list_find_friend_by_uri(lf->friend_list, full_uri)) {
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(full_uri, linphone_friend_ref(lf));
bctbx_map_cchar_insert_and_delete(lf->friend_list->friends_map_uri, pair);
}
ms_free(normalized_number);
lfpnsu = ms_new0(LinphoneFriendPhoneNumberSipUri, 1);
lfpnsu->number = ms_strdup(phone_number);
......
This diff is collapsed.
......@@ -784,6 +784,7 @@ struct _LinphoneFriendList {
LinphoneAddress *rls_addr;
MSList *friends;
bctbx_map_t *friends_map;
bctbx_map_t *friends_map_uri;
unsigned char *content_digest;
int expected_notification_version;
unsigned int storage_id;
......
......@@ -246,6 +246,7 @@ static bool_t subscribe_to_callee_presence(LinphoneCoreManager* caller_mgr,Linph
}
/* BEWARE this test will fail if the machine it is run on is behind an active firewall not sending ICMP errors on incoming connections! */
/* It will create a leak of NOTIFY because during marie error after network switch off, Pauline will never received the acknowledgement of the notify ...*/
static void subscribe_failure_handle_by_app(void) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_tcp_rc");
......
......@@ -374,6 +374,159 @@ end:
unlink(friends_db);
bc_free(friends_db);
}
static void friends_sqlite_store_lot_of_friends(void) {
LinphoneCoreVTable *v_table = linphone_core_v_table_new();
LinphoneCore* lc = linphone_core_new(v_table, NULL, NULL, NULL);
sqlite3 *db;
int i;
char* errmsg = NULL;
char *key;
int ret;
char *buf;
ret = sqlite3_open(lc->friends_db_file, &db);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,
"CREATE TABLE IF NOT EXISTS friends ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"friend_list_id INTEGER,"
"sip_uri TEXT,"
"subscribe_policy INTEGER,"
"send_subscribe INTEGER,"
"ref_key TEXT,"
"vCard TEXT,"
"vCard_etag TEXT,"
"vCard_url TEXT,"
"presence_received INTEGER"
");", 0, 0, &errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,"END",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ms_message("Départ :\n");
ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
for (i = 0; i < 20000; i++) {
buf = sqlite3_mprintf("INSERT INTO friends VALUES(NULL,%u,%Q,%i,%i,'key_%i',%Q,%Q,%Q,%i);",
i,
"dummy_addr",
0,
0,
i,
NULL,
NULL,
NULL,
0
);
ret = sqlite3_exec(db,buf,0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
sqlite3_free(buf);
}
ret = sqlite3_exec(db,"END",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ms_message("Fin :\n");
ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db, "DELETE FROM friends;",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,"END",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
sqlite3_close(db);
linphone_core_destroy(lc);
linphone_core_v_table_destroy(v_table);
}
static void friends_sqlite_find_friend_in_lot_of_friends(void) {
LinphoneCoreVTable *v_table = linphone_core_v_table_new();
LinphoneCore* lc = linphone_core_new(v_table, NULL, NULL, NULL);
sqlite3 *db;
int i;
char* errmsg = NULL;
char *key;
int ret;
char *buf;
bctoolboxTimeSpec t1;
bctoolboxTimeSpec t2;
ret = sqlite3_open(lc->friends_db_file, &db);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,
"CREATE TABLE IF NOT EXISTS friends ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"friend_list_id INTEGER,"
"sip_uri TEXT,"
"subscribe_policy INTEGER,"
"send_subscribe INTEGER,"
"ref_key TEXT,"
"vCard TEXT,"
"vCard_etag TEXT,"
"vCard_url TEXT,"
"presence_received INTEGER"
");", 0, 0, &errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,"END",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
for (i = 0; i < 20000; i++) {
buf = sqlite3_mprintf("INSERT INTO friends VALUES(NULL,%u,%Q,%i,%i,'key_%i',%Q,%Q,%Q,%i);",
i,
"dummy_addr",
0,
0,
i,
NULL,
NULL,
NULL,
0
);
ret = sqlite3_exec(db,buf,0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
sqlite3_free(buf);
//ms_message("%i",i);
}
ret = sqlite3_exec(db,"END",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
bctbx_get_cur_time(&t1);
ms_message("Départ : %li : %li\n", t1.tv_sec, t1.tv_nsec);
for (i = 0; i < 20000; i++) {
buf = sqlite3_mprintf("SELECT * FROM friends WHERE ref_key LIKE 'key_%i';",
i);
ret = sqlite3_exec(db,buf,0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
sqlite3_free(buf);
}
bctbx_get_cur_time(&t2);
ms_message("Fin : %li : %li\n", t2.tv_sec, t2.tv_nsec);
ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db, "DELETE FROM friends;",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
ret = sqlite3_exec(db,"END",0,0,&errmsg);
BC_ASSERT_TRUE(ret ==SQLITE_OK);
sqlite3_close(db);
linphone_core_destroy(lc);
linphone_core_v_table_destroy(v_table);
}
#endif
typedef struct _LinphoneCardDAVStats {
......@@ -812,6 +965,52 @@ end:
linphone_friend_unref(lf);
linphone_core_manager_destroy(manager);
}
static void insert_lot_of_friends_map_test(void) {
int i;
bctbx_map_t *friends_map = bctbx_mmap_cchar_new();
bctbx_pair_t *pair;
bctbx_iterator_t *it;
char *key[64];
ms_message("Départ\n");
for(i = 0; i < 20000; i++) {
snprintf(key, sizeof(key),"key_%i",i);
pair = bctbx_pair_cchar_new(key,i);
bctbx_map_cchar_insert_and_delete(friends_map, pair);
}
ms_message("Fin\n");
bctbx_iterator_cchar_delete(it);
bctbx_mmap_cchar_delete(friends_map);
}
static void find_friend_by_ref_key_in_lot_of_friends_test(void) {
int i;
int j;
bctbx_map_t *friends_map = bctbx_mmap_cchar_new();
bctbx_pair_t *pair;
bctbx_iterator_t *it;
bctoolboxTimeSpec t1;
bctoolboxTimeSpec t2;
char *key[64];
for(i = 0; i < 20000; i++) {
snprintf(key, sizeof(key),"key_%i",i);
pair = bctbx_pair_cchar_new(key,i);
bctbx_map_cchar_insert_and_delete(friends_map, pair);
}
bctbx_get_cur_time(&t1);
ms_message("Départ : %li : %li\n",t1.tv_sec, t1.tv_nsec);
for(i = 0; i < 20000; i++) {
snprintf(key, sizeof(key),"key_%i",i);
it = bctbx_map_cchar_find_key(friends_map, key);
j = (int)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it));
BC_ASSERT_TRUE(i == j);
bctbx_iterator_cchar_delete(it);
}
bctbx_get_cur_time(&t2);
ms_message("Fin : %li : %li\n", t2.tv_sec, t2.tv_nsec);
bctbx_mmap_cchar_delete(friends_map);
}
static void find_friend_by_ref_key_empty_list_test(void) {
LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE);
LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc);
......@@ -834,6 +1033,8 @@ test_t vcard_tests[] = {
TEST_NO_TAG("Friends working if no db set", friends_if_no_db_set),
TEST_NO_TAG("Friends storage migration from rc to db", friends_migration),
TEST_NO_TAG("Friends storage in sqlite database", friends_sqlite_storage),
TEST_NO_TAG("20000 Friends storage in sqlite database", friends_sqlite_store_lot_of_friends),
TEST_NO_TAG("Find friend in database of 20000 objects", friends_sqlite_find_friend_in_lot_of_friends),
#endif
TEST_NO_TAG("CardDAV clean", carddav_clean), // This is to ensure the content of the test addressbook is in the correct state for the following tests
TEST_NO_TAG("CardDAV synchronization", carddav_sync),
......@@ -844,6 +1045,8 @@ test_t vcard_tests[] = {
TEST_NO_TAG("CardDAV multiple synchronizations", carddav_multiple_sync),
TEST_NO_TAG("CardDAV client to server and server to client sync", carddav_server_to_client_and_client_to_sever_sync),
TEST_NO_TAG("Find friend by ref key", find_friend_by_ref_key_test),
TEST_NO_TAG("create a map and insert 20000 objects", insert_lot_of_friends_map_test),
TEST_NO_TAG("Find ref key in 20000 objects map", find_friend_by_ref_key_in_lot_of_friends_test),
TEST_NO_TAG("Find friend by ref key in empty list", find_friend_by_ref_key_empty_list_test)
};
......
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