diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index b9cdd0b61..2d6311502 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -82,6 +82,7 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev belle_sip_header_from_t* from_header; belle_sip_header_to_t* to; belle_sip_header_content_type_t* content_type; + belle_sip_response_t* resp; from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); char* from; @@ -115,6 +116,9 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev } } else { ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); + resp=belle_sip_response_create_from_request(req,500); + belle_sip_provider_send_response(((Sal*)sal)->prov,resp); + return; } @@ -190,7 +194,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even belle_sip_uri_set_transport_param(contact_uri,belle_sip_header_via_get_transport_lowercase(via_header)); } if (belle_sip_header_via_get_listening_port(via_header) - != belle_sip_listening_point_get_well_known_port(belle_sip_header_via_get_transport(via_header))) { + != belle_sip_listening_point_get_well_known_port(belle_sip_header_via_get_transport(via_header))) { belle_sip_uri_set_port(contact_uri,belle_sip_header_via_get_listening_port(via_header) ); } contact_updated=TRUE; @@ -199,42 +203,41 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even if (received!=NULL || rport>0) { if (sal_op_get_contact(op)){ contact_address = BELLE_SIP_HEADER_ADDRESS(sal_address_clone(sal_op_get_contact_address(op))); - contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_address)); - if (received && strcmp(received,belle_sip_uri_get_host(contact_uri))!=0) { - /*need to update host*/ - belle_sip_uri_set_host(contact_uri,received); - contact_updated=TRUE; - } - contact_port = belle_sip_uri_get_port(contact_uri); - if (rport>0 && rport!=contact_port && (contact_port+rport)!=5060) { - /*need to update port*/ - belle_sip_uri_set_port(contact_uri,rport); - contact_updated=TRUE; - } + } + contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_address)); + if (received && strcmp(received,belle_sip_uri_get_host(contact_uri))!=0) { + /*need to update host*/ + belle_sip_uri_set_host(contact_uri,received); + contact_updated=TRUE; + } + contact_port = belle_sip_uri_get_port(contact_uri); + if (rport>0 && rport!=contact_port && (contact_port+rport)!=5060) { + /*need to update port*/ + belle_sip_uri_set_port(contact_uri,rport); + contact_updated=TRUE; + } - /*try to fix transport if needed (very unlikely)*/ - if (strcasecmp(belle_sip_header_via_get_transport(via_header),"UDP")!=0) { - if (!belle_sip_uri_get_transport_param(contact_uri) + /*try to fix transport if needed (very unlikely)*/ + if (strcasecmp(belle_sip_header_via_get_transport(via_header),"UDP")!=0) { + if (!belle_sip_uri_get_transport_param(contact_uri) ||strcasecmp(belle_sip_uri_get_transport_param(contact_uri),belle_sip_header_via_get_transport(via_header))!=0) { - belle_sip_uri_set_transport_param(contact_uri,belle_sip_header_via_get_transport_lowercase(via_header)); - contact_updated=TRUE; - } - } else { - if (belle_sip_uri_get_transport_param(contact_uri)) { - contact_updated=TRUE; - belle_sip_uri_set_transport_param(contact_uri,NULL); - } + belle_sip_uri_set_transport_param(contact_uri,belle_sip_header_via_get_transport_lowercase(via_header)); + contact_updated=TRUE; + } + } else { + if (belle_sip_uri_get_transport_param(contact_uri)) { + contact_updated=TRUE; + belle_sip_uri_set_transport_param(contact_uri,NULL); } } - } - if (contact_updated) { + if (contact_updated) { new_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(contact_address)); ms_message("Updating contact from [%s] to [%s] for [%p]",sal_op_get_contact(op),new_contact,op); sal_op_set_contact(op,new_contact); belle_sip_free(new_contact); } - if (contact_address)belle_sip_object_unref(contact_address); - + if (contact_address)belle_sip_object_unref(contact_address); + } /*update request/response * maybe only the transaction should be kept*/ old_request=op->request; @@ -265,6 +268,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even } } op->callbacks.process_response_event(op,event); + } else { ms_error("Unhandled event response [%p]",event); } diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 91006ae0d..94920b7b2 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -196,20 +196,23 @@ static void call_response_event(void *op_base, const belle_sip_response_event_t switch (op->state) { case SalOpStateEarly:/*invite case*/ case SalOpStateActive: /*re-invite case*/ - handle_sdp_from_response(op,response); - ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); - if (ack==NULL) { - ms_error("This call has been already terminated."); + if (code >=200) { + handle_sdp_from_response(op,response); + ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); + if (ack==NULL) { + ms_error("This call has been already terminated."); - return ; - } - if (op->sdp_answer){ - set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer); - op->sdp_answer=NULL; - } - belle_sip_dialog_send_ack(op->dialog,ack); - op->state=SalOpStateActive; - op->base.root->callbacks.call_accepted(op); + return ; + } + if (op->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer); + op->sdp_answer=NULL; + } + belle_sip_dialog_send_ack(op->dialog,ack); + /*if (op->state != SalOpStateActive)*/ + op->base.root->callbacks.call_accepted(op); + op->state=SalOpStateActive; + } break; case SalOpStateTerminated: @@ -425,16 +428,29 @@ void sal_op_call_fill_cbs(SalOp*op) { op->callbacks.process_request_event=process_request_event; op->callbacks.process_dialog_terminated=process_dialog_terminated; } -int sal_call_notify_ringing(SalOp *op, bool_t early_media){ - belle_sip_response_t* ringing_response; - - /*if early media send also 180 and 183 */ - if (early_media){ - ms_fatal("not implemented yet"); +static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* response) { + if (op->base.local_media){ + /*this is the case where we received an invite without SDP*/ + if (op->sdp_offering) { + set_sdp_from_desc(BELLE_SIP_MESSAGE(response),op->base.local_media); + }else{ + if (op->sdp_answer==NULL) sdp_process(op); + if (op->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer); + op->sdp_answer=NULL; + } + } }else{ - ringing_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),180); - belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response); + ms_error("You are accepting a call but not defined any media capabilities !"); } +} +int sal_call_notify_ringing(SalOp *op, bool_t early_media){ + int status_code =early_media?183:180; + belle_sip_response_t* ringing_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status_code); + if (early_media){ + handle_offer_answer_response(op,ringing_response); + } + belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response); return 0; } @@ -461,20 +477,8 @@ int sal_call_accept(SalOp*h){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header)); } - if (h->base.local_media){ - /*this is the case where we received an invite without SDP*/ - if (h->sdp_offering) { - set_sdp_from_desc(BELLE_SIP_MESSAGE(response),h->base.local_media); - }else{ - if (h->sdp_answer==NULL) sdp_process(h); - if (h->sdp_answer){ - set_sdp(BELLE_SIP_MESSAGE(response),h->sdp_answer); - h->sdp_answer=NULL; - } - } - }else{ - ms_error("You are accepting a call but not defined any media capabilities !"); - } + handle_offer_answer_response(h,response); + belle_sip_server_transaction_send_response(h->pending_server_trans,response); return 0; } @@ -523,8 +527,13 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti } int sal_call_update(SalOp *op, const char *subject){ belle_sip_request_t *reinvite=belle_sip_dialog_create_request(op->dialog,"INVITE"); + /*belle_sdp_session_description_t* session_desc;*/ + belle_sip_header_contact_t* contact=belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(reinvite),belle_sip_header_create( "Subject", subject)); + /*need to add contact header for re-invite*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(reinvite),BELLE_SIP_HEADER(contact)); sal_op_fill_invite(op, reinvite); + return sal_op_send_request(op,reinvite); } SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){ diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index a79d179ce..94419e79d 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -90,8 +90,9 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { /*ping: main purpose is to obtain its own contact address behind firewalls*/ int sal_ping(SalOp *op, const char *from, const char *to){ - ms_fatal("sal_ping not implemented yet"); - return -1; + sal_op_set_from(op,from); + sal_op_set_to(op,to); + return sal_op_send_request(op,sal_op_build_request(op,"OPTION")); } void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message) { diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index 7ad1c404e..b11b2f839 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -36,10 +36,12 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve 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_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; int response_code = belle_sip_response_get_status_code(response); int expires=-1; + char* tmp_string; if (response_code<200) return;/*nothing to do*/ @@ -48,9 +50,14 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve 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_equals, (const void*)sal_op_get_contact_address(op)); + contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list,(belle_sip_compare_func)belle_sip_header_contact_equals, (const void*)original_contact); if (!contact_header_list) { - ms_error("no matching contact for [%s]", sal_op_get_contact(op)); + contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list,(belle_sip_compare_func)belle_sip_header_contact_equals, (const void*)sal_op_get_contact_address(op)); + } + if (!contact_header_list) { + tmp_string=belle_sip_object_to_string(BELLE_SIP_OBJECT(original_contact)); + ms_error("no matching contact neither for [%s] nor [%s]", tmp_string, sal_op_get_contact(op)); + belle_sip_free(tmp_string); } else { expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header_list->data)); } @@ -63,8 +70,10 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve } } if (expires<0) { - ms_message("Neither Expires header nor corresponding Contact header found"); - expires=0; + if ((expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(original_request),BELLE_SIP_EXPIRES))) { + 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); + } } op->base.root->callbacks.register_success(op,expires>0); diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 8521bc6e0..7cce3c791 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -376,6 +376,7 @@ static void linphone_core_manager_destroy(LinphoneCoreManager* mgr) { static bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) { LinphoneProxyConfig* proxy; linphone_core_get_default_proxy(callee_mgr->lc,&proxy); + int retry=0; CU_ASSERT_PTR_NOT_NULL_FATAL(proxy); @@ -386,7 +387,16 @@ static bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_m CU_ASSERT_TRUE_FATAL(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1)); CU_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc)); CU_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,1); - CU_ASSERT_TRUE_FATAL(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallOutgoingRinging,1)); + + while ((caller_mgr->stat.number_of_LinphoneCallOutgoingRinging<1 + || caller_mgr->stat.number_of_LinphoneCallOutgoingEarlyMedia<1) && retry++ <20) { + linphone_core_iterate(caller_mgr->lc); + linphone_core_iterate(callee_mgr->lc); + ms_usleep(100000); + } + + + CU_ASSERT_TRUE_FATAL(caller_mgr->stat.number_of_LinphoneCallOutgoingRinging|caller_mgr->stat.number_of_LinphoneCallOutgoingEarlyMedia); linphone_core_get_default_proxy(caller_mgr->lc,&proxy); CU_ASSERT_PTR_NOT_NULL_FATAL(proxy); @@ -602,6 +612,24 @@ static void simple_subscribe() { linphone_core_manager_destroy(pauline); } +static void call_early_media() { + LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_early_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc"); + + + CU_ASSERT_TRUE(call(pauline,marie)); + + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingEarlyMedia,1); + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1); + /*just to sleep*/ + linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + int init_test_suite () { CU_pSuite pSuite = CU_add_suite("liblinphone", init, uninit); @@ -643,6 +671,9 @@ CU_pSuite pSuite = CU_add_suite("liblinphone", init, uninit); if (NULL == CU_add_test(pSuite, "simple_call", simple_call)) { return CU_get_error(); } + if (NULL == CU_add_test(pSuite, "call_early_media", call_early_media)) { + return CU_get_error(); + } if (NULL == CU_add_test(pSuite, "call_terminated_by_caller", call_terminated_by_caller)) { return CU_get_error(); }