diff --git a/coreapi/carddav.c b/coreapi/carddav.c index 4e747ff31..0eeb05961 100644 --- a/coreapi/carddav.c +++ b/coreapi/carddav.c @@ -59,12 +59,22 @@ void linphone_carddav_synchronize(LinphoneCardDavContext *cdc) { linphone_carddav_get_current_ctag(cdc); } -static void linphone_carddav_sync_done(LinphoneCardDavContext *cdc, bool_t success, const char *msg) { +static void linphone_carddav_client_to_server_sync_done(LinphoneCardDavContext *cdc, bool_t success, const char *msg) { + if (!success) { + ms_error("[carddav] CardDAV client to server sync failure: %s", msg); + } + + if (cdc->sync_done_cb) { + cdc->sync_done_cb(cdc, success, msg); + } +} + +static void linphone_carddav_server_to_client_sync_done(LinphoneCardDavContext *cdc, bool_t success, const char *msg) { if (success) { ms_debug("CardDAV sync successful, saving new cTag: %i", cdc->ctag); linphone_friend_list_update_revision(cdc->friend_list, cdc->ctag); } else { - ms_error("[carddav] CardDAV sync failure: %s", msg); + ms_error("[carddav] CardDAV server to client sync failure: %s", msg); } if (cdc->sync_done_cb) { @@ -87,6 +97,10 @@ static int find_matching_friend(LinphoneFriend *lf1, LinphoneFriend *lf2) { return strcmp(uid1, uid2); } +static void linphone_carddav_response_free(LinphoneCardDavResponse *response) { + ms_free(response); +} + static void linphone_carddav_vcards_pulled(LinphoneCardDavContext *cdc, MSList *vCards) { if (vCards != NULL && ms_list_size(vCards) > 0) { MSList *friends = cdc->friend_list->friends; @@ -140,9 +154,9 @@ static void linphone_carddav_vcards_pulled(LinphoneCardDavContext *cdc, MSList * } vCards = ms_list_next(vCards); } + ms_list_free_with_data(vCards, (void (*)(void *))linphone_carddav_response_free); } - ms_list_free(vCards); - linphone_carddav_sync_done(cdc, TRUE, NULL); + linphone_carddav_server_to_client_sync_done(cdc, TRUE, NULL); } static MSList* parse_vcards_from_xml_response(const char *body) { @@ -213,7 +227,7 @@ static void linphone_carddav_vcards_fetched(LinphoneCardDavContext *cdc, MSList ms_debug("Local friend eTag is %s, remote vCard eTag is %s", etag, response->etag); if (lvc && etag && strcmp(etag, response->etag) == 0) { ms_list_remove(vCards, vCard); - ms_free(response); + linphone_carddav_response_free(response); } } } @@ -234,8 +248,8 @@ static void linphone_carddav_vcards_fetched(LinphoneCardDavContext *cdc, MSList temp_list = ms_list_free_with_data(temp_list, (void (*)(void *))linphone_friend_unref); linphone_carddav_pull_vcards(cdc, vCards); + ms_list_free_with_data(vCards, (void (*)(void *))linphone_carddav_response_free); } - ms_list_free(vCards); } static MSList* parse_vcards_etags_from_xml_response(const char *body) { @@ -282,7 +296,7 @@ static void linphone_carddav_ctag_fetched(LinphoneCardDavContext *cdc, int ctag) linphone_carddav_fetch_vcards(cdc); } else { ms_message("No changes found on server, skipping sync"); - linphone_carddav_sync_done(cdc, TRUE, "Synchronization skipped because cTag already up to date"); + linphone_carddav_server_to_client_sync_done(cdc, TRUE, "Synchronization skipped because cTag already up to date"); } } @@ -316,9 +330,31 @@ static void linphone_carddav_query_free(LinphoneCardDavQuery *query) { query->http_request_listener = NULL; } + // Context will be freed later (in sync_done) + query->context = NULL; + ms_free(query); } +static bool_t is_query_client_to_server_sync(LinphoneCardDavQuery *query) { + if (!query) { + ms_error("[carddav] query is NULL..."); + return FALSE; + } + switch(query->type) { + case LinphoneCardDavQueryTypePropfind: + case LinphoneCardDavQueryTypeAddressbookQuery: + case LinphoneCardDavQueryTypeAddressbookMultiget: + return FALSE; + case LinphoneCardDavQueryTypePut: + case LinphoneCardDavQueryTypeDelete: + return TRUE; + default: + ms_error("[carddav] Unknown request: %i", query->type); + } + return FALSE; +} + static void process_response_from_carddav_request(void *data, const belle_http_response_event_t *event) { LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)data; @@ -351,7 +387,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, NULL); + linphone_carddav_client_to_server_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 @@ -359,19 +395,18 @@ static void process_response_from_carddav_request(void *data, const belle_http_r MSList *vcard = NULL; LinphoneCardDavResponse *response = (LinphoneCardDavResponse *)ms_new0(LinphoneCardDavResponse, 1); response->url = linphone_vcard_get_url(lvc); - response->context = query->context; vcard = ms_list_append(vcard, response); linphone_carddav_pull_vcards(query->context, vcard); - ms_list_free(vcard); + ms_list_free_with_data(vcard, (void (*)(void *))linphone_carddav_response_free); } } else { - linphone_carddav_sync_done(query->context, FALSE, "No LinphoneFriend found in user_date field of query"); + linphone_carddav_client_to_server_sync_done(query->context, FALSE, "No LinphoneFriend found in user_data field of query"); } } break; case LinphoneCardDavQueryTypeDelete: - linphone_carddav_sync_done(query->context, TRUE, NULL); + linphone_carddav_client_to_server_sync_done(query->context, TRUE, NULL); break; default: ms_error("[carddav] Unknown request: %i", query->type); @@ -380,10 +415,18 @@ static void process_response_from_carddav_request(void *data, const belle_http_r } else { char msg[100]; snprintf(msg, sizeof(msg), "Unexpected HTTP response code: %i", code); - linphone_carddav_sync_done(query->context, FALSE, msg); + if (is_query_client_to_server_sync(query)) { + linphone_carddav_client_to_server_sync_done(query->context, FALSE, msg); + } else { + linphone_carddav_server_to_client_sync_done(query->context, FALSE, msg); + } } } else { - linphone_carddav_sync_done(query->context, FALSE, "No response found"); + if (is_query_client_to_server_sync(query)) { + linphone_carddav_client_to_server_sync_done(query->context, FALSE, "No response found"); + } else { + linphone_carddav_server_to_client_sync_done(query->context, FALSE, "No response found"); + } } linphone_carddav_query_free(query); } @@ -391,8 +434,12 @@ static void process_response_from_carddav_request(void *data, const belle_http_r static void process_io_error_from_carddav_request(void *data, const belle_sip_io_error_event_t *event) { LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)data; ms_error("[carddav] I/O error during CardDAV request sending"); + if (is_query_client_to_server_sync(query)) { + linphone_carddav_client_to_server_sync_done(query->context, FALSE, "I/O error during CardDAV request sending"); + } else { + linphone_carddav_server_to_client_sync_done(query->context, FALSE, "I/O error during CardDAV request sending"); + } linphone_carddav_query_free(query); - linphone_carddav_sync_done(query->context, FALSE, "I/O error during CardDAV request sending"); } static void process_auth_requested_from_carddav_request(void *data, belle_sip_auth_event_t *event) { @@ -420,7 +467,11 @@ static void process_auth_requested_from_carddav_request(void *data, belle_sip_au if (!auth_infos) { ms_error("[carddav] Authentication requested during CardDAV request sending, and username/password weren't provided"); - linphone_carddav_sync_done(query->context, FALSE, "Authentication requested during CardDAV request sending, and username/password weren't provided"); + if (is_query_client_to_server_sync(query)) { + linphone_carddav_client_to_server_sync_done(query->context, FALSE, "Authentication requested during CardDAV request sending, and username/password weren't provided"); + } else { + linphone_carddav_server_to_client_sync_done(query->context, FALSE, "Authentication requested during CardDAV request sending, and username/password weren't provided"); + } linphone_carddav_query_free(query); } } @@ -439,6 +490,7 @@ static void linphone_carddav_send_query(LinphoneCardDavQuery *query) { cdc->sync_done_cb(cdc, FALSE, "Could not send request, URL is invalid"); } belle_sip_error("Could not send request, URL %s is invalid", query->url); + linphone_carddav_query_free(query); return; } req = belle_http_request_create(query->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), NULL); @@ -449,6 +501,7 @@ static void linphone_carddav_send_query(LinphoneCardDavQuery *query) { } belle_sip_object_unref(uri); belle_sip_error("Could not create belle_http_request_t"); + linphone_carddav_query_free(query); return; } diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 40f083802..ec299cd29 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -538,8 +538,14 @@ static void carddav_updated(LinphoneCardDavContext *cdc, LinphoneFriend *lf_new, } void linphone_friend_list_synchronize_friends_from_server(LinphoneFriendList *list) { - LinphoneCardDavContext *cdc = linphone_carddav_context_new(list); - + LinphoneCardDavContext *cdc = NULL; + + if (!list || !list->uri || !list->lc) { + ms_error("FATAL"); + return; + } + + cdc = linphone_carddav_context_new(list); if (cdc) { cdc->contact_created_cb = carddav_created; cdc->contact_removed_cb = carddav_removed; diff --git a/coreapi/private.h b/coreapi/private.h index 3ff12e184..a7f4f9b90 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1290,7 +1290,6 @@ struct _LinphoneCardDavQuery { }; struct _LinphoneCardDavResponse { - LinphoneCardDavContext *context; const char *etag; const char *url; const char *vcard; diff --git a/tester/vcard_tester.c b/tester/vcard_tester.c index b27419b95..674088d93 100644 --- a/tester/vcard_tester.c +++ b/tester/vcard_tester.c @@ -405,9 +405,9 @@ static void carddav_sync(void) { linphone_carddav_set_updated_contact_callback(c, carddav_updated_contact); linphone_carddav_synchronize(c); - wait_for_until(manager->lc, NULL, &stats->new_contact_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->new_contact_count, 1, 5000); BC_ASSERT_EQUAL(stats->new_contact_count, 1, int, "%i"); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); ms_free(stats); @@ -431,7 +431,7 @@ static void carddav_sync_2(void) { unlink(friends_db); linphone_core_set_friends_database_path(manager->lc, friends_db); - BC_ASSERT_EQUAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); linphone_friend_unref(lf); linphone_carddav_set_user_data(c, stats); @@ -442,11 +442,11 @@ static void carddav_sync_2(void) { linphone_carddav_synchronize(c); - wait_for_until(manager->lc, NULL, &stats->new_contact_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->new_contact_count, 1, 5000); BC_ASSERT_EQUAL(stats->new_contact_count, 1, int, "%i"); - wait_for_until(manager->lc, NULL, &stats->removed_contact_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->removed_contact_count, 1, 5000); BC_ASSERT_EQUAL(stats->removed_contact_count, 1, int, "%i"); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); ms_free(stats); @@ -473,7 +473,7 @@ static void carddav_sync_3(void) { unlink(friends_db); linphone_core_set_friends_database_path(manager->lc, friends_db); - BC_ASSERT_EQUAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); linphone_friend_unref(lf); linphone_carddav_set_user_data(c, stats); @@ -484,15 +484,16 @@ static void carddav_sync_3(void) { linphone_carddav_synchronize(c); - wait_for_until(manager->lc, NULL, &stats->updated_contact_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->updated_contact_count, 1, 5000); BC_ASSERT_EQUAL(stats->updated_contact_count, 1, int, "%i"); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); ms_free(stats); unlink(friends_db); ms_free(friends_db); linphone_carddav_context_destroy(c); + c = NULL; linphone_core_manager_destroy(manager); } @@ -519,11 +520,11 @@ static void carddav_sync_4(void) { BC_ASSERT_PTR_NULL(linphone_vcard_get_uid(lvc)); linphone_carddav_put_vcard(c, lf); BC_ASSERT_PTR_NOT_NULL(linphone_vcard_get_uid(lvc)); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); linphone_carddav_delete_vcard(c, lf); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 2, int, "%i"); linphone_friend_unref(lf); @@ -581,13 +582,13 @@ static void carddav_integration(void) { BC_ASSERT_EQUAL(ms_list_size(lfl->dirty_friends_to_update), 0, int, "%d"); BC_ASSERT_EQUAL(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, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); 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); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 2, int, "%i"); linphone_friend_unref(lf); lf = NULL; @@ -605,14 +606,14 @@ static void carddav_integration(void) { BC_ASSERT_EQUAL(lfl->revision, 0, int, "%i"); linphone_friend_list_synchronize_friends_from_server(lfl); - wait_for_until(manager->lc, NULL, &stats->new_contact_count, 0, 2000); + wait_for_until(manager->lc, NULL, &stats->new_contact_count, 0, 5000); BC_ASSERT_EQUAL(stats->new_contact_count, 0, int, "%i"); - wait_for_until(manager->lc, NULL, &stats->removed_contact_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->removed_contact_count, 1, 5000); BC_ASSERT_EQUAL(stats->removed_contact_count, 1, int, "%i"); - wait_for_until(manager->lc, NULL, &stats->updated_contact_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->updated_contact_count, 1, 5000); 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); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 3, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); BC_ASSERT_EQUAL(ms_list_size(lfl->friends), 1, int, "%i"); @@ -643,6 +644,7 @@ static void carddav_clean(void) { // This is to ensure the content of the test LinphoneFriendListCbs *cbs = linphone_friend_list_get_callbacks(lfl); LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); MSList *friends = NULL; + MSList *friends_iterator = NULL; LinphoneFriend *lf = NULL; LinphoneVcard *lvc = NULL; @@ -655,26 +657,28 @@ static void carddav_clean(void) { // This is to ensure the content of the test linphone_friend_list_set_uri(lfl, CARDDAV_SERVER); linphone_friend_list_synchronize_friends_from_server(lfl); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); 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; + friends_iterator = friends; + while (friends_iterator) { + LinphoneFriend *lf = (LinphoneFriend *)friends_iterator->data; linphone_friend_list_remove_friend(lfl, lf); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); 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); + friends_iterator = ms_list_next(friends_iterator); } + ms_list_free(friends); lvc = linphone_vcard_new_from_vcard4_buffer("BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sylvain@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); linphone_vcard_set_url(lvc, "http://dav.linphone.org/card.php/addressbooks/tester/default/me.vcf"); lf = linphone_friend_new_from_vcard(lvc); linphone_friend_list_add_friend(lfl, lf); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); ms_free(stats); @@ -698,13 +702,13 @@ static void carddav_multiple_sync(void) { linphone_friend_list_set_uri(lfl, CARDDAV_SERVER); linphone_friend_list_synchronize_friends_from_server(lfl); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); linphone_friend_list_synchronize_friends_from_server(lfl); - wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 2000); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 5000); 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); + wait_for_until(manager->lc, NULL, &stats->sync_done_count, 3, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); BC_ASSERT_EQUAL(stats->removed_contact_count, 0, int, "%i");