static void linphone_vcard_import_export_friends_test(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); const bctbx_list_t *friends = linphone_friend_list_get_friends(lfl); char *import_filepath = bc_tester_res("vcards/vcards.vcf"); char *export_filepath = bc_tester_file("export_vcards.vcf"); int count = 0; BC_ASSERT_EQUAL(bctbx_list_size(friends), 0, int, "%d"); count = linphone_friend_list_import_friends_from_vcard4_file(lfl, import_filepath); BC_ASSERT_EQUAL(count, 3, int, "%d"); friends = linphone_friend_list_get_friends(lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends), 3, int, "%d"); linphone_friend_list_export_friends_as_vcard4_file(lfl, export_filepath); lfl = linphone_core_create_friend_list(manager->lc); count = linphone_friend_list_import_friends_from_vcard4_file(lfl, export_filepath); BC_ASSERT_EQUAL(count, 3, int, "%d"); friends = linphone_friend_list_get_friends(lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends), 3, int, "%d"); linphone_friend_list_unref(lfl); remove(export_filepath); ms_free(import_filepath); ms_free(export_filepath); linphone_core_manager_destroy(manager); }
static void linphone_vcard_phone_numbers_and_sip_addresses(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:[email protected]\r\nIMPP;TYPE=home:sip:[email protected]\r\nTEL;TYPE=work:0952636505\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); bctbx_list_t *sip_addresses = linphone_friend_get_addresses(lf); bctbx_list_t *phone_numbers = linphone_friend_get_phone_numbers(lf); LinphoneAddress *addr = NULL; BC_ASSERT_EQUAL(bctbx_list_size(sip_addresses), 2, int, "%i"); BC_ASSERT_EQUAL(bctbx_list_size(phone_numbers), 1, int, "%i"); if (sip_addresses) bctbx_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); if (phone_numbers) bctbx_list_free(phone_numbers); linphone_friend_unref(lf); lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nTEL;TYPE=work:0952636505\r\nTEL:0476010203\r\nEND:VCARD\r\n"); lf = linphone_friend_new_from_vcard(lvc); sip_addresses = linphone_friend_get_addresses(lf); phone_numbers = linphone_friend_get_phone_numbers(lf); BC_ASSERT_EQUAL(bctbx_list_size(sip_addresses), 0, int, "%i"); BC_ASSERT_EQUAL(bctbx_list_size(phone_numbers), 2, int, "%i"); if (sip_addresses) bctbx_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); if (phone_numbers) bctbx_list_free(phone_numbers); addr = linphone_address_new("sip:[email protected]"); linphone_friend_add_address(lf, addr); linphone_address_unref(addr); sip_addresses = linphone_friend_get_addresses(lf); BC_ASSERT_EQUAL(bctbx_list_size(sip_addresses), 1, int, "%i"); if (sip_addresses) bctbx_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); linphone_friend_remove_phone_number(lf, "0952636505"); phone_numbers = linphone_friend_get_phone_numbers(lf); BC_ASSERT_EQUAL(bctbx_list_size(phone_numbers), 1, int, "%i"); if (phone_numbers) bctbx_list_free(phone_numbers); linphone_friend_remove_phone_number(lf, "0476010203"); phone_numbers = linphone_friend_get_phone_numbers(lf); BC_ASSERT_EQUAL(bctbx_list_size(phone_numbers), 0, int, "%i"); if (phone_numbers) bctbx_list_free(phone_numbers); addr = linphone_address_new("sip:[email protected]"); linphone_friend_remove_address(lf, addr); linphone_address_unref(addr); sip_addresses = linphone_friend_get_addresses(lf); BC_ASSERT_EQUAL(bctbx_list_size(sip_addresses), 0, int, "%i"); if (sip_addresses) bctbx_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); linphone_friend_add_phone_number(lf, "+33952636505"); phone_numbers = linphone_friend_get_phone_numbers(lf); BC_ASSERT_EQUAL(bctbx_list_size(phone_numbers), 1, int, "%i"); if (phone_numbers) bctbx_list_free(phone_numbers); linphone_friend_unref(lf); lf = NULL; lvc = NULL; linphone_core_manager_destroy(manager); }
static void linphone_vcard_import_a_lot_of_friends_test(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); char *import_filepath = bc_tester_res("vcards/thousand_vcards.vcf"); clock_t start, end; double elapsed = 0; const bctbx_list_t *friends = NULL; FILE *infile = NULL; char *buffer = NULL; long numbytes = 0; size_t readbytes; start = clock(); linphone_friend_list_import_friends_from_vcard4_file(lfl, import_filepath); end = clock(); friends = linphone_friend_list_get_friends(lfl); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends), 1000, unsigned int, "%u"); // Now that we accept Friends without a SIP URI, the result must be equal to 1000 elapsed = (double)(end - start); ms_message("Imported a thousand of vCards from file in %f seconds", elapsed / CLOCKS_PER_SEC); lfl = linphone_core_create_friend_list(manager->lc); infile = fopen(import_filepath, "rb"); BC_ASSERT_PTR_NOT_NULL(infile); if (infile) { fseek(infile, 0L, SEEK_END); numbytes = ftell(infile); fseek(infile, 0L, SEEK_SET); buffer = (char*)ms_malloc((numbytes + 1) * sizeof(char)); readbytes = fread(buffer, sizeof(char), numbytes, infile); fclose(infile); buffer[readbytes] = '\0'; start = clock(); linphone_friend_list_import_friends_from_vcard4_buffer(lfl, buffer); end = clock(); ms_free(buffer); } friends = linphone_friend_list_get_friends(lfl); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends), 1000, unsigned int, "%u"); // Now that we accept Friends without a SIP URI, the result must be equal to 1000 elapsed = (double)(end - start); ms_message("Imported a thousand of vCards from buffer in %f seconds", elapsed / CLOCKS_PER_SEC); linphone_friend_list_unref(lfl); ms_free(import_filepath); linphone_core_manager_destroy(manager); }
void linphone_core_migrate_friends_from_rc_to_db(LinphoneCore *lc) { LpConfig *lpc = NULL; LinphoneFriend *lf = NULL; LinphoneFriendList *lfl = linphone_core_get_default_friend_list(lc); int i; #ifndef SQLITE_STORAGE_ENABLED ms_warning("linphone has been compiled without sqlite, can't migrate friends"); 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", "friends_migration_done", 0) == 1) { ms_warning("the friends migration has already been done, skipping..."); return; } if (bctbx_list_size(linphone_friend_list_get_friends(lfl)) > 0 && lfl->storage_id == 0) { linphone_core_remove_friend_list(lc, lfl); lfl = linphone_core_create_friend_list(lc); linphone_core_add_friend_list(lc, lfl); linphone_friend_list_unref(lfl); } for (i = 0; (lf = linphone_friend_new_from_config_file(lc, i)) != NULL; i++) { char friend_section[32]; const LinphoneAddress *addr = linphone_friend_get_address(lf); if (addr) { const char *displayName = linphone_address_get_display_name(addr); char *address = NULL; if (!displayName) { displayName = linphone_address_get_username(addr); } address = linphone_address_as_string(addr); if (!linphone_friend_create_vcard(lf, displayName)) { ms_warning("Couldn't create vCard for friend %s", address); } else { linphone_vcard_add_sip_address(linphone_friend_get_vcard(lf), address); } ms_free(address); linphone_friend_list_add_friend(lfl, lf); linphone_friend_unref(lf); snprintf(friend_section, sizeof(friend_section), "friend_%i", i); lp_config_clean_section(lpc, friend_section); } } ms_debug("friends migration successful: %i friends migrated", i); lp_config_set_int(lpc, "misc", "friends_migration_done", 1); }
static void friends_if_no_db_set(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); LinphoneFriend *lf = linphone_core_create_friend(manager->lc); LinphoneAddress *addr = linphone_address_new("sip:[email protected]"); const bctbx_list_t *friends = NULL; LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); linphone_friend_set_address(lf, addr); linphone_friend_set_name(lf, "Sylvain"); linphone_friend_list_add_friend(lfl, lf); friends = linphone_friend_list_get_friends(lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends), 1, int, "%d"); linphone_friend_list_remove_friend(lfl, lf); linphone_friend_unref(lf); friends = linphone_friend_list_get_friends(lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends), 0, int, "%d"); linphone_friend_list_unref(lfl); linphone_address_unref(addr); linphone_core_manager_destroy(manager); }
static void simple_subscribe_with_friend_from_rc(void) { LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline"); LinphoneCoreManager *marie = presence_linphone_core_manager_new_with_rc_name("marie", "pauline_as_friend_rc"); LinphoneFriend *pauline_as_friend; BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_core_get_friend_list(marie->lc)), 1, unsigned int , "%u"); if (bctbx_list_size(linphone_core_get_friend_list(marie->lc))>0) { pauline_as_friend = (LinphoneFriend*)linphone_core_get_friend_list(marie->lc)->data; linphone_friend_set_address(pauline_as_friend, pauline->identity); /*hack to update addr with port number*/ } BC_ASSERT_TRUE (wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnline,1)); BC_ASSERT_EQUAL(pauline->stat.number_of_NewSubscriptionRequest,1, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived,1, int, "%d"); linphone_core_manager_destroy(marie); /*unsubscribe is not reported ?*/ BC_ASSERT_FALSE(wait_for(NULL,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,2)); /*just to wait for unsubscription even if not notified*/ linphone_core_manager_destroy(pauline); }
static void friends_migration(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("friends_rc", FALSE); LpConfig *lpc = linphone_core_get_config(manager->lc); LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); const bctbx_list_t *friends = linphone_friend_list_get_friends(lfl); bctbx_list_t *friends_from_db = NULL; char *friends_db = bc_tester_file("friends.db"); BC_ASSERT_EQUAL(bctbx_list_size(friends), 3, int, "%d"); BC_ASSERT_EQUAL(lp_config_get_int(lpc, "misc", "friends_migration_done", 0), 0, int, "%i"); unlink(friends_db); linphone_core_set_friends_database_path(manager->lc, friends_db); lfl = linphone_core_get_default_friend_list(manager->lc); friends = linphone_friend_list_get_friends(lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends), 3, int, "%d"); friends_from_db = linphone_core_fetch_friends_from_db(manager->lc, lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends_from_db), 3, int, "%d"); BC_ASSERT_EQUAL(lp_config_get_int(lpc, "misc", "friends_migration_done", 0), 1, int, "%i"); friends_from_db = bctbx_list_free_with_data(friends_from_db, (void (*)(void *))linphone_friend_unref); unlink(friends_db); ms_free(friends_db); linphone_core_manager_destroy(manager); }
static void quality_reporting_not_sent_if_call_not_started(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); LinphoneCallLog* out_call_log; LinphoneCall* out_call; linphone_core_set_max_calls(pauline->lc,0); out_call = linphone_core_invite(marie->lc,"pauline"); BC_ASSERT_PTR_NOT_NULL(out_call); if(out_call == NULL) goto end; linphone_call_ref(out_call); BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallError,1, 10000)); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1, int, "%d"); if (bctbx_list_size(linphone_core_get_call_logs(marie->lc))>0) { out_call_log=(LinphoneCallLog*)(linphone_core_get_call_logs(marie->lc)->data); BC_ASSERT_PTR_NOT_NULL(out_call_log); BC_ASSERT_EQUAL(linphone_call_log_get_status(out_call_log),LinphoneCallAborted, int, "%d"); }
int main(int argc, char *argv[]){ LinphoneCoreVTable vtable={0}; LinphoneCore *lc; LinphoneVideoPolicy policy; int i; LinphoneAddress *addr=NULL; LCSipTransports tp; char * tmp = NULL; LpConfig * lp_config = lp_config_new(NULL); int max_call_duration=3600; static const char *media_file = NULL; policy.automatically_accept=TRUE; signal(SIGINT,stop); #ifndef _WIN32 signal(SIGUSR1,stats); signal(SIGUSR2,dump_call_logs); #endif for(i = 1; i < argc; ++i) { if (strcmp(argv[i], "--verbose") == 0) { linphone_core_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); } else if (strcmp(argv[i], "--max-call-duration") == 0){ max_call_duration = atoi(argv[++i]); } else if (strcmp(argv[i], "--listening-uri") == 0){ addr = linphone_address_new(argv[++i]); if (!addr) { printf("Error, bad sip uri"); helper(argv[0]); } /* switch(linphone_address_get_transport(addr)) { case LinphoneTransportUdp: case LinphoneTransportTcp: break; default: ms_error("Error, bad sip uri [%s] transport, should be udp | tcp",argv[i]); helper(); break; }*/ } else if (strcmp(argv[i], "--media-file") == 0){ i++; if (i<argc){ media_file = argv[i]; }else helper(argv[0]); } else { helper(argv[0]); } } if (!addr) { addr = linphone_address_new("sip:[email protected]:5060"); } lp_config_set_string(lp_config,"sip","bind_address",linphone_address_get_domain(addr)); lp_config_set_string(lp_config,"rtp","bind_address",linphone_address_get_domain(addr)); lp_config_set_int(lp_config,"misc","history_max_size",100000); vtable.call_state_changed=call_state_changed; lc=linphone_core_new_with_config(&vtable,lp_config,NULL); linphone_core_enable_video_capture(lc,TRUE); linphone_core_enable_video_display(lc,FALSE); linphone_core_set_video_policy(lc,&policy); linphone_core_enable_keep_alive(lc,FALSE); /*instead of using sound capture card, a file is played to the calling party*/ linphone_core_set_use_files(lc,TRUE); linphone_core_enable_echo_cancellation(lc, FALSE); /*no need for local echo cancellation when playing files*/ if (!media_file){ linphone_core_set_play_file(lc,PACKAGE_DATA_DIR "/sounds/linphone/hello16000.wav"); linphone_core_set_preferred_framerate(lc,5); }else{ PayloadType *pt = linphone_core_find_payload_type(lc, "opus", 48000, -1); /*if opus is present, give it a bitrate for good quality with music, and stereo enabled*/ if (pt){ linphone_core_set_payload_type_bitrate(lc, pt, 150); payload_type_set_send_fmtp(pt, "stereo=1"); payload_type_set_recv_fmtp(pt, "stereo=1"); } linphone_core_set_play_file(lc, media_file); linphone_core_set_preferred_video_size_by_name(lc, "720p"); } { MSWebCamDesc *desc = ms_mire_webcam_desc_get(); if (desc){ ms_web_cam_manager_add_cam(ms_factory_get_web_cam_manager(linphone_core_get_ms_factory(lc)),ms_web_cam_new(desc)); linphone_core_set_video_device(lc,"Mire: Mire (synthetic moving picture)"); } } memset(&tp,0,sizeof(LCSipTransports)); tp.udp_port = linphone_address_get_port(addr); tp.tcp_port = linphone_address_get_port(addr); linphone_core_set_sip_transports(lc,&tp); linphone_core_set_audio_port_range(lc,1024,65000); linphone_core_set_video_port_range(lc,1024,65000); linphone_core_set_primary_contact(lc,tmp=linphone_address_as_string(addr)); ms_free(tmp); /* main loop for receiving notifications and doing background linphonecore work: */ while(running){ const bctbx_list_t * iterator; linphone_core_iterate(lc); ms_usleep(50000); if (print_stats) { ms_message("*********************************"); ms_message("*Current number of calls [%10u] *", (unsigned int)bctbx_list_size(linphone_core_get_calls(lc))); ms_message("*Number of calls until now [%10u] *", (unsigned int)bctbx_list_size(linphone_core_get_call_logs(lc))); ms_message("*********************************"); print_stats=FALSE; } if (dump_stats) { ms_message("*********************************"); for (iterator=linphone_core_get_call_logs(lc);iterator!=NULL;iterator=iterator->next) { LinphoneCallLog *call_log=(LinphoneCallLog *)iterator->data; char * tmp_str = linphone_call_log_to_str(call_log); ms_message("\n%s",tmp_str); ms_free(tmp_str); } dump_stats=FALSE; ms_message("*********************************"); } for (iterator=linphone_core_get_calls(lc);iterator!=NULL;iterator=iterator->next) { LinphoneCall *call=(LinphoneCall *)iterator->data; if (linphone_call_get_duration(call) > max_call_duration) { ms_message("Terminating call [%p] after [%i] s",call,linphone_call_get_duration(call)); linphone_core_terminate_call(lc,call); break; } } } ms_message("Shutting down...\n"); linphone_core_destroy(lc); ms_message("Exited\n"); return 0; }
bctbx_list_t* linphone_core_fetch_friends_lists_from_db(LinphoneCore *lc) { char *buf; uint64_t begin,end; bctbx_list_t *result = NULL; bctbx_list_t *elem = NULL; if (!lc || lc->friends_db == NULL) { ms_warning("Either lc is NULL or friends database wasn't initialized with linphone_core_friends_storage_init() yet"); return NULL; } buf = sqlite3_mprintf("SELECT * FROM friends_lists ORDER BY id"); begin = ortp_get_cur_time_ms(); linphone_sql_request_friends_list(lc->friends_db, buf, &result); end = ortp_get_cur_time_ms(); ms_message("%s(): %u results fetched, completed in %i ms",__FUNCTION__, (unsigned int)bctbx_list_size(result), (int)(end-begin)); sqlite3_free(buf); for(elem = result; elem != NULL; elem = elem->next) { LinphoneFriendList *lfl = (LinphoneFriendList *)elem->data; lfl->lc = lc; lfl->friends = linphone_core_fetch_friends_from_db(lc, lfl); } return result; }
bctbx_list_t* linphone_core_fetch_friends_from_db(LinphoneCore *lc, LinphoneFriendList *list) { char *buf; uint64_t begin,end; bctbx_list_t *result = NULL; bctbx_list_t *elem = NULL; if (!lc || lc->friends_db == NULL || list == NULL) { ms_warning("Either lc (or list) is NULL or friends database wasn't initialized with linphone_core_friends_storage_init() yet"); return NULL; } linphone_vcard_context_set_user_data(lc->vcard_context, &result); buf = sqlite3_mprintf("SELECT * FROM friends WHERE friend_list_id = %u ORDER BY id", list->storage_id); begin = ortp_get_cur_time_ms(); linphone_sql_request_friend(lc->friends_db, buf, lc->vcard_context); end = ortp_get_cur_time_ms(); ms_message("%s(): %u results fetched, completed in %i ms",__FUNCTION__, (unsigned int)bctbx_list_size(result), (int)(end-begin)); sqlite3_free(buf); for(elem = result; elem != NULL; elem = elem->next) { LinphoneFriend *lf = (LinphoneFriend *)elem->data; lf->lc = lc; lf->friend_list = list; } linphone_vcard_context_set_user_data(lc->vcard_context, NULL); return result; }
static void carddav_integration(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:[email protected]\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); LinphoneVcard *lvc2 = NULL; LinphoneFriend *lf2 = NULL; LinphoneFriendListCbs *cbs = NULL; LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); const char *refkey = "toto"; char *address = NULL; LinphoneAddress *addr; linphone_friend_list_set_uri(lfl, CARDDAV_SERVER); cbs = linphone_friend_list_get_callbacks(lfl); linphone_friend_list_cbs_set_user_data(cbs, stats); 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(bctbx_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(bctbx_list_size(lfl->dirty_friends_to_update), 1, int, "%d"); 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(bctbx_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(bctbx_list_size(lfl->friends), 0, int, "%d"); 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; lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:[email protected]\r\nEND:VCARD\r\n"); lf = linphone_friend_new_from_vcard(lvc); BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); linphone_friend_unref(lf); lvc2 = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:[email protected]\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); linphone_vcard_set_url(lvc2, "/card.php/addressbooks/tester/default/me.vcf"); lf2 = linphone_friend_new_from_vcard(lvc2); linphone_friend_set_ref_key(lf2, refkey); BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf2), LinphoneFriendListOK, int, "%d"); 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, 5000); BC_ASSERT_EQUAL(stats->new_contact_count, 0, int, "%i"); 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, 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, 5000); BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); BC_ASSERT_EQUAL(bctbx_list_size(lfl->friends), 1, int, "%i"); lf = (LinphoneFriend *)lfl->friends->data; BC_ASSERT_STRING_EQUAL(lf->refkey, refkey); BC_ASSERT_EQUAL(lf->storage_id, lf2->storage_id, unsigned int, "%u"); linphone_friend_unref(lf2); addr = linphone_friend_get_address(lf); address = linphone_address_as_string_uri_only(addr); BC_ASSERT_STRING_EQUAL(address, "sip:[email protected]"); ms_free(address); linphone_address_unref(addr); linphone_friend_edit(lf); linphone_friend_done(lf); BC_ASSERT_EQUAL(bctbx_list_size(lf->friend_list->dirty_friends_to_update), 0, int, "%i"); linphone_core_set_network_reachable(manager->lc, FALSE); //To prevent the CardDAV update linphone_friend_edit(lf); linphone_friend_set_name(lf, "François Grisez"); linphone_friend_done(lf); BC_ASSERT_EQUAL(bctbx_list_size(lf->friend_list->dirty_friends_to_update), 1, int, "%i"); ms_free(stats); linphone_friend_list_unref(lfl); linphone_core_manager_destroy(manager); }
static bool_t stateful_analyzer_process_rtcp(MSQosAnalyzer *objbase, mblk_t *rtcp){ MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase; const report_block_t *rb=NULL; if (rtcp_is_SR(rtcp)){ rb=rtcp_SR_get_report_block(rtcp,0); }else if (rtcp_is_RR(rtcp)){ rb=rtcp_RR_get_report_block(rtcp,0); } if (rb && report_block_get_ssrc(rb)==rtp_session_get_send_ssrc(obj->session)){ if (ortp_loss_rate_estimator_process_report_block(objbase->lre,obj->session,rb)){ int i; float loss_rate = ortp_loss_rate_estimator_get_value(objbase->lre); float up_bw = stateful_qos_analyzer_upload_bandwidth(obj,report_block_get_high_ext_seq(rb)); obj->curindex++; /*flush bandwidth estimation measures for seq number lower than remote report block received*/ for (i=0;i<BW_HISTORY;i++){ if (obj->upload_bandwidth[i].seq_number<report_block_get_high_ext_seq(rb)){ obj->upload_bandwidth[i].seq_number=0; obj->upload_bandwidth[i].up_bandwidth=0.f; } } /* Always skip the first report, since values might be erroneous due to initialization of multiples objects (encoder/decoder/stats computing..) Instead assume loss rate is a good estimation of network capacity */ if (obj->curindex==1) { obj->network_loss_rate=loss_rate; return TRUE; } obj->latest=ms_new0(rtcpstatspoint_t, 1); obj->latest->timestamp=ms_time(0); obj->latest->bandwidth=up_bw; obj->latest->loss_percent=loss_rate; obj->latest->rtt=rtp_session_get_round_trip_propagation(obj->session); obj->rtcpstatspoint=bctbx_list_insert_sorted(obj->rtcpstatspoint, obj->latest, (bctbx_compare_func)sort_by_bandwidth); /*if the measure was 0% loss, reset to 0% every measures below it*/ if (obj->latest->loss_percent < 1e-5){ bctbx_list_t *it=obj->rtcpstatspoint; bctbx_list_t *latest_pos=bctbx_list_find(obj->rtcpstatspoint,obj->latest); while (it!=latest_pos->next){ ((rtcpstatspoint_t *)it->data)->loss_percent=0.f; it = it->next; } } ms_message("MSStatefulQosAnalyzer[%p]: one more %d: %f %f", obj, obj->curindex-1, obj->latest->bandwidth, obj->latest->loss_percent); if (bctbx_list_size(obj->rtcpstatspoint) > ESTIM_HISTORY){ size_t prev_size = bctbx_list_size(obj->rtcpstatspoint); /*clean everything which occurred 60 sec or more ago*/ time_t clear_time = ms_time(0) - 60; obj->rtcpstatspoint = bctbx_list_remove_custom(obj->rtcpstatspoint, (bctbx_compare_func)earlier_than, &clear_time); ms_message("MSStatefulQosAnalyzer[%p]: reached list maximum capacity " "(count=%u) --> Cleaned list (count=%u)", obj, (unsigned int)prev_size, (unsigned int)bctbx_list_size(obj->rtcpstatspoint)); } return TRUE; } } return FALSE; }
static void friends_sqlite_storage(void) { LinphoneCoreVTable *v_table = linphone_core_v_table_new(); LinphoneCore* lc = NULL; LinphoneFriendList *lfl = NULL; LinphoneFriend *lf = NULL; LinphoneFriend *lf2 = NULL; LinphoneVcard *lvc = linphone_vcard_new(); LinphoneAddress *addr = linphone_address_new("sip:[email protected]"); const bctbx_list_t *friends = NULL; bctbx_list_t *friends_from_db = NULL; bctbx_list_t *friends_lists_from_db = NULL; char *friends_db = bc_tester_file("friends.db"); LinphoneFriendListStats *stats = (LinphoneFriendListStats *)ms_new0(LinphoneFriendListStats, 1); LinphoneAddress *laddress = NULL, *laddress2 = NULL; char *address = NULL, *address2 = NULL; v_table->friend_list_created = friend_list_created_cb; v_table->friend_list_removed = friend_list_removed_cb; lc = linphone_core_new(v_table, NULL, NULL, NULL); friends = linphone_friend_list_get_friends(linphone_core_get_default_friend_list(lc)); lfl = linphone_core_create_friend_list(lc); linphone_friend_list_set_user_data(lfl, stats); BC_ASSERT_EQUAL(bctbx_list_size(friends), 0, int, "%d"); unlink(friends_db); linphone_core_set_friends_database_path(lc, friends_db); friends_from_db = linphone_core_fetch_friends_from_db(lc, linphone_core_get_default_friend_list(lc)); BC_ASSERT_EQUAL(bctbx_list_size(friends_from_db), 0, int, "%d"); linphone_vcard_set_etag(lvc, "\"123-456789\""); linphone_vcard_set_url(lvc, "http://dav.somewhere.fr/addressbook/me/someone.vcf"); lf = linphone_friend_new_from_vcard(lvc); linphone_friend_set_address(lf, addr); linphone_friend_set_name(lf, "Sylvain"); linphone_core_add_friend_list(lc, lfl); wait_for_until(lc, NULL, &stats->new_list_count, 1, 1000); BC_ASSERT_EQUAL(stats->new_list_count, 1, int, "%i"); linphone_friend_list_unref(lfl); linphone_friend_list_set_display_name(lfl, "Test"); BC_ASSERT_EQUAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%i"); linphone_friend_unref(lf); BC_ASSERT_EQUAL(lfl->storage_id, 1, unsigned int, "%u"); BC_ASSERT_EQUAL(lf->storage_id, 1, unsigned int, "%u"); friends = linphone_friend_list_get_friends(linphone_core_get_default_friend_list(lc)); BC_ASSERT_EQUAL(bctbx_list_size(friends), 0, int, "%d"); friends_lists_from_db = linphone_core_fetch_friends_lists_from_db(lc); BC_ASSERT_EQUAL(bctbx_list_size(friends_lists_from_db), 1, int, "%d"); friends_from_db = ((LinphoneFriendList *)friends_lists_from_db->data)->friends; BC_ASSERT_EQUAL(bctbx_list_size(friends_from_db), 1, int, "%d"); lf2 = (LinphoneFriend *)friends_from_db->data; BC_ASSERT_PTR_NOT_NULL(lf2->lc); BC_ASSERT_PTR_NOT_NULL(lf2->friend_list); friends_lists_from_db = bctbx_list_free_with_data(friends_lists_from_db, (void (*)(void *))linphone_friend_list_unref); friends_from_db = linphone_core_fetch_friends_from_db(lc, lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends_from_db), 1, int, "%d"); if (bctbx_list_size(friends_from_db) < 1) { goto end; } lf2 = (LinphoneFriend *)friends_from_db->data; BC_ASSERT_STRING_EQUAL(linphone_friend_get_name(lf2), linphone_friend_get_name(lf)); BC_ASSERT_EQUAL(lf2->storage_id, lf->storage_id, unsigned int, "%u"); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_etag(linphone_friend_get_vcard(lf2)), linphone_vcard_get_etag(linphone_friend_get_vcard(lf))); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_url(linphone_friend_get_vcard(lf2)), linphone_vcard_get_url(linphone_friend_get_vcard(lf))); laddress = linphone_friend_get_address(lf); address = linphone_address_as_string(laddress); laddress2 = linphone_friend_get_address(lf2); address2 = linphone_address_as_string(laddress2); BC_ASSERT_STRING_EQUAL(address2, address); linphone_address_unref(laddress); linphone_address_unref(laddress2); ms_free(address); ms_free(address2); linphone_friend_edit(lf); linphone_friend_set_name(lf, "Margaux"); linphone_friend_done(lf); friends_from_db = bctbx_list_free_with_data(friends_from_db, (void (*)(void *))linphone_friend_unref); friends_from_db = linphone_core_fetch_friends_from_db(lc, lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends_from_db), 1, int, "%d"); if (bctbx_list_size(friends_from_db) < 1) { goto end; } lf2 = (LinphoneFriend *)friends_from_db->data; BC_ASSERT_STRING_EQUAL(linphone_friend_get_name(lf2), "Margaux"); friends_from_db = bctbx_list_free_with_data(friends_from_db, (void (*)(void *))linphone_friend_unref); linphone_friend_list_remove_friend(lfl, lf); friends = linphone_friend_list_get_friends(linphone_core_get_default_friend_list(lc)); BC_ASSERT_EQUAL(bctbx_list_size(friends), 0, int, "%d"); friends_from_db = linphone_core_fetch_friends_from_db(lc, lfl); BC_ASSERT_EQUAL(bctbx_list_size(friends_from_db), 0, int, "%d"); linphone_core_remove_friend_list(lc, lfl); wait_for_until(lc, NULL, &stats->removed_list_count, 1, 1000); BC_ASSERT_EQUAL(stats->removed_list_count, 1, int, "%i"); end: ms_free(stats); unlink(friends_db); ms_free(friends_db); linphone_address_unref(addr); linphone_core_destroy(lc); linphone_core_v_table_destroy(v_table); }
static double compute_available_bw(MSStatefulQosAnalyzer *obj){ bctbx_list_t *it; double constant_network_loss = 0.; double mean_bw = 0.; bctbx_list_t *current = obj->rtcpstatspoint; bctbx_list_t *last = current; size_t size = bctbx_list_size(obj->rtcpstatspoint); if (current == NULL){ ms_message("MSStatefulQosAnalyzer[%p]: no points available for estimation", obj); return -1; } while (last->next){ last = last->next; } if (size > 3){ smooth_values(obj); } /*suppose that first point is a reliable estimation of the constant network loss rate*/ constant_network_loss = ((rtcpstatspoint_t *)obj->rtcpstatspoint->data)->loss_percent; ms_message("MSStatefulQosAnalyzer[%p]:\tconstant_network_loss=%f", obj, constant_network_loss); #ifdef DEBUG for (it = obj->rtcpstatspoint; it != NULL; it=it->next){ rtcpstatspoint_t * point = (rtcpstatspoint_t *)it->data; (void)point; ms_message("MSStatefulQosAnalyzer[%p]:\t\tsorted values %d: %f %f", obj, bctbx_list_position(obj->rtcpstatspoint, it), point->bandwidth, point->loss_percent); } #endif if (size == 1){ rtcpstatspoint_t *p = (rtcpstatspoint_t *)current->data; ms_message("MSStatefulQosAnalyzer[%p]: one single point", obj); mean_bw = p->bandwidth * ((p->loss_percent>1e-5) ? (100-p->loss_percent)/100.f:2); }else{ while (current!=NULL && ((rtcpstatspoint_t*)current->data)->loss_percent<3+constant_network_loss){ ms_message("MSStatefulQosAnalyzer[%p]:\t%d is stable", obj, bctbx_list_position(obj->rtcpstatspoint, current)); /*find the last stable measure point, starting from highest bandwidth*/ for (it=last;it!=current;it=it->prev){ if (((rtcpstatspoint_t *)it->data)->loss_percent <= 3 + ((rtcpstatspoint_t*)current->data)->loss_percent){ ms_message("MSStatefulQosAnalyzer[%p]:\t%d is less than %d", obj, bctbx_list_position(obj->rtcpstatspoint, it), bctbx_list_position(obj->rtcpstatspoint, current)); current = it; break; } } /*current is the first unstable point, so taking the next one*/ current = current->next; } /*all points are below the constant loss rate threshold: there might be bad network conditions but no congestion*/ if (current == NULL){ mean_bw = 2 * ((rtcpstatspoint_t*)last->data)->bandwidth; /*only first packet is stable*/ }else if (current->prev == obj->rtcpstatspoint){ rtcpstatspoint_t *p = (rtcpstatspoint_t *)current->prev->data; mean_bw = p->bandwidth * (100 - p->loss_percent) / 100.; /*otherwise, there is a congestion detected starting at "current"*/ }else{ rtcpstatspoint_t *laststable = (rtcpstatspoint_t*)current->prev->data; rtcpstatspoint_t *firstunstable = (rtcpstatspoint_t*)current->data; mean_bw = .5*(laststable->bandwidth+firstunstable->bandwidth); } ms_message("MSStatefulQosAnalyzer[%p]: [0->%d] last stable is %d(%f;%f)" , obj , bctbx_list_position(obj->rtcpstatspoint, last) , bctbx_list_position(obj->rtcpstatspoint, (current ? current->prev : last)) , ((rtcpstatspoint_t*) (current ? current->prev->data : last->data))->bandwidth , ((rtcpstatspoint_t*) (current ? current->prev->data : last->data))->loss_percent); if (current!=NULL){ ms_message("MSStatefulQosAnalyzer[%p]: , first unstable is %d(%f;%f)" , obj , bctbx_list_position(obj->rtcpstatspoint, current) , ((rtcpstatspoint_t*) current->data)->bandwidth , ((rtcpstatspoint_t*) current->data)->loss_percent); } } ms_message("MSStatefulQosAnalyzer[%p]: --> estimated_available_bw=%f", obj, mean_bw); obj->network_loss_rate = constant_network_loss; obj->congestion_bandwidth = mean_bw; return mean_bw; }
static void stateful_analyzer_suggest_action(MSQosAnalyzer *objbase, MSRateControlAction *action){ MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase; double curbw = 0; double bw = 0; rtcpstatspoint_t* greatest_pt = NULL; /*if this is the first measure, there is not enough reliable data to use; we assume loss rate is due to non congestionned network. This is mainly useful in the case loss rate is high (>30%), to reduce quality even before the second RTCP report which can be really used. */ if (obj->curindex==1){ if (obj->network_loss_rate!=0.f){ action->type=MSRateControlActionDecreaseBitrate; action->value=(int)obj->network_loss_rate; } }else { curbw = obj->latest ? obj->latest->bandwidth : 0.; bw = compute_available_bw(obj); greatest_pt = bctbx_list_size(obj->rtcpstatspoint) ? (rtcpstatspoint_t*)bctbx_list_nth_data(obj->rtcpstatspoint, (int)bctbx_list_size(obj->rtcpstatspoint)-1) : NULL; /*try a burst every 50 seconds (10 RTCP packets)*/ if (obj->curindex % 10 == 6){ ms_message("MSStatefulQosAnalyzer[%p]: try burst!", obj); obj->burst_state = MSStatefulQosAnalyzerBurstEnable; } /*test a min burst to avoid overestimation of available bandwidth but only if there is some loss*/ else if (greatest_pt!=NULL && greatest_pt->loss_percent>1 && (obj->curindex % 10 == 2 || obj->curindex % 10 == 3)){ ms_message("MSStatefulQosAnalyzer[%p]: try minimal burst!", obj); bw *= .33; } /*no bandwidth estimation computed*/ if (bw <= 0 || curbw <= 0){ action->type=MSRateControlActionDoNothing; action->value=0; }else if (bw > curbw){ action->type=MSRateControlActionIncreaseQuality; action->value=MAX(0, (int)(100 * (bw / curbw - 1))); }else{ action->type=MSRateControlActionDecreaseBitrate; action->value=MAX(10, (int)(-100 * (bw / curbw - 1))); } } ms_message("MSStatefulQosAnalyzer[%p]: %s of value %d", obj, ms_rate_control_action_type_name(action->type), action->value); if (objbase->on_action_suggested!=NULL){ int i; char *data[4]; int datac = sizeof(data) / sizeof(data[0]); data[0]=ms_strdup("%loss rtt_ms cur_bw"); data[1]=ms_strdup_printf("%d %d %d" , obj->latest?(int)obj->latest->loss_percent:0 , obj->latest?(int)obj->latest->rtt:0 , obj->latest?(int)obj->latest->bandwidth:0 ); data[2]=ms_strdup("action_type action_value est_bw"); data[3]=ms_strdup_printf("%s %d %d" , ms_rate_control_action_type_name(action->type) , action->value , (int)bw ); objbase->on_action_suggested(objbase->on_action_suggested_user_pointer, datac, (const char**)data); for (i=0;i<datac;++i){ ms_free(data[i]); } } }
static char * create_resource_list_xml(const LinphoneFriendList *list) { char *xml_content = NULL; bctbx_list_t *elem; xmlBufferPtr buf; xmlTextWriterPtr writer; int err; if (bctbx_list_size(list->friends) <= 0) return NULL; buf = xmlBufferCreate(); if (buf == NULL) { ms_error("%s: Error creating the XML buffer", __FUNCTION__); return NULL; } writer = xmlNewTextWriterMemory(buf, 0); if (writer == NULL) { ms_error("%s: Error creating the XML writer", __FUNCTION__); return NULL; } xmlTextWriterSetIndent(writer,1); err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); if (err >= 0) { err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"resource-lists", (const xmlChar *)"urn:ietf:params:xml:ns:resource-lists"); } if (err >= 0) { err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi", NULL, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance"); } if (err>= 0) { err = xmlTextWriterStartElement(writer, (const xmlChar *)"list"); } for (elem = list->friends; elem != NULL; elem = elem->next) { LinphoneFriend *lf = (LinphoneFriend *)elem->data; char *uri = linphone_address_as_string_uri_only(lf->uri); if (err >= 0) { err = xmlTextWriterStartElement(writer, (const xmlChar *)"entry"); } if (err >= 0) { err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"uri", (const xmlChar *)uri); } if (err >= 0) { /* Close the "entry" element. */ err = xmlTextWriterEndElement(writer); } if (uri) ms_free(uri); } if (err >= 0) { /* Close the "list" element. */ err = xmlTextWriterEndElement(writer); } if (err >= 0) { /* Close the "resource-lists" element. */ err = xmlTextWriterEndElement(writer); } if (err >= 0) { err = xmlTextWriterEndDocument(writer); } if (err > 0) { /* xmlTextWriterEndDocument returns the size of the content. */ xml_content = ms_strdup((char *)buf->content); } xmlFreeTextWriter(writer); xmlBufferFree(buf); return xml_content; }