Commit 488dadc4 authored by jehan's avatar jehan

use belle-sip-refresher for registration

parent fa4a074f
......@@ -35,6 +35,10 @@
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="coreapi"/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="tester"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
......@@ -198,4 +202,5 @@
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>
......@@ -23,11 +23,12 @@ SalAddress * sal_address_new(const char *uri){
belle_sip_header_address_t* result;
if (uri) {
result=belle_sip_header_address_parse (uri);
/*may return NULL*/
} else {
result = belle_sip_header_address_new();
belle_sip_header_address_set_uri(result,belle_sip_uri_new());
}
belle_sip_object_ref(result);
if (result) belle_sip_object_ref(result);
return (SalAddress *)result;
}
SalAddress * sal_address_clone(const SalAddress *addr){
......
......@@ -534,3 +534,6 @@ int sal_reset_transports(Sal *ctx){
void sal_set_dscp(Sal *ctx, int dscp){
ms_warning("sal_set_dscp not implemented");
}
void sal_set_send_error(Sal *sal,int value) {
belle_sip_stack_set_send_error(sal->stack,value);
}
......@@ -55,7 +55,7 @@ struct SalOp{
belle_sip_server_transaction_t* pending_server_trans;
belle_sip_client_transaction_t* pending_inv_client_trans;
SalAuthInfo* auth_info;
unsigned long int registration_refresh_timer;
belle_sip_refresher_t* registration_refresher;
bool_t sdp_offering;
belle_sip_dialog_t* dialog;
belle_sip_header_address_t *replaces;
......@@ -83,7 +83,7 @@ void sal_op_resend_request(SalOp* op, belle_sip_request_t* request);
void sal_process_authentication(SalOp *op, belle_sip_response_t *response);
bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size);
void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) ;
/*presence*/
void sal_op_presence_fill_cbs(SalOp*op);
......
......@@ -28,11 +28,12 @@ SalOp * sal_op_new(Sal *sal){
void sal_op_release(SalOp *op){
if (op->request) belle_sip_object_unref(op->request);
if (op->registration_refresh_timer>0) {
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
}
if (op->auth_info) sal_auth_info_delete(op->auth_info);
if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer);
if (op->registration_refresher) {
belle_sip_refresher_stop(op->registration_refresher);
belle_sip_object_unref(op->registration_refresher);
}
__sal_op_free(op);
return ;
}
......@@ -115,12 +116,19 @@ int sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
belle_sip_client_transaction_t* client_transaction;
belle_sip_provider_t* prov=op->base.root->prov;
belle_sip_header_route_t* route_header;
belle_sip_uri_t* outbound_proxy=NULL;
MSList* iterator;
if (!op->dialog) {
/*don't put route header if dialog is in confirmed state*/
for(iterator=(MSList*)sal_op_get_route_addresses(op);iterator!=NULL;iterator=iterator->next) {
route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(iterator->data));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(route_header));
if(!outbound_proxy) {
/*first toute is outbound proxy*/
outbound_proxy=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(iterator->data));
} else {
/*next are Route headers*/
route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(iterator->data));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(route_header));
}
}
}
......@@ -135,26 +143,11 @@ int sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
/*hmm just in case we already have authentication param in cache*/
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL);
}
return belle_sip_client_transaction_send_request(client_transaction);
return belle_sip_client_transaction_send_request_to(client_transaction,outbound_proxy/*might be null*/);
}
/*return TRUE if error code*/
bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size) {
int code = belle_sip_response_get_status_code(response);
belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason");
*sal_err=SalErrorUnknown;
*sal_reason = SalReasonUnknown;
if (reason_header){
snprintf(reason
,reason_size
,"%s %s"
,belle_sip_response_get_reason_phrase(response)
,belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(reason_header)));
} else {
strncpy(reason,belle_sip_response_get_reason_phrase(response),reason_size);
}
if (code >=400) {
void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) {
switch(code) {
case 400:
*sal_err=SalErrorUnknown;
......@@ -195,6 +188,25 @@ bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,S
}else *sal_err=SalErrorNoResponse;
/* no break */
}
}
/*return TRUE if error code*/
bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size) {
int code = belle_sip_response_get_status_code(response);
belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason");
*sal_err=SalErrorUnknown;
*sal_reason = SalReasonUnknown;
if (reason_header){
snprintf(reason
,reason_size
,"%s %s"
,belle_sip_response_get_reason_phrase(response)
,belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(reason_header)));
} else {
strncpy(reason,belle_sip_response_get_reason_phrase(response),reason_size);
}
if (code>400) {
sal_compute_sal_errors_from_code(code,sal_err,sal_reason);
return TRUE;
} else {
return FALSE;
......
......@@ -24,38 +24,51 @@ static void register_process_io_error(void *user_ctx, const belle_sip_io_error_e
ms_error("process_io_error not implemented yet");
}
static void register_refresh(SalOp* op) {
op->registration_refresh_timer=0;
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_CSEQ);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
sal_op_send_request(op,op->request);
static void register_refresher_listener ( const belle_sip_refresher_t* refresher
,void* user_pointer
,unsigned int status_code
,const char* reason_phrase) {
SalOp* op = (SalOp*)user_pointer;
SalError sal_err;
SalReason sal_reason;
ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op));
if(status_code ==200) {
op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->registration_refresher)>0);
} else if (status_code>=400) {
sal_compute_sal_errors_from_code(status_code,&sal_err,&sal_reason);
op->base.root->callbacks.register_failure(op,sal_err,sal_reason,reason_phrase);
} else {
ms_warning("Register refresher know what to do with this status code");
}
}
static void register_response_event(void *user_ctx, const belle_sip_response_event_t *event){
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
belle_sip_response_t* response = belle_sip_response_event_get_response(event);
/* belle_sip_request_t* original_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
belle_sip_header_expires_t* expires_header;
belle_sip_request_t* original_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
belle_sip_header_contact_t* original_contact=belle_sip_message_get_header_by_type(original_request,belle_sip_header_contact_t);
const belle_sip_list_t* contact_header_list;
char* tmp_string;*/
belle_sip_header_service_route_t* service_route;
belle_sip_header_address_t* service_route_address=NULL;
int response_code = belle_sip_response_get_status_code(response);
int expires=-1;
char* tmp_string;
/*int expires=-1;*/
if (response_code<200) return;/*nothing to do*/
switch (response_code) {
case 200: {
contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT);
/* contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT);
if (contact_header_list) {
contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list,(belle_sip_compare_func)belle_sip_header_contact_not_equals, (const void*)original_contact);
if (!contact_header_list) {
/*reset header list*/
reset header list
contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT);
contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list,(belle_sip_compare_func)belle_sip_header_contact_not_equals, (const void*)sal_op_get_contact_address(op));
}
......@@ -69,7 +82,7 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve
}
if (expires<0 ) {
/*no contact with expire, looking for Expires header*/
no contact with expire, looking for Expires header
if ((expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_EXPIRES))) {
expires = belle_sip_header_expires_get_expires(expires_header);
}
......@@ -79,7 +92,7 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve
expires = belle_sip_header_expires_get_expires(expires_header);
ms_message("Neither Expires header nor corresponding Contact header found, using expires value [%i] from request",expires);
}
}
}*/
/*check service route rfc3608*/
if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) {
service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route)));
......@@ -87,14 +100,11 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve
sal_op_set_service_route(op,(const SalAddress*)service_route_address);
if (service_route_address) belle_sip_object_unref(service_route_address);
op->base.root->callbacks.register_success(op,expires>0);
/*always cancel pending refresh if any*/
if (op->registration_refresh_timer>0) {
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
op->registration_refresh_timer=0;
}
if (expires>0) {
op->registration_refresh_timer = belle_sip_main_loop_add_timeout(belle_sip_stack_get_main_loop(op->base.root->stack),(belle_sip_source_func_t)register_refresh,op,expires*1000);
op->base.root->callbacks.register_success(op,TRUE);
if (/*expires>0 &&*/ !op->registration_refresher) {
op->registration_refresher = belle_sip_client_transaction_create_refresher(client_transaction);
belle_sip_refresher_set_listener(op->registration_refresher,register_refresher_listener,op);
}
break;
......@@ -159,16 +169,13 @@ int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
}
int sal_register_refresh(SalOp *op, int expires){
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_CSEQ);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
send_register_request_with_expires(op,op->request,expires);
return 0;
if (op->registration_refresher)
return belle_sip_refresher_refresh(op->registration_refresher,expires);
else
return -1;
}
int sal_unregister(SalOp *op){
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_CSEQ);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
send_register_request_with_expires(op,op->request,0);
return 0;
return sal_register_refresh(op,0);
}
......@@ -346,6 +346,9 @@ const char *sal_op_get_contact(const SalOp *op){
}
const char *sal_op_get_route(const SalOp *op){
#ifdef BELLE_SIP
ms_fatal("sal_op_get_route not supported, use sal_op_get_route_addresses instead");
#endif
return ((SalOpBase*)op)->route;
}
......
......@@ -488,4 +488,7 @@ void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/);
void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin);
void __sal_op_free(SalOp *b);
/*test api*/
/*0 for no error*/
void sal_set_send_error(Sal *sal,int value);
#endif
......@@ -278,7 +278,7 @@ max-expires=86400
# Minimum expire time for a REGISTER, in seconds.
# Default value: 60
min-expires=60
min-expires=1
# File containing the static records to add to database at startup.
# Format: one 'sip_uri contact_header' by line. Example:
......@@ -466,11 +466,11 @@ sdp-port-range-max=65535
# a total bandwith below this value expressed in kbit/s. Use 0 to
# disable the feature
# Default value: 0
h264-filtering-bandwidth=0
#h264-filtering-bandwidth=0
# When above option is activated, keep one I frame over this number.
# Default value: 1
h264-iframe-decim=1
#h264-iframe-decim=1
##
## The purpose of the Transcoder module is to transparently transcode
......
......@@ -18,6 +18,8 @@
#include <stdio.h>
#include "CUnit/Basic.h"
#include "linphonecore.h"
#include "private.h"
const char *test_domain="sipopen.example.org";
const char *auth_domain="sip.example.org";
......@@ -111,19 +113,33 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo
}
}
static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username) {
ms_message("Auth info requested for user id [%s] at realm [%s]\n"
,username
,realm);
stats* counters = (stats*)linphone_core_get_user_data(lc);
counters->number_of_auth_info_requested++;
LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
}
static LinphoneCore* create_lc() {
static LinphoneCore* create_lc_with_auth(unsigned int with_auth) {
LinphoneCoreVTable v_table;
LinphoneCore* lc;
memset (&v_table,0,sizeof(v_table));
v_table.registration_state_changed=registration_state_changed;
if (with_auth) {
v_table.auth_info_requested=auth_info_requested;
}
lc = linphone_core_new(&v_table,NULL,NULL,NULL);
linphone_core_set_user_data(lc,&global_stat);
return lc;
}
static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* domain,const char* route) {
static LinphoneCore* create_lc() {
return create_lc_with_auth(0);
}
static void register_with_refresh_base(LinphoneCore* lc, bool_t refresh,const char* domain,const char* route) {
int retry=0;
LCSipTransports transport = {5070,5070,0,5071};
......@@ -141,7 +157,7 @@ static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* d
const char* server_addr = linphone_address_get_domain(from);
linphone_proxy_config_enable_register(proxy_cfg,TRUE);
linphone_proxy_config_expires(proxy_cfg,30);
linphone_proxy_config_expires(proxy_cfg,1);
if (route) {
linphone_proxy_config_set_route(proxy_cfg,route);
linphone_proxy_config_set_server_addr(proxy_cfg,route);
......@@ -153,41 +169,70 @@ static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* d
linphone_core_add_proxy_config(lc,proxy_cfg);
linphone_core_set_default_proxy(lc,proxy_cfg);
while (counters->number_of_LinphoneRegistrationOk<1 && retry++ <20) {
while (counters->number_of_LinphoneRegistrationOk<1+(refresh!=0) && retry++ <310) {
linphone_core_iterate(lc);
ms_usleep(100000);
}
CU_ASSERT_TRUE(linphone_proxy_config_is_registered(proxy_cfg));
if (refresh) {
/*wait until refresh*/
while (counters->number_of_LinphoneRegistrationOk<2 && retry++ <310) {
CU_ASSERT_TRUE_FATAL(linphone_proxy_config_is_registered(proxy_cfg));
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationNone,0);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,1+(refresh!=0));
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,1+(refresh!=0));
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,0);
}
static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* domain,const char* route) {
stats* counters = (stats*)linphone_core_get_user_data(lc);
register_with_refresh_base(lc,refresh,domain,route);
linphone_core_destroy(lc);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,1);
}
static void register_with_refresh_with_send_error(void) {
int retry=0;
LinphoneCore* lc = create_lc_with_auth(1);
stats* counters = (stats*)linphone_core_get_user_data(lc);
LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
register_with_refresh_base(lc,TRUE,auth_domain,NULL);
/*simultate a network error*/
sal_set_send_error(lc->sal, -1);
while (counters->number_of_LinphoneRegistrationFailed<1 && retry++ <20) {
linphone_core_iterate(lc);
ms_usleep(100000);
}
linphone_core_destroy(lc);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationNone,0);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,2);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,2);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,1);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0);
} else {
linphone_core_destroy(lc);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationNone,0);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,1);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,1);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,1);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0);
}
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,1);
linphone_core_destroy(lc);
CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,0);
}
static void simple_register(){
LinphoneCore* lc = create_lc();
stats* counters = (stats*)linphone_core_get_user_data(lc);
register_with_refresh(lc,FALSE,NULL,NULL);
CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0);
}
/*take care of min expires configuration from server*/
static void simple_register_with_refresh() {
LinphoneCore* lc = create_lc();
stats* counters = (stats*)linphone_core_get_user_data(lc);
register_with_refresh(lc,TRUE,NULL,NULL);
CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0);
}
static void simple_auth_register_with_refresh() {
LinphoneCore* lc = create_lc_with_auth(1);
stats* counters = (stats*)linphone_core_get_user_data(lc);
register_with_refresh(lc,TRUE,auth_domain,NULL);
CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,1);
}
static void simple_tcp_register(){
char route[256];
sprintf(route,"sip:%s;transport=tcp",test_domain);
......@@ -210,16 +255,7 @@ static void simple_authenticated_register(){
CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0);
}
static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username) {
ms_message("Auth info requested for user id [%s] at realm [%s]\n"
,username
,realm);
stats* counters = (stats*)linphone_core_get_user_data(lc);
counters->number_of_auth_info_requested++;
LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
}
static void authenticated_register_with_no_initial_credentials(){
LinphoneCoreVTable v_table;
......@@ -654,7 +690,7 @@ CU_pSuite pSuite = CU_add_suite("Setup", init, uninit);
}
pSuite = CU_add_suite("Register", init, uninit);
if (NULL == CU_add_test(pSuite, "simple register tester", simple_register)) {
if (NULL == CU_add_test(pSuite, "simple_register_tester", simple_register)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "tcp register tester", simple_tcp_register)) {
......@@ -669,6 +705,17 @@ CU_pSuite pSuite = CU_add_suite("Setup", init, uninit);
if (NULL == CU_add_test(pSuite, "register with digest auth tester without initial credentials", authenticated_register_with_no_initial_credentials)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "simple_register_with_refresh", simple_register_with_refresh)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "simple_auth_register_with_refresh", simple_auth_register_with_refresh)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "register_with_refresh_with_send_error", register_with_refresh_with_send_error)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "multi account", multiple_proxy)) {
return CU_get_error();
}
......
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