diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 7c9c8026c..9efbbb7ee 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -318,6 +318,8 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_ belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event); belle_sip_request_t* req; belle_sip_response_t* resp; + bool_t release_call=FALSE; + if (client_transaction) { req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction)); @@ -328,9 +330,21 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_ if (op->state ==SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(req))==0 && (!resp || (belle_sip_response_get_status_code(resp) !=401 - && belle_sip_response_get_status_code(resp) !=407))) { - if (op->dialog==NULL) call_set_released(op); + && belle_sip_response_get_status_code(resp) !=407)) + && op->dialog==NULL) { + release_call=TRUE; } + if (server_transaction){ + if (op->pending_server_trans==server_transaction){ + belle_sip_object_unref(op->pending_server_trans); + op->pending_server_trans=NULL; + } + if (op->pending_update_server_trans==server_transaction){ + belle_sip_object_unref(op->pending_update_server_trans); + op->pending_update_server_trans=NULL; + } + } + if (release_call) call_set_released(op); } static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) { @@ -777,6 +791,7 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti belle_sip_response_t* response; belle_sip_header_contact_t* contact=NULL; int status=sal_reason_to_sip_code(reason); + belle_sip_transaction_t *trans; if (reason==SalReasonRedirect){ if (redirection!=NULL) { @@ -788,9 +803,15 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti ms_error("Cannot redirect to null"); } } - response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status); + trans=(belle_sip_transaction_t*)op->pending_server_trans; + if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; + if (!trans){ + ms_error("sal_call_decline(): no pending transaction to decline."); + return -1; + } + response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(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); + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); return 0; } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index ef17b080b..f60e230f8 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -152,7 +152,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia ms_message("Network parameters have changed, update them."); linphone_core_update_streams_destinations(lc, call, oldmd, new_md); } - if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) { + if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) { ms_message("Crypto parameters have changed, update them."); linphone_call_update_crypto_parameters(call, oldmd, new_md); } @@ -535,7 +535,7 @@ static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t } if (is_update && prev_result_desc && md){ int diff=sal_media_description_equals(prev_result_desc,md); - if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ + if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ ms_warning("Cannot accept this update, it is changing parameters that require user approval"); sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ return; @@ -655,7 +655,6 @@ static void call_terminated(SalOp *op, const char *from){ } static int resume_call_after_failed_transfer(LinphoneCall *call){ - ms_message("!!!!!!!!!!resume_call_after_failed_transfer"); if (call->was_automatically_paused && call->state==LinphoneCallPausing) return BELLE_SIP_CONTINUE; /*was still in pausing state*/ @@ -663,7 +662,7 @@ static int resume_call_after_failed_transfer(LinphoneCall *call){ if (sal_op_is_idle(call->op)){ linphone_core_resume_call(call->core,call); }else { - ms_message("!!!!!!!!!!resume_call_after_failed_transfer, salop was busy"); + ms_message("resume_call_after_failed_transfer(), salop was busy"); return BELLE_SIP_CONTINUE; } } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 08c619ff1..94d2e20f4 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2228,7 +2228,7 @@ void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){ static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDescription *local_st_desc, SalStreamDescription *old_stream, SalStreamDescription *new_stream, MediaStream *ms){ int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag); if (crypto_idx >= 0) { - if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) + if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) media_stream_set_srtp_send_key(ms,new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key); if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){ media_stream_set_srtp_recv_key(ms,new_stream->crypto[0].algo,new_stream->crypto[0].master_key); diff --git a/coreapi/sal.c b/coreapi/sal.c index ff252ca3d..b8395c897 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -280,9 +280,11 @@ int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStre if (sd1->proto != sd2->proto) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) { if ((sd1->crypto[i].tag != sd2->crypto[i].tag) - || (sd1->crypto[i].algo != sd2->crypto[i].algo) - || (strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) { - result |= SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED; + || (sd1->crypto[i].algo != sd2->crypto[i].algo)){ + result|=SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED; + } + if ((strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) { + result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; } } diff --git a/include/sal/sal.h b/include/sal/sal.h index f64edd8e2..8f81f320d 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -68,13 +68,15 @@ typedef enum { SalTransportDTLS /*DTLS*/ }SalTransport; -#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00 -#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED 0x01 -#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED 0x02 -#define SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED 0x04 -#define SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED 0x08 +#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00 +#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED (1) +#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED (1<<1) +#define SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED (1<<2) +#define SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED (1<<3) +#define SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED (1<<4) + #define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED |\ - SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED |SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED) + SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED |SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED | SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED) const char* sal_transport_to_string(SalTransport transport); SalTransport sal_transport_parse(const char*); diff --git a/tester/call_tester.c b/tester/call_tester.c index 2f90b7291..19d8a5983 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1931,6 +1931,67 @@ static void call_with_file_player(void) { ms_free(recordpath); } +static bool_t is_format_supported(LinphoneCore *lc, const char *fmt){ + const char **formats=linphone_core_get_supported_file_formats(lc); + for(;*formats!=NULL;++formats){ + if (strcasecmp(*formats,fmt)==0) return TRUE; + } + return FALSE; +} + +static void call_with_mkv_file_player(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphonePlayer *player; + char hellomkv[256]; + char hellowav[256]; + char *recordpath; + double similar; + + if (!is_format_supported(marie->lc,"mkv")){ + ms_warning("Test skipped, no mkv support."); + goto end; + } + recordpath = create_filepath(liblinphone_tester_writable_dir_prefix, "record", "wav"); + /*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/ + unlink(recordpath); + + snprintf(hellowav,sizeof(hellowav), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); + snprintf(hellomkv,sizeof(hellomkv), "%s/sounds/hello8000.mkv", liblinphone_tester_file_prefix); + + /*caller uses soundcard*/ + + /*callee is recording and plays file*/ + linphone_core_use_files(pauline->lc,TRUE); + linphone_core_set_play_file(pauline->lc,hellowav); /*just to send something but we are not testing what is sent by pauline*/ + linphone_core_set_record_file(pauline->lc,recordpath); + + CU_ASSERT_TRUE(call(marie,pauline)); + + player=linphone_call_get_player(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NOT_NULL(player); + if (player){ + CU_ASSERT_TRUE(linphone_player_open(player,hellomkv,on_eof,marie)==0); + CU_ASSERT_TRUE(linphone_player_start(player)==0); + } + CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000)); + + /*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)); + CU_ASSERT_TRUE(ms_audio_diff(hellowav,recordpath,&similar,NULL,NULL)==0); + CU_ASSERT_TRUE(similar>0.9); + CU_ASSERT_TRUE(similar<=1.0); + ms_free(recordpath); + +end: + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + +} + + static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -3062,7 +3123,8 @@ test_t call_tests[] = { { "ZRTP call",zrtp_call}, { "ZRTP video call",zrtp_video_call}, { "SRTP call with declined srtp", call_with_declined_srtp }, - { "Call with file player", call_with_file_player}, + { "Call with file player", call_with_file_player}, + { "Call with mkv file player", call_with_mkv_file_player}, #ifdef VIDEO_ENABLED { "Simple video call",video_call}, { "Simple video call using policy",video_call_using_policy},