Commit 269f8d1c authored by Simon Morlat's avatar Simon Morlat

add new API to obtain full details about failures (calls, registration, events).

Fix bug when receiving a 487 after cancelling call, resulting in a call waiting tone to be played.
parent 90733896
......@@ -162,8 +162,8 @@ void sal_process_authentication(SalOp *op) {
static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){
belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_event_get_dialog(event);
SalOp* op = belle_sip_dialog_get_application_data(dialog);
if (op && op->callbacks.process_dialog_terminated) {
op->callbacks.process_dialog_terminated(op,event);
if (op && op->callbacks && op->callbacks->process_dialog_terminated) {
op->callbacks->process_dialog_terminated(op,event);
} else {
ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog);
}
......@@ -177,8 +177,8 @@ static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *e
op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
/*also reset auth count on IO error*/
op->auth_requests=0;
if (op->callbacks.process_io_error) {
op->callbacks.process_io_error(op,event);
if (op->callbacks && op->callbacks->process_io_error) {
op->callbacks->process_io_error(op,event);
}
} else {
/*ms_error("sal process_io_error not implemented yet for non transaction");*/
......@@ -290,8 +290,8 @@ static void process_request_event(void *ud, const belle_sip_request_event_t *eve
sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req);
sal_op_assign_recv_headers(op,(belle_sip_message_t*)req);
if (op->callbacks.process_request_event) {
op->callbacks.process_request_event(op,event);
if (op->callbacks && op->callbacks->process_request_event) {
op->callbacks->process_request_event(op,event);
} else {
ms_error("sal process_request_event not implemented yet");
}
......@@ -329,7 +329,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
sal_op_assign_recv_headers(op,(belle_sip_message_t*)response);
if (op->callbacks.process_response_event) {
if (op->callbacks && op->callbacks->process_response_event) {
/*handle authorization*/
switch (response_code) {
case 200:
......@@ -365,7 +365,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
/*not an auth request*/
op->auth_requests=0;
}
op->callbacks.process_response_event(op,event);
op->callbacks->process_response_event(op,event);
} else {
ms_error("Unhandled event response [%p]",event);
}
......@@ -375,8 +375,8 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
if (op && op->callbacks.process_timeout) {
op->callbacks.process_timeout(op,event);
if (op && op->callbacks && op->callbacks->process_timeout) {
op->callbacks->process_timeout(op,event);
} else {
ms_error("Unhandled event timeout [%p]",event);
}
......@@ -393,8 +393,8 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans
trans=BELLE_SIP_TRANSACTION(server_transaction);
op = (SalOp*)belle_sip_transaction_get_application_data(trans);
if (op && op->callbacks.process_transaction_terminated) {
op->callbacks.process_transaction_terminated(op,event);
if (op && op->callbacks && op->callbacks->process_transaction_terminated) {
op->callbacks->process_transaction_terminated(op,event);
} else {
ms_message("Unhandled transaction terminated [%p]",trans);
}
......@@ -443,6 +443,7 @@ Sal * sal_init(){
sal->refresher_retry_after=60000; /*default value in ms*/
return sal;
}
void sal_set_user_pointer(Sal *sal, void *user_data){
sal->up=user_data;
}
......
......@@ -76,7 +76,8 @@ const char* sal_op_type_to_string(SalOpType type);
struct SalOp{
SalOpBase base;
belle_sip_listener_callbacks_t callbacks;
const belle_sip_listener_callbacks_t *callbacks;
SalErrorInfo error_info;
belle_sip_client_transaction_t *pending_auth_transaction;
belle_sip_server_transaction_t* pending_server_trans;
belle_sip_server_transaction_t* pending_update_server_trans;
......@@ -132,8 +133,10 @@ bool_t sal_op_is_secure(const SalOp* op);
void sal_process_authentication(SalOp *op);
belle_sip_header_contact_t* sal_op_create_contact(SalOp *op) ;
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) ;
bool_t _sal_compute_sal_errors(belle_sip_response_t* response, SalReason* sal_reason, char* reason, size_t reason_size);
SalReason _sal_reason_from_sip_code(int code);
void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response);
/*presence*/
void sal_op_presence_fill_cbs(SalOp*op);
/*messaging*/
......
......@@ -38,19 +38,8 @@ static void call_set_released_and_unref(SalOp* op) {
static void call_set_error(SalOp* op,belle_sip_response_t* response){
SalError error=SalErrorUnknown;
SalReason sr=SalReasonUnknown;
belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason");
char* reason=(char*)belle_sip_response_get_reason_phrase(response);
int code = belle_sip_response_get_status_code(response);
if (reason_header){
reason = ms_strdup_printf("%s %s",reason,belle_sip_header_get_unparsed_value(reason_header));
}
sal_compute_sal_errors_from_code(code,&error,&sr);
op->base.root->callbacks.call_failure(op,error,sr,reason,code);
if (reason_header != NULL){
ms_free(reason);
}
sal_op_set_error_info_from_response(op,response);
op->base.root->callbacks.call_failure(op);
}
static void sdp_process(SalOp *h){
......@@ -127,7 +116,8 @@ static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event
if (!op->dialog) {
/*call terminated very early*/
op->base.root->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,"Service Unavailable",503);
sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO error",NULL);
op->base.root->callbacks.call_failure(op);
call_set_released(op);
} else {
/*dialog will terminated shortly, nothing to do*/
......@@ -290,7 +280,8 @@ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t
if (!op->dialog) {
/*call terminated very early*/
op->base.root->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,"Request Timeout",408);
sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL);
op->base.root->callbacks.call_failure(op);
call_set_released(op);
} else {
/*dialog will terminated shortly, nothing to do*/
......@@ -631,13 +622,18 @@ int sal_call(SalOp *op, const char *from, const char *to){
return sal_op_send_request(op,invite);
}
static belle_sip_listener_callbacks_t call_op_callbacks={0};
void sal_op_call_fill_cbs(SalOp*op) {
op->callbacks.process_io_error=call_process_io_error;
op->callbacks.process_response_event=call_process_response;
op->callbacks.process_timeout=call_process_timeout;
op->callbacks.process_transaction_terminated=call_process_transaction_terminated;
op->callbacks.process_request_event=process_request_event;
op->callbacks.process_dialog_terminated=process_dialog_terminated;
if (call_op_callbacks.process_response_event==NULL){
call_op_callbacks.process_io_error=call_process_io_error;
call_op_callbacks.process_response_event=call_process_response;
call_op_callbacks.process_timeout=call_process_timeout;
call_op_callbacks.process_transaction_terminated=call_process_transaction_terminated;
call_op_callbacks.process_request_event=process_request_event;
call_op_callbacks.process_dialog_terminated=process_dialog_terminated;
}
op->callbacks=&call_op_callbacks;
op->type=SalOpCall;
}
......
......@@ -37,8 +37,6 @@ static void subscribe_refresher_listener (belle_sip_refresher_t* refresher
,unsigned int status_code
,const char* reason_phrase) {
SalOp* op = (SalOp*)user_pointer;
SalError error=SalErrorUnknown;
SalReason sr=SalReasonUnknown;
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;
......@@ -50,8 +48,8 @@ static void subscribe_refresher_listener (belle_sip_refresher_t* refresher
set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr));
}
if (status_code>=200){
sal_compute_sal_errors_from_code(status_code,&error,&sr);
op->base.root->callbacks.subscribe_response(op,sss,error,sr);
sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL);
op->base.root->callbacks.subscribe_response(op,sss);
}else if (status_code==0){
op->base.root->callbacks.on_expire(op);
}
......@@ -172,13 +170,18 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
}
}
static belle_sip_listener_callbacks_t op_subscribe_callbacks={ 0 };
void sal_op_subscribe_fill_cbs(SalOp*op) {
op->callbacks.process_io_error=subscribe_process_io_error;
op->callbacks.process_response_event=subscribe_response_event;
op->callbacks.process_timeout=subscribe_process_timeout;
op->callbacks.process_transaction_terminated=subscribe_process_transaction_terminated;
op->callbacks.process_request_event=subscribe_process_request_event;
op->callbacks.process_dialog_terminated=subscribe_process_dialog_terminated;
if (op_subscribe_callbacks.process_io_error==NULL){
op_subscribe_callbacks.process_io_error=subscribe_process_io_error;
op_subscribe_callbacks.process_response_event=subscribe_response_event;
op_subscribe_callbacks.process_timeout=subscribe_process_timeout;
op_subscribe_callbacks.process_transaction_terminated=subscribe_process_transaction_terminated;
op_subscribe_callbacks.process_request_event=subscribe_process_request_event;
op_subscribe_callbacks.process_dialog_terminated=subscribe_process_dialog_terminated;
}
op->callbacks=&op_subscribe_callbacks;
op->type=SalOpSubscribe;
}
......
......@@ -62,6 +62,7 @@ void sal_op_release_impl(SalOp *op){
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans);
if (op->event) belle_sip_object_unref(op->event);
sal_error_info_reset(&op->error_info);
__sal_op_free(op);
return ;
}
......@@ -334,6 +335,12 @@ int sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
SalReason sal_reason_to_sip_code(SalReason r){
int ret=500;
switch(r){
case SalReasonNone:
ret=200;
break;
case SalReasonIOError:
ret=503;
break;
case SalReasonUnknown:
ret=400;
break;
......@@ -401,110 +408,123 @@ SalReason sal_reason_to_sip_code(SalReason r){
return ret;
}
void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) {
*sal_err=SalErrorFailure;
SalReason _sal_reason_from_sip_code(int code) {
if (code>=100 && code<300) return SalReasonNone;
switch(code) {
case 0:
return SalReasonIOError;
case 301:
*sal_reason=SalReasonMovedPermanently;
break;
return SalReasonMovedPermanently;
case 302:
*sal_reason=SalReasonRedirect;
break;
return SalReasonRedirect;
case 401:
case 407:
*sal_reason=SalReasonUnauthorized;
break;
return SalReasonUnauthorized;
case 403:
*sal_reason=SalReasonForbidden;
break;
return SalReasonForbidden;
case 404:
*sal_reason=SalReasonNotFound;
break;
return SalReasonNotFound;
case 408:
*sal_reason=SalReasonRequestTimeout;
break;
return SalReasonRequestTimeout;
case 410:
*sal_reason=SalReasonGone;
break;
return SalReasonGone;
case 415:
*sal_reason=SalReasonUnsupportedContent;
break;
return SalReasonUnsupportedContent;
case 422:
ms_error ("422 not implemented yet");;
break;
case 480:
*sal_reason=SalReasonTemporarilyUnavailable;
break;
return SalReasonTemporarilyUnavailable;
case 481:
*sal_reason=SalReasonNoMatch;
break;
return SalReasonNoMatch;
case 484:
*sal_reason=SalReasonAddressIncomplete;
break;
return SalReasonAddressIncomplete;
case 486:
*sal_reason=SalReasonBusy;
break;
return SalReasonBusy;
case 487:
break;
return SalReasonNone;
case 488:
*sal_reason=SalReasonNotAcceptable;
break;
return SalReasonNotAcceptable;
case 491:
*sal_reason=SalReasonRequestPending;
break;
return SalReasonRequestPending;
case 501:
*sal_reason=SalReasonNotImplemented;
break;
return SalReasonNotImplemented;
case 502:
*sal_reason=SalReasonBadGateway;
break;
return SalReasonBadGateway;
case 504:
*sal_reason=SalReasonServerTimeout;
break;
return SalReasonServerTimeout;
case 600:
*sal_reason=SalReasonDoNotDisturb;
break;
return SalReasonDoNotDisturb;
case 603:
*sal_reason=SalReasonDeclined;
break;
return SalReasonDeclined;
case 503:
*sal_reason=SalReasonServiceUnavailable;
break;
return SalReasonServiceUnavailable;
default:
if (code>=300){
*sal_err=SalErrorFailure;
*sal_reason=SalReasonUnknown;
}else if (code>=100){
*sal_err=SalErrorNone;
*sal_reason=SalReasonUnknown;
}else if (code==0){
*sal_err=SalErrorNoResponse;
}
/* no break */
return SalReasonUnknown;
}
return SalReasonUnknown;
}
/*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_get_unparsed_value(reason_header));
} else {
strncpy(reason,belle_sip_response_get_reason_phrase(response),reason_size);
const SalErrorInfo *sal_error_info_none(void){
static SalErrorInfo none={
SalReasonNone,
"Ok",
200,
NULL,
NULL
};
return &none;
}
void sal_error_info_reset(SalErrorInfo *ei){
if (ei->status_string){
ms_free(ei->status_string);
ei->status_string=NULL;
}
if (code>=400) {
sal_compute_sal_errors_from_code(code,sal_err,sal_reason);
return TRUE;
} else {
return FALSE;
if (ei->warnings){
ms_free(ei->warnings);
ei->warnings=NULL;
}
if (ei->full_string){
ms_free(ei->full_string);
ei->full_string=NULL;
}
ei->protocol_code=0;
ei->reason=SalReasonNone;
}
void sal_error_info_set(SalErrorInfo *ei, SalReason reason, int code, const char *status_string, const char *warning){
sal_error_info_reset(ei);
if (reason==SalReasonUnknown) ei->reason=_sal_reason_from_sip_code(code);
else ei->reason=reason;
ei->protocol_code=code;
ei->status_string=status_string ? ms_strdup(status_string) : NULL;
ei->warnings=warning ? ms_strdup(warning) : NULL;
if (ei->status_string){
if (ei->warnings)
ei->full_string=ms_strdup_printf("%s %s",ei->status_string,ei->warnings);
else ei->full_string=ms_strdup(ei->status_string);
}
}
void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response){
int code = belle_sip_response_get_status_code(response);
const char *reason_phrase=belle_sip_response_get_reason_phrase(response);
/*Remark: the reason header is to be used mainly in SIP requests, thus the use and prototype of this function should be changed.*/
belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason");
belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning");
SalErrorInfo *ei=&op->error_info;
const char *warnings;
warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL;
if (warnings==NULL) warnings=reason_header ? belle_sip_header_get_unparsed_value(reason_header) : NULL;
sal_error_info_set(ei,SalReasonUnknown,code,reason_phrase,warnings);
}
const SalErrorInfo *sal_op_get_error_info(const SalOp *op){
return &op->error_info;
}
void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) {
......
......@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void process_error( SalOp* op) {
if (op->dir == SalOpDirOutgoing) {
op->base.root->callbacks.text_delivery_update(op, SalTextDeliveryFailed, SalReasonUnknown);
op->base.root->callbacks.text_delivery_update(op, SalTextDeliveryFailed);
} else {
ms_warning("unexpected io error for incoming message on op [%p]",op);
}
......@@ -30,33 +30,20 @@ static void process_error( SalOp* op) {
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
SalOp* op = (SalOp*)user_ctx;
// belle_sip_object_t* source = belle_sip_io_error_event_get_source(event);
// if (BELLE_SIP_IS_INSTANCE_OF(source,belle_sip_transaction_t)) {
// /*reset op to make sure transaction terminated does not need op*/
// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(source),NULL);
// }
sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO Error",NULL);
process_error(op);
}
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
SalOp* op=(SalOp*)user_ctx;
// belle_sip_client_transaction_t *client_transaction=belle_sip_timeout_event_get_client_transaction(event);
// belle_sip_server_transaction_t *server_transaction=belle_sip_timeout_event_get_server_transaction(event);
// /*reset op to make sure transaction terminated does not need op*/
// if (client_transaction) {
// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);
// } else {
// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),NULL);
// }
sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL);
process_error(op);
}
static void process_response_event(void *op_base, const belle_sip_response_event_t *event){
SalOp* op = (SalOp*)op_base;
/*belle_sip_client_transaction_t *client_transaction=belle_sip_response_event_get_client_transaction(event);*/
int code = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
SalTextDeliveryStatus status;
SalReason reason=SalReasonUnknown;
SalError err=SalErrorNone;
sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event));
if (code>=100 && code <200)
status=SalTextDeliveryInProgress;
......@@ -64,13 +51,10 @@ static void process_response_event(void *op_base, const belle_sip_response_event
status=SalTextDeliveryDone;
else
status=SalTextDeliveryFailed;
if (status != SalTextDeliveryInProgress) {
/*reset op to make sure transaction terminated does not need op
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*/
}
sal_compute_sal_errors_from_code(code,&err,&reason);
op->base.root->callbacks.text_delivery_update(op,status, reason);
op->base.root->callbacks.text_delivery_update(op,status);
}
static bool_t is_plain_text(belle_sip_header_content_type_t* content_type) {
return strcmp("text",belle_sip_header_content_type_get_type(content_type))==0
&& strcmp("plain",belle_sip_header_content_type_get_subtype(content_type))==0;
......@@ -191,10 +175,15 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg)
return sal_message_send(op,from,to,"text/plain",msg);
}
static belle_sip_listener_callbacks_t op_message_callbacks={0};
void sal_op_message_fill_cbs(SalOp*op) {
op->callbacks.process_io_error=process_io_error;
op->callbacks.process_response_event=process_response_event;
op->callbacks.process_timeout=process_timeout;
op->callbacks.process_request_event=process_request_event;
if (op_message_callbacks.process_io_error==NULL){
op_message_callbacks.process_io_error=process_io_error;
op_message_callbacks.process_response_event=process_response_event;
op_message_callbacks.process_timeout=process_timeout;
op_message_callbacks.process_request_event=process_request_event;
}
op->callbacks=&op_message_callbacks;
op->type=SalOpMessage;
}
......@@ -94,13 +94,12 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
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};
SalError error=SalErrorUnknown;
SalReason sr=SalReasonUnknown;
belle_sip_header_expires_t* expires;
sal_op_set_error_info_from_response(op,response);
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));
if (code>=300) {
ms_message("subscription to [%s] rejected",sal_op_get_to(op));
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
return;
}
......@@ -267,13 +266,18 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
}
}
static belle_sip_listener_callbacks_t op_presence_callbacks={0};
void sal_op_presence_fill_cbs(SalOp*op) {
op->callbacks.process_io_error=presence_process_io_error;
op->callbacks.process_response_event=presence_response_event;
op->callbacks.process_timeout=presence_process_timeout;
op->callbacks.process_transaction_terminated=presence_process_transaction_terminated;
op->callbacks.process_request_event=presence_process_request_event;
op->callbacks.process_dialog_terminated=presence_process_dialog_terminated;
if (op_presence_callbacks.process_request_event==NULL){
op_presence_callbacks.process_io_error=presence_process_io_error;
op_presence_callbacks.process_response_event=presence_response_event;
op_presence_callbacks.process_timeout=presence_process_timeout;
op_presence_callbacks.process_transaction_terminated=presence_process_transaction_terminated;
op_presence_callbacks.process_request_event=presence_process_request_event;
op_presence_callbacks.process_dialog_terminated=presence_process_dialog_terminated;
}
op->callbacks=&op_presence_callbacks;
op->type=SalOpPresence;
}
......
......@@ -35,24 +35,26 @@ static void publish_refresher_listener (belle_sip_refresher_t* refresher
}else if (status_code==0){
op->base.root->callbacks.on_expire(op);
}else if (status_code>=200){
SalError err;
SalReason reason;
sal_compute_sal_errors_from_code(status_code,&err,&reason);
op->base.root->callbacks.on_publish_response(op,err,reason);
sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL);
op->base.root->callbacks.on_publish_response(op);
}
}
static void publish_response_event(void *userctx, const belle_sip_response_event_t *event){
SalOp *op=(SalOp*)userctx;
int code=belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
SalError err;
SalReason reason;
sal_compute_sal_errors_from_code(code,&err,&reason);
op->base.root->callbacks.on_publish_response(op,err,reason);
sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event));
if (op->error_info.protocol_code>=200){
op->base.root->callbacks.on_publish_response(op);
}
}
void sal_op_publish_fill_cbs(SalOp*op) {
op->callbacks.process_response_event=publish_response_event;
static belle_sip_listener_callbacks_t op_publish_callbacks={0};
void sal_op_publish_fill_cbs(SalOp *op) {
if (op_publish_callbacks.process_response_event==NULL){
op_publish_callbacks.process_response_event=publish_response_event;
}
op->callbacks=&op_publish_callbacks;
op->type=SalOpPublish;
}
......
......@@ -24,8 +24,6 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
,unsigned int status_code
,const char* reason_phrase) {
SalOp* op = (SalOp*)user_pointer;
SalError sal_err;
SalReason sal_reason;
belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));
ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op));
......@@ -57,9 +55,8 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
chooses not to re-register, the UA SHOULD discard any stored service
route for that address-of-record. */
sal_op_set_service_route(op,NULL);
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);
sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL);
op->base.root->callbacks.register_failure(op);
if (op->auth_info) {
/*add pending auth*/
sal_add_pending_auth(op->base.root,op);
......
This diff is collapsed.
......@@ -160,7 +160,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
identity=linphone_proxy_config_get_identity(proxy);
}else identity=linphone_core_get_primary_contact(cr->lc);
/*sending out of calls*/
op = sal_op_new(cr->lc->sal);
msg->op = op = sal_op_new(cr->lc->sal);
linphone_configure_op(cr->lc,op,cr->peer_url,msg->custom_headers,lp_config_get_int(cr->lc->config,"sip","chat_msg_with_contact",0));
sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/
}
......@@ -779,6 +779,7 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg)
* Destroys a LinphoneChatMessage.
**/
void linphone_chat_message_destroy(LinphoneChatMessage* msg) {
if (msg->op) sal_op_release(msg->op);
if (msg->message) ms_free(msg->message);
if (msg->external_body_url) ms_free(msg->external_body_url);
if (msg->from) linphone_address_destroy(msg->from);
......@@ -787,9 +788,17 @@ void linphone_chat_message_destroy(LinphoneChatMessage* msg) {
ms_free(msg);
}
/**
* Get full details about delivery error of a chat message.
* @param msg a LinphoneChatMessage
* @return a LinphoneErrorInfo describing the details.
**/
const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg){
return linphone_error_info_from_sal_op(msg->op);
}
LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg) {
return msg->reason;
return linphone_error_info_get_reason(linphone_chat_message_get_error_info(msg));
}
/**
......
......@@ -114,12 +114,12 @@ LinphonePublishState linphone_event_get_publish_state(const LinphoneEvent *lev){
return lev->publish_state;
}
void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason){
lev->reason=reason;
const LinphoneErrorInfo *linphone_event_get_error_info(const LinphoneEvent *lev){
return linphone_error_info_from_sal_op(lev->op);
}
LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev){
return lev->reason;
return linphone_error_info_get_reason(linphone_event_get_error_info(lev));
}
LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){
......
......@@ -207,6 +207,11 @@ LINPHONE_PUBLIC int linphone_event_update_publish(LinphoneEvent *lev, const Linp
**/
LINPHONE_PUBLIC LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev);
/**
* Get full details about an error occured.
**/
const LinphoneErrorInfo *linphone_event_get_error_info(const LinphoneEvent *lev);
/**
* Get subscription state. If the event object was not created by a subscription mechanism, #LinphoneSubscriptionNone is returned.
**/
......
......@@ -793,11 +793,11 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
call->state=cstate;
}
if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){
switch(call->reason){
case LinphoneReasonDeclined:
switch(call->non_op_error.reason){
case SalReasonDeclined:
call->log->status=LinphoneCallDeclined;
break;
case LinphoneReasonNotAnswered:
case SalReasonRequestTimeout:
call->log->status=LinphoneCallMissed;
break;
default:
......@@ -814,6 +814,11 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
lc->vtable.call_state_changed(lc,call,cstate,message);
if (cstate==LinphoneCallReleased){
if (call->op!=NULL) {
/*transfer the last error so that it can be obtained even in Released state*/
if (call->non_op_error.reason==SalReasonNone){
const SalErrorInfo *ei=sal_op_get_error_info(call->op);
sal_error_info_set(&call->non_op_error,ei->reason,ei->protocol_code,ei->status_string,ei->warnings);
}