Commit 005140d3 authored by Simon Morlat's avatar Simon Morlat

improve notification of generic subscribe errors

parent 71f81ce6
......@@ -18,19 +18,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sal_impl.h"
static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
ms_error("subscribe_process_io_error not implemented yet");
}
static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
SalOp* op= (SalOp*)ctx;
if (op->dialog) {
op->dialog=NULL;
sal_op_unref(op);
}
}
SalSubscribeStatus get_subscription_state(belle_sip_message_t *msg){
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t);
SalSubscribeStatus sss=SalSubscribeNone;
......@@ -45,73 +32,49 @@ SalSubscribeStatus get_subscription_state(belle_sip_message_t *msg){
return sss;
}
static void subscribe_response_event(void *op_base, const belle_sip_response_event_t *event){
SalOp* op = (SalOp*)op_base;
belle_sip_dialog_state_t dialog_state;
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
belle_sip_response_t* response=belle_sip_response_event_get_response(event);
belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
int code = belle_sip_response_get_status_code(response);
char reason[256]={0};
static void subscribe_refresher_listener (belle_sip_refresher_t* refresher
,void* user_pointer
,unsigned int status_code
,const char* reason_phrase) {
SalOp* op = (SalOp*)user_pointer;
SalError error=SalErrorUnknown;
SalReason sr=SalReasonUnknown;
belle_sip_header_expires_t* expires;
SalSubscribeStatus sss=get_subscription_state(BELLE_SIP_MESSAGE(response));
belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher));
/*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/
SalSubscribeStatus sss=SalSubscribeTerminated;
if (sal_compute_sal_errors(response,&error,&sr,reason, sizeof(reason))) {
ms_error("subscription to [%s] rejected reason [%s]",sal_op_get_to(op),reason[0]!=0?reason:sal_reason_to_string(sr));
op->base.root->callbacks.subscribe_response(op,SalSubscribeTerminated,error,sr);
return;
ms_message("Subscribe refresher [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none");
if (status_code>=200 && status_code<300){
if (status_code==200) sss=SalSubscribeActive;
else if (status_code==202) sss=SalSubscribePending;
set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr));
}
set_or_update_dialog(op_base,belle_sip_response_event_get_dialog(event));
if (!op->dialog) {
ms_message("subscribe op [%p] received out of dialog answer [%i]",op,code);
return;
if (status_code>=200){
sal_compute_sal_errors_from_code(status_code,&error,&sr);
op->base.root->callbacks.subscribe_response(op,sss,error,sr);
}
dialog_state=belle_sip_dialog_get_state(op->dialog);
switch(dialog_state) {
case BELLE_SIP_DIALOG_NULL:
case BELLE_SIP_DIALOG_EARLY: {
ms_error("subscribe op [%p] receive an unexpected answer [%i]",op,code);
break;
}
case BELLE_SIP_DIALOG_CONFIRMED: {
if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0) {
expires=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t);
if(op->refresher) {
belle_sip_refresher_stop(op->refresher);
belle_sip_object_unref(op->refresher);
op->refresher=NULL;
}
if (expires>0){
op->refresher=belle_sip_client_transaction_create_refresher(client_transaction);
if (op->refresher) belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher);
}
if (sss==SalSubscribeNone) sss=SalSubscribeActive; /*without Subscription-state header, consider subscription is accepted.*/
op->base.root->callbacks.subscribe_response(op,sss,SalErrorNone,SalReasonUnknown);
}
break;
}
case BELLE_SIP_DIALOG_TERMINATED:
if (op->refresher) {
belle_sip_refresher_stop(op->refresher);
belle_sip_object_unref(op->refresher);
op->refresher=NULL;
}
break;
default: {
ms_error("subscribe op [%p] receive answer [%i] not implemented",op,code);
}
/* no break */
}
static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
ms_error("subscribe_process_io_error not implemented yet");
}
static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
SalOp* op= (SalOp*)ctx;
if (op->dialog) {
op->dialog=NULL;
sal_op_unref(op);
}
}
static void subscribe_response_event(void *op_base, const belle_sip_response_event_t *event){
}
static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
ms_message("subscribe_process_timeout not implemented yet");
}
static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
ms_message("subscribe_process_transaction_terminated not implemented yet");
}
static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBody * body){
......@@ -191,7 +154,8 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
} else if (strcmp("SUBSCRIBE",method)==0) {
/*either a refresh of an unsubscribe*/
if (expires && belle_sip_header_expires_get_expires(expires)>0) {
resp=sal_op_create_response_from_request(op,req,200);
belle_sip_server_transaction_send_response(server_transaction,resp);
} else if(expires) {
ms_message("Unsubscribe received from [%s]",sal_op_get_from(op));
resp=sal_op_create_response_from_request(op,req,200);
......@@ -235,36 +199,29 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event
belle_sip_object_ref(op->event);
}
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
}else{
req=belle_sip_dialog_create_request(op->dialog,"SUBSCRIBE");
if (!req) {
ms_error("Cannot create subscribe refresh.");
return -1;
}
if (expires==-1){
belle_sip_transaction_t *last=(belle_sip_transaction_t*)op->pending_client_trans;
belle_sip_message_t *msg=BELLE_SIP_MESSAGE(belle_sip_transaction_get_request(last));
belle_sip_header_expires_t *eh=belle_sip_message_get_header_by_type(msg,belle_sip_header_expires_t);
expires=belle_sip_header_expires_get_expires(eh);
}
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
sal_op_add_body(op,(belle_sip_message_t*)req,body);
return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener);
}else if (op->refresher){
const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
/* modify last request to update body*/
sal_op_add_body(op,(belle_sip_message_t*)last_req,body);
return belle_sip_refresher_refresh(op->refresher,expires);
}
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
sal_op_add_body(op,(belle_sip_message_t*)req,body);
return sal_op_send_request(op,req);
ms_warning("sal_subscribe(): no dialog and no refresher ?");
return -1;
}
int sal_unsubscribe(SalOp *op){
belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"SUBSCRIBE"):NULL; /*cannot create request if dialog not set yet*/
if (!req) {
ms_error("Cannot unsubscribe to [%s]",sal_op_get_to(op));
return -1;
if (op->refresher){
const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
sal_op_add_body(op,(belle_sip_message_t*)last_req,NULL);
belle_sip_refresher_refresh(op->refresher,0);
return 0;
}
if (op->refresher)
belle_sip_refresher_stop(op->refresher);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(0)));
return sal_op_send_request(op,req);
return -1;
}
int sal_subscribe_accept(SalOp *op){
......
......@@ -435,7 +435,7 @@ bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,S
} else {
strncpy(reason,belle_sip_response_get_reason_phrase(response),reason_size);
}
if (code>400) {
if (code>=400) {
sal_compute_sal_errors_from_code(code,sal_err,sal_reason);
return TRUE;
} else {
......
......@@ -91,7 +91,7 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat
if (lc->vtable.subscription_state_changed){
lc->vtable.subscription_state_changed(lev->lc,lev,state);
}
if (state==LinphoneSubscriptionError || state==LinphoneSubscriptionTerminated){
if (state==LinphoneSubscriptionTerminated){
linphone_event_unref(lev);
}
}
......
mediastreamer2 @ 5003385d
Subproject commit 214f82f8942f9d1c419f038dbd33b36b65e2a1e6
Subproject commit 5003385d52f715b60772da879b4655463890ffd1
......@@ -120,12 +120,15 @@ static void subscribe_test_declined(void) {
}
static void subscribe_test_with_args(bool_t terminated_by_subscriber) {
static void subscribe_test_with_args(bool_t terminated_by_subscriber, bool_t test_refreshing) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
LinphoneContent content;
LinphoneEvent *lev;
int expires= test_refreshing ? 4 : 600;
MSList* lcs=ms_list_append(NULL,marie->lc);
lcs=ms_list_append(lcs,pauline->lc);
......@@ -134,7 +137,7 @@ static void subscribe_test_with_args(bool_t terminated_by_subscriber) {
content.data=(char*)subscribe_content;
content.size=strlen(subscribe_content);
lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",600,&content);
lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",expires,&content);
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000));
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000));
......@@ -143,6 +146,11 @@ static void subscribe_test_with_args(bool_t terminated_by_subscriber) {
/*make sure marie receives first notification before terminating*/
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,1,1000));
if (test_refreshing){
wait_for_list(lcs,NULL,0,6000);
CU_ASSERT_TRUE(linphone_event_get_subscription_state(pauline->lev)==LinphoneSubscriptionActive);
}
if (terminated_by_subscriber){
linphone_event_terminate(lev);
......@@ -159,11 +167,18 @@ static void subscribe_test_with_args(bool_t terminated_by_subscriber) {
}
static void subscribe_test_terminated_by_subscriber(void){
subscribe_test_with_args(TRUE);
subscribe_test_with_args(TRUE,FALSE);
}
static void subscribe_test_terminated_by_notifier(void){
subscribe_test_with_args(FALSE);
subscribe_test_with_args(FALSE,FALSE);
}
/* Caution: this test does not really check that the subscribe are refreshed, because the core is not managing the expiration of
* unrefreshed subscribe dialogs. So it is just checking that it is not crashing.
*/
static void subscribe_test_refreshed(void){
subscribe_test_with_args(TRUE,TRUE);
}
static void publish_test_with_args(bool_t refresh){
......@@ -218,6 +233,7 @@ static void publish_no_auto_test(){
test_t event_tests[] = {
{ "Subscribe declined" , subscribe_test_declined },
{ "Subscribe terminated by subscriber", subscribe_test_terminated_by_subscriber },
{ "Subscribe refreshed", subscribe_test_refreshed },
{ "Subscribe terminated by notifier", subscribe_test_terminated_by_notifier },
{ "Publish", publish_test },
{ "Publish without automatic refresh",publish_no_auto_test }
......
......@@ -143,13 +143,13 @@ bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value) {
bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) {
int retry=0;
MSList* iterator;
while (*counter<value && retry++ <timeout_ms/100) {
while ((counter==NULL || *counter<value) && retry++ <timeout_ms/100) {
for (iterator=lcs;iterator!=NULL;iterator=iterator->next) {
linphone_core_iterate((LinphoneCore*)(iterator->data));
}
ms_usleep(100000);
}
if(*counter<value) return FALSE;
if(counter && *counter<value) return FALSE;
else return TRUE;
}
......
......@@ -204,6 +204,7 @@ private:
mPropertyName=mName.substr(6,string::npos);
if (!mPropertyName.empty()){
mPropertyName[0]=tolower(mPropertyName[0]);
mPropertyName+="Enabled";
mPropertyBehaviour=Write;
}
}else if (mName.find("set")==0 && mArgs.size()==1){
......@@ -217,6 +218,7 @@ private:
if (enabled_pos==goodpos){
mPropertyName=mName.substr(0,goodpos);
if (!mPropertyName.empty()){
mPropertyName+="Enabled";
mPropertyBehaviour=Read;
}
}
......
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