From 0370aa9e90f381f4cde65fc81fae4db909cd683b Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 2 Feb 2016 17:09:21 +0100 Subject: [PATCH] Added new callback for synchronization done + fixed small issue: when contact was removed from the server, it was trying to remove it again --- coreapi/carddav.c | 6 +++--- coreapi/friendlist.c | 41 ++++++++++++++++++++++++++++++++++------- coreapi/friendlist.h | 28 ++++++++++++++++++++++++++++ coreapi/private.h | 1 + tester/vcard_tester.c | 42 ++++++++++++++++++++++++++++++++++-------- 5 files changed, 100 insertions(+), 18 deletions(-) diff --git a/coreapi/carddav.c b/coreapi/carddav.c index 87aa9eda8..1bd3b3378 100644 --- a/coreapi/carddav.c +++ b/coreapi/carddav.c @@ -133,7 +133,7 @@ static void linphone_carddav_vcards_pulled(LinphoneCardDavContext *cdc, MSList * } } ms_list_free(vCards); - linphone_carddav_sync_done(cdc, TRUE, ""); + linphone_carddav_sync_done(cdc, TRUE, NULL); } static MSList* parse_vcards_from_xml_response(const char *body) { @@ -342,7 +342,7 @@ static void process_response_from_carddav_request(void *data, const belle_http_r } linphone_vcard_set_etag(lvc, etag); - linphone_carddav_sync_done(query->context, TRUE, ""); + linphone_carddav_sync_done(query->context, TRUE, NULL); linphone_friend_unref(lf); } else { // For some reason, server didn't return the eTag of the updated/created vCard @@ -362,7 +362,7 @@ static void process_response_from_carddav_request(void *data, const belle_http_r } break; case LinphoneCardDavQueryTypeDelete: - linphone_carddav_sync_done(query->context, TRUE, ""); + linphone_carddav_sync_done(query->context, TRUE, NULL); break; default: ms_error("Unknown request: %i", query->type); diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 28a85a2ff..df48f116b 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -80,6 +80,14 @@ void linphone_friend_list_cbs_set_contact_updated(LinphoneFriendListCbs *cbs, Li cbs->contact_updated_cb = cb; } +LinphoneFriendListSyncStateChangedCb linphone_friend_list_cbs_get_sync_status_changed(const LinphoneFriendListCbs *cbs) { + return cbs->sync_state_changed_cb; +} + +void linphone_friend_list_cbs_set_sync_status_changed(LinphoneFriendListCbs *cbs, LinphoneFriendListSyncStateChangedCb cb) { + cbs->sync_state_changed_cb = cb; +} + static char * create_resource_list_xml(const LinphoneFriendList *list) { char *xml_content = NULL; MSList *elem; @@ -425,21 +433,30 @@ LinphoneFriendListStatus linphone_friend_list_import_friend(LinphoneFriendList * return LinphoneFriendListOK; } -static void carddav_done(LinphoneCardDavContext *cdc, bool_t success, const char *msg) { +static void carddav_done(LinphoneCardDavContext *cdc, bool_t success, const char *msg) { + if (cdc && cdc->friend_list->cbs->sync_state_changed_cb) { + cdc->friend_list->cbs->sync_state_changed_cb(cdc->friend_list, success ? LinphoneFriendListSyncSuccessful : LinphoneFriendListSyncFailure, msg); + } linphone_carddav_context_destroy(cdc); } -LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *lf) { +static LinphoneFriendListStatus _linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *lf, bool_t remove_from_server) { MSList *elem = ms_list_find(list->friends, lf); - LinphoneCardDavContext *cdc = linphone_carddav_context_new(list); if (elem == NULL) return LinphoneFriendListNonExistentFriend; #ifdef FRIENDS_SQL_STORAGE_ENABLED linphone_core_remove_friend_from_db(lf->lc, lf); #endif - if (cdc) { - cdc->sync_done_cb = carddav_done; - linphone_carddav_delete_vcard(cdc, lf); + if (remove_from_server) { + LinphoneVCard *lvc = linphone_friend_get_vcard(lf); + if (lvc && linphone_vcard_get_uid(lvc)) { + LinphoneCardDavContext *cdc = linphone_carddav_context_new(list); + cdc->sync_done_cb = carddav_done; + if (cdc->friend_list->cbs->sync_state_changed_cb) { + cdc->friend_list->cbs->sync_state_changed_cb(cdc->friend_list, LinphoneFriendListSyncStarted, NULL); + } + linphone_carddav_delete_vcard(cdc, lf); + } } lf->friend_list = NULL; @@ -448,6 +465,10 @@ LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList * return LinphoneFriendListOK; } +LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *lf) { + return _linphone_friend_list_remove_friend(list, lf, TRUE); +} + const MSList * linphone_friend_list_get_friends(const LinphoneFriendList *list) { return list->friends; } @@ -461,6 +482,9 @@ void linphone_friend_list_update_dirty_friends(LinphoneFriendList *list) { while (dirty_friends) { LinphoneFriend *lf = (LinphoneFriend *)dirty_friends->data; if (lf) { + if (cdc->friend_list->cbs->sync_state_changed_cb) { + cdc->friend_list->cbs->sync_state_changed_cb(cdc->friend_list, LinphoneFriendListSyncStarted, NULL); + } linphone_carddav_put_vcard(cdc, lf); } dirty_friends = ms_list_next(dirty_friends); @@ -482,7 +506,7 @@ static void carddav_created(LinphoneCardDavContext *cdc, LinphoneFriend *lf) { static void carddav_removed(LinphoneCardDavContext *cdc, LinphoneFriend *lf) { if (cdc) { LinphoneFriendList *lfl = cdc->friend_list; - linphone_friend_list_remove_friend(lfl, lf); + _linphone_friend_list_remove_friend(lfl, lf, FALSE); if (cdc->friend_list->cbs->contact_deleted_cb) { cdc->friend_list->cbs->contact_deleted_cb(lfl, lf); } @@ -513,6 +537,9 @@ void linphone_friend_list_synchronize_friends_from_server(LinphoneFriendList *li cdc->contact_removed_cb = carddav_removed; cdc->contact_updated_cb = carddav_updated; cdc->sync_done_cb = carddav_done; + if (cdc && cdc->friend_list->cbs->sync_state_changed_cb) { + cdc->friend_list->cbs->sync_state_changed_cb(cdc->friend_list, LinphoneFriendListSyncStarted, NULL); + } linphone_carddav_synchronize(cdc); } } diff --git a/coreapi/friendlist.h b/coreapi/friendlist.h index 7d907ac61..9d24df966 100644 --- a/coreapi/friendlist.h +++ b/coreapi/friendlist.h @@ -49,6 +49,15 @@ typedef enum _LinphoneFriendListStatus { LinphoneFriendListInvalidFriend } LinphoneFriendListStatus; +/** + * Enum describing the status of a CardDAV synchronization + */ +typedef enum _LinphoneFriendListSyncStatus { + LinphoneFriendListSyncStarted, + LinphoneFriendListSyncSuccessful, + LinphoneFriendListSyncFailure +} LinphoneFriendListSyncStatus; + /** * The LinphoneFriendList object representing a list of friends. **/ @@ -252,6 +261,11 @@ typedef void (*LinphoneFriendListContactDeletedCb)(LinphoneFriendList *list, Lin **/ typedef void (*LinphoneFriendListContactUpdatedCb)(LinphoneFriendList *list, LinphoneFriend *new_friend, LinphoneFriend *old_friend); +/** + * Callback used to notify the status of the synchronization has changed +**/ +typedef void (*LinphoneFriendListSyncStateChangedCb)(LinphoneFriendList *list, LinphoneFriendListSyncStatus status, const char *msg); + /** * Get the LinphoneFriendListCbs object associated with a LinphoneFriendList. * @param[in] request LinphoneXmlRpcRequest object @@ -328,6 +342,20 @@ LINPHONE_PUBLIC LinphoneFriendListContactUpdatedCb linphone_friend_list_cbs_get_ **/ LINPHONE_PUBLIC void linphone_friend_list_cbs_set_contact_updated(LinphoneFriendListCbs *cbs, LinphoneFriendListContactUpdatedCb cb); +/** + * Get the sync status changed callback. + * @param[in] cbs LinphoneFriendListCbs object. + * @return The current sync status changedcallback. +**/ +LINPHONE_PUBLIC LinphoneFriendListSyncStateChangedCb linphone_friend_list_cbs_get_sync_status_changed(const LinphoneFriendListCbs *cbs); + +/** + * Set the contact updated callback. + * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cb The sync status changed to be used. +**/ +LINPHONE_PUBLIC void linphone_friend_list_cbs_set_sync_status_changed(LinphoneFriendListCbs *cbs, LinphoneFriendListSyncStateChangedCb cb); + /** * Starts a CardDAV synchronization using value set using linphone_friend_list_set_uri. * @param[in] list LinphoneFriendList object. diff --git a/coreapi/private.h b/coreapi/private.h index 713a82e8f..f79683b56 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -702,6 +702,7 @@ struct _LinphoneFriendListCbs { LinphoneFriendListContactCreatedCb contact_created_cb; LinphoneFriendListContactDeletedCb contact_deleted_cb; LinphoneFriendListContactUpdatedCb contact_updated_cb; + LinphoneFriendListSyncStateChangedCb sync_state_changed_cb; }; BELLE_SIP_DECLARE_VPTR(LinphoneFriendListCbs); diff --git a/tester/vcard_tester.c b/tester/vcard_tester.c index 73860f1c2..e1d21343b 100644 --- a/tester/vcard_tester.c +++ b/tester/vcard_tester.c @@ -439,6 +439,15 @@ static void carddav_contact_updated(LinphoneFriendList *list, LinphoneFriend *ne stats->updated_contact_count++; } +static void carddav_sync_status_changed(LinphoneFriendList *list, LinphoneFriendListSyncStatus status, const char *msg) { + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + char *state = status == LinphoneFriendListSyncStarted ? "Sync started" : (status == LinphoneFriendListSyncFailure ? "Sync failure" : "Sync successful"); + ms_message("[CardDAV] %s : %s", state, msg); + if (status == LinphoneFriendListSyncFailure || status == LinphoneFriendListSyncSuccessful) { + stats->sync_done_count++; + } +} + static void carddav_integration(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); @@ -456,30 +465,34 @@ static void carddav_integration(void) { linphone_friend_list_cbs_set_contact_created(cbs, carddav_contact_created); linphone_friend_list_cbs_set_contact_deleted(cbs, carddav_contact_deleted); linphone_friend_list_cbs_set_contact_updated(cbs, carddav_contact_updated); + linphone_friend_list_cbs_set_sync_status_changed(cbs, carddav_sync_status_changed); linphone_core_add_friend_list(manager->lc, lfl); BC_ASSERT_PTR_NULL(linphone_vcard_get_uid(lvc)); BC_ASSERT_EQUAL(ms_list_size(lfl->dirty_friends_to_update), 0, int, "%d"); BC_ASSERT_EQUAL_FATAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); BC_ASSERT_EQUAL(ms_list_size(lfl->dirty_friends_to_update), 1, int, "%d"); - wait_for_until(manager->lc, NULL, NULL, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); BC_ASSERT_EQUAL(ms_list_size(lfl->dirty_friends_to_update), 0, int, "%d"); BC_ASSERT_PTR_NOT_NULL(linphone_vcard_get_uid(lvc)); linphone_friend_list_remove_friend(lfl, lf); BC_ASSERT_EQUAL(ms_list_size(lfl->friends), 0, int, "%d"); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 2, int, "%i"); linphone_friend_unref(lf); lf = NULL; lvc = linphone_vcard_new_from_vcard4_buffer("BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); lf = linphone_friend_new_from_vcard(lvc); - BC_ASSERT_EQUAL_FATAL(linphone_friend_list_import_friend(lfl, lf, FALSE), LinphoneFriendListOK, int, "%d"); + BC_ASSERT_EQUAL_FATAL(linphone_friend_list_add_local_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); linphone_friend_unref(lf); lvc2 = linphone_vcard_new_from_vcard4_buffer("BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); linphone_vcard_set_url(lvc2, "/sabredav/addressbookserver.php/addressbooks/sylvain/default/me.vcf"); lf2 = linphone_friend_new_from_vcard(lvc2); linphone_friend_set_ref_key(lf2, refkey); - BC_ASSERT_EQUAL_FATAL(linphone_friend_list_import_friend(lfl, lf2, FALSE), LinphoneFriendListOK, int, "%d"); + BC_ASSERT_EQUAL_FATAL(linphone_friend_list_add_local_friend(lfl, lf2), LinphoneFriendListOK, int, "%d"); linphone_friend_unref(lf2); BC_ASSERT_EQUAL(lfl->revision, 0, int, "%i"); @@ -491,6 +504,8 @@ static void carddav_integration(void) { wait_for_until(manager->lc, NULL, &stats->updated_contact_count, 1, 2000); BC_ASSERT_EQUAL(stats->updated_contact_count, 1, int, "%i"); BC_ASSERT_NOT_EQUAL(lfl->revision, 0, int, "%i"); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 3, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); BC_ASSERT_EQUAL_FATAL(ms_list_size(lfl->friends), 1, int, "%i"); lf = (LinphoneFriend *)lfl->friends->data; @@ -526,17 +541,22 @@ static void carddav_clean(void) { // This is to ensure the content of the test linphone_friend_list_cbs_set_contact_created(cbs, carddav_contact_created); linphone_friend_list_cbs_set_contact_deleted(cbs, carddav_contact_deleted); linphone_friend_list_cbs_set_contact_updated(cbs, carddav_contact_updated); + linphone_friend_list_cbs_set_sync_status_changed(cbs, carddav_sync_status_changed); linphone_core_add_friend_list(manager->lc, lfl); linphone_friend_list_set_uri(lfl, "http://192.168.0.230/sabredav/addressbookserver.php/addressbooks/sylvain/default"); linphone_friend_list_synchronize_friends_from_server(lfl); - wait_for_until(manager->lc, NULL, NULL, 0, 5000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); + stats->sync_done_count = 0; friends = ms_list_copy(lfl->friends); while (friends) { LinphoneFriend *lf = (LinphoneFriend *)friends->data; linphone_friend_list_remove_friend(lfl, lf); - wait_for_until(manager->lc, NULL, NULL, 0, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); + stats->sync_done_count = 0; stats->removed_contact_count = 0; friends = ms_list_next(friends); } @@ -545,7 +565,8 @@ static void carddav_clean(void) { // This is to ensure the content of the test linphone_vcard_set_url(lvc, "http://192.168.0.230/sabredav/addressbookserver.php/addressbooks/sylvain/default/me.vcf"); lf = linphone_friend_new_from_vcard(lvc); linphone_friend_list_add_friend(lfl, lf); - wait_for_until(manager->lc, NULL, NULL, 0, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); ms_free(stats); linphone_friend_unref(lf); @@ -563,14 +584,19 @@ static void carddav_multiple_sync(void) { linphone_friend_list_cbs_set_contact_created(cbs, carddav_contact_created); linphone_friend_list_cbs_set_contact_deleted(cbs, carddav_contact_deleted); linphone_friend_list_cbs_set_contact_updated(cbs, carddav_contact_updated); + linphone_friend_list_cbs_set_sync_status_changed(cbs, carddav_sync_status_changed); linphone_core_add_friend_list(manager->lc, lfl); linphone_friend_list_set_uri(lfl, "http://192.168.0.230/sabredav/addressbookserver.php/addressbooks/sylvain/default"); linphone_friend_list_synchronize_friends_from_server(lfl); - wait_for_until(manager->lc, NULL, NULL, 0, 5000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); linphone_friend_list_synchronize_friends_from_server(lfl); - wait_for_until(manager->lc, NULL, NULL, 0, 5000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 2, int, "%i"); linphone_friend_list_synchronize_friends_from_server(lfl); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 3, 2000); + BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); BC_ASSERT_EQUAL(stats->removed_contact_count, 0, int, "%i"); linphone_friend_list_unref(lfl);