From 447076314e3482e429232f54b3f5754802bcb1d7 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Mon, 11 Jun 2012 17:34:40 +0200 Subject: [PATCH] implement sal_call_decline --- coreapi/bellesip_sal/sal_impl.c | 55 +++++++++-- coreapi/bellesip_sal/sal_impl.h | 11 +++ coreapi/bellesip_sal/sal_op_call.c | 109 +++++++++++++++++++-- coreapi/bellesip_sal/sal_op_impl.c | 30 +++++- coreapi/bellesip_sal/sal_op_registration.c | 40 +++----- coreapi/linphonecore.c | 3 +- coreapi/sal.c | 7 +- coreapi/sal.h | 3 + tester/liblinphone_tester.c | 10 +- 9 files changed, 220 insertions(+), 48 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 696f55807..5176669ee 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -45,8 +45,6 @@ static void process_authentication(SalOp *op, belle_sip_message_t *response) { authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_message_get_header(response,BELLE_SIP_PROXY_AUTHENTICATE)); } - - op->auth_info.realm=(char*)belle_sip_header_www_authenticate_get_realm(authenticate); op->auth_info.username=(char*)belle_sip_uri_get_user(uri); if (authenticate) { @@ -67,10 +65,55 @@ static void process_dialog_terminated(void *user_ctx, const belle_sip_dialog_ter static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ ms_error("process_io_error not implemented yet"); } -static void process_request_event(void *user_ctx, const belle_sip_request_event_t *event) { - /*belle_sip_server_transaction_t* server_transaction = belle_sip_request_event_get_server_transaction(event); - SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(server_transaction));*/ - ms_error("sal process_request_event not implemented yet"); +static void process_request_event(void *sal, const belle_sip_request_event_t *event) { + SalOp* op; + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event); + belle_sip_header_address_t* origin_address; + belle_sip_header_address_t* address; + belle_sip_header_from_t* from; + belle_sip_header_to_t* to; + + if (dialog) { + op=(SalOp*)belle_sip_dialog_get_application_data(dialog); + } else if (strcmp("INVITE",belle_sip_request_get_method(req))==0) { + op=sal_op_new((Sal*)sal); + sal_op_call_fill_cbs(op); + } else { + ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); + } + + if (!op->base.from_address) { + from=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); + sal_op_set_from_address(op,(SalAddress*)address); + belle_sip_object_unref(address); + } + if (!op->base.to_address) { + to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))); + sal_op_set_to_address(op,(SalAddress*)address); + belle_sip_object_unref(address); + } + + if (!op->base.origin) { + /*set origin uri*/ + origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req)); + __sal_op_set_network_origin_address(op,(SalAddress*)origin_address); + belle_sip_object_unref(origin_address); + } + if (!op->base.remote_ua) { + sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req)); + } + + if (op->callbacks.process_request_event) { + op->callbacks.process_request_event(op,event); + } else { + ms_error("sal process_request_event not implemented yet"); + } + } static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){ diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 33a7e0ea2..4369e687f 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -40,13 +40,24 @@ struct SalOp{ belle_sip_listener_callbacks_t callbacks; belle_sip_request_t* request; belle_sip_response_t* response; + belle_sip_server_transaction_t* pending_server_trans; SalAuthInfo auth_info; unsigned long int registration_refresh_timer; bool_t sdp_offering; + belle_sip_dialog_t* dialog; + belle_sip_header_address_t *replaces; + belle_sip_header_address_t *referred_by; + bool_t auto_answer_asked; }; belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *sal); int sdp_to_media_description(belle_sdp_session_description_t *sdp, SalMediaDescription *desc); belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method); + +void sal_op_call_fill_cbs(SalOp*op); + +void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message); +void sal_op_send_request(SalOp* op, belle_sip_request_t* request); +void sal_op_resend_request(SalOp* op, belle_sip_request_t* request); #endif /* SAL_IMPL_H_ */ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 543cdcd0c..a2050616b 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -29,6 +29,59 @@ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t } static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { ms_error("process_transaction_terminated not implemented yet"); +} +static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { + SalOp* op = (SalOp*)op_base; + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); + belle_sip_object_ref(server_transaction); + if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); + op->pending_server_trans=server_transaction; + + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_header_t* replace_header; + belle_sip_dialog_state_t dialog_state; + belle_sdp_session_description_t* sdp; + belle_sip_header_t* call_info; + if (!op->dialog) { + op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans)); + belle_sip_dialog_set_application_data(op->dialog,op); + ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); + } + dialog_state=belle_sip_dialog_get_state(op->dialog); + switch(dialog_state) { + + case BELLE_SIP_DIALOG_NULL: { + if (!op->replaces && (replace_header=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"replaces"))) { + op->replaces=belle_sip_header_address_parse(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(replace_header))); + belle_sip_object_ref(op->replaces); + } else if(op->replaces) { + ms_warning("replace header already set"); + } + if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))) { + op->sdp_offering=FALSE; + op->base.remote_media=sal_media_description_new(); + sdp_to_media_description(sdp,op->base.remote_media); + belle_sip_object_unref(sdp); + }else + op->sdp_offering=TRUE; + + if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) { + if( strstr(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(call_info)),"answer-after=") != NULL) { + op->auto_answer_asked=TRUE; + ms_message("The caller asked to automatically answer the call(Emergency?)\n"); + } + } + + op->base.root->callbacks.call_received(op); + + break; + } + default: { + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + } + } + + } static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc){ belle_sdp_session_description_t* session_desc=media_description_to_sdp(desc); @@ -89,16 +142,20 @@ int sal_call(SalOp *op, const char *from, const char *to){ route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(route_header)); } + sal_op_call_fill_cbs(op); + client_transaction = belle_sip_provider_create_client_transaction(prov,req); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op); + op->dialog=belle_sip_provider_create_dialog(prov,BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_client_transaction_send_request(client_transaction); + return 0; +} +void sal_op_call_fill_cbs(SalOp*op) { op->callbacks.process_io_error=call_process_io_error; op->callbacks.process_response_event=call_response_event; op->callbacks.process_timeout=call_process_timeout; op->callbacks.process_transaction_terminated=call_process_transaction_terminated; - client_transaction = belle_sip_provider_create_client_transaction(prov,req); - belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op); - belle_sip_client_transaction_send_request(client_transaction); - - return 0; + op->callbacks.process_request_event=process_request_event; } int sal_call_notify_ringing(SalOp *h, bool_t early_media){ ms_fatal("sal_call_notify_ringing not implemented yet"); @@ -109,9 +166,45 @@ int sal_call_accept(SalOp*h){ ms_fatal("sal_call_accept not implemented yet"); return -1; } -int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/){ - ms_fatal("sal_call_decline not implemented yet"); - return -1; +int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){ + belle_sip_response_t* response; + belle_sip_header_contact_t* contact=NULL; + int status; + switch(reason) { + case SalReasonBusy: + status=486; + break; + case SalReasonTemporarilyUnavailable: + status=480; + break; + case SalReasonDoNotDisturb: + status=600; + break; + case SalReasonMedia: + status=415; + break; + case SalReasonRedirect: + if(redirection!=NULL) { + if (strstr(redirection,"sip:")!=0) status=302; + status=380; + contact= belle_sip_header_contact_new(); + belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); + break; + } else { + ms_error("Cannot redirect to null"); + } + /* no break */ + + default: + status=500; + ms_error("Unexpected decline reason [%i]",reason); + /* no break */ + } + response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status); + if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); + belle_sip_server_transaction_send_response(op->pending_server_trans,response); + return 0; + } int sal_call_update(SalOp *h, const char *subject){ ms_fatal("sal_call_update not implemented yet"); diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 89d6e8644..1fad0188f 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -27,11 +27,11 @@ SalOp * sal_op_new(Sal *sal){ } void sal_op_release(SalOp *op){ - __sal_op_free(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); } + __sal_op_free(op); return ; } void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){ @@ -70,7 +70,7 @@ void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){ goto error; } belle_sip_message_set_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_HEADER(authorization)); - sal_register_refresh(op,-1); + sal_op_resend_request(op,op->request); return; error: @@ -78,6 +78,7 @@ error: return ; } + void sal_op_cancel_authentication(SalOp *h){ ms_fatal("sal_op_cancel_authentication not implemented yet"); return ; @@ -170,4 +171,29 @@ int sal_ping(SalOp *op, const char *from, const char *to){ return -1; } +void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message) { + belle_sip_header_user_agent_t* user_agent=belle_sip_message_get_header_by_type(message,belle_sip_header_user_agent_t); + char user_agent_string[256]; + if(belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) { + op->base.remote_ua=ms_strdup(user_agent_string); + } +} +void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) { + 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,request); +} +void 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; + if (sal_op_get_route_address(op)) { + route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(route_header)); + } + client_transaction = belle_sip_provider_create_client_transaction(prov,request); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op); + belle_sip_client_transaction_send_request(client_transaction); + +} diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index fb7257319..20ec119a9 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -20,8 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -static void send_register_request(SalOp* op, belle_sip_request_t* request); - static void register_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ ms_error("process_io_error not implemented yet"); } @@ -30,7 +28,7 @@ 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); - send_register_request(op,op->request); + sal_op_send_request(op,op->request); } static bool_t is_contact_equal(belle_sip_header_contact_t* a,belle_sip_header_contact_t* b) { if (!a | !b) return FALSE; @@ -74,10 +72,12 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve } op->base.root->callbacks.register_success(op,expires_header&&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) { - 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 = 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); } @@ -100,31 +100,15 @@ static void register_process_transaction_terminated(void *user_ctx, const belle_ -static void send_register_request(SalOp* op, belle_sip_request_t* request) { - belle_sip_client_transaction_t* client_transaction; - belle_sip_provider_t* prov=op->base.root->prov; - op->callbacks.process_io_error=register_process_io_error; - op->callbacks.process_response_event=register_response_event; - op->callbacks.process_timeout=register_process_timeout; - op->callbacks.process_transaction_terminated=register_process_transaction_terminated; - client_transaction = belle_sip_provider_create_client_transaction(prov,request); - belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op); - belle_sip_client_transaction_send_request(client_transaction); - -} /*if expire = -1, does not change expires*/ static void send_register_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) { belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES); - belle_sip_header_route_t* route_header; - if (sal_op_get_route_address(op)) { - route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(route_header)); - } - if (!expires_header) { + + if (!expires_header && expires>=0) { belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new())); + belle_sip_header_expires_set_expires(expires_header,expires); } - if (expires>=0) belle_sip_header_expires_set_expires(expires_header,expires); - send_register_request(op,request); + sal_op_send_request(op,request); } @@ -134,6 +118,10 @@ int sal_register(SalOp *op, const char *proxy, const char *from, int expires){ sal_op_set_from(op,from); sal_op_set_to(op,from); sal_op_set_route(op,proxy); + op->callbacks.process_io_error=register_process_io_error; + op->callbacks.process_response_event=register_response_event; + op->callbacks.process_timeout=register_process_timeout; + op->callbacks.process_transaction_terminated=register_process_transaction_terminated; req = sal_op_build_request(op,"REGISTER"); belle_sip_uri_t* req_uri = belle_sip_request_get_uri(req); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index f02a457b5..f64edcb83 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2585,6 +2585,7 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call) { call = the_call; } + sal_call_terminate(call->op); terminate_call(lc,call); @@ -4179,7 +4180,7 @@ void sip_config_uninit(LinphoneCore *lc) Sleep(100); #endif } - + if (i>=20) ms_warning("Cannot complete unregistration, giving up"); ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy); ms_list_free(config->proxies); config->proxies=NULL; diff --git a/coreapi/sal.c b/coreapi/sal.c index 77b2d5e6c..90fa26fab 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -324,9 +324,14 @@ void __sal_op_init(SalOp *b, Sal *sal){ } void __sal_op_set_network_origin(SalOp *op, const char *origin){ - assign_string(&((SalOpBase*)op)->origin,origin); + SET_PARAM(op,origin); } +void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin){ + char* address_string=sal_address_as_string(origin); /*can probably be optimized*/ + __sal_op_set_network_origin(op,address_string); + ms_free(address_string); +} void __sal_op_free(SalOp *op){ SalOpBase *b=(SalOpBase *)op; diff --git a/coreapi/sal.h b/coreapi/sal.h index 32d5c514c..941b23516 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -174,6 +174,7 @@ typedef struct SalOpBase{ char *to; SalAddress* to_address; char *origin; + SalAddress* origin_address; char *remote_ua; SalMediaDescription *local_media; SalMediaDescription *remote_media; @@ -336,6 +337,7 @@ const SalAddress* sal_op_get_route_address(const SalOp *op); const char *sal_op_get_proxy(const SalOp *op); /*for incoming requests, returns the origin of the packet as a sip uri*/ const char *sal_op_get_network_origin(const SalOp *op); +const SalAddress *sal_op_get_network_origin_address(const SalOp *op); /*returns far-end "User-Agent" string */ const char *sal_op_get_remote_ua(const SalOp *op); void *sal_op_get_user_pointer(const SalOp *op); @@ -400,6 +402,7 @@ void sal_disable_logs(); /*internal API */ void __sal_op_init(SalOp *b, Sal *sal); 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); #endif diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 1a4ec8d40..4f6ae1b16 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -244,7 +244,7 @@ static LinphoneCore* configure_lc(LinphoneCoreVTable* v_table) { LinphoneCore* lc; int retry=0; - memset (v_table,0,sizeof(LinphoneCoreVTable)); + reset_counters(); lc = linphone_core_new(v_table,NULL,"./multi_account_lrc",NULL); @@ -260,6 +260,7 @@ static LinphoneCore* configure_lc(LinphoneCoreVTable* v_table) { static void multiple_proxy(){ LinphoneCoreVTable v_table; LinphoneCore* lc; + memset (&v_table,0,sizeof(LinphoneCoreVTable)); v_table.registration_state_changed=registration_state_changed; lc=configure_lc(&v_table); linphone_core_destroy(lc); @@ -296,6 +297,7 @@ static void simple_call_declined() { LinphoneCore* lc; int retry=0; + memset (&v_table,0,sizeof(LinphoneCoreVTable)); v_table.registration_state_changed=registration_state_changed; v_table.call_state_changed=call_state_changed; lc=configure_lc(&v_table); @@ -314,6 +316,7 @@ static void simple_call_declined() { int init_test_suite () { CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit); + if (NULL == CU_add_test(pSuite, "simple call declined", simple_call_declined)) { return CU_get_error(); } @@ -341,9 +344,8 @@ CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit); if (NULL == CU_add_test(pSuite, "multi account", multiple_proxy)) { return CU_get_error(); } - if (NULL == CU_add_test(pSuite, "simple call declined", simple_call_declined)) { - return CU_get_error(); - } + + return 0; } int main (int argc, char *argv[]) {