Commit a3bb622b authored by Simon Morlat's avatar Simon Morlat
Browse files

Allow proxy config with dependencies to be added in any order in the...

Allow proxy config with dependencies to be added in any order in the LinphoneCore. The resolution of dependencies is then performed each time a new LinphoneProxyConfig is added.
parent 6f26c3b4
......@@ -111,8 +111,6 @@ struct _LinphoneProxyConfig
bool_t commit;
bool_t reg_sendregister;
/* Used to completely disable registration on a dependent proxy config. (Won't be enabled back even if it's 'master' proxy config state goes to LinphoneRegistrationOk) */
bool_t reg_dependent_disabled;
bool_t publish;
bool_t dial_escape_plus;
......
......@@ -177,7 +177,6 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cf
}
}
cfg->depends_on = depends_on ? ms_strdup(depends_on) : NULL;
cfg->reg_dependent_disabled = cfg->depends_on && !cfg->reg_sendregister;
if (idkey) {
cfg->idkey = ms_strdup(idkey);
} else {
......@@ -267,6 +266,10 @@ void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){
linphone_event_unref(cfg->presence_publish_event);
cfg->presence_publish_event=NULL;
}
if (cfg->dependency){
linphone_proxy_config_unref(cfg->dependency);
cfg->dependency = NULL;
}
}
void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){
......@@ -444,36 +447,49 @@ LinphoneStatus linphone_proxy_config_set_routes(LinphoneProxyConfig *cfg, const
return 0;
}
static void _linphone_core_resolve_proxy_config_dependencies(LinphoneCore *lc){
LinphoneProxyConfig *cfg;
const bctbx_list_t *elem;
for(elem = lc->sip_conf.proxies; elem != NULL; elem = elem->next){
cfg = (LinphoneProxyConfig*)elem->data;
if (cfg->dependency != NULL && cfg->depends_on != NULL) {
LinphoneProxyConfig *master_cfg = linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on);
if (master_cfg != NULL && master_cfg != cfg->dependency) {
ms_error("LinphoneProxyConfig has a dependency but idkeys do not match: [%s] != [%s], breaking dependency now.", cfg->depends_on, cfg->dependency->idkey);
linphone_proxy_config_unref(cfg->dependency);
cfg->dependency = NULL;
return;
}else if (master_cfg == NULL){
ms_warning("LinphoneProxyConfig [%p] depends on proxy config [%p], which is not currently in the list.", cfg, cfg->dependency);
}
}
if (cfg->depends_on != NULL && cfg->dependency == NULL) {
LinphoneProxyConfig *dependency = linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on);
if (dependency == NULL) {
ms_warning("LinphoneProxyConfig marked as dependent but no proxy configuration found for idkey [%s]", cfg->depends_on);
return;
} else {
ms_message("LinphoneProxyConfig [%p] now depends on master LinphoneProxyConfig [%p]", cfg, dependency);
cfg->dependency = linphone_proxy_config_ref(dependency);
}
}
}
}
bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *cfg){
if (cfg->reg_proxy==NULL)
return FALSE;
if (cfg->identity_address==NULL)
return FALSE;
if (cfg->dependency != NULL && cfg->depends_on != NULL) {
if (linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on) != cfg->dependency) {
ms_warning("LinphoneProxyConfig as a dependency but idkeys do not match: [%s] != [%s]", cfg->depends_on, cfg->dependency->idkey);
return FALSE;
}
}
if (cfg->depends_on != NULL && cfg->dependency == NULL) {
LinphoneProxyConfig *dependency = linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on);
if (dependency == NULL) {
ms_warning("LinphoneProxyConfig marked as dependent but no proxy configuration found for idkey [%s]", cfg->depends_on);
return FALSE;
} else {
cfg->dependency = linphone_proxy_config_ref(dependency);
}
}
_linphone_core_resolve_proxy_config_dependencies(lc);
return TRUE;
}
void linphone_proxy_config_enableregister(LinphoneProxyConfig *cfg, bool_t val){
if (val != cfg->reg_sendregister) cfg->register_changed = TRUE;
cfg->reg_sendregister = val;
if (cfg->dependency && !val) {
cfg->reg_dependent_disabled = TRUE;
}
}
void linphone_proxy_config_set_expires(LinphoneProxyConfig *cfg, int val){
......@@ -1175,15 +1191,8 @@ void linphone_core_remove_dependent_proxy_config(LinphoneCore *lc, LinphoneProxy
if (tmp != cfg && tmp->dependency == cfg) {
ms_message("Updating dependent proxy config [%p] caused by removal of 'master' proxy config idkey[%s]", tmp, cfg->idkey);
linphone_proxy_config_set_dependency(tmp, NULL);
linphone_proxy_config_edit(tmp);
//Only re-enable register if proxy wasn't explicitely disabled
linphone_proxy_config_enable_register(tmp, tmp->reg_dependent_disabled != TRUE);
tmp->reg_dependent_disabled = FALSE;
linphone_proxy_config_done(tmp);
//Force update on dependent if master wasn't registered
if (cfg->state != LinphoneRegistrationOk) {
linphone_proxy_config_update(tmp);
}
cfg->commit = TRUE;
linphone_proxy_config_update(tmp);
}
}
}
......@@ -1422,8 +1431,6 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc
CONFIGURE_STRING_VALUE(cfg, config, key, conference_factory_uri, "conference_factory_uri");
cfg->reg_dependent_disabled = cfg->depends_on && !cfg->reg_sendregister;
return cfg;
}
......@@ -1468,7 +1475,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){
return FALSE;
}
if (cfg->dependency) {
return linphone_proxy_config_get_state(cfg->dependency) == LinphoneRegistrationOk && !cfg->reg_dependent_disabled;
return linphone_proxy_config_get_state(cfg->dependency) == LinphoneRegistrationOk;
}
return TRUE;
}
......@@ -1520,8 +1527,13 @@ void _linphone_update_dependent_proxy_config(LinphoneProxyConfig *cfg, LinphoneR
for (;it;it = it->next) {
LinphoneProxyConfig *tmp = reinterpret_cast<LinphoneProxyConfig *>(it->data);
ms_message("_linphone_update_dependent_proxy_config(): %p is registered, checking for [%p] ->dependency=%p", cfg, tmp, tmp->dependency);
if (tmp != cfg && tmp->dependency == cfg) {
if (tmp->reg_dependent_disabled) continue;
if (!tmp->reg_sendregister) {
ms_message("Dependant proxy config [%p] has registration disabled, so it will not register.", tmp);
continue;
}
linphone_proxy_config_edit(tmp);
if (state == LinphoneRegistrationOk) {
// Force dependent proxy config to re-register
......
......@@ -381,6 +381,8 @@ void linphone_core_manager_stop(LinphoneCoreManager *mgr);
void linphone_core_manager_uninit_after_stop_async(LinphoneCoreManager *mgr);
void linphone_core_manager_reinit(LinphoneCoreManager *mgr);
void linphone_core_manager_restart(LinphoneCoreManager *mgr, bool_t check_for_proxies);
/* This function is used to restore the fake DNS which is lost after a linphone_core_stop() */
void linphone_core_manager_setup_dns(LinphoneCoreManager *mgr);
void linphone_core_manager_uninit(LinphoneCoreManager *mgr);
void linphone_core_manager_wait_for_stun_resolution(LinphoneCoreManager *mgr);
void linphone_core_manager_destroy(LinphoneCoreManager* mgr);
......
......@@ -373,57 +373,156 @@ static void proxy_config_dependent_register_state_changed(void) {
}
//Dependent proxy config pointing to inexistant other proxy configuration.
static void invalid_dependent_proxy_config(void) {
//A dependent proxy config should behave as a normal one after removal of dependency
static void dependent_proxy_dependency_removal(void) {
LinphoneCoreManager *marie = linphone_core_manager_create("marie_dependent_proxy_rc");
const bctbx_list_t *proxyConfigs = linphone_core_get_proxy_config_list(marie->lc);
LinphoneProxyConfig *master = (LinphoneProxyConfig *) proxyConfigs->data;
LinphoneProxyConfig *dependent = (LinphoneProxyConfig *) proxyConfigs->next->data;
linphone_core_remove_proxy_config(marie->lc, dependent);
linphone_core_set_network_reachable(marie->lc, FALSE);
linphone_core_remove_proxy_config(marie->lc, master);
proxyConfigs = linphone_core_get_proxy_config_list(marie->lc);
BC_ASSERT_EQUAL(bctbx_list_size(proxyConfigs), 0, int, "%d");
BC_ASSERT_EQUAL(bctbx_list_size(proxyConfigs), 1, int, "%d");
linphone_core_add_proxy_config(marie->lc, master);
linphone_core_set_network_reachable(marie->lc, TRUE);
linphone_proxy_config_set_dependency(dependent, master);
BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 1));
linphone_proxy_config_set_idkey(master, "invalid");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneRegistrationOk, 1, int, "%d");
//Adding a dependent proxy config linking to inexistent dependency should fail
BC_ASSERT_EQUAL(linphone_core_add_proxy_config(marie->lc, dependent), -1, int, "%d");
linphone_core_manager_destroy(marie);
}
proxyConfigs = linphone_core_get_proxy_config_list(marie->lc);
static void dependent_proxy_dependency_with_core_reloaded(void){
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_external_rc");
LinphoneCoreManager *marie = linphone_core_manager_new("marie_dependent_proxy_rc");
LinphoneProxyConfig *marie_cfg = linphone_core_get_default_proxy_config(marie->lc);
LinphoneProxyConfig *marie_dependent_cfg = (LinphoneProxyConfig *) linphone_core_get_proxy_config_list(marie->lc)->next->data;
LinphoneAddress *marie_master_address, *marie_secondary_address;
BC_ASSERT_PTR_NOT_NULL(marie_cfg);
BC_ASSERT_PTR_NOT_NULL(marie_dependent_cfg);
BC_ASSERT_TRUE(wait_for(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 2));
BC_ASSERT_PTR_EQUAL(marie_cfg, linphone_proxy_config_get_dependency(marie_dependent_cfg));
marie_master_address = linphone_address_clone(linphone_proxy_config_get_identity_address(marie_cfg));
marie_secondary_address = linphone_address_clone(linphone_proxy_config_get_identity_address(marie_dependent_cfg));
/* Clear all proxy config, wait for unregistration*/
linphone_core_clear_proxy_config(marie->lc);
BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationCleared, 2));
BC_ASSERT_EQUAL(bctbx_list_size(proxyConfigs), 1, int, "%d");
/* Now re-enter the proxy config in reverse order: the dependant first, the master second. */
marie_dependent_cfg = linphone_core_create_proxy_config(marie->lc);
linphone_proxy_config_set_identity_address(marie_dependent_cfg, marie_secondary_address);
linphone_proxy_config_set_server_addr(marie_dependent_cfg, "sip:external.example.org:5068;transport=tcp");
linphone_proxy_config_set_route(marie_dependent_cfg, "sip:external.example.org:5068;transport=tcp");
linphone_proxy_config_enable_register(marie_dependent_cfg, TRUE);
marie_cfg = linphone_core_create_proxy_config(marie->lc);
linphone_proxy_config_set_identity_address(marie_cfg, marie_master_address);
linphone_proxy_config_set_server_addr(marie_cfg, "sip:sipopen.example.org;transport=tls");
linphone_proxy_config_enable_register(marie_cfg, TRUE);
/* Now add them to the core: */
linphone_core_add_proxy_config(marie->lc, marie_dependent_cfg);
linphone_core_add_proxy_config(marie->lc, marie_cfg);
linphone_core_set_default_proxy_config(marie->lc, marie_cfg);
/* Setup their dependency: */
linphone_proxy_config_set_dependency(marie_dependent_cfg, marie_cfg);
BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 4));
BC_ASSERT_PTR_EQUAL(marie_cfg, linphone_proxy_config_get_dependency(marie_dependent_cfg));
/* Then everything should work as if order was the same as before. */
linphone_core_manager_destroy(marie);
}
const LinphoneAddress *marie_cfg_contact = linphone_proxy_config_get_contact(marie_cfg);
const LinphoneAddress *marie_dependent_cfg_contact = linphone_proxy_config_get_contact(marie_dependent_cfg);
//A dependent proxy config should behave as a normal one after removal of dependency
static void dependent_proxy_dependency_removal(void) {
LinphoneCoreManager *marie = linphone_core_manager_create("marie_dependent_proxy_rc");
const bctbx_list_t *proxyConfigs = linphone_core_get_proxy_config_list(marie->lc);
LinphoneProxyConfig *master = (LinphoneProxyConfig *) proxyConfigs->data;
BC_ASSERT_TRUE(linphone_proxy_config_address_equal(marie_cfg_contact, marie_dependent_cfg_contact) == LinphoneProxyConfigAddressEqual);
//Cut link for dependent proxy config, then call its identity address and check that we receive the call
//(which would be received through the 'master' proxy config server)
linphone_core_set_network_reachable(marie->lc, FALSE);
linphone_proxy_config_edit(marie_dependent_cfg);
linphone_proxy_config_enable_register(marie_dependent_cfg, FALSE);
linphone_proxy_config_done(marie_dependent_cfg);
linphone_core_set_network_reachable(marie->lc, TRUE);
linphone_core_remove_proxy_config(marie->lc, master);
wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 5); //One more time for 'master' proxy config
proxyConfigs = linphone_core_get_proxy_config_list(marie->lc);
LinphoneAddress *marie_dependent_addr = linphone_address_new(linphone_proxy_config_get_identity(marie_dependent_cfg));
BC_ASSERT_EQUAL(bctbx_list_size(proxyConfigs), 1, int, "%d");
linphone_core_invite_address(pauline->lc, marie_dependent_addr);
linphone_core_set_network_reachable(marie->lc, TRUE);
if (BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallIncomingReceived, 1, 10000))) {
linphone_call_accept(linphone_core_get_current_call(marie->lc));
BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1, 10000));
BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1, 10000));
end_call(pauline, marie);
}
linphone_address_unref(marie_dependent_addr);
/* re-enable marie's registration on dependent proxy config*/
linphone_proxy_config_edit(marie_dependent_cfg);
linphone_proxy_config_enable_register(marie_dependent_cfg, TRUE);
linphone_proxy_config_done(marie_dependent_cfg);
wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 6);
/* Now marie's core stops and restarts. */
linphone_core_stop(marie->lc);
linphone_core_start(marie->lc);
linphone_core_manager_setup_dns(marie);
/* Check that configuration could be reloaded correctly */
BC_ASSERT_EQUAL(bctbx_list_size(linphone_core_get_proxy_config_list(marie->lc)), 2, int, "%i");
BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 8));
/* And make new call attempt */
marie_cfg = (LinphoneProxyConfig *) linphone_core_get_proxy_config_list(marie->lc)->next->data;
marie_dependent_cfg = (LinphoneProxyConfig *) linphone_core_get_proxy_config_list(marie->lc)->data;
BC_ASSERT_PTR_EQUAL(marie_cfg, linphone_proxy_config_get_dependency(marie_dependent_cfg));
BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 1));
marie_cfg_contact = linphone_proxy_config_get_contact(marie_cfg);
marie_dependent_cfg_contact = linphone_proxy_config_get_contact(marie_dependent_cfg);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneRegistrationOk, 1, int, "%d");
BC_ASSERT_TRUE(linphone_proxy_config_address_equal(marie_cfg_contact, marie_dependent_cfg_contact) == LinphoneProxyConfigAddressEqual);
//Cut link for dependent proxy config, then call its identity address and check that we receive the call
//(which would be received through the 'master' proxy config server)
linphone_core_set_network_reachable(marie->lc, FALSE);
linphone_proxy_config_edit(marie_dependent_cfg);
linphone_proxy_config_enable_register(marie_dependent_cfg, FALSE);
linphone_proxy_config_done(marie_dependent_cfg);
linphone_core_set_network_reachable(marie->lc, TRUE);
wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 9); //One more time for 'master' proxy config
marie_dependent_addr = linphone_address_new(linphone_proxy_config_get_identity(marie_dependent_cfg));
linphone_core_invite_address(pauline->lc, marie_dependent_addr);
if (BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallIncomingReceived, 2, 10000))) {
linphone_call_accept(linphone_core_get_current_call(marie->lc));
BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2, 10000));
BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2, 10000));
end_call(pauline, marie);
}
linphone_address_unref(marie_dependent_addr);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
test_t proxy_config_tests[] = {
......@@ -434,10 +533,10 @@ test_t proxy_config_tests[] = {
TEST_NO_TAG("Load new default value for proxy config", load_dynamic_proxy_config),
TEST_NO_TAG("Single route", single_route),
TEST_NO_TAG("Proxy dependency", dependent_proxy_config),
TEST_NO_TAG("Invalid dependent proxy", invalid_dependent_proxy_config),
TEST_NO_TAG("Dependent proxy dependency register", proxy_config_dependent_register),
TEST_NO_TAG("Dependent proxy state changed", proxy_config_dependent_register_state_changed),
TEST_NO_TAG("Dependent proxy dependency removal", dependent_proxy_dependency_removal)
TEST_NO_TAG("Dependent proxy dependency removal", dependent_proxy_dependency_removal),
TEST_ONE_TAG("Dependent proxy dependency with core reloaded", dependent_proxy_dependency_with_core_reloaded, "LeaksMemory")
};
test_suite_t proxy_config_test_suite = {"Proxy config", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
......
......@@ -126,13 +126,7 @@ void reset_counters( stats* counters) {
memset(counters,0,sizeof(stats));
}
void configure_lc(LinphoneCore *lc, const char *path, void *user_data) {
linphone_core_enable_ipv6(lc, liblinphonetester_ipv6);
linphone_core_set_sip_transport_timeout(lc, liblinphonetester_transport_timeout);
linphone_core_set_user_data(lc, user_data);
sal_enable_test_features(linphone_core_get_sal(lc), TRUE);
static void setup_dns(LinphoneCore *lc, const char *path){
if (strcmp(userhostsfile, "none") != 0) {
char *dnsuserhostspath = strchr(userhostsfile, '/') ? ms_strdup(userhostsfile) : ms_strdup_printf("%s/%s", path, userhostsfile);
sal_set_dns_user_hosts_file(linphone_core_get_sal(lc), dnsuserhostspath);
......@@ -142,6 +136,16 @@ void configure_lc(LinphoneCore *lc, const char *path, void *user_data) {
}
}
void configure_lc(LinphoneCore *lc, const char *path, void *user_data) {
linphone_core_enable_ipv6(lc, liblinphonetester_ipv6);
linphone_core_set_sip_transport_timeout(lc, liblinphonetester_transport_timeout);
linphone_core_set_user_data(lc, user_data);
sal_enable_test_features(linphone_core_get_sal(lc), TRUE);
setup_dns(lc, path);
}
LinphoneCore *configure_lc_from(LinphoneCoreCbs *cbs, const char *path, LinphoneConfig *config, void *user_data) {
LinphoneCore *lc;
char *ringpath = NULL;
......@@ -340,6 +344,9 @@ static void avoid_pulseaudio_hack(LinphoneCoreManager *mgr){
}
#endif
void linphone_core_manager_setup_dns(LinphoneCoreManager *mgr){
setup_dns(mgr->lc, bc_tester_get_resource_dir_prefix());
}
void linphone_core_manager_configure (LinphoneCoreManager *mgr) {
LinphoneImNotifPolicy *im_notif_policy;
......
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