Commit bb6d6605 authored by jehan's avatar jehan
Browse files

rework proxy config management edit()/done() method to only send unregister...

rework proxy config management edit()/done() method to only send unregister message when really needed
parent 93de3b19
......@@ -5664,7 +5664,7 @@ void sip_config_uninit(LinphoneCore *lc)
if (lc->network_reachable) {
for(elem=config->proxies;elem!=NULL;elem=ms_list_next(elem)){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
linphone_proxy_config_edit(cfg); /* to unregister */
_linphone_proxy_config_unregister(cfg); /* to unregister without changing the stored flag enable_register */
}
ms_message("Unregistration started.");
......
......@@ -393,6 +393,9 @@ LinphoneProxyConfig * is_a_linphone_proxy_config(void *user_pointer);
void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description);
static const int linphone_proxy_config_magic=0x7979;
bool_t linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b);
bool_t linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj);
void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj);
/*chat*/
void linphone_chat_message_destroy(LinphoneChatMessage* msg);
......@@ -428,6 +431,12 @@ struct _LinphoneProxyConfig
void* user_data;
time_t deletion_date;
LinphonePrivacyMask privacy;
/*use to check if server config has changed between edit() and done()*/
LinphoneAddress *saved_proxy;
LinphoneAddress *saved_identity;
LinphoneAddress *saved_route;
/*---*/
};
struct _LinphoneAuthInfo
......
......@@ -26,6 +26,60 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
#include <ctype.h>
/*store current config related to server location*/
static void linphone_proxy_config_store_server_config(LinphoneProxyConfig* obj) {
if (obj->saved_identity) linphone_address_destroy(obj->saved_identity);
if (obj->reg_identity)
obj->saved_identity = linphone_address_new(obj->reg_identity);
else
obj->saved_identity = NULL;
if (obj->saved_proxy) linphone_address_destroy(obj->saved_proxy);
if (obj->reg_proxy)
obj->saved_proxy = linphone_address_new(obj->reg_proxy);
else
obj->saved_proxy = NULL;
if (obj->saved_route) linphone_address_destroy(obj->saved_route);
if (obj->reg_route)
obj->saved_route = linphone_address_new(obj->reg_route);
else
obj->saved_route = NULL;
}
bool_t linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b) {
if (a == NULL && b == NULL)
return TRUE;
else if (!a || !b)
return FALSE;
if (linphone_address_weak_equal(a,b)) {
/*also check both transport and uri */
if (!(linphone_address_is_secure(a) ^ linphone_address_is_secure(b))) {
return linphone_address_get_transport(a) == linphone_address_get_transport(b);
} else
return FALSE; /*secure flag not equals*/
} else
return FALSE; /*either username, domain or port ar not equals*/
}
bool_t linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj) {
LinphoneAddress *current_identity=obj->reg_identity?linphone_address_new(obj->reg_identity):NULL;
LinphoneAddress *current_proxy=obj->reg_proxy?linphone_address_new(obj->reg_proxy):NULL;
LinphoneAddress *current_route=obj->reg_route?linphone_address_new(obj->reg_route):NULL;
if (!linphone_proxy_config_address_equal(obj->saved_identity,current_identity))
return TRUE;
if (!linphone_proxy_config_address_equal(obj->saved_proxy,current_proxy))
return TRUE;
if (!linphone_proxy_config_address_equal(obj->saved_route,current_route))
return TRUE;
return FALSE;
}
void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
MSList *elem;
......@@ -106,6 +160,9 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
if (obj->publish_op) sal_op_release(obj->publish_op);
if (obj->contact_params) ms_free(obj->contact_params);
if (obj->contact_uri_params) ms_free(obj->contact_uri_params);
if (obj->saved_proxy!=NULL) linphone_address_destroy(obj->saved_proxy);
if (obj->saved_identity!=NULL) ms_free(obj->saved_identity);
if (obj->saved_route!=NULL) ms_free(obj->saved_route);
ms_free(obj);
}
......@@ -265,21 +322,16 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
**/
void linphone_proxy_config_edit(LinphoneProxyConfig *obj){
if (obj->publish && obj->publish_op){
/*unpublish*/
sal_publish_presence(obj->publish_op,NULL,NULL,0,(SalPresenceModel *)NULL);
sal_op_release(obj->publish_op);
obj->publish_op=NULL;
}
if (obj->reg_sendregister){
/* unregister */
if (obj->state == LinphoneRegistrationOk
|| obj->state == LinphoneRegistrationProgress) {
sal_unregister(obj->op);
} else {
/*stop refresher*/
if (obj->op) sal_op_stop_refreshing(obj->op);
}
/*unpublish*/
sal_publish_presence(obj->publish_op,NULL,NULL,0,(SalPresenceModel *)NULL);
sal_op_release(obj->publish_op);
obj->publish_op=NULL;
}
/*store current config related to server location*/
linphone_proxy_config_store_server_config(obj);
/*stop refresher in any case*/
if (obj->op) sal_op_stop_refreshing(obj->op);
}
void linphone_proxy_config_apply(LinphoneProxyConfig *obj,LinphoneCore *lc){
......@@ -336,6 +388,14 @@ LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *obj){
return ret;
}
/**
* unregister without moving the register_enable flag
*/
void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) {
if (obj->state == LinphoneRegistrationOk) {
sal_unregister(obj->op);
}
}
static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
if (obj->reg_sendregister){
......@@ -360,8 +420,14 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
}
ms_free(proxy_string);
} else {
/*stop refresher, just in case*/
if (obj->op) sal_op_stop_refreshing(obj->op);
/* unregister if registered*/
if (obj->state == LinphoneRegistrationProgress) {
linphone_proxy_config_set_state(obj,LinphoneRegistrationCleared,"Registration cleared");
}
_linphone_proxy_config_unregister(obj);
}
}
......@@ -843,7 +909,19 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const cha
**/
int linphone_proxy_config_done(LinphoneProxyConfig *obj)
{
if (!linphone_proxy_config_check(obj->lc,obj)) return -1;
if (!linphone_proxy_config_check(obj->lc,obj))
return -1;
/*check if server address as changed*/
if (linphone_proxy_config_is_server_config_changed(obj)) {
/* server config has changed, need to unregister from previous first*/
if (obj->op) {
_linphone_proxy_config_unregister(obj);
sal_op_set_user_pointer(obj->op,NULL); /*we don't want to receive status for this un register*/
sal_op_unref(obj->op); /*but we keep refresher to handle authentication if needed*/
obj->op=NULL;
}
}
obj->commit=TRUE;
linphone_proxy_config_write_all_to_config_file(obj->lc);
return 0;
......
......@@ -551,6 +551,9 @@ void sal_op_set_to_address(SalOp *op, const SalAddress *to);
SalOp *sal_op_ref(SalOp* h);
void sal_op_stop_refreshing(SalOp *op);
void sal_op_release(SalOp *h);
/*same as release, but does not stop refresher if any*/
void* sal_op_unref(SalOp* op);
void sal_op_authenticate(SalOp *h, const SalAuthInfo *info);
void sal_op_cancel_authentication(SalOp *h);
void sal_op_set_user_pointer(SalOp *h, void *up);
......
......@@ -119,7 +119,8 @@ static void register_with_refresh_base_3(LinphoneCore* lc
linphone_core_add_proxy_config(lc,proxy_cfg);
linphone_core_set_default_proxy(lc,proxy_cfg);
while (counters->number_of_LinphoneRegistrationOk<1+(refresh!=0) && retry++ <310) {
while (counters->number_of_LinphoneRegistrationOk<1+(refresh!=0)
&& retry++ <(110 /*only wait 11 s if final state is progress*/+(expected_final_state==LinphoneRegistrationProgress?0:200))) {
linphone_core_iterate(lc);
if (counters->number_of_auth_info_requested>0 && linphone_proxy_config_get_state(proxy_cfg) == LinphoneRegistrationFailed && late_auth_info) {
if (!linphone_core_get_auth_info_list(lc)) {
......@@ -197,6 +198,52 @@ static void simple_register(){
linphone_core_manager_destroy(lcm);
}
static void simple_unregister(){
LinphoneCoreManager* lcm = create_lcm();
stats* counters = &lcm->stat;
LinphoneProxyConfig* proxy_config;
register_with_refresh_base(lcm->lc,FALSE,NULL,NULL);
linphone_core_get_default_proxy(lcm->lc,&proxy_config);
linphone_proxy_config_edit(proxy_config);
reset_counters(counters); /*clear stats*/
/*nothing is supposed to arrive until done*/
CU_ASSERT_FALSE(wait_for_until(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationCleared,1,3000));
linphone_proxy_config_enable_register(proxy_config,FALSE);
linphone_proxy_config_done(proxy_config);
CU_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationCleared,1));
linphone_core_manager_destroy(lcm);
}
static void change_expires(){
LinphoneCoreManager* lcm = create_lcm();
stats* counters = &lcm->stat;
LinphoneProxyConfig* proxy_config;
register_with_refresh_base(lcm->lc,FALSE,NULL,NULL);
linphone_core_get_default_proxy(lcm->lc,&proxy_config);
linphone_proxy_config_edit(proxy_config);
reset_counters(counters); /*clear stats*/
/*nothing is supposed to arrive until done*/
CU_ASSERT_FALSE(wait_for_until(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationCleared,1,3000));
linphone_proxy_config_set_expires(proxy_config,3);
linphone_proxy_config_done(proxy_config);
CU_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,1));
/*wait 2s without receive refresh*/
CU_ASSERT_FALSE(wait_for_until(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,2,2000));
/* now, it should be ok*/
CU_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,2));
linphone_core_manager_destroy(lcm);
}
/*take care of min expires configuration from server*/
static void simple_register_with_refresh() {
LinphoneCoreManager* lcm = create_lcm();
......@@ -467,6 +514,101 @@ static void transport_change(){
linphone_core_manager_destroy(mgr);
}
static void proxy_transport_change(){
LinphoneCoreManager* lcm = create_lcm();
stats* counters = &lcm->stat;
LinphoneProxyConfig* proxy_config;
LinphoneAddress* addr;
char* addr_as_string;
LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/
register_with_refresh_base(lcm->lc,FALSE,auth_domain,NULL);
linphone_core_get_default_proxy(lcm->lc,&proxy_config);
reset_counters(counters); /*clear stats*/
linphone_proxy_config_edit(proxy_config);
CU_ASSERT_FALSE(wait_for_until(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationCleared,1,3000));
addr = linphone_address_new(linphone_proxy_config_get_addr(proxy_config));
if (LinphoneTransportTcp == linphone_address_get_transport(addr)) {
linphone_address_set_transport(addr,LinphoneTransportUdp);
} else {
linphone_address_set_transport(addr,LinphoneTransportTcp);
}
linphone_proxy_config_set_server_addr(proxy_config,addr_as_string=linphone_address_as_string(addr));
linphone_proxy_config_done(proxy_config);
CU_ASSERT(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,1));
/*as we change p[roxy server destination, we should'nt be notified about the clear*/
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,0);
ms_free(addr_as_string);
linphone_address_destroy(addr);
linphone_core_manager_destroy(lcm);
}
static void proxy_transport_change_with_wrong_port() {
LinphoneCoreManager* lcm = create_lcm();
stats* counters = &lcm->stat;
LinphoneProxyConfig* proxy_config;
LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/
char route[256];
LCSipTransports transport= {LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM};
sprintf(route,"sip:%s",test_route);
linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/
register_with_refresh_base_3(lcm->lc, FALSE, auth_domain, "sip2.linphone.org:5987", 0,transport,LinphoneRegistrationProgress);
linphone_core_get_default_proxy(lcm->lc,&proxy_config);
linphone_proxy_config_edit(proxy_config);
CU_ASSERT_FALSE(wait_for_until(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationCleared,1,3000));
linphone_proxy_config_set_server_addr(proxy_config,route);
linphone_proxy_config_done(proxy_config);
CU_ASSERT(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,1));
/*as we change proxy server destination, we should'nt be notified about the clear*/
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,0);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,1);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,1);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0);
linphone_core_manager_destroy(lcm);
}
static void proxy_transport_change_with_wrong_port_givin_up() {
LinphoneCoreManager* lcm = create_lcm();
stats* counters = &lcm->stat;
LinphoneProxyConfig* proxy_config;
LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/
char route[256];
LCSipTransports transport= {LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM};
sprintf(route,"sip:%s",test_route);
linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/
register_with_refresh_base_3(lcm->lc, FALSE, auth_domain, "sip2.linphone.org:5987", 0,transport,LinphoneRegistrationProgress);
linphone_core_get_default_proxy(lcm->lc,&proxy_config);
linphone_proxy_config_edit(proxy_config);
CU_ASSERT_FALSE(wait_for_until(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationCleared,1,3000));
linphone_proxy_config_enableregister(proxy_config,FALSE);
linphone_proxy_config_done(proxy_config);
CU_ASSERT(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationCleared,1));
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,0);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,1);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0);
linphone_core_manager_destroy(lcm);
}
static void io_recv_error(){
LinphoneCoreManager *mgr;
LinphoneCore* lc;
......@@ -567,22 +709,17 @@ static void io_recv_error_without_active_register(){
for (proxys=ms_list_copy(linphone_core_get_proxy_config_list(lc));proxys!=NULL;proxys=proxys->next) {
LinphoneProxyConfig* proxy_cfg=(LinphoneProxyConfig*)proxys->data;
linphone_proxy_config_edit(proxy_cfg);
linphone_proxy_config_enableregister(proxy_cfg,FALSE);
linphone_proxy_config_done(proxy_cfg);
}
ms_list_free(proxys);
/*wait for unregistrations*/
CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationCleared,register_ok /*because 1 udp*/));
for (proxys=ms_list_copy(linphone_core_get_proxy_config_list(lc));proxys!=NULL;proxys=proxys->next) {
LinphoneProxyConfig* proxy_cfg=(LinphoneProxyConfig*)proxys->data;
linphone_proxy_config_enable_register(proxy_cfg,FALSE);
linphone_proxy_config_done(proxy_cfg);
}
ms_list_free(proxys);
sal_set_recv_error(lc->sal, 0);
/*nothing should happen because no active registration*/
CU_ASSERT_FALSE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationProgress,2*(register_ok-number_of_udp_proxy) /*because 1 udp*/));
CU_ASSERT_FALSE(wait_for_until(lc,lc,&counters->number_of_LinphoneRegistrationProgress,2*(register_ok-number_of_udp_proxy) /*because 1 udp*/,3000));
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0)
......@@ -669,6 +806,7 @@ static void tls_wildcard_register(){
test_t register_tests[] = {
{ "Simple register", simple_register },
{ "Simple register unregister", simple_unregister },
{ "TCP register", simple_tcp_register },
{ "TCP register compatibility mode", simple_tcp_register_compatibility_mode },
{ "TLS register", simple_tls_register },
......@@ -688,7 +826,11 @@ test_t register_tests[] = {
{ "Authenticated register with refresh", simple_auth_register_with_refresh },
{ "Register with refresh and send error", register_with_refresh_with_send_error },
{ "Multi account", multiple_proxy },
{ "Transport change", transport_change },
{ "Transport changes", transport_change },
{ "Proxy transport changes", proxy_transport_change},
{ "Proxy transport changes with wrong address at first", proxy_transport_change_with_wrong_port},
{ "Proxy transport changes with wrong address, giving up",proxy_transport_change_with_wrong_port_givin_up},
{ "Change expires", change_expires},
{ "Network state change", network_state_change },
{ "Io recv error", io_recv_error },
{ "Io recv error with recovery", io_recv_error_retry_immediatly},
......
......@@ -21,7 +21,7 @@
#include "linphonecore.h"
#include "liblinphone_tester.h"
#include "lpconfig.h"
#include "private.h"
static void core_init_test(void) {
LinphoneCoreVTable v_table;
......@@ -104,10 +104,70 @@ static void linphone_lpconfig_from_buffer(){
lp_config_destroy(conf);
}
void linphone_proxy_config_address_equal_test() {
LinphoneAddress *a = linphone_address_new("sip:toto@titi");
LinphoneAddress *b = linphone_address_new("sips:toto@titi");
LinphoneAddress *c = linphone_address_new("sip:toto@titi;transport=tcp");
LinphoneAddress *d = linphone_address_new("sip:toto@titu");
LinphoneAddress *e = linphone_address_new("sip:toto@titi;transport=udp");
CU_ASSERT_FALSE(linphone_proxy_config_address_equal(a,NULL));
CU_ASSERT_FALSE(linphone_proxy_config_address_equal(a,b));
CU_ASSERT_FALSE(linphone_proxy_config_address_equal(a,c));
CU_ASSERT_FALSE(linphone_proxy_config_address_equal(a,d));
CU_ASSERT_TRUE(linphone_proxy_config_address_equal(a,e));
CU_ASSERT_TRUE(linphone_proxy_config_address_equal(NULL,NULL));
linphone_address_destroy(a);
linphone_address_destroy(b);
linphone_address_destroy(c);
linphone_address_destroy(d);
}
void linphone_proxy_config_is_server_config_changed_test() {
LinphoneProxyConfig* proxy_config = linphone_proxy_config_new();
linphone_proxy_config_set_identity(proxy_config,"sip:toto@titi");
linphone_proxy_config_edit(proxy_config);
linphone_proxy_config_set_identity(proxy_config,"sips:toto@titi");
CU_ASSERT_TRUE(linphone_proxy_config_is_server_config_changed(proxy_config));
linphone_proxy_config_set_server_addr(proxy_config,"sip:sip.linphone.org");
linphone_proxy_config_edit(proxy_config);
linphone_proxy_config_set_server_addr(proxy_config,"sip:toto.com");
CU_ASSERT_TRUE(linphone_proxy_config_is_server_config_changed(proxy_config));
linphone_proxy_config_set_route(proxy_config,"sip:sip.linphone.org");
linphone_proxy_config_edit(proxy_config);
linphone_proxy_config_set_route(proxy_config,"sip:sip.linphone.org:4444");
CU_ASSERT_TRUE(linphone_proxy_config_is_server_config_changed(proxy_config));
linphone_proxy_config_set_route(proxy_config,"sip:sip.linphone.org");
linphone_proxy_config_edit(proxy_config);
linphone_proxy_config_set_route(proxy_config,"sip:sip.linphone.org;transport=tcp");
CU_ASSERT_TRUE(linphone_proxy_config_is_server_config_changed(proxy_config));
linphone_proxy_config_set_route(proxy_config,"sip:sip.linphone.org");
linphone_proxy_config_edit(proxy_config);
linphone_proxy_config_set_route(proxy_config,"sip:sip.linphone.org;param=blue");
CU_ASSERT_FALSE(linphone_proxy_config_is_server_config_changed(proxy_config));
linphone_proxy_config_edit(proxy_config);
linphone_proxy_config_set_contact_parameters(proxy_config,"blabla=blue");
CU_ASSERT_FALSE(linphone_proxy_config_is_server_config_changed(proxy_config));
linphone_proxy_config_edit(proxy_config);
linphone_proxy_config_enable_register(proxy_config,TRUE);
CU_ASSERT_FALSE(linphone_proxy_config_is_server_config_changed(proxy_config));
linphone_proxy_config_destroy(proxy_config);
}
test_t setup_tests[] = {
{ "Linphone Address", linphone_address_test },
{ "Linphone proxy config address equal (internal api)", linphone_proxy_config_address_equal_test},
{ "Linphone proxy config server address change (internal api)", linphone_proxy_config_is_server_config_changed_test},
{ "Linphone core init/uninit", core_init_test },
{ "Linphone random transport port",core_sip_transport_test},
{ "Linphone interpret url", linphone_interpret_url_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