From 15d7543a49844b9b0bf392f70716cb678e3d281c Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 15 Apr 2014 13:43:25 +0200 Subject: [PATCH 01/83] change default behavior regarding changing srtp keys. They are now not changed by reINVITEs. --- coreapi/linphonecall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index e3127a3e6..4b5f985d4 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -248,7 +248,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){ LinphoneCore *lc=call->core; int i; SalMediaDescription *old_md=call->localdesc; - bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0); + bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1); for(i=0; in_active_streams; i++) { if (md->streams[i].proto == SalProtoRtpSavp) { From 8c1be075000abb15f38cc0318c5ba50568e17196 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 15 Apr 2014 15:18:01 +0200 Subject: [PATCH 02/83] update ms2 and ortp --- mediastreamer2 | 2 +- oRTP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediastreamer2 b/mediastreamer2 index 13d0cee33..1cdbfc4d6 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 13d0cee33672690daca1a7252c9f3a7022da95bd +Subproject commit 1cdbfc4d675784aa1832ad9af10c5d8aa6c11776 diff --git a/oRTP b/oRTP index 6330e3d1c..beee1f20d 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 6330e3d1c792515826be7116fb31086284faa430 +Subproject commit beee1f20d69af3d04cd27fcc00b3830620066367 From 0bb0bb23eaea96f4e634544afeb87d9571111ad7 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 15 Apr 2014 15:37:02 +0200 Subject: [PATCH 03/83] fix non-null terminated string in provisioning from file --- coreapi/remote_provisioning.c | 1 + 1 file changed, 1 insertion(+) diff --git a/coreapi/remote_provisioning.c b/coreapi/remote_provisioning.c index bcae9e798..7b5d6367d 100644 --- a/coreapi/remote_provisioning.c +++ b/coreapi/remote_provisioning.c @@ -62,6 +62,7 @@ static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* fseek(f, 0, SEEK_SET); char* provisioning = ms_malloc(fsize + 1); + provisioning[fsize]='\0'; if (fread(provisioning, fsize, 1, f)==0){ ms_error("Could not read xml provisioning file from %s",file_path); status=-1; From f8cd001a225b5544515afac0753bf997b51a0590 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Wed, 16 Apr 2014 13:00:20 +0200 Subject: [PATCH 04/83] Update ms2 --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 1cdbfc4d6..41db9323b 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 1cdbfc4d675784aa1832ad9af10c5d8aa6c11776 +Subproject commit 41db9323be6a6d136949ee5fdba1198c38a7d787 From 92762859a476f2f82396d94d0e5cfa003ba37bf8 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 16 Apr 2014 15:35:10 +0200 Subject: [PATCH 05/83] stop warning about missing tls --- coreapi/linphonecore.c | 8 +++++--- tester/call_tester.c | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index d6b3f842c..b80514e58 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1955,9 +1955,11 @@ static int apply_transports(LinphoneCore *lc){ transport_error(lc,"tcp",tr->tcp_port); } } - if (tr->tls_port!=0){ - if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){ - transport_error(lc,"tls",tr->tls_port); + if (linphone_core_sip_transport_supported(LinphoneTransportTls)){ + if (tr->tls_port!=0){ + if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){ + transport_error(lc,"tls",tr->tls_port); + } } } apply_user_agent(lc); diff --git a/tester/call_tester.c b/tester/call_tester.c index c655e4b88..3e8ef9475 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -542,6 +542,8 @@ static void _call_with_ice(bool_t random_ports) { CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); + CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); + liblinphone_tester_check_rtcp(marie,pauline); /*then close the call*/ linphone_core_terminate_all_calls(pauline->lc); From 59655c7d51933cc3ed40056452efb7a7b285890e Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 16 Apr 2014 16:21:08 +0200 Subject: [PATCH 06/83] fix compilation --- coreapi/linphonecore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index b80514e58..7c30c3b17 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1955,7 +1955,7 @@ static int apply_transports(LinphoneCore *lc){ transport_error(lc,"tcp",tr->tcp_port); } } - if (linphone_core_sip_transport_supported(LinphoneTransportTls)){ + if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){ if (tr->tls_port!=0){ if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){ transport_error(lc,"tls",tr->tls_port); From f9c8c72c01978b6faa042dcaea942c688e60ee83 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 17 Apr 2014 16:02:25 +0200 Subject: [PATCH 07/83] refactor ICE in liblinphone so that processing is centralized in a few methods, rather than spread into several methods. --- coreapi/linphonecall.c | 107 ++++++++++++++++++++++++----------------- coreapi/linphonecore.c | 73 ++++++---------------------- coreapi/private.h | 1 + 3 files changed, 80 insertions(+), 101 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 4b5f985d4..eb4a00551 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -648,14 +648,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro linphone_call_init_media_streams(call); switch (linphone_core_get_firewall_policy(call->core)) { case LinphonePolicyUseIce: - /*start ICE gathering*/ - linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op)); - linphone_call_start_media_streams_for_ice_gathering(call); - if (linphone_core_gather_ice_candidates(call->core,call)<0) { - /* Ice candidates gathering failed, proceed with the call anyway. */ - linphone_call_delete_ice_session(call); - linphone_call_stop_media_streams_for_ice_gathering(call); - } + linphone_call_prepare_ice(call,TRUE); break; case LinphonePolicyUseStun: call->ping_time=linphone_core_run_stun_tests(call->core,call); @@ -1431,6 +1424,60 @@ static void port_config_set_random_choosed(LinphoneCall *call, int stream_index, call->media_ports[stream_index].rtcp_port=rtp_session_get_local_rtcp_port(session); } +static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){ + MediaStream *ms=stream_index == 0 ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream; + if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ + IceCheckList *cl; + rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE); + rtp_session_set_symmetric_rtp(ms->sessions.rtp_session, FALSE); + cl=ice_session_check_list(call->ice_session, stream_index); + if (cl == NULL && create_checklist) { + cl=ice_check_list_new(); + ice_session_add_check_list(call->ice_session, cl); + ms_message("Created new ICE check list for stream [%i]",stream_index); + } + if (cl){ + ms->ice_check_list = cl; + ice_check_list_set_rtp_session(ms->ice_check_list, ms->sessions.rtp_session); + } + } +} + +int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ + SalMediaDescription *remote; + bool_t has_video=FALSE; + + if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ + if (incoming_offer){ + remote=sal_call_get_remote_media_description(call->op); + has_video=linphone_core_media_description_contains_video_stream(remote); + }else has_video=call->params.has_video; + + _linphone_call_prepare_ice_for_stream(call,0,TRUE); + if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE); + /*start ICE gathering*/ + if (incoming_offer) + linphone_core_update_ice_from_remote_media_description(call,remote); + if (!ice_session_candidates_gathered(call->ice_session)){ + if (call->audiostream->ms.state==MSStreamInitialized) + audio_stream_prepare_sound(call->audiostream, NULL, NULL); +#ifdef VIDEO_ENABLED + if (has_video && call->videostream && call->videostream->ms.state==MSStreamInitialized) { + video_stream_prepare_video(call->videostream); + } +#endif + if (linphone_core_gather_ice_candidates(call->core,call)<0) { + /* Ice candidates gathering failed, proceed with the call anyway. */ + linphone_call_delete_ice_session(call); + linphone_call_stop_media_streams_for_ice_gathering(call); + return -1; + } + return 1;/*gathering in progress, wait*/ + } + } + return 0; +} + void linphone_call_init_audio_stream(LinphoneCall *call){ LinphoneCore *lc=call->core; AudioStream *audiostream; @@ -1481,18 +1528,11 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port); rtp_session_set_transports(audiostream->ms.sessions.rtp_session,artp,artcp); } - if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ - rtp_session_set_pktinfo(audiostream->ms.sessions.rtp_session, TRUE); - rtp_session_set_symmetric_rtp(audiostream->ms.sessions.rtp_session, FALSE); - if (ice_session_check_list(call->ice_session, 0) == NULL) { - ice_session_add_check_list(call->ice_session, ice_check_list_new()); - } - audiostream->ms.ice_check_list = ice_session_check_list(call->ice_session, 0); - ice_check_list_set_rtp_session(audiostream->ms.ice_check_list, audiostream->ms.sessions.rtp_session); - } call->audiostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(audiostream->ms.sessions.rtp_session,call->audiostream_app_evq); + + _linphone_call_prepare_ice_for_stream(call,0,FALSE); } void linphone_call_init_video_stream(LinphoneCall *call){ @@ -1527,23 +1567,11 @@ void linphone_call_init_video_stream(LinphoneCall *call){ } call->videostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq); + _linphone_call_prepare_ice_for_stream(call,1,FALSE); #ifdef TEST_EXT_RENDERER video_stream_set_render_callback(call->videostream,rendercb,NULL); #endif } - /*eventually re-create the ICE check list that may have been destroyed if the stream wasn't used recently*/ - if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ - rtp_session_set_pktinfo(call->videostream->ms.sessions.rtp_session, TRUE); - rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session, FALSE); - if (ice_session_check_list(call->ice_session, 1) == NULL) { - ice_session_add_check_list(call->ice_session, ice_check_list_new()); - } - call->videostream->ms.ice_check_list = ice_session_check_list(call->ice_session, 1); - ice_check_list_set_rtp_session(call->videostream->ms.ice_check_list, call->videostream->ms.sessions.rtp_session); - ms_message ("creating new ice video check list [%p] for session [%p]",call->videostream->ms.ice_check_list,call->videostream->ms.sessions.rtp_session); - } - - #else call->videostream=NULL; #endif @@ -2082,19 +2110,10 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut linphone_address_destroy(me); } -void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call){ - audio_stream_prepare_sound(call->audiostream, NULL, NULL); -#ifdef VIDEO_ENABLED - if (call->videostream) { - video_stream_prepare_video(call->videostream); - } -#endif -} - void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){ - audio_stream_unprepare_sound(call->audiostream); + if(call->audiostream && call->audiostream->ms.state==MSStreamPreparing) audio_stream_unprepare_sound(call->audiostream); #ifdef VIDEO_ENABLED - if (call->videostream) { + if (call->videostream && call->videostream->ms.state==MSStreamPreparing) { video_stream_unprepare_video(call->videostream); } #endif @@ -2671,8 +2690,10 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ break; } } else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) { - linphone_core_start_accept_call_update(call->core, call); - linphone_core_update_ice_state_in_call_stats(call); + if (call->state==LinphoneCallUpdatedByRemote){ + linphone_core_start_accept_call_update(call->core, call); + linphone_core_update_ice_state_in_call_stats(call); + } } else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) { ice_session_restart(call->ice_session); ice_session_set_role(call->ice_session, IR_Controlling); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 7c30c3b17..bd852968e 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2843,22 +2843,16 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const /* this call becomes now the current one*/ lc->current_call=call; linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); + call->log->start_date_time=time(NULL); linphone_call_init_media_streams(call); + if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { /* Defer the start of the call after the ICE gathering process. */ - linphone_call_start_media_streams_for_ice_gathering(call); - call->log->start_date_time=time(NULL); - if (linphone_core_gather_ice_candidates(lc,call)<0) { - /* Ice candidates gathering failed, proceed with the call anyway. */ - linphone_call_delete_ice_session(call); - linphone_call_stop_media_streams_for_ice_gathering(call); - } else { - defer = TRUE; - } + if (linphone_call_prepare_ice(call,FALSE)==1) + defer=TRUE; } else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) { #ifdef BUILD_UPNP - call->log->start_date_time=time(NULL); if (linphone_core_update_upnp(lc,call)<0) { /* uPnP port mappings failed, proceed with the call anyway. */ linphone_call_delete_upnp_session(call); @@ -2880,7 +2874,6 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const call->ping_op=sal_op_new(lc->sal); sal_ping(call->ping_op,from,real_url); sal_op_set_user_pointer(call->ping_op,call); - call->log->start_date_time=time(NULL); defer = TRUE; } } @@ -3106,9 +3099,7 @@ int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){ const char *subject; - if (call->ice_session != NULL) { - linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session); - } + linphone_call_make_local_media_description(lc,call); #ifdef BUILD_UPNP if(call->upnp_session != NULL) { linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); @@ -3155,10 +3146,6 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho // Video removing if((call->videostream != NULL) && !params->has_video) { - if (call->ice_session != NULL) { - ice_session_remove_check_list(call->ice_session, call->videostream->ms.ice_check_list); - call->videostream->ms.ice_check_list = NULL; - } #ifdef BUILD_UPNP if(call->upnp_session != NULL) { if (linphone_core_update_upnp(lc, call)<0) { @@ -3171,27 +3158,18 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho #endif /* VIDEO_ENABLED */ _linphone_call_params_copy(&call->params,params); - linphone_call_make_local_media_description(lc, call); + err=linphone_call_prepare_ice(call,FALSE); + if (err==1) { + ms_message("Defer call update to gather ICE candidates"); + return 0; + } #ifdef VIDEO_ENABLED // Video adding if (!has_video && call->params.has_video) { - if (call->ice_session != NULL) { - /* Defer call update until the ICE candidates gathering process has finished. */ - ms_message("Defer call update to gather ICE candidates"); - linphone_call_init_video_stream(call); - video_stream_prepare_video(call->videostream); - if (linphone_core_gather_ice_candidates(lc,call)<0) { - /* Ice candidates gathering failed, proceed with the call anyway. */ - linphone_call_delete_ice_session(call); - } else { - return err; - } - } #ifdef BUILD_UPNP if(call->upnp_session != NULL) { ms_message("Defer call update to add uPnP port mappings"); - linphone_call_init_video_stream(call); video_stream_prepare_video(call->videostream); if (linphone_core_update_upnp(lc, call)<0) { /* uPnP port mappings failed, proceed with the call anyway. */ @@ -3202,7 +3180,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho } #endif //BUILD_UPNP } -#endif +#endif //VIDEO_ENABLED err = linphone_core_start_update_call(lc, call); }else{ #ifdef VIDEO_ENABLED @@ -3248,13 +3226,9 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call) /* Defer the sending of the answer until there are no losing pairs left. */ return 0; } - linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session); } -#ifdef BUILD_UPNP - if(call->upnp_session != NULL) { - linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); - } -#endif //BUILD_UPNP + linphone_call_make_local_media_description(lc,call); + linphone_call_update_remote_session_id_and_ver(call); sal_call_set_local_media_description(call->op,call->localdesc); sal_call_accept(call->op); @@ -3328,20 +3302,9 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons } call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc); linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/ - linphone_call_make_local_media_description(lc,call); if (call->ice_session != NULL) { - linphone_core_update_ice_from_remote_media_description(call, remote_desc); -#ifdef VIDEO_ENABLED - if ((call->ice_session != NULL) && !ice_session_candidates_gathered(call->ice_session)) { - if ((call->params.has_video) && (call->params.has_video != old_has_video)) { - video_stream_prepare_video(call->videostream); - if (linphone_core_gather_ice_candidates(lc,call)<0) { - /* Ice candidates gathering failed, proceed with the call anyway. */ - linphone_call_delete_ice_session(call); - } else return 0; - } - } -#endif //VIDEO_ENABLED + if (linphone_call_prepare_ice(call,TRUE)==1) + return 0;/*deferred to completion of ICE gathering*/ } #ifdef BUILD_UPNP @@ -3665,9 +3628,6 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) return -1; } linphone_call_make_local_media_description(lc,call); - if (call->ice_session != NULL) { - linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session); - } #ifdef BUILD_UPNP if(call->upnp_session != NULL) { linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); @@ -3761,9 +3721,6 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ if (call->audiostream) audio_stream_play(call->audiostream, NULL); linphone_call_make_local_media_description(lc,call); - if (call->ice_session != NULL) { - linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session); - } #ifdef BUILD_UPNP if(call->upnp_session != NULL) { linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); diff --git a/coreapi/private.h b/coreapi/private.h index 69ca8c728..45dc5f305 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -804,6 +804,7 @@ bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc); const char *linphone_core_create_uuid(LinphoneCore *lc); void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); void linphone_call_create_op(LinphoneCall *call); +int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer); void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body); LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref); SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc); From 43aa6ef34f33962fc2b583906d75139af213d88a Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Thu, 17 Apr 2014 16:22:43 +0200 Subject: [PATCH 08/83] change encryption state management --- coreapi/bellesip_sal/sal_sdp.c | 20 +-- coreapi/linphonecall.c | 74 ++++++----- coreapi/private.h | 2 - include/sal/sal.h | 5 +- mediastreamer2 | 2 +- oRTP | 2 +- tester/call_tester.c | 232 ++++++++++++++++++++++----------- tester/liblinphone_tester.h | 4 + tester/tester.c | 1 + 9 files changed, 210 insertions(+), 132 deletions(-) diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 2c9411841..0ee29e6da 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -149,22 +149,22 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session const char *enc_name=NULL; switch ( stream->crypto[j].algo ) { - case AES_128_SHA1_80: + case MS_AES_128_SHA1_80: enc_name="AES_CM_128_HMAC_SHA1_80"; break; - case AES_128_SHA1_32: + case MS_AES_128_SHA1_32: enc_name="AES_CM_128_HMAC_SHA1_32"; break; - case AES_256_SHA1_32: + case MS_AES_256_SHA1_32: enc_name="AES_CM_256_HMAC_SHA1_32"; break; - case AES_256_SHA1_80: + case MS_AES_256_SHA1_80: enc_name="AES_CM_256_HMAC_SHA1_32"; break; - case AES_128_NO_AUTH: + case MS_AES_128_NO_AUTH: ms_warning ( "Unsupported crypto suite: AES_128_NO_AUTH" ); break; - case NO_CIPHER_SHA1_80: + case MS_NO_CIPHER_SHA1_80: ms_warning ( "Unsupported crypto suite: NO_CIPHER_SHA1_80" ); break; default: @@ -351,13 +351,13 @@ static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *med tmp2 ); if ( nb == 3 ) { if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 ){ - stream->crypto[valid_count].algo = AES_128_SHA1_80; + stream->crypto[valid_count].algo = MS_AES_128_SHA1_80; }else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 ){ - stream->crypto[valid_count].algo = AES_128_SHA1_32; + stream->crypto[valid_count].algo = MS_AES_128_SHA1_32; }else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_32",tmp ) == 0 ){ - stream->crypto[valid_count].algo = AES_256_SHA1_32; + stream->crypto[valid_count].algo = MS_AES_256_SHA1_32; }else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_80",tmp ) == 0 ){ - stream->crypto[valid_count].algo = AES_256_SHA1_80; + stream->crypto[valid_count].algo = MS_AES_256_SHA1_80; }else { ms_warning ( "Failed to parse crypto-algo: '%s'", tmp ); stream->crypto[valid_count].algo = 0; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index eb4a00551..eda356c05 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -95,22 +95,21 @@ bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){ } static bool_t linphone_call_are_all_streams_encrypted(LinphoneCall *call) { - // Check ZRTP encryption in audiostream - if (!call->audiostream_encrypted) { - return FALSE; - } - -#ifdef VIDEO_ENABLED - // If video enabled, check ZRTP encryption in videostream - { - const LinphoneCallParams *params=linphone_call_get_current_params(call); - if (params->has_video && !call->videostream_encrypted) { - return FALSE; + int number_of_encrypted_stream = 0; + int number_of_active_stream = 0; + if (call) { + if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) { + number_of_active_stream++; + if(media_stream_is_secured((MediaStream *)call->audiostream)) + number_of_encrypted_stream++; + } + if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) { + number_of_active_stream++; + if (media_stream_is_secured((MediaStream *)call->videostream)) + number_of_encrypted_stream++; } } -#endif - - return TRUE; + return number_of_active_stream>0 & number_of_active_stream==number_of_encrypted_stream; } void propagate_encryption_changed(LinphoneCall *call){ @@ -131,9 +130,6 @@ void propagate_encryption_changed(LinphoneCall *call){ #ifdef VIDEO_ENABLED static void linphone_call_videostream_encryption_changed(void *data, bool_t encrypted){ LinphoneCall *call = (LinphoneCall *)data; - - ms_message("Video stream is %s", encrypted ? "encrypted" : "not encrypted"); - call->videostream_encrypted=encrypted; propagate_encryption_changed(call); } #endif @@ -141,10 +137,8 @@ static void linphone_call_videostream_encryption_changed(void *data, bool_t encr static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) { char status[255]={0}; LinphoneCall *call; - ms_message("Audio stream is %s ", encrypted ? "encrypted" : "not encrypted"); call = (LinphoneCall *)data; - call->audiostream_encrypted=encrypted; if (encrypted && call->core->vtable.display_status != NULL) { snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token); @@ -260,11 +254,11 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){ } }else{ md->streams[i].crypto[0].tag = 1; - md->streams[i].crypto[0].algo = AES_128_SHA1_80; + md->streams[i].crypto[0].algo = MS_AES_128_SHA1_80; if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key, SAL_SRTP_KEY_SIZE)) md->streams[i].crypto[0].algo = 0; md->streams[i].crypto[1].tag = 2; - md->streams[i].crypto[1].algo = AES_128_SHA1_32; + md->streams[i].crypto[1].algo = MS_AES_128_SHA1_32; if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key, SAL_SRTP_KEY_SIZE)) md->streams[i].crypto[1].algo = 0; md->streams[i].crypto[2].algo = 0; @@ -482,6 +476,7 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, call->log=linphone_call_log_new(call, from, to); call->owns_call_log=TRUE; call->camera_enabled=TRUE; + call->current_params.media_encryption=LinphoneMediaEncryptionNone; linphone_core_get_audio_port_range(call->core, &min_port, &max_port); port_config_set(call,0,min_port,max_port); @@ -916,6 +911,16 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ } #endif + if (linphone_call_are_all_streams_encrypted(call)) { + if (linphone_call_get_authentication_token(call)) { + call->current_params.media_encryption=LinphoneMediaEncryptionZRTP; + } else { + call->current_params.media_encryption=LinphoneMediaEncryptionSRTP; + } + } else { + call->current_params.media_encryption=LinphoneMediaEncryptionNone; + } + return &call->current_params; } @@ -1903,12 +1908,10 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna if (crypto_idx >= 0) { media_stream_set_srtp_recv_key(&call->audiostream->ms,stream->crypto[0].algo,stream->crypto[0].master_key); media_stream_set_srtp_send_key(&call->audiostream->ms,stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key); - call->audiostream_encrypted=TRUE; } else { ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag); - call->audiostream_encrypted=FALSE; } - }else call->audiostream_encrypted=FALSE; + } configure_rtp_session_for_rtcp_xr(lc, call, SalAudio); audio_stream_start_full( call->audiostream, @@ -2022,14 +2025,10 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna if (!is_inactive){ if (vstream->proto == SalProtoRtpSavp) { int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag); - if (crypto_idx >= 0) { media_stream_set_srtp_recv_key(&call->videostream->ms,vstream->crypto[0].algo,vstream->crypto[0].master_key); media_stream_set_srtp_send_key(&call->videostream->ms,vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key); - call->videostream_encrypted=TRUE; - }else call->videostream_encrypted=FALSE; - }else{ - call->videostream_encrypted=FALSE; + } } configure_rtp_session_for_rtcp_xr(lc, call, SalVideo); @@ -2090,11 +2089,17 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) { OrtpZrtpParams params; - /*will be set later when zrtp is activated*/ - call->current_params.media_encryption=LinphoneMediaEncryptionNone; - + memset(¶ms,0,sizeof(OrtpZrtpParams)); + /*call->current_params.media_encryption will be set later when zrtp is activated*/ params.zid_file=lc->zrtp_secrets_cache; audio_stream_enable_zrtp(call->audiostream,¶ms); +#if VIDEO_ENABLED + if (media_stream_is_secured((MediaStream *)call->audiostream) && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) { + /*audio stream is already encrypted and video stream is active*/ + memset(¶ms,0,sizeof(OrtpZrtpParams)); + video_stream_enable_zrtp(call->videostream,call->audiostream,¶ms); + } +#endif }else{ call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ? LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone; @@ -2144,8 +2149,7 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio); if (call->audiostream && local_st_desc && old_stream && new_stream && update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->audiostream->ms)){ - call->audiostream_encrypted = TRUE; - }else call->audiostream_encrypted = FALSE; + } #ifdef VIDEO_ENABLED local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalVideo); @@ -2153,9 +2157,7 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalVideo); if (call->videostream && local_st_desc && old_stream && new_stream && update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->videostream->ms)){ - call->videostream_encrypted = TRUE; } - call->videostream_encrypted = FALSE; #endif } diff --git a/coreapi/private.h b/coreapi/private.h index 45dc5f305..6634a3344 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -224,8 +224,6 @@ struct _LinphoneCall bool_t owns_call_log; bool_t ringing_beep; /* whether this call is ringing through an already existent current call*/ - bool_t videostream_encrypted; - bool_t audiostream_encrypted; bool_t auth_token_verified; bool_t defer_update; diff --git a/include/sal/sal.h b/include/sal/sal.h index 1dba31f90..d0215c89c 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -30,9 +30,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "config.h" #endif -#include "mediastreamer2/mscommon.h" +#include "mediastreamer2/mediastream.h" #include "ortp/rtpsession.h" -#include "ortp/ortp_srtp.h" #include "belle-sip/belle-sip.h" #ifndef LINPHONE_PUBLIC @@ -171,7 +170,7 @@ typedef struct SalIceRemoteCandidate { typedef struct SalSrtpCryptoAlgo { unsigned int tag; - enum ortp_srtp_crypto_suite_t algo; + MSCryptoSuite algo; char master_key[SAL_SRTP_KEY_SIZE]; } SalSrtpCryptoAlgo; diff --git a/mediastreamer2 b/mediastreamer2 index 41db9323b..5363f6d64 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 41db9323be6a6d136949ee5fdba1198c38a7d787 +Subproject commit 5363f6d6487f44c0fa898647b7b859857db13283 diff --git a/oRTP b/oRTP index beee1f20d..891f3da68 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit beee1f20d69af3d04cd27fcc00b3830620066367 +Subproject commit 891f3da6817e30b606493840f305250f81a254bd diff --git a/tester/call_tester.c b/tester/call_tester.c index 3e8ef9475..067292942 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -24,6 +24,7 @@ #include "private.h" #include "liblinphone_tester.h" +static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy); void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){ char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); @@ -59,7 +60,22 @@ void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState CU_FAIL("unexpected event");break; } } - +void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) { + char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); + char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); + stats* counters; + ms_message(" %s call from [%s] to [%s], is now [%s]",linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing" + ,from + ,to + ,(on?"encrypted":"unencrypted")); + ms_free(to); + ms_free(from); + counters = get_stats(lc); + if (on) + counters->number_of_LinphoneCallEncryptedOn++; + else + counters->number_of_LinphoneCallEncryptedOff++; +} void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { char* to=linphone_address_as_string(linphone_call_get_call_log(transfered)->to); char* from=linphone_address_as_string(linphone_call_get_call_log(transfered)->from); @@ -198,12 +214,19 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr && wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1); - if (linphone_core_get_media_encryption(caller_mgr->lc) - && linphone_core_get_media_encryption(callee_mgr->lc)) { + if (linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionNone + && linphone_core_get_media_encryption(callee_mgr->lc) != LinphoneMediaEncryptionNone) { + /*wait for encryption to be on, in case of zrtp, it can take a few seconds*/ + if (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionZRTP) + wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_caller.number_of_LinphoneCallEncryptedOn+1); + if (linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionZRTP) + wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_callee.number_of_LinphoneCallEncryptedOn+1); + { const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee_mgr->lc)); CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc)); call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc)); CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc)); + } } return result; } @@ -516,6 +539,17 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee } ms_usleep(50000); } + + /*make sure encryption mode are preserved*/ + if (c1) { + const LinphoneCallParams* call_param = linphone_call_get_current_params(c1); + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc)); + } + if (c2) { + const LinphoneCallParams* call_param = linphone_call_get_current_params(c2); + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(callee->lc)); + } + return success; } @@ -703,6 +737,15 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) LinphoneVideoPolicy caller_policy; LinphoneCallParams* callee_params; LinphoneCall* call_obj; + stats initial_caller_stat=caller->stat; + stats initial_callee_stat=callee->stat; + + if (linphone_call_get_state(linphone_core_get_current_call(callee->lc)) != LinphoneCallStreamsRunning + || linphone_call_get_state(linphone_core_get_current_call(caller->lc)) != LinphoneCallStreamsRunning ) { + ms_warning("bad state for adding video"); + return FALSE; + } + caller_policy.automatically_accept=TRUE; caller_policy.automatically_initiate=TRUE; linphone_core_enable_video_capture(callee->lc, TRUE); @@ -710,8 +753,8 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) linphone_core_enable_video_capture(caller->lc, TRUE); linphone_core_enable_video_display(caller->lc, FALSE); linphone_core_set_video_policy(caller->lc,&caller_policy); - stats initial_caller_stat=caller->stat; - stats initial_callee_stat=callee->stat; + + if ((call_obj = linphone_core_get_current_call(callee->lc))) { callee_params = linphone_call_params_copy(linphone_call_get_current_params(call_obj)); @@ -726,6 +769,21 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))); + if (linphone_core_get_media_encryption(caller->lc) != LinphoneMediaEncryptionNone + && linphone_core_get_media_encryption(callee->lc) != LinphoneMediaEncryptionNone) { + /*wait for encryption to be on, in case of zrtp, it can take a few seconds*/ + if (linphone_core_get_media_encryption(caller->lc) == LinphoneMediaEncryptionZRTP) + wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallEncryptedOn,initial_caller_stat.number_of_LinphoneCallEncryptedOn+1); + if (linphone_core_get_media_encryption(callee->lc) == LinphoneMediaEncryptionZRTP) + wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallEncryptedOn,initial_callee_stat.number_of_LinphoneCallEncryptedOn+1); + + { + const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)); + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc)); + call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)); + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc)); + } + } linphone_call_set_next_video_frame_decoded_callback(call_obj,linphone_call_cb,callee->lc); /*send vfu*/ @@ -824,19 +882,21 @@ static void video_call(void) { marie_call=linphone_core_get_current_call(marie->lc); pauline_call=linphone_core_get_current_call(pauline->lc); - CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marie_call))); - CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(pauline_call))); + if (marie_call && pauline_call ) { + CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marie_call))); + CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(pauline_call))); - /*check video path*/ - linphone_call_set_next_video_frame_decoded_callback(marie_call,linphone_call_cb,marie->lc); - linphone_call_send_vfu_request(marie_call); - CU_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1)); + /*check video path*/ + linphone_call_set_next_video_frame_decoded_callback(marie_call,linphone_call_cb,marie->lc); + linphone_call_send_vfu_request(marie_call); + CU_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1)); - liblinphone_tester_check_rtcp(marie,pauline); + liblinphone_tester_check_rtcp(marie,pauline); - linphone_core_terminate_all_calls(pauline->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_terminate_all_calls(pauline->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); @@ -1139,45 +1199,17 @@ static void simple_conference(void) { } -static void encrypted_call(LinphoneMediaEncryption mode) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - - if (linphone_core_media_encryption_supported(marie->lc,mode)) { - linphone_core_set_media_encryption(marie->lc,mode); - linphone_core_set_media_encryption(pauline->lc,mode); - - CU_ASSERT_TRUE(call(pauline,marie)); - - CU_ASSERT_EQUAL(linphone_core_get_media_encryption(marie->lc),mode); - CU_ASSERT_EQUAL(linphone_core_get_media_encryption(pauline->lc),mode); - if (linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP - && linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP) { - /*check SAS*/ - CU_ASSERT_STRING_EQUAL(linphone_call_get_authentication_token(linphone_core_get_current_call(pauline->lc)) - ,linphone_call_get_authentication_token(linphone_core_get_current_call(marie->lc))); - } - liblinphone_tester_check_rtcp(pauline,marie); - /*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)); - } else { - ms_warning ("Not tested because %s not available", linphone_media_encryption_to_string(mode)); - } - linphone_core_manager_destroy(marie); - linphone_core_manager_destroy(pauline); -} static void srtp_call() { - encrypted_call(LinphoneMediaEncryptionSRTP); + call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyNoFirewall); } -/* - * future work static void zrtp_call() { - encrypted_call(LinphoneMediaEncryptionZRTP); -}*/ + call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyNoFirewall); +} +static void zrtp_video_call() { + call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyNoFirewall); +} static void call_with_declined_srtp(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); @@ -1197,43 +1229,70 @@ static void call_with_declined_srtp(void) { linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -#ifdef VIDEO_ENABLED -static void srtp_video_ice_call(void) { + +static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy) { int i=0; -#else -static void srtp_ice_call(void) { -#endif LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + if (enable_relay) { + linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); + } + if (linphone_core_media_encryption_supported(marie->lc,mode)) { + linphone_core_set_media_encryption(marie->lc,mode); + linphone_core_set_media_encryption(pauline->lc,mode); - if (linphone_core_media_encryption_supported(marie->lc,LinphoneMediaEncryptionSRTP)) { - linphone_core_set_media_encryption(marie->lc,LinphoneMediaEncryptionSRTP); - linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionSRTP); - - linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce); + linphone_core_set_firewall_policy(marie->lc,policy); linphone_core_set_stun_server(marie->lc,"stun.linphone.org"); - linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce); + linphone_core_set_firewall_policy(pauline->lc,policy); linphone_core_set_stun_server(pauline->lc,"stun.linphone.org"); CU_ASSERT_TRUE(call(pauline,marie)); + if (linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP + && linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP) { + /*wait for SAS*/ + int i; + for (i=0;i<10;i++) { + if (linphone_call_get_authentication_token(linphone_core_get_current_call(pauline->lc)) + && + linphone_call_get_authentication_token(linphone_core_get_current_call(marie->lc))) { + /*check SAS*/ + CU_ASSERT_STRING_EQUAL(linphone_call_get_authentication_token(linphone_core_get_current_call(pauline->lc)) + ,linphone_call_get_authentication_token(linphone_core_get_current_call(marie->lc))); + liblinphone_tester_check_rtcp(pauline,marie); + break; + } + linphone_core_iterate(marie->lc); + linphone_core_iterate(pauline->lc); + ms_usleep(200000); + } - CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); -#ifdef VIDEO_ENABLED - for (i=0;i<100;i++) { /*fixme to workaround a crash*/ - ms_usleep(20000); - linphone_core_iterate(marie->lc); - linphone_core_iterate(pauline->lc); } - add_video(pauline,marie); + if (policy == LinphonePolicyUseIce) + CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); + if (enable_video) { + if (linphone_core_video_supported(marie->lc)) { + for (i=0;i<100;i++) { /*fixme to workaround a crash*/ + ms_usleep(20000); + linphone_core_iterate(marie->lc); + linphone_core_iterate(pauline->lc); + } + + add_video(pauline,marie); + if (policy == LinphonePolicyUseIce) + CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); + + liblinphone_tester_check_rtcp(marie,pauline); + /*wait for ice to found the direct path*/ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,1)); + } else { + ms_warning ("not tested because video not available"); + } + + } - CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); - liblinphone_tester_check_rtcp(marie,pauline); - /*wait for ice to found the direct path*/ - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,1)); -#endif - /*just to sleep*/ linphone_core_terminate_all_calls(marie->lc); @@ -1246,9 +1305,21 @@ static void srtp_ice_call(void) { linphone_core_manager_destroy(pauline); } - - - +static void srtp_video_ice_call(void) { + call_base(LinphoneMediaEncryptionSRTP,TRUE,FALSE,LinphonePolicyUseIce); +} +static void srtp_ice_call(void) { + call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce); +} +static void zrtp_video_ice_call(void) { + /*encrypted_ice_call(LinphoneMediaEncryptionZRTP,TRUE,FALSE);*/ +} +static void zrtp_ice_call(void) { + /*encrypted_ice_call(LinphoneMediaEncryptionZRTP,FALSE,FALSE);*/ +} +static void zrtp_ice_call_with_relay(void) { + /*encrypted_ice_call(LinphoneMediaEncryptionZRTP,FALSE,TRUE);*/ +} static void early_media_call(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_early_rc"); @@ -1901,17 +1972,20 @@ test_t call_tests[] = { { "Call paused resumed", call_paused_resumed }, { "Call paused resumed from callee", call_paused_resumed_from_callee }, { "SRTP call", srtp_call }, - /*{ "ZRTP call",zrtp_call}, futur work*/ + { "ZRTP call",zrtp_call}, + { "ZRTP video call",zrtp_video_call}, { "SRTP call with declined srtp", call_with_declined_srtp }, #ifdef VIDEO_ENABLED { "Simple video call",video_call}, { "SRTP ice video call", srtp_video_ice_call }, + { "ZRTP ice video call", zrtp_video_ice_call }, { "Call with video added", call_with_video_added }, { "Call with video added (random ports)", call_with_video_added_random_ports }, { "Call with video declined",call_with_declined_video}, -#else - { "SRTP ice call", srtp_ice_call }, #endif + { "SRTP ice call", srtp_ice_call }, + { "ZRTP ice call", zrtp_ice_call }, + { "ZRTP ice call with relay", zrtp_ice_call_with_relay}, { "Call with privacy", call_with_privacy }, { "Call with privacy 2", call_with_privacy2 }, { "Call rejected because of wrong credential", call_rejected_because_wrong_credentials}, diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index d9dc9b914..5e5767bab 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -181,6 +181,9 @@ typedef struct _stats { int number_of_LinphoneConfiguringSkipped; int number_of_LinphoneConfiguringFailed; int number_of_LinphoneConfiguringSuccessful; + + int number_of_LinphoneCallEncryptedOn; + int number_of_LinphoneCallEncryptedOff; }stats; typedef struct _LinphoneCoreManager { @@ -212,6 +215,7 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *ev, Lin void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state); void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content); void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message); +void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token); LinphoneAddress * create_linphone_address(const char * domain); bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value); diff --git a/tester/tester.c b/tester/tester.c index caeb78009..2d734b074 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -205,6 +205,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f mgr->v_table.notify_received=linphone_notify_received; mgr->v_table.publish_state_changed=linphone_publish_state_changed; mgr->v_table.configuring_status=linphone_configuration_status; + mgr->v_table.call_encryption_changed=linphone_call_encryption_changed; reset_counters(&mgr->stat); if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file); From 8417c0b18d8f5d6575e3d64a06dce8dc44009fb4 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 7 Apr 2014 16:50:27 +0200 Subject: [PATCH 09/83] Quality reporting: on call end, send a PUBLISH message with call quality data (work in progress) --- build/android/Android.mk | 3 +- build/vsx/LibLinphone/LibLinphone.vcxproj | 3 +- coreapi/CMakeLists.txt | 1 + coreapi/Makefile.am | 1 + coreapi/linphonecall.c | 1 + coreapi/linphonecore.c | 3 + coreapi/quality_reporting.c | 125 ++++++++++++++++++++++ coreapi/quality_reporting.h | 34 ++++++ 8 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 coreapi/quality_reporting.c create mode 100644 coreapi/quality_reporting.h diff --git a/build/android/Android.mk b/build/android/Android.mk index 18fbbdbfd..d815a11a9 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -64,7 +64,8 @@ LOCAL_SRC_FILES := \ xml.c \ xml2lpc.c \ lpc2xml.c \ - remote_provisioning.c + remote_provisioning.c \ + quality_reporting.c ifndef LINPHONE_VERSION LINPHONE_VERSION = "Devel" diff --git a/build/vsx/LibLinphone/LibLinphone.vcxproj b/build/vsx/LibLinphone/LibLinphone.vcxproj index 9bc9aadf9..bc1f56695 100644 --- a/build/vsx/LibLinphone/LibLinphone.vcxproj +++ b/build/vsx/LibLinphone/LibLinphone.vcxproj @@ -203,6 +203,7 @@ + @@ -275,4 +276,4 @@ - \ No newline at end of file + diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 8b2650950..05ae3d811 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -74,6 +74,7 @@ set(SOURCE_FILES offeranswer.c presence.c proxy.c + quality_reporting.c remote_provisioning.c sal.c siplogin.c diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 68d78447f..5edc54059 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -56,6 +56,7 @@ liblinphone_la_SOURCES=\ xml2lpc.c \ lpc2xml.c \ remote_provisioning.c \ + quality_reporting.c \ $(GITVERSION_FILE) if BUILD_UPNP diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index eb4a00551..c095898ae 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -782,6 +782,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const Indeed it does not change the state of the call (still paused or running)*/ call->state=cstate; } + if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){ switch(call->non_op_error.reason){ case SalReasonDeclined: diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index bd852968e..23090baba 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sipsetup.h" #include "lpconfig.h" #include "private.h" +#include "quality_reporting.h" #include #include @@ -3469,6 +3470,8 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ /*stop ringing*/ linphone_core_stop_ringing(lc); + linphone_quality_reporting_submit(call); + linphone_call_stop_media_streams(call); #ifdef BUILD_UPNP diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c new file mode 100644 index 000000000..e3d25c424 --- /dev/null +++ b/coreapi/quality_reporting.c @@ -0,0 +1,125 @@ +/* +linphone +Copyright (C) 2014 - Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include "linphonecore.h" +#include "private.h" +#include "sal/sal.h" + +#define PRINT2(x, f) ms_message(#x ": " #f, x) +#define PRINT(x) PRINT2(x, "%s") + +void linphone_quality_reporting_submit(LinphoneCall* call) { + // example at http://tools.ietf.org/html/rfc6035#section-4.7.3 + // only if this is a linphone account + // only if call succeeded + // to: collector@sip.linphone.com + // executed AFTER BYE's "OK" response has been received + // expires value? + // un envoi à faire par stream ? (ssrc différent pour chaque stream) + // memory leaks + + LinphoneContent content = {0}; + LinphoneAddress *addr; + int expires = 3600; + const char *remote_identity; + const char *local_identity; + const char *orig_identity; + const char *local_ip = call->localdesc->addr; //or call->localip ? + const char *remote_ip = "TODO"; + uint32_t local_ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); + uint32_t remote_ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); + + int local_port = 0; //TODO + int remote_port = 0;//linphone_address_get_port(linphone_call_get_remote_address(call)); + + if (call->dir == LinphoneCallIncoming) { + remote_identity = linphone_address_as_string(call->log->from); + local_identity = linphone_address_as_string(call->log->to); + orig_identity = remote_identity; + } else { + remote_identity = linphone_address_as_string(call->log->to); + local_identity = linphone_address_as_string(call->log->from); + orig_identity = local_identity; + } + + ms_message("Submitting PUBLISH packet for call between %s and %s", local_identity, remote_identity); + + PRINT(call->dest_proxy->contact_params); + PRINT(call->dest_proxy->contact_uri_params); + PRINT(call->dest_proxy->dial_prefix); + PRINT(call->dest_proxy->realm); + PRINT(call->dest_proxy->type); + PRINT(call->dest_proxy->reg_identity); + PRINT(call->dest_proxy->reg_proxy); + PRINT(call->dest_proxy->reg_route); + + PRINT(sal_op_get_route(call->op)); + PRINT(sal_op_get_from(call->op)); + PRINT(sal_op_get_to(call->op)); + PRINT(sal_op_get_proxy(call->op)); + PRINT(sal_op_get_remote_contact(call->op)); + PRINT(sal_op_get_network_origin(call->op)); + + PRINT(call->log->refkey); + PRINT(call->localdesc->addr); + + PRINT2(call->log->start_date_time, "%ld"); + PRINT2(call->log->start_date_time + call->log->duration, "%ld"); + PRINT(linphone_timestamp_to_rfc3339_string(call->log->start_date_time)); + + + content.type = ms_strdup("application"); + content.subtype = ms_strdup("vq-rtcpxr"); + content.data = ms_strdup_printf(_("VQSessionReport: CallTerm\r\n")); + content.data = ms_strdup_printf(_("%sCallID: %s\r\n"), content.data, call->log->call_id); + content.data = ms_strdup_printf(_("%sLocalID: %s\r\n"), content.data, local_identity); + content.data = ms_strdup_printf(_("%sRemoteID: %s\r\n"), content.data, remote_identity); + content.data = ms_strdup_printf(_("%sOrigID: %s\r\n"), content.data, orig_identity); + + // content.data = ms_strdup_printf(_("%sLocalGroup: %s\r\n"), content.data, "TO_DO"); + // content.data = ms_strdup_printf(_("%sRemoteGroup: %s\r\n"), content.data, "TO_DO"); + content.data = ms_strdup_printf(_("%sLocalAddr: IP=%s PORT=%d SSRC=%d\r\n"), content.data, local_ip, local_port, local_ssrc); + // content.data = ms_strdup_printf(_("%sLocalMAC: %s\r\n"), content.data, "TO_DO"); + content.data = ms_strdup_printf(_("%sRemoteAddr: IP=%s PORT=%d SSRC=%d\r\n"), content.data, remote_ip, remote_port, remote_ssrc); + // content.data = ms_strdup_printf(_("%sRemoteMAC: %s\r\n"), content.data, "TO_DO"); + + content.data = ms_strdup_printf(_("%sLocalMetrics:\r\n"), content.data); + content.data = ms_strdup_printf(_("%sTimestamps: START=%s STOP=%s\r\n"), content.data, + linphone_timestamp_to_rfc3339_string(call->log->start_date_time), + linphone_timestamp_to_rfc3339_string(call->log->start_date_time + call->log->duration)); + content.data = ms_strdup_printf(_("%sRemoteMetrics:\r\n"), content.data, "TO_DO"); + + content.data = ms_strdup_printf(_("%sRemoteMetrics:\r\n"), content.data, "TO_DO"); + content.data = ms_strdup_printf(_("%sTimestamps: %s\r\n"), content.data, "TO_DO"); + content.data = ms_strdup_printf(_("%sDialogID: %s\r\n"), content.data, "TO_DO"); + + content.size = strlen((char*)content.data); + + addr = linphone_address_new("sip:collector@sip.linphone.org"); + + ms_message("packet content: %s", (char*)content.data); + linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); + + linphone_address_destroy(addr); +} + diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h new file mode 100644 index 000000000..f56d2b1bd --- /dev/null +++ b/coreapi/quality_reporting.h @@ -0,0 +1,34 @@ +/* +linphone +Copyright (C) 2014 - Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef quality_reporting_h +#define quality_reporting_h + +#include "linphonecore.h" + +#ifdef __cplusplus +extern "C"{ +#endif +void linphone_quality_reporting_submit(LinphoneCall* call); + +#ifdef __cplusplus +} +#endif + +#endif From ce0d3bde0ed0b5ba84fc11a2bc7d61e4f281e80b Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Tue, 8 Apr 2014 14:37:08 +0200 Subject: [PATCH 10/83] Set timestamp_to_string method accessible from other coreAPI files --- coreapi/presence.c | 4 ++-- coreapi/private.h | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/coreapi/presence.c b/coreapi/presence.c index af4c5184d..08996329f 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -170,7 +170,7 @@ static time_t parse_timestamp(const char *timestamp) { return seconds - timezone; } -static char * timestamp_to_string(time_t timestamp) { +char * linphone_timestamp_to_rfc3339_string(time_t timestamp) { char timestamp_str[22]; struct tm *ret; #ifndef WIN32 @@ -1604,7 +1604,7 @@ static void write_xml_presence_note_obj(LinphonePresenceNote *note, struct _pres static int write_xml_presence_timestamp(xmlTextWriterPtr writer, time_t timestamp) { int err; - char *timestamp_str = timestamp_to_string(timestamp); + char *timestamp_str = linphone_timestamp_to_rfc3339_string(timestamp); err = xmlTextWriterWriteElement(writer, (const xmlChar *)"timestamp", (const xmlChar *)timestamp_str); if (timestamp_str) ms_free(timestamp_str); return err; diff --git a/coreapi/private.h b/coreapi/private.h index 45dc5f305..e2feef54a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -854,11 +854,18 @@ char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char * void linphone_free_xml_text_content(const char *text); xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression); +/***************************************************************************** + * OTHER UTILITY FUNCTIONS * + ****************************************************************************/ +char * linphone_timestamp_to_rfc3339_string(time_t timestamp); + + static inline const LinphoneErrorInfo *linphone_error_info_from_sal_op(const SalOp *op){ if (op==NULL) return (LinphoneErrorInfo*)sal_error_info_none(); return (const LinphoneErrorInfo*)sal_op_get_error_info(op); } + /** Belle Sip-based objects need unique ids */ From ee0a646d9338d581159223802f74c526ee5af516 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Tue, 8 Apr 2014 17:37:28 +0200 Subject: [PATCH 11/83] Use a struct to store reporting data --- coreapi/quality_reporting.c | 165 ++++++++++++++++++++++++++---------- 1 file changed, 120 insertions(+), 45 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index e3d25c424..03f9bb65f 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -25,9 +25,105 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "private.h" #include "sal/sal.h" -#define PRINT2(x, f) ms_message(#x ": " #f, x) +#define PRINT2(x, f) printf(#x ": " #f "\n", x) #define PRINT(x) PRINT2(x, "%s") +// since printf family functions are LOCALE dependent, float separator may differ +// depending on the user's locale (LC_NUMERIC env var). +static char * float_to_one_decimal_string(float f) { + int floor_part = (int)f; + int one_decimal_part = (int) (10.f * (f - floor_part)); + + return ms_strdup_printf(_("%d.%d"), floor_part, one_decimal_part); +} + +struct _reporting_metrics_st { + time_t ts_start; + time_t ts_stop; + + int sd_pt; + char * sd_pd; + int sd_sr; + int sd_fd; + int sd_fo; + int sd_fpp; + int sd_pps; + char * sd_fmtp; + int sd_plc; + char * sd_ssup; + + int jb_jba; + int jb_jbr; + int jb_jbn; + int jb_jbm; + int jb_jbx; + + float pl_nlr; + float pl_jdr; + + int bgl_bld; + int bgl_bd; + float bgl_gld; + int bgl_gd; + int bgl_gmin; + + int d_rtd; + int d_esd; + int d_sowd; + int d_iaj; + int d_maj; + + int s_sl; + int s_nl; + int s_rerl; + + int qe_rlq; + int qe_rcq; + int qe_extri; + float qe_moslq; + float qe_moscq; + char * qe_qoeestalg; +}; + +static char * add_metrics(char * dest, struct _reporting_metrics_st rm) { + char * tmp = dest; + + dest = ms_strdup_printf(_("%sTimestamps:START=%s STOP=%s\r\n"), tmp, + linphone_timestamp_to_rfc3339_string(rm.ts_start), + linphone_timestamp_to_rfc3339_string(rm.ts_stop)); + ms_free(tmp); + tmp = dest; + dest = ms_strdup_printf(_("%sSessionDesc:PT=%d PD=%s SR=%d FD=%d FO=%d FPP=%d PPS=%d FMTP=%s PLC=%d SSUP=%s\r\n"), + tmp, rm.sd_pt, rm.sd_pd, rm.sd_sr, rm.sd_fd, rm.sd_fo, rm.sd_fpp, rm.sd_pps, rm.sd_fmtp, rm.sd_plc, rm.sd_ssup); + ms_free(tmp); + tmp = dest; + dest = ms_strdup_printf(_("%sJitterBuffer:JBA=%d JBR=%d JBN=%d JBM=%d JBX=%d\r\n"), + tmp, rm.jb_jba, rm.jb_jbr, rm.jb_jbn, rm.jb_jbm, rm.jb_jbx); + ms_free(tmp); + tmp = dest; + dest = ms_strdup_printf(_("%sPacketLoss:NLR=%s JDR=%s\r\n"), + tmp, float_to_one_decimal_string(rm.pl_nlr), float_to_one_decimal_string(rm.pl_jdr)); + ms_free(tmp); + tmp = dest; + dest = ms_strdup_printf(_("%sBurstGapLoss:BLD=%d BD=%d GLD=%s GD=%d GMIN=%d\r\n"), + tmp, rm.bgl_bld, rm.bgl_bd, float_to_one_decimal_string(rm.bgl_gld), rm.bgl_gd, rm.bgl_gmin); + ms_free(tmp); + tmp = dest; + dest = ms_strdup_printf(_("%sDelay:RTD=%d ESD=%d SOWD=%d IAJ=%d MAJ=%d\r\n"), + tmp, rm.d_rtd, rm.d_esd, rm.d_sowd, rm.d_iaj, rm.d_maj); + ms_free(tmp); + tmp = dest; + dest = ms_strdup_printf(_("%sSignal:SL=%d NL=%d RERL=%d\r\n"), + tmp, rm.s_sl, rm.s_nl, rm.s_rerl); + ms_free(tmp); + tmp = dest; + dest = ms_strdup_printf(_("%sQualityEst:RLQ=%d RCQ=%d EXTRI=%d MOSLQ=%s MOSCQ=%s QoEEstAlg=%s\r\n"), + tmp, rm.qe_rlq, rm.qe_rcq, rm.qe_extri, float_to_one_decimal_string(rm.qe_moslq), float_to_one_decimal_string(rm.qe_moscq), rm.qe_qoeestalg); + ms_free(tmp); + + return dest; +} + void linphone_quality_reporting_submit(LinphoneCall* call) { // example at http://tools.ietf.org/html/rfc6035#section-4.7.3 // only if this is a linphone account @@ -37,21 +133,24 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { // expires value? // un envoi à faire par stream ? (ssrc différent pour chaque stream) // memory leaks - + // belle_sip_snprintf + //ex RERL 404 code différent potentiellement avec info manquante + // 3611 pour savoir les valeurs pour les champs non disponibles LinphoneContent content = {0}; LinphoneAddress *addr; int expires = 3600; + const char *local_ip = "TODO";//stream dependentcall->localdesc->addr; //or call->localip ? + const char *remote_ip = "TODO"; + int local_port = 0; //TODO + int remote_port = 0;//linphone_address_get_port(linphone_call_get_remote_address(call)); + uint32_t local_ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); + uint32_t remote_ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); + struct _reporting_metrics_st local_metrics = {0}; + struct _reporting_metrics_st remote_metrics = {0}; + const char *remote_identity; const char *local_identity; const char *orig_identity; - const char *local_ip = call->localdesc->addr; //or call->localip ? - const char *remote_ip = "TODO"; - uint32_t local_ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); - uint32_t remote_ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); - - int local_port = 0; //TODO - int remote_port = 0;//linphone_address_get_port(linphone_call_get_remote_address(call)); - if (call->dir == LinphoneCallIncoming) { remote_identity = linphone_address_as_string(call->log->from); local_identity = linphone_address_as_string(call->log->to); @@ -64,30 +163,6 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { ms_message("Submitting PUBLISH packet for call between %s and %s", local_identity, remote_identity); - PRINT(call->dest_proxy->contact_params); - PRINT(call->dest_proxy->contact_uri_params); - PRINT(call->dest_proxy->dial_prefix); - PRINT(call->dest_proxy->realm); - PRINT(call->dest_proxy->type); - PRINT(call->dest_proxy->reg_identity); - PRINT(call->dest_proxy->reg_proxy); - PRINT(call->dest_proxy->reg_route); - - PRINT(sal_op_get_route(call->op)); - PRINT(sal_op_get_from(call->op)); - PRINT(sal_op_get_to(call->op)); - PRINT(sal_op_get_proxy(call->op)); - PRINT(sal_op_get_remote_contact(call->op)); - PRINT(sal_op_get_network_origin(call->op)); - - PRINT(call->log->refkey); - PRINT(call->localdesc->addr); - - PRINT2(call->log->start_date_time, "%ld"); - PRINT2(call->log->start_date_time + call->log->duration, "%ld"); - PRINT(linphone_timestamp_to_rfc3339_string(call->log->start_date_time)); - - content.type = ms_strdup("application"); content.subtype = ms_strdup("vq-rtcpxr"); content.data = ms_strdup_printf(_("VQSessionReport: CallTerm\r\n")); @@ -104,22 +179,22 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { // content.data = ms_strdup_printf(_("%sRemoteMAC: %s\r\n"), content.data, "TO_DO"); content.data = ms_strdup_printf(_("%sLocalMetrics:\r\n"), content.data); - content.data = ms_strdup_printf(_("%sTimestamps: START=%s STOP=%s\r\n"), content.data, - linphone_timestamp_to_rfc3339_string(call->log->start_date_time), - linphone_timestamp_to_rfc3339_string(call->log->start_date_time + call->log->duration)); - content.data = ms_strdup_printf(_("%sRemoteMetrics:\r\n"), content.data, "TO_DO"); - - content.data = ms_strdup_printf(_("%sRemoteMetrics:\r\n"), content.data, "TO_DO"); - content.data = ms_strdup_printf(_("%sTimestamps: %s\r\n"), content.data, "TO_DO"); + local_metrics.ts_start = call->log->start_date_time; + local_metrics.ts_stop = call->log->start_date_time + call->log->duration; + content.data = add_metrics((char*)content.data, local_metrics); + + content.data = ms_strdup_printf(_("%sRemoteMetrics:\r\n"), content.data); + remote_metrics.bgl_gld = 42.34f; + content.data = add_metrics((char*)content.data, remote_metrics); content.data = ms_strdup_printf(_("%sDialogID: %s\r\n"), content.data, "TO_DO"); + // for debug purpose only + PRINT(content.data); + content.size = strlen((char*)content.data); - + addr = linphone_address_new("sip:collector@sip.linphone.org"); - - ms_message("packet content: %s", (char*)content.data); linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); - linphone_address_destroy(addr); } From 2e07b6730fd476f861f97d96ad4bb17b4c597234 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Wed, 9 Apr 2014 15:06:56 +0200 Subject: [PATCH 12/83] Continuing quality reporting - use a buffer with belle_sip_snprintf instead of ms_strdup_printf (multiple new allocations) --- coreapi/quality_reporting.c | 224 ++++++++++++++++++++++-------------- 1 file changed, 140 insertions(+), 84 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 03f9bb65f..cee2d8a4a 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -25,22 +25,68 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "private.h" #include "sal/sal.h" +#include + #define PRINT2(x, f) printf(#x ": " #f "\n", x) #define PRINT(x) PRINT2(x, "%s") // since printf family functions are LOCALE dependent, float separator may differ // depending on the user's locale (LC_NUMERIC env var). static char * float_to_one_decimal_string(float f) { - int floor_part = (int)f; - int one_decimal_part = (int) (10.f * (f - floor_part)); + float rounded_f = floorf(f * 10 + .5f) / 10; + + int floor_part = (int) rounded_f; + int one_decimal_part = floorf (10 * (rounded_f - floor_part) + .5f); return ms_strdup_printf(_("%d.%d"), floor_part, one_decimal_part); } -struct _reporting_metrics_st { +static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offset, const char *fmt, va_list args) { + belle_sip_error_code ret; + size_t prevoffset = *offset; + +#ifndef WIN32 + va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/ + va_copy(cap,args); + ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, cap); + va_end(cap); +#else + ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, args); +#endif + + // if we are out of memory, we add some size to buffer + if (ret == BELLE_SIP_BUFFER_OVERFLOW) { + ms_warning("Buffer was too small to contain the whole report - doubling its size from %lu to %lu", *buff_size, 2 * *buff_size); + *buff_size += 2048; + *buff = (char *) ms_realloc(*buff, *buff_size); + + *offset = prevoffset; + // recall myself since we did not write all things into the buffer but + // only part of it + append_to_buffer_valist(buff, buff_size, offset, fmt, args); + } +} + +static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + append_to_buffer_valist(buff, buff_size, offset, fmt, args); + va_end(args); +} + + +struct _reporting_addr_st { + char * ip; + int port; + uint32_t ssrc; +}; + +struct _reporting_content_metrics_st { + // timestamps - mandatory time_t ts_start; time_t ts_stop; + // session description - optional int sd_pt; char * sd_pd; int sd_sr; @@ -52,31 +98,37 @@ struct _reporting_metrics_st { int sd_plc; char * sd_ssup; + // jitter buffet - optional int jb_jba; int jb_jbr; int jb_jbn; int jb_jbm; int jb_jbx; + // packet loss - optional float pl_nlr; float pl_jdr; + // burst gap loss - optional int bgl_bld; int bgl_bd; float bgl_gld; int bgl_gd; int bgl_gmin; + // delay - optional int d_rtd; int d_esd; int d_sowd; int d_iaj; int d_maj; + // signal - optional int s_sl; int s_nl; int s_rerl; + // quality estimates - optional int qe_rlq; int qe_rcq; int qe_extri; @@ -85,43 +137,66 @@ struct _reporting_metrics_st { char * qe_qoeestalg; }; -static char * add_metrics(char * dest, struct _reporting_metrics_st rm) { - char * tmp = dest; +struct _reporting_session_report_st { + struct { + char * call_id; + char * local_id; + char * remote_id; + char * orig_id; + struct _reporting_addr_st local_addr; + struct _reporting_addr_st remote_addr; + char * local_group; + char * remote_group; - dest = ms_strdup_printf(_("%sTimestamps:START=%s STOP=%s\r\n"), tmp, + char * local_mac_addr; // optional + char * remote_mac_addr; // optional + } info; + + struct _reporting_content_metrics_st local_metrics; + struct _reporting_content_metrics_st remote_metrics; // optional + + char * dialog_id; // optional +}; + +struct _reporting_session_report_st get_stats(LinphoneCall * call) { + struct _reporting_session_report_st stats = {{0}}; + stats.info.local_addr.ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); + stats.info.remote_addr.ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); + stats.info.call_id = call->log->call_id; + if (call->dir == LinphoneCallIncoming) { + stats.info.remote_id = linphone_address_as_string(call->log->from); + stats.info.local_id = linphone_address_as_string(call->log->to); + stats.info.orig_id = stats.info.remote_id; + } else { + stats.info.remote_id = linphone_address_as_string(call->log->to); + stats.info.local_id = linphone_address_as_string(call->log->from); + stats.info.orig_id = stats.info.local_id; + } + stats.local_metrics.ts_start = call->log->start_date_time; + stats.local_metrics.ts_stop = call->log->start_date_time + linphone_call_get_duration(call); + + return stats; +} + + +static void add_metrics(char ** buffer, size_t * size, size_t * offset, struct _reporting_content_metrics_st rm) { + append_to_buffer(buffer, size, offset, "Timestamps:START=%s STOP=%s\r\n", linphone_timestamp_to_rfc3339_string(rm.ts_start), linphone_timestamp_to_rfc3339_string(rm.ts_stop)); - ms_free(tmp); - tmp = dest; - dest = ms_strdup_printf(_("%sSessionDesc:PT=%d PD=%s SR=%d FD=%d FO=%d FPP=%d PPS=%d FMTP=%s PLC=%d SSUP=%s\r\n"), - tmp, rm.sd_pt, rm.sd_pd, rm.sd_sr, rm.sd_fd, rm.sd_fo, rm.sd_fpp, rm.sd_pps, rm.sd_fmtp, rm.sd_plc, rm.sd_ssup); - ms_free(tmp); - tmp = dest; - dest = ms_strdup_printf(_("%sJitterBuffer:JBA=%d JBR=%d JBN=%d JBM=%d JBX=%d\r\n"), - tmp, rm.jb_jba, rm.jb_jbr, rm.jb_jbn, rm.jb_jbm, rm.jb_jbx); - ms_free(tmp); - tmp = dest; - dest = ms_strdup_printf(_("%sPacketLoss:NLR=%s JDR=%s\r\n"), - tmp, float_to_one_decimal_string(rm.pl_nlr), float_to_one_decimal_string(rm.pl_jdr)); - ms_free(tmp); - tmp = dest; - dest = ms_strdup_printf(_("%sBurstGapLoss:BLD=%d BD=%d GLD=%s GD=%d GMIN=%d\r\n"), - tmp, rm.bgl_bld, rm.bgl_bd, float_to_one_decimal_string(rm.bgl_gld), rm.bgl_gd, rm.bgl_gmin); - ms_free(tmp); - tmp = dest; - dest = ms_strdup_printf(_("%sDelay:RTD=%d ESD=%d SOWD=%d IAJ=%d MAJ=%d\r\n"), - tmp, rm.d_rtd, rm.d_esd, rm.d_sowd, rm.d_iaj, rm.d_maj); - ms_free(tmp); - tmp = dest; - dest = ms_strdup_printf(_("%sSignal:SL=%d NL=%d RERL=%d\r\n"), - tmp, rm.s_sl, rm.s_nl, rm.s_rerl); - ms_free(tmp); - tmp = dest; - dest = ms_strdup_printf(_("%sQualityEst:RLQ=%d RCQ=%d EXTRI=%d MOSLQ=%s MOSCQ=%s QoEEstAlg=%s\r\n"), - tmp, rm.qe_rlq, rm.qe_rcq, rm.qe_extri, float_to_one_decimal_string(rm.qe_moslq), float_to_one_decimal_string(rm.qe_moscq), rm.qe_qoeestalg); - ms_free(tmp); - - return dest; + append_to_buffer(buffer, size, offset, "SessionDesc:PT=%d PD=%s SR=%d FD=%d FO=%d FPP=%d PPS=%d FMTP=%s PLC=%d SSUP=%s\r\n", + rm.sd_pt, rm.sd_pd, rm.sd_sr, rm.sd_fd, rm.sd_fo, rm.sd_fpp, rm.sd_pps, rm.sd_fmtp, rm.sd_plc, rm.sd_ssup); + append_to_buffer(buffer, size, offset, "JitterBuffer:JBA=%d JBR=%d JBN=%d JBM=%d JBX=%d\r\n", + rm.jb_jba, rm.jb_jbr, rm.jb_jbn, rm.jb_jbm, rm.jb_jbx); + append_to_buffer(buffer, size, offset, "PacketLoss:NLR=%s JDR=%s\r\n", + float_to_one_decimal_string(rm.pl_nlr), float_to_one_decimal_string(rm.pl_jdr)); + append_to_buffer(buffer, size, offset, "BurstGapLoss:BLD=%d BD=%d GLD=%s GD=%d GMIN=%d\r\n", + rm.bgl_bld, rm.bgl_bd, float_to_one_decimal_string(rm.bgl_gld), rm.bgl_gd, rm.bgl_gmin); + append_to_buffer(buffer, size, offset, "Delay:RTD=%d ESD=%d SOWD=%d IAJ=%d MAJ=%d\r\n", + rm.d_rtd, rm.d_esd, rm.d_sowd, rm.d_iaj, rm.d_maj); + append_to_buffer(buffer, size, offset, "Signal:SL=%d NL=%d RERL=%d\r\n", + rm.s_sl, rm.s_nl, rm.s_rerl); + append_to_buffer(buffer, size, offset, "QualityEst:RLQ=%d RCQ=%d EXTRI=%d MOSLQ=%s MOSCQ=%s QoEEstAlg=%s\r\n", + rm.qe_rlq, rm.qe_rcq, rm.qe_extri, float_to_one_decimal_string(rm.qe_moslq), float_to_one_decimal_string(rm.qe_moscq), rm.qe_qoeestalg); } void linphone_quality_reporting_submit(LinphoneCall* call) { @@ -131,62 +206,43 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { // to: collector@sip.linphone.com // executed AFTER BYE's "OK" response has been received // expires value? - // un envoi à faire par stream ? (ssrc différent pour chaque stream) - // memory leaks - // belle_sip_snprintf - //ex RERL 404 code différent potentiellement avec info manquante + // one send by stream (different ssrc) + // memory leaks strings - append_to_buffer + // ex RERL 404 code différent potentiellement avec info manquante // 3611 pour savoir les valeurs pour les champs non disponibles LinphoneContent content = {0}; LinphoneAddress *addr; int expires = 3600; - const char *local_ip = "TODO";//stream dependentcall->localdesc->addr; //or call->localip ? - const char *remote_ip = "TODO"; - int local_port = 0; //TODO - int remote_port = 0;//linphone_address_get_port(linphone_call_get_remote_address(call)); - uint32_t local_ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); - uint32_t remote_ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); - struct _reporting_metrics_st local_metrics = {0}; - struct _reporting_metrics_st remote_metrics = {0}; - - const char *remote_identity; - const char *local_identity; - const char *orig_identity; - if (call->dir == LinphoneCallIncoming) { - remote_identity = linphone_address_as_string(call->log->from); - local_identity = linphone_address_as_string(call->log->to); - orig_identity = remote_identity; - } else { - remote_identity = linphone_address_as_string(call->log->to); - local_identity = linphone_address_as_string(call->log->from); - orig_identity = local_identity; - } - - ms_message("Submitting PUBLISH packet for call between %s and %s", local_identity, remote_identity); - + struct _reporting_session_report_st stats = get_stats(call); + size_t offset = 0; + size_t size = 2048; + char * buffer = (char *) malloc(sizeof(char) * size); content.type = ms_strdup("application"); content.subtype = ms_strdup("vq-rtcpxr"); - content.data = ms_strdup_printf(_("VQSessionReport: CallTerm\r\n")); - content.data = ms_strdup_printf(_("%sCallID: %s\r\n"), content.data, call->log->call_id); - content.data = ms_strdup_printf(_("%sLocalID: %s\r\n"), content.data, local_identity); - content.data = ms_strdup_printf(_("%sRemoteID: %s\r\n"), content.data, remote_identity); - content.data = ms_strdup_printf(_("%sOrigID: %s\r\n"), content.data, orig_identity); - // content.data = ms_strdup_printf(_("%sLocalGroup: %s\r\n"), content.data, "TO_DO"); - // content.data = ms_strdup_printf(_("%sRemoteGroup: %s\r\n"), content.data, "TO_DO"); - content.data = ms_strdup_printf(_("%sLocalAddr: IP=%s PORT=%d SSRC=%d\r\n"), content.data, local_ip, local_port, local_ssrc); - // content.data = ms_strdup_printf(_("%sLocalMAC: %s\r\n"), content.data, "TO_DO"); - content.data = ms_strdup_printf(_("%sRemoteAddr: IP=%s PORT=%d SSRC=%d\r\n"), content.data, remote_ip, remote_port, remote_ssrc); - // content.data = ms_strdup_printf(_("%sRemoteMAC: %s\r\n"), content.data, "TO_DO"); + append_to_buffer(&buffer, &size, &offset, "VQSessionReport: CallTerm\r\n"); + append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", stats.info.call_id); + append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", stats.info.local_id); + append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", stats.info.remote_id); + append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", stats.info.orig_id); + + append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", stats.info.local_group); + append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", stats.info.remote_group); + append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", stats.info.local_addr.ip, stats.info.local_addr.port, stats.info.local_addr.ssrc); + append_to_buffer(&buffer, &size, &offset, "LocalMAC: %s\r\n", stats.info.local_mac_addr); + append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", stats.info.remote_addr.ip, stats.info.remote_addr.port, stats.info.remote_addr.ssrc); + append_to_buffer(&buffer, &size, &offset, "RemoteMAC: %s\r\n", stats.info.remote_mac_addr); - content.data = ms_strdup_printf(_("%sLocalMetrics:\r\n"), content.data); - local_metrics.ts_start = call->log->start_date_time; - local_metrics.ts_stop = call->log->start_date_time + call->log->duration; - content.data = add_metrics((char*)content.data, local_metrics); + append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); + add_metrics(&buffer, &size, &offset, stats.local_metrics); - content.data = ms_strdup_printf(_("%sRemoteMetrics:\r\n"), content.data); - remote_metrics.bgl_gld = 42.34f; - content.data = add_metrics((char*)content.data, remote_metrics); - content.data = ms_strdup_printf(_("%sDialogID: %s\r\n"), content.data, "TO_DO"); + append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); + add_metrics(&buffer, &size, &offset, stats.remote_metrics); + if (stats.dialog_id != NULL) { + append_to_buffer(&buffer, &size, &offset, "DialogID: %s\r\n", stats.dialog_id); + } + + content.data = buffer; // for debug purpose only PRINT(content.data); From b32e79218d93059be61486b56cef9d49d87224eb Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Wed, 9 Apr 2014 16:03:09 +0200 Subject: [PATCH 13/83] Quality reporting: added all fields and a bit of refactoring --- coreapi/quality_reporting.c | 159 ++++++++++++++++++++++++------------ 1 file changed, 105 insertions(+), 54 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index cee2d8a4a..f07b363ff 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -83,58 +83,85 @@ struct _reporting_addr_st { struct _reporting_content_metrics_st { // timestamps - mandatory - time_t ts_start; - time_t ts_stop; + struct { + time_t start; + time_t stop; + } timestamps; // session description - optional - int sd_pt; - char * sd_pd; - int sd_sr; - int sd_fd; - int sd_fo; - int sd_fpp; - int sd_pps; - char * sd_fmtp; - int sd_plc; - char * sd_ssup; + struct { + int payload_type; + char * payload_desc; //mime type + int sample_rate; //clock rate + int frame_duration; //(no) ptime? à vérifier - audio only + int frame_ocets; //no + int frames_per_sec; //no + int packets_per_sec; //no + char * fmtp; //pt.recv_fmtp + int packet_loss_concealment; //voip metrics - audio only + char * silence_suppression_state; //no + } session_description; // jitter buffet - optional - int jb_jba; - int jb_jbr; - int jb_jbn; - int jb_jbm; - int jb_jbx; + struct { + int adaptive; // constant + int rate; // constant + int nominal; // no may vary during the call <- average? worst score? + int max; // no may vary during the call <- average? + int abs_max; // constant + } jitter_buffer; // packet loss - optional - float pl_nlr; - float pl_jdr; + struct { + float network_packet_loss_rate; // voip metrics (loss rate) + conversion + float jitter_buffer_discard_rate; //idem + } packet_loss; - // burst gap loss - optional - int bgl_bld; - int bgl_bd; - float bgl_gld; - int bgl_gd; - int bgl_gmin; + // burst gap loss - optional + // (no) currently not implemented + struct { + int burst_loss_density; + int burst_duration; + float gap_loss_density; + int gap_Duration; + int min_gap_threshold; + } burst_gap_loss; // delay - optional - int d_rtd; - int d_esd; - int d_sowd; - int d_iaj; - int d_maj; + struct { + int round_trip_delay; // no - vary + int end_system_delay; // no - not implemented yet + int one_way_delay; // no + int symm_one_way_delay; // no - vary (depends on round_trip_delay) + not implemented (depends on end_system_delay) + int interarrival_jitter; // no - not implemented yet + int mean_abs_jitter; // (no)? - to check + } delay; // signal - optional - int s_sl; - int s_nl; - int s_rerl; + struct { + int level; // no - vary + int noise_level; // no - vary + int residual_echo_return_loss; // no + } signal; // quality estimates - optional - int qe_rlq; - int qe_rcq; - int qe_extri; - float qe_moslq; - float qe_moscq; - char * qe_qoeestalg; + struct { + int rlq; // linked to moslq + int rcq; //voip metrics R factor - no - vary or avg + float moslq; // no - vary or avg - voip metrics + float moscq; // no - vary or avg - voip metrics + + + int extri; // no + int extro; // no + char * rlqestalg; // no to all alg + char * rcqestalg; + char * moslqestalg; + char * moscqestalg; + char * extriestalg; + char * extroutestalg; + char * qoestalg; + } quality_estimates; }; struct _reporting_session_report_st { @@ -161,8 +188,19 @@ struct _reporting_session_report_st { struct _reporting_session_report_st get_stats(LinphoneCall * call) { struct _reporting_session_report_st stats = {{0}}; stats.info.local_addr.ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); + stats.info.local_addr.port = rtp_session_get_local_port(call->audiostream->ms.session); stats.info.remote_addr.ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); + // remote address rem_addr stats.info.call_id = call->log->call_id; + // pour l'ip: itérer sur les streams pour trouver le bon type + // call->resultdesc->streams[0].type + // call->resultdesc->streams[0].rtp_addr + + // const rtp_stats_t * rtp_stats = rtp_session_get_stats(call->audiostream->ms.session); + // rtp_stats-> + + stats.local_metrics.session_description.payload_type = call->params.audio_codec->type; + if (call->dir == LinphoneCallIncoming) { stats.info.remote_id = linphone_address_as_string(call->log->from); stats.info.local_id = linphone_address_as_string(call->log->to); @@ -172,8 +210,8 @@ struct _reporting_session_report_st get_stats(LinphoneCall * call) { stats.info.local_id = linphone_address_as_string(call->log->from); stats.info.orig_id = stats.info.local_id; } - stats.local_metrics.ts_start = call->log->start_date_time; - stats.local_metrics.ts_stop = call->log->start_date_time + linphone_call_get_duration(call); + stats.local_metrics.timestamps.start = call->log->start_date_time; + stats.local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); return stats; } @@ -181,22 +219,35 @@ struct _reporting_session_report_st get_stats(LinphoneCall * call) { static void add_metrics(char ** buffer, size_t * size, size_t * offset, struct _reporting_content_metrics_st rm) { append_to_buffer(buffer, size, offset, "Timestamps:START=%s STOP=%s\r\n", - linphone_timestamp_to_rfc3339_string(rm.ts_start), - linphone_timestamp_to_rfc3339_string(rm.ts_stop)); + linphone_timestamp_to_rfc3339_string(rm.timestamps.start), + linphone_timestamp_to_rfc3339_string(rm.timestamps.stop)); append_to_buffer(buffer, size, offset, "SessionDesc:PT=%d PD=%s SR=%d FD=%d FO=%d FPP=%d PPS=%d FMTP=%s PLC=%d SSUP=%s\r\n", - rm.sd_pt, rm.sd_pd, rm.sd_sr, rm.sd_fd, rm.sd_fo, rm.sd_fpp, rm.sd_pps, rm.sd_fmtp, rm.sd_plc, rm.sd_ssup); + rm.session_description.payload_type, rm.session_description.payload_desc, rm.session_description.sample_rate, + rm.session_description.frame_duration, rm.session_description.frame_ocets, rm.session_description.frames_per_sec, + rm.session_description.packets_per_sec, rm.session_description.fmtp, rm.session_description.packet_loss_concealment, + rm.session_description.silence_suppression_state); append_to_buffer(buffer, size, offset, "JitterBuffer:JBA=%d JBR=%d JBN=%d JBM=%d JBX=%d\r\n", - rm.jb_jba, rm.jb_jbr, rm.jb_jbn, rm.jb_jbm, rm.jb_jbx); + rm.jitter_buffer.adaptive, rm.jitter_buffer.rate, rm.jitter_buffer.nominal, rm.jitter_buffer.max, rm.jitter_buffer.abs_max); append_to_buffer(buffer, size, offset, "PacketLoss:NLR=%s JDR=%s\r\n", - float_to_one_decimal_string(rm.pl_nlr), float_to_one_decimal_string(rm.pl_jdr)); + float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate), + float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate)); append_to_buffer(buffer, size, offset, "BurstGapLoss:BLD=%d BD=%d GLD=%s GD=%d GMIN=%d\r\n", - rm.bgl_bld, rm.bgl_bd, float_to_one_decimal_string(rm.bgl_gld), rm.bgl_gd, rm.bgl_gmin); - append_to_buffer(buffer, size, offset, "Delay:RTD=%d ESD=%d SOWD=%d IAJ=%d MAJ=%d\r\n", - rm.d_rtd, rm.d_esd, rm.d_sowd, rm.d_iaj, rm.d_maj); + rm.burst_gap_loss.burst_loss_density, rm.burst_gap_loss.burst_duration, + float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density), rm.burst_gap_loss.gap_Duration, + rm.burst_gap_loss.min_gap_threshold); + append_to_buffer(buffer, size, offset, "Delay:RTD=%d ESD=%d OWD=%d SOWD=%d IAJ=%d MAJ=%d\r\n", + rm.delay.round_trip_delay, rm.delay.end_system_delay, rm.delay.one_way_delay, rm.delay.symm_one_way_delay, + rm.delay.interarrival_jitter, rm.delay.mean_abs_jitter); append_to_buffer(buffer, size, offset, "Signal:SL=%d NL=%d RERL=%d\r\n", - rm.s_sl, rm.s_nl, rm.s_rerl); - append_to_buffer(buffer, size, offset, "QualityEst:RLQ=%d RCQ=%d EXTRI=%d MOSLQ=%s MOSCQ=%s QoEEstAlg=%s\r\n", - rm.qe_rlq, rm.qe_rcq, rm.qe_extri, float_to_one_decimal_string(rm.qe_moslq), float_to_one_decimal_string(rm.qe_moscq), rm.qe_qoeestalg); + rm.signal.level, rm.signal.noise_level, rm.signal.residual_echo_return_loss); + append_to_buffer(buffer, size, offset, "QualityEst:RLQ=%d RLQEstAlg=%s RCQ=%d RCQEstAlgo=%s EXTRI=%d ExtRIEstAlg=%s EXTRO=%d ExtROEstAlg=%s MOSLQ=%s MOSLQEstAlgo=%s MOSCQ=%s MOSCQEstAlgo=%s QoEEstAlg=%s\r\n", + rm.quality_estimates.rlq, rm.quality_estimates.rlqestalg, + rm.quality_estimates.rcq, rm.quality_estimates.rcqestalg, + rm.quality_estimates.extri, rm.quality_estimates.extriestalg, + rm.quality_estimates.extro, rm.quality_estimates.extroutestalg, + float_to_one_decimal_string(rm.quality_estimates.moslq), rm.quality_estimates.moslqestalg, + float_to_one_decimal_string(rm.quality_estimates.moscq), rm.quality_estimates.moscqestalg, + rm.quality_estimates.qoestalg); } void linphone_quality_reporting_submit(LinphoneCall* call) { @@ -226,8 +277,8 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", stats.info.remote_id); append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", stats.info.orig_id); - append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", stats.info.local_group); - append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", stats.info.remote_group); + append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", stats.info.local_group); //linphone-CALLID + append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", stats.info.remote_group); //idem append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", stats.info.local_addr.ip, stats.info.local_addr.port, stats.info.local_addr.ssrc); append_to_buffer(&buffer, &size, &offset, "LocalMAC: %s\r\n", stats.info.local_mac_addr); append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", stats.info.remote_addr.ip, stats.info.remote_addr.port, stats.info.remote_addr.ssrc); From e6524c1d8f035ed5bf12c1874738fa13e2632231 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 10 Apr 2014 11:24:54 +0200 Subject: [PATCH 14/83] Quality reporting: filling some available fields from reporting struct --- coreapi/quality_reporting.c | 120 +++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 37 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index f07b363ff..84271287d 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -27,6 +27,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +/*************************************************************************** + * TODO / REMINDER LIST + ****************************************************************************/ + // example at http://tools.ietf.org/html/rfc6035#section-4.7.3 + // only if this is a linphone account + // only if call succeeded + // executed AFTER BYE's "OK" response has been received + // to: collector@sip.linphone.com or not + // expires value? + // one send by stream (different ssrc) + // ex RERL 404 code différent potentiellement avec info manquante + // 3611 pour savoir les valeurs pour les champs non disponibles + // video : que se passe t-il si on arrete / resume la vidéo + // memory leaks + #define PRINT2(x, f) printf(#x ": " #f "\n", x) #define PRINT(x) PRINT2(x, "%s") @@ -45,14 +60,14 @@ static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offs belle_sip_error_code ret; size_t prevoffset = *offset; -#ifndef WIN32 + #ifndef WIN32 va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/ va_copy(cap,args); ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, cap); va_end(cap); -#else + #else ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, args); -#endif + #endif // if we are out of memory, we add some size to buffer if (ret == BELLE_SIP_BUFFER_OVERFLOW) { @@ -62,7 +77,7 @@ static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offs *offset = prevoffset; // recall myself since we did not write all things into the buffer but - // only part of it + // only a part of it append_to_buffer_valist(buff, buff_size, offset, fmt, args); } } @@ -91,15 +106,15 @@ struct _reporting_content_metrics_st { // session description - optional struct { int payload_type; - char * payload_desc; //mime type - int sample_rate; //clock rate - int frame_duration; //(no) ptime? à vérifier - audio only - int frame_ocets; //no - int frames_per_sec; //no - int packets_per_sec; //no - char * fmtp; //pt.recv_fmtp - int packet_loss_concealment; //voip metrics - audio only - char * silence_suppression_state; //no + char * payload_desc; // mime type + int sample_rate; // clock rate + int frame_duration; // to check (ptime?) - audio only + int frame_ocets; // no + int frames_per_sec; // no + int packets_per_sec; // no + char * fmtp; // pt.recv_fmtp + int packet_loss_concealment; // in voip metrics - audio only + char * silence_suppression_state; // no } session_description; // jitter buffet - optional @@ -146,10 +161,10 @@ struct _reporting_content_metrics_st { // quality estimates - optional struct { - int rlq; // linked to moslq - int rcq; //voip metrics R factor - no - vary or avg - float moslq; // no - vary or avg - voip metrics - float moscq; // no - vary or avg - voip metrics + int rlq; // linked to moslq - in [0..120] + int rcq; //voip metrics R factor - no - vary or avg in [0..120] + float moslq; // no - vary or avg - voip metrics - in [0..4.9] + float moscq; // no - vary or avg - voip metrics - in [0..4.9] int extri; // no @@ -197,9 +212,35 @@ struct _reporting_session_report_st get_stats(LinphoneCall * call) { // call->resultdesc->streams[0].rtp_addr // const rtp_stats_t * rtp_stats = rtp_session_get_stats(call->audiostream->ms.session); - // rtp_stats-> + const MSQualityIndicator * qi = media_stream_get_quality_indicator(&call->audiostream->ms); stats.local_metrics.session_description.payload_type = call->params.audio_codec->type; + stats.local_metrics.session_description.payload_desc = ms_strdup(call->params.audio_codec->mime_type); + stats.local_metrics.session_description.sample_rate = call->params.audio_codec->clock_rate; + stats.local_metrics.session_description.fmtp = ms_strdup(call->params.audio_codec->recv_fmtp); + //stats.local_metrics.session_description.packet_loss_concealment = ms_quality_indicator_get_local_late_rate(qi); + + stats.local_metrics.packet_loss.jitter_buffer_discard_rate = ms_quality_indicator_get_local_loss_rate(qi); + + stats.local_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); + if (10 <= stats.local_metrics.quality_estimates.rlq + && stats.local_metrics.quality_estimates.rlq <= 50) { + stats.local_metrics.quality_estimates.moslq = stats.local_metrics.quality_estimates.rlq / 10.f; + } else { + stats.local_metrics.quality_estimates.moslq = -1; + } + stats.local_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); + if (10 <= stats.local_metrics.quality_estimates.rcq + && stats.local_metrics.quality_estimates.rcq <= 50) { + stats.local_metrics.quality_estimates.moscq = stats.local_metrics.quality_estimates.rcq / 10.f; + } else { + stats.local_metrics.quality_estimates.moscq = -1; + } + + // NOT FOUND + // int packet_loss_concealment; // in voip metrics - audio only + // jitter buffer + // jitter_buffer_discard_rate if (call->dir == LinphoneCallIncoming) { stats.info.remote_id = linphone_address_as_string(call->log->from); @@ -216,11 +257,17 @@ struct _reporting_session_report_st get_stats(LinphoneCall * call) { return stats; } +static void add_metrics(char ** buffer, size_t * size, size_t * offset, struct _reporting_content_metrics_st rm) { + char * timpstamps_start_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.start); + char * timpstamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop); + char * network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate); + char * jitter_buffer_discard_rate_str = float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate); + char * gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density); + char * moslq_str = float_to_one_decimal_string(rm.quality_estimates.moslq); + char * moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq); -static void add_metrics(char ** buffer, size_t * size, size_t * offset, struct _reporting_content_metrics_st rm) { append_to_buffer(buffer, size, offset, "Timestamps:START=%s STOP=%s\r\n", - linphone_timestamp_to_rfc3339_string(rm.timestamps.start), - linphone_timestamp_to_rfc3339_string(rm.timestamps.stop)); + timpstamps_start_str, timpstamps_stop_str); append_to_buffer(buffer, size, offset, "SessionDesc:PT=%d PD=%s SR=%d FD=%d FO=%d FPP=%d PPS=%d FMTP=%s PLC=%d SSUP=%s\r\n", rm.session_description.payload_type, rm.session_description.payload_desc, rm.session_description.sample_rate, rm.session_description.frame_duration, rm.session_description.frame_ocets, rm.session_description.frames_per_sec, @@ -229,11 +276,11 @@ static void add_metrics(char ** buffer, size_t * size, size_t * offset, struct _ append_to_buffer(buffer, size, offset, "JitterBuffer:JBA=%d JBR=%d JBN=%d JBM=%d JBX=%d\r\n", rm.jitter_buffer.adaptive, rm.jitter_buffer.rate, rm.jitter_buffer.nominal, rm.jitter_buffer.max, rm.jitter_buffer.abs_max); append_to_buffer(buffer, size, offset, "PacketLoss:NLR=%s JDR=%s\r\n", - float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate), - float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate)); + network_packet_loss_rate_str, + jitter_buffer_discard_rate_str); append_to_buffer(buffer, size, offset, "BurstGapLoss:BLD=%d BD=%d GLD=%s GD=%d GMIN=%d\r\n", rm.burst_gap_loss.burst_loss_density, rm.burst_gap_loss.burst_duration, - float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density), rm.burst_gap_loss.gap_Duration, + gap_loss_density_str, rm.burst_gap_loss.gap_Duration, rm.burst_gap_loss.min_gap_threshold); append_to_buffer(buffer, size, offset, "Delay:RTD=%d ESD=%d OWD=%d SOWD=%d IAJ=%d MAJ=%d\r\n", rm.delay.round_trip_delay, rm.delay.end_system_delay, rm.delay.one_way_delay, rm.delay.symm_one_way_delay, @@ -245,29 +292,28 @@ static void add_metrics(char ** buffer, size_t * size, size_t * offset, struct _ rm.quality_estimates.rcq, rm.quality_estimates.rcqestalg, rm.quality_estimates.extri, rm.quality_estimates.extriestalg, rm.quality_estimates.extro, rm.quality_estimates.extroutestalg, - float_to_one_decimal_string(rm.quality_estimates.moslq), rm.quality_estimates.moslqestalg, - float_to_one_decimal_string(rm.quality_estimates.moscq), rm.quality_estimates.moscqestalg, + moslq_str, rm.quality_estimates.moslqestalg, + moscq_str, rm.quality_estimates.moscqestalg, rm.quality_estimates.qoestalg); + + free(timpstamps_start_str); + free(timpstamps_stop_str); + free(network_packet_loss_rate_str); + free(jitter_buffer_discard_rate_str); + free(gap_loss_density_str); + free(moslq_str); + free(moscq_str); } void linphone_quality_reporting_submit(LinphoneCall* call) { - // example at http://tools.ietf.org/html/rfc6035#section-4.7.3 - // only if this is a linphone account - // only if call succeeded - // to: collector@sip.linphone.com - // executed AFTER BYE's "OK" response has been received - // expires value? - // one send by stream (different ssrc) - // memory leaks strings - append_to_buffer - // ex RERL 404 code différent potentiellement avec info manquante - // 3611 pour savoir les valeurs pour les champs non disponibles LinphoneContent content = {0}; LinphoneAddress *addr; int expires = 3600; struct _reporting_session_report_st stats = get_stats(call); size_t offset = 0; size_t size = 2048; - char * buffer = (char *) malloc(sizeof(char) * size); + char * buffer = (char *) ms_malloc(size); + content.type = ms_strdup("application"); content.subtype = ms_strdup("vq-rtcpxr"); From 3c71544b24ef3f5421b2fd9bb789d9af59188b84 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 10 Apr 2014 12:58:08 +0200 Subject: [PATCH 15/83] Store reporting struct in linphone call --- coreapi/linphonecall.c | 3 + coreapi/private.h | 5 + coreapi/quality_reporting.c | 247 ++++++++++++------------------------ coreapi/quality_reporting.h | 112 ++++++++++++++++ 4 files changed, 200 insertions(+), 167 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index c095898ae..f9574f576 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1849,6 +1849,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna playfile=lc->play_file; recfile=lc->rec_file; call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); + call->audio_reporting=ms_new0(reporting_session_report_t,1); if (used_pt!=-1){ call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); @@ -1978,6 +1979,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,vstream->proto,SalVideo); call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt); + call->video_reporting=ms_new0(reporting_session_report_t,1); + if (used_pt!=-1){ VideoStreamDir dir=VideoStreamSendRecv; MSWebCam *cam=lc->video_conf.device; diff --git a/coreapi/private.h b/coreapi/private.h index e2feef54a..9e37f11b7 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -34,6 +34,7 @@ extern "C" { #include "linphonecore_utils.h" #include "sal/sal.h" #include "sipsetup.h" +#include "quality_reporting.h" #include #include @@ -191,6 +192,10 @@ struct _LinphoneCall StunCandidate ac,vc; /*audio video ip/port discovered by STUN*/ struct _AudioStream *audiostream; /**/ struct _VideoStream *videostream; + + reporting_session_report_t *audio_reporting; + reporting_session_report_t *video_reporting; + MSAudioEndpoint *endpoint; /*used for conferencing*/ char *refer_to; LinphoneCallParams params; diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 84271287d..5e82b4a96 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -89,152 +89,57 @@ static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, con va_end(args); } - -struct _reporting_addr_st { - char * ip; - int port; - uint32_t ssrc; -}; - -struct _reporting_content_metrics_st { - // timestamps - mandatory - struct { - time_t start; - time_t stop; - } timestamps; - - // session description - optional - struct { - int payload_type; - char * payload_desc; // mime type - int sample_rate; // clock rate - int frame_duration; // to check (ptime?) - audio only - int frame_ocets; // no - int frames_per_sec; // no - int packets_per_sec; // no - char * fmtp; // pt.recv_fmtp - int packet_loss_concealment; // in voip metrics - audio only - char * silence_suppression_state; // no - } session_description; - - // jitter buffet - optional - struct { - int adaptive; // constant - int rate; // constant - int nominal; // no may vary during the call <- average? worst score? - int max; // no may vary during the call <- average? - int abs_max; // constant - } jitter_buffer; - - // packet loss - optional - struct { - float network_packet_loss_rate; // voip metrics (loss rate) + conversion - float jitter_buffer_discard_rate; //idem - } packet_loss; - - // burst gap loss - optional - // (no) currently not implemented - struct { - int burst_loss_density; - int burst_duration; - float gap_loss_density; - int gap_Duration; - int min_gap_threshold; - } burst_gap_loss; - - // delay - optional - struct { - int round_trip_delay; // no - vary - int end_system_delay; // no - not implemented yet - int one_way_delay; // no - int symm_one_way_delay; // no - vary (depends on round_trip_delay) + not implemented (depends on end_system_delay) - int interarrival_jitter; // no - not implemented yet - int mean_abs_jitter; // (no)? - to check - } delay; - - // signal - optional - struct { - int level; // no - vary - int noise_level; // no - vary - int residual_echo_return_loss; // no - } signal; - - // quality estimates - optional - struct { - int rlq; // linked to moslq - in [0..120] - int rcq; //voip metrics R factor - no - vary or avg in [0..120] - float moslq; // no - vary or avg - voip metrics - in [0..4.9] - float moscq; // no - vary or avg - voip metrics - in [0..4.9] - - - int extri; // no - int extro; // no - char * rlqestalg; // no to all alg - char * rcqestalg; - char * moslqestalg; - char * moscqestalg; - char * extriestalg; - char * extroutestalg; - char * qoestalg; - } quality_estimates; -}; - -struct _reporting_session_report_st { - struct { - char * call_id; - char * local_id; - char * remote_id; - char * orig_id; - struct _reporting_addr_st local_addr; - struct _reporting_addr_st remote_addr; - char * local_group; - char * remote_group; - - char * local_mac_addr; // optional - char * remote_mac_addr; // optional - } info; - - struct _reporting_content_metrics_st local_metrics; - struct _reporting_content_metrics_st remote_metrics; // optional - - char * dialog_id; // optional -}; - -struct _reporting_session_report_st get_stats(LinphoneCall * call) { - struct _reporting_session_report_st stats = {{0}}; - stats.info.local_addr.ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); - stats.info.local_addr.port = rtp_session_get_local_port(call->audiostream->ms.session); - stats.info.remote_addr.ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); - // remote address rem_addr - stats.info.call_id = call->log->call_id; - // pour l'ip: itérer sur les streams pour trouver le bon type - // call->resultdesc->streams[0].type - // call->resultdesc->streams[0].rtp_addr - - // const rtp_stats_t * rtp_stats = rtp_session_get_stats(call->audiostream->ms.session); +reporting_session_report_t * update_stats(LinphoneCall * call) { + int count; + reporting_session_report_t * stats = call->audio_reporting; const MSQualityIndicator * qi = media_stream_get_quality_indicator(&call->audiostream->ms); + const PayloadType * payload; - stats.local_metrics.session_description.payload_type = call->params.audio_codec->type; - stats.local_metrics.session_description.payload_desc = ms_strdup(call->params.audio_codec->mime_type); - stats.local_metrics.session_description.sample_rate = call->params.audio_codec->clock_rate; - stats.local_metrics.session_description.fmtp = ms_strdup(call->params.audio_codec->recv_fmtp); - //stats.local_metrics.session_description.packet_loss_concealment = ms_quality_indicator_get_local_late_rate(qi); - - stats.local_metrics.packet_loss.jitter_buffer_discard_rate = ms_quality_indicator_get_local_loss_rate(qi); - - stats.local_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); - if (10 <= stats.local_metrics.quality_estimates.rlq - && stats.local_metrics.quality_estimates.rlq <= 50) { - stats.local_metrics.quality_estimates.moslq = stats.local_metrics.quality_estimates.rlq / 10.f; - } else { - stats.local_metrics.quality_estimates.moslq = -1; + if (stats == NULL) { + ms_warning("No reporting created for this stream"); + return NULL; } - stats.local_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); - if (10 <= stats.local_metrics.quality_estimates.rcq - && stats.local_metrics.quality_estimates.rcq <= 50) { - stats.local_metrics.quality_estimates.moscq = stats.local_metrics.quality_estimates.rcq / 10.f; + + stats->info.local_addr.ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); + stats->info.local_addr.port = rtp_session_get_local_port(call->audiostream->ms.session); + stats->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); + // memcpy(stats->info.remote_addr.ip, &call->audiostream->ms.session->rtp.rem_addr, call->audiostream->ms.session->rtp.rem_addrlen); + stats->info.call_id = call->log->call_id; + for (count = 0; count < call->resultdesc->n_total_streams; ++count) { + if (call->resultdesc->streams[count].type == SalAudio) { + stats->info.local_addr.ip = call->resultdesc->streams[count].rtp_addr; + break; + } + } + if (count == call->resultdesc->n_total_streams) { + ms_warning("Could not find the associated stream of type %d", SalAudio); + } + + payload = call->params.audio_codec; + if (payload != NULL) { + stats->local_metrics.session_description.payload_type = payload->type; + stats->local_metrics.session_description.payload_desc = ms_strdup(payload->mime_type); + stats->local_metrics.session_description.sample_rate = payload->clock_rate; + stats->local_metrics.session_description.fmtp = ms_strdup(payload->recv_fmtp); } else { - stats.local_metrics.quality_estimates.moscq = -1; + // ... + } + + //stats->local_metrics.session_description.packet_loss_concealment = ms_quality_indicator_get_local_late_rate(qi); + stats->local_metrics.packet_loss.jitter_buffer_discard_rate = ms_quality_indicator_get_local_loss_rate(qi); + stats->local_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); + if (10 <= stats->local_metrics.quality_estimates.rlq + && stats->local_metrics.quality_estimates.rlq <= 50) { + stats->local_metrics.quality_estimates.moslq = stats->local_metrics.quality_estimates.rlq / 10.f; + } else { + stats->local_metrics.quality_estimates.moslq = -1; + } + stats->local_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); + if (10 <= stats->local_metrics.quality_estimates.rcq + && stats->local_metrics.quality_estimates.rcq <= 50) { + stats->local_metrics.quality_estimates.moscq = stats->local_metrics.quality_estimates.rcq / 10.f; + } else { + stats->local_metrics.quality_estimates.moscq = -1; } // NOT FOUND @@ -243,21 +148,21 @@ struct _reporting_session_report_st get_stats(LinphoneCall * call) { // jitter_buffer_discard_rate if (call->dir == LinphoneCallIncoming) { - stats.info.remote_id = linphone_address_as_string(call->log->from); - stats.info.local_id = linphone_address_as_string(call->log->to); - stats.info.orig_id = stats.info.remote_id; + stats->info.remote_id = linphone_address_as_string(call->log->from); + stats->info.local_id = linphone_address_as_string(call->log->to); + stats->info.orig_id = stats->info.remote_id; } else { - stats.info.remote_id = linphone_address_as_string(call->log->to); - stats.info.local_id = linphone_address_as_string(call->log->from); - stats.info.orig_id = stats.info.local_id; + stats->info.remote_id = linphone_address_as_string(call->log->to); + stats->info.local_id = linphone_address_as_string(call->log->from); + stats->info.orig_id = stats->info.local_id; } - stats.local_metrics.timestamps.start = call->log->start_date_time; - stats.local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + stats->local_metrics.timestamps.start = call->log->start_date_time; + stats->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); return stats; } -static void add_metrics(char ** buffer, size_t * size, size_t * offset, struct _reporting_content_metrics_st rm) { +static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, reporting_content_metrics_t rm) { char * timpstamps_start_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.start); char * timpstamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop); char * network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate); @@ -309,34 +214,42 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { LinphoneContent content = {0}; LinphoneAddress *addr; int expires = 3600; - struct _reporting_session_report_st stats = get_stats(call); + reporting_session_report_t *stats = update_stats(call); size_t offset = 0; size_t size = 2048; - char * buffer = (char *) ms_malloc(size); + char * buffer; + + // Somehow the reporting was not created, hence no need to go further + if (stats == NULL) { + PRINT("STATS ARE NULL!"); + return; + } + + buffer = (char *) ms_malloc(size); content.type = ms_strdup("application"); content.subtype = ms_strdup("vq-rtcpxr"); append_to_buffer(&buffer, &size, &offset, "VQSessionReport: CallTerm\r\n"); - append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", stats.info.call_id); - append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", stats.info.local_id); - append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", stats.info.remote_id); - append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", stats.info.orig_id); + append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", stats->info.call_id); + append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", stats->info.local_id); + append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", stats->info.remote_id); + append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", stats->info.orig_id); - append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", stats.info.local_group); //linphone-CALLID - append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", stats.info.remote_group); //idem - append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", stats.info.local_addr.ip, stats.info.local_addr.port, stats.info.local_addr.ssrc); - append_to_buffer(&buffer, &size, &offset, "LocalMAC: %s\r\n", stats.info.local_mac_addr); - append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", stats.info.remote_addr.ip, stats.info.remote_addr.port, stats.info.remote_addr.ssrc); - append_to_buffer(&buffer, &size, &offset, "RemoteMAC: %s\r\n", stats.info.remote_mac_addr); + append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", stats->info.local_group); //linphone-CALLID + append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", stats->info.remote_group); //idem + append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", stats->info.local_addr.ip, stats->info.local_addr.port, stats->info.local_addr.ssrc); + append_to_buffer(&buffer, &size, &offset, "LocalMAC: %s\r\n", stats->info.local_mac_addr); + append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", stats->info.remote_addr.ip, stats->info.remote_addr.port, stats->info.remote_addr.ssrc); + append_to_buffer(&buffer, &size, &offset, "RemoteMAC: %s\r\n", stats->info.remote_mac_addr); append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); - add_metrics(&buffer, &size, &offset, stats.local_metrics); + append_metrics_to_buffer(&buffer, &size, &offset, stats->local_metrics); append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); - add_metrics(&buffer, &size, &offset, stats.remote_metrics); - if (stats.dialog_id != NULL) { - append_to_buffer(&buffer, &size, &offset, "DialogID: %s\r\n", stats.dialog_id); + append_metrics_to_buffer(&buffer, &size, &offset, stats->remote_metrics); + if (stats->dialog_id != NULL) { + append_to_buffer(&buffer, &size, &offset, "DialogID: %s\r\n", stats->dialog_id); } content.data = buffer; diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index f56d2b1bd..b8b1a42e4 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -25,6 +25,118 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef __cplusplus extern "C"{ #endif + +typedef struct reporting_addr { + char * ip; + int port; + uint32_t ssrc; +} reporting_addr_t; + +typedef struct reporting_content_metrics { + // timestamps - mandatory + struct { + time_t start; + time_t stop; + } timestamps; + + // session description - optional + struct { + int payload_type; + char * payload_desc; // mime type + int sample_rate; // clock rate + int frame_duration; // to check (ptime?) - audio only + int frame_ocets; // no + int frames_per_sec; // no + int packets_per_sec; // no + char * fmtp; // pt.recv_fmtp + int packet_loss_concealment; // in voip metrics - audio only + char * silence_suppression_state; // no + } session_description; + + // jitter buffet - optional + struct { + int adaptive; // constant + int rate; // constant + int nominal; // no may vary during the call <- average? worst score? + int max; // no may vary during the call <- average? + int abs_max; // constant + } jitter_buffer; + + // packet loss - optional + struct { + float network_packet_loss_rate; // voip metrics (loss rate) + conversion + float jitter_buffer_discard_rate; //idem + } packet_loss; + + // burst gap loss - optional + // (no) currently not implemented + struct { + int burst_loss_density; + int burst_duration; + float gap_loss_density; + int gap_Duration; + int min_gap_threshold; + } burst_gap_loss; + + // delay - optional + struct { + int round_trip_delay; // no - vary + int end_system_delay; // no - not implemented yet + int one_way_delay; // no + int symm_one_way_delay; // no - vary (depends on round_trip_delay) + not implemented (depends on end_system_delay) + int interarrival_jitter; // no - not implemented yet + int mean_abs_jitter; // (no)? - to check + } delay; + + // signal - optional + struct { + int level; // no - vary + int noise_level; // no - vary + int residual_echo_return_loss; // no + } signal; + + // quality estimates - optional + struct { + int rlq; // linked to moslq - in [0..120] + int rcq; //voip metrics R factor - no - vary or avg in [0..120] + float moslq; // no - vary or avg - voip metrics - in [0..4.9] + float moscq; // no - vary or avg - voip metrics - in [0..4.9] + + + int extri; // no + int extro; // no + char * rlqestalg; // no to all alg + char * rcqestalg; + char * moslqestalg; + char * moscqestalg; + char * extriestalg; + char * extroutestalg; + char * qoestalg; + } quality_estimates; +} reporting_content_metrics_t; + +typedef struct reporting_session_report { + struct { + char * call_id; + char * local_id; + char * remote_id; + char * orig_id; + reporting_addr_t local_addr; + reporting_addr_t remote_addr; + char * local_group; + char * remote_group; + + char * local_mac_addr; // optional + char * remote_mac_addr; // optional + } info; + + reporting_content_metrics_t local_metrics; + reporting_content_metrics_t remote_metrics; // optional + + char * dialog_id; // optional +} reporting_session_report_t; + + void linphone_quality_reporting_submit(LinphoneCall* call); #ifdef __cplusplus From 0200eb2213dae5d1fc613f18ddf2cd4d37de89bd Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 10 Apr 2014 16:04:48 +0200 Subject: [PATCH 16/83] Quality reporting: remove unimplemented fields and split content filling to an one-field-at-a-time process --- coreapi/linphonecall.c | 8 +- coreapi/linphonecore.c | 2 +- coreapi/private.h | 3 +- coreapi/quality_reporting.c | 289 +++++++++++++++++++++++++----------- coreapi/quality_reporting.h | 38 ++--- 5 files changed, 227 insertions(+), 113 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index f9574f576..d1e2d15b7 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1849,7 +1849,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna playfile=lc->play_file; recfile=lc->rec_file; call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); - call->audio_reporting=ms_new0(reporting_session_report_t,1); + call->reports[LINPHONE_CALL_STATS_AUDIO]=ms_new0(reporting_session_report_t,1); if (used_pt!=-1){ call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); @@ -1979,7 +1979,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,vstream->proto,SalVideo); call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt); - call->video_reporting=ms_new0(reporting_session_report_t,1); + call->reports[LINPHONE_CALL_STATS_VIDEO]=ms_new0(reporting_session_report_t,1); if (used_pt!=-1){ VideoStreamDir dir=VideoStreamSendRecv; @@ -2752,6 +2752,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse evd->packet = NULL; call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); + linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { @@ -2762,6 +2763,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse evd->packet = NULL; call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); + linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) @@ -2797,6 +2799,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse evd->packet = NULL; call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); + linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_AUDIO); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { @@ -2807,6 +2810,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse evd->packet = NULL; call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); + linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_AUDIO); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 23090baba..12078604b 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3470,7 +3470,7 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ /*stop ringing*/ linphone_core_stop_ringing(lc); - linphone_quality_reporting_submit(call); + linphone_reporting_publish(call, LINPHONE_CALL_STATS_AUDIO); linphone_call_stop_media_streams(call); diff --git a/coreapi/private.h b/coreapi/private.h index 9e37f11b7..4d32a23e6 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -193,8 +193,7 @@ struct _LinphoneCall struct _AudioStream *audiostream; /**/ struct _VideoStream *videostream; - reporting_session_report_t *audio_reporting; - reporting_session_report_t *video_reporting; + reporting_session_report_t * reports[2]; MSAudioEndpoint *endpoint; /*used for conferencing*/ char *refer_to; diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 5e82b4a96..dc1b1c511 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -40,7 +40,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // ex RERL 404 code différent potentiellement avec info manquante // 3611 pour savoir les valeurs pour les champs non disponibles // video : que se passe t-il si on arrete / resume la vidéo - // memory leaks + // memory leaks + char* strdup + // bouger l'appel de fonction au bon endroit (si c l'autre qui raccroche on envoi pas les données là) #define PRINT2(x, f) printf(#x ": " #f "\n", x) #define PRINT(x) PRINT2(x, "%s") @@ -89,79 +90,90 @@ static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, con va_end(args); } -reporting_session_report_t * update_stats(LinphoneCall * call) { +static reporting_session_report_t * update_report(LinphoneCall * call, int stats_type) { int count; - reporting_session_report_t * stats = call->audio_reporting; - const MSQualityIndicator * qi = media_stream_get_quality_indicator(&call->audiostream->ms); + reporting_session_report_t * report = call->reports[stats_type]; + MediaStream stream; + const MSQualityIndicator * qi = NULL; const PayloadType * payload; + RtpSession * session = NULL; - if (stats == NULL) { + + if (report == NULL) { ms_warning("No reporting created for this stream"); return NULL; } - stats->info.local_addr.ssrc = rtp_session_get_send_ssrc(call->audiostream->ms.session); - stats->info.local_addr.port = rtp_session_get_local_port(call->audiostream->ms.session); - stats->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(call->audiostream->ms.session); - // memcpy(stats->info.remote_addr.ip, &call->audiostream->ms.session->rtp.rem_addr, call->audiostream->ms.session->rtp.rem_addrlen); - stats->info.call_id = call->log->call_id; + if (stats_type == LINPHONE_CALL_STATS_AUDIO) { + stream = call->audiostream->ms; + payload = call->current_params.audio_codec; + } else { + stream = call->videostream->ms; + payload = call->current_params.video_codec; + } + session = stream.sessions.rtp_session; + qi = media_stream_get_quality_indicator(&stream); + + report->info.local_addr.ssrc = rtp_session_get_send_ssrc(session); + report->info.local_addr.port = rtp_session_get_local_port(session); + report->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(session); + // memcpy(report->info.remote_addr.ip, &session->rtp.rem_addr, session->rtp.rem_addrlen); + report->info.call_id = call->log->call_id; + report->info.local_group = ms_strdup_printf(_("linphone-%s"), report->info.call_id); + report->info.remote_group = ms_strdup(report->info.local_group); for (count = 0; count < call->resultdesc->n_total_streams; ++count) { - if (call->resultdesc->streams[count].type == SalAudio) { - stats->info.local_addr.ip = call->resultdesc->streams[count].rtp_addr; + if (call->resultdesc->streams[count].type == stats_type) { + report->info.local_addr.ip = ms_strdup(call->resultdesc->streams[count].rtp_addr); break; } } if (count == call->resultdesc->n_total_streams) { - ms_warning("Could not find the associated stream of type %d", SalAudio); + ms_warning("Could not find the associated stream of type %d", stats_type); } - payload = call->params.audio_codec; if (payload != NULL) { - stats->local_metrics.session_description.payload_type = payload->type; - stats->local_metrics.session_description.payload_desc = ms_strdup(payload->mime_type); - stats->local_metrics.session_description.sample_rate = payload->clock_rate; - stats->local_metrics.session_description.fmtp = ms_strdup(payload->recv_fmtp); + report->local_metrics.session_description.payload_type = payload->type; + report->local_metrics.session_description.payload_desc = ms_strdup(payload->mime_type); + report->local_metrics.session_description.sample_rate = payload->clock_rate; + report->local_metrics.session_description.fmtp = ms_strdup(payload->recv_fmtp); } else { // ... } - //stats->local_metrics.session_description.packet_loss_concealment = ms_quality_indicator_get_local_late_rate(qi); - stats->local_metrics.packet_loss.jitter_buffer_discard_rate = ms_quality_indicator_get_local_loss_rate(qi); - stats->local_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); - if (10 <= stats->local_metrics.quality_estimates.rlq - && stats->local_metrics.quality_estimates.rlq <= 50) { - stats->local_metrics.quality_estimates.moslq = stats->local_metrics.quality_estimates.rlq / 10.f; + //report->local_metrics.session_description.packet_loss_concealment = ms_quality_indicator_get_local_late_rate(qi); + report->local_metrics.packet_loss.jitter_buffer_discard_rate = ms_quality_indicator_get_local_loss_rate(qi); + report->local_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); + if (10 <= report->local_metrics.quality_estimates.rlq + && report->local_metrics.quality_estimates.rlq <= 50) { + report->local_metrics.quality_estimates.moslq = report->local_metrics.quality_estimates.rlq / 10.f; } else { - stats->local_metrics.quality_estimates.moslq = -1; + report->local_metrics.quality_estimates.moslq = -1; } - stats->local_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); - if (10 <= stats->local_metrics.quality_estimates.rcq - && stats->local_metrics.quality_estimates.rcq <= 50) { - stats->local_metrics.quality_estimates.moscq = stats->local_metrics.quality_estimates.rcq / 10.f; + report->local_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); + if (10 <= report->local_metrics.quality_estimates.rcq + && report->local_metrics.quality_estimates.rcq <= 50) { + report->local_metrics.quality_estimates.moscq = report->local_metrics.quality_estimates.rcq / 10.f; } else { - stats->local_metrics.quality_estimates.moscq = -1; + report->local_metrics.quality_estimates.moscq = -1; } - // NOT FOUND - // int packet_loss_concealment; // in voip metrics - audio only - // jitter buffer - // jitter_buffer_discard_rate - if (call->dir == LinphoneCallIncoming) { - stats->info.remote_id = linphone_address_as_string(call->log->from); - stats->info.local_id = linphone_address_as_string(call->log->to); - stats->info.orig_id = stats->info.remote_id; + report->info.remote_id = linphone_address_as_string(call->log->from); + report->info.local_id = linphone_address_as_string(call->log->to); + report->info.orig_id = report->info.remote_id; } else { - stats->info.remote_id = linphone_address_as_string(call->log->to); - stats->info.local_id = linphone_address_as_string(call->log->from); - stats->info.orig_id = stats->info.local_id; + report->info.remote_id = linphone_address_as_string(call->log->to); + report->info.local_id = linphone_address_as_string(call->log->from); + report->info.orig_id = report->info.local_id; } - stats->local_metrics.timestamps.start = call->log->start_date_time; - stats->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + report->local_metrics.timestamps.start = call->log->start_date_time; + report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); - return stats; + return report; } +#define APPEND_STR_TO_BUFFER(buffer, size, offset, fmt, arg) if (arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg); + static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, reporting_content_metrics_t rm) { char * timpstamps_start_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.start); char * timpstamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop); @@ -171,35 +183,67 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off char * moslq_str = float_to_one_decimal_string(rm.quality_estimates.moslq); char * moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq); - append_to_buffer(buffer, size, offset, "Timestamps:START=%s STOP=%s\r\n", + append_to_buffer(buffer, size, offset, "Timestamps:START=%s STOP=%s", timpstamps_start_str, timpstamps_stop_str); - append_to_buffer(buffer, size, offset, "SessionDesc:PT=%d PD=%s SR=%d FD=%d FO=%d FPP=%d PPS=%d FMTP=%s PLC=%d SSUP=%s\r\n", - rm.session_description.payload_type, rm.session_description.payload_desc, rm.session_description.sample_rate, - rm.session_description.frame_duration, rm.session_description.frame_ocets, rm.session_description.frames_per_sec, - rm.session_description.packets_per_sec, rm.session_description.fmtp, rm.session_description.packet_loss_concealment, - rm.session_description.silence_suppression_state); - append_to_buffer(buffer, size, offset, "JitterBuffer:JBA=%d JBR=%d JBN=%d JBM=%d JBX=%d\r\n", - rm.jitter_buffer.adaptive, rm.jitter_buffer.rate, rm.jitter_buffer.nominal, rm.jitter_buffer.max, rm.jitter_buffer.abs_max); - append_to_buffer(buffer, size, offset, "PacketLoss:NLR=%s JDR=%s\r\n", - network_packet_loss_rate_str, - jitter_buffer_discard_rate_str); - append_to_buffer(buffer, size, offset, "BurstGapLoss:BLD=%d BD=%d GLD=%s GD=%d GMIN=%d\r\n", - rm.burst_gap_loss.burst_loss_density, rm.burst_gap_loss.burst_duration, - gap_loss_density_str, rm.burst_gap_loss.gap_Duration, - rm.burst_gap_loss.min_gap_threshold); - append_to_buffer(buffer, size, offset, "Delay:RTD=%d ESD=%d OWD=%d SOWD=%d IAJ=%d MAJ=%d\r\n", - rm.delay.round_trip_delay, rm.delay.end_system_delay, rm.delay.one_way_delay, rm.delay.symm_one_way_delay, - rm.delay.interarrival_jitter, rm.delay.mean_abs_jitter); - append_to_buffer(buffer, size, offset, "Signal:SL=%d NL=%d RERL=%d\r\n", - rm.signal.level, rm.signal.noise_level, rm.signal.residual_echo_return_loss); - append_to_buffer(buffer, size, offset, "QualityEst:RLQ=%d RLQEstAlg=%s RCQ=%d RCQEstAlgo=%s EXTRI=%d ExtRIEstAlg=%s EXTRO=%d ExtROEstAlg=%s MOSLQ=%s MOSLQEstAlgo=%s MOSCQ=%s MOSCQEstAlgo=%s QoEEstAlg=%s\r\n", - rm.quality_estimates.rlq, rm.quality_estimates.rlqestalg, - rm.quality_estimates.rcq, rm.quality_estimates.rcqestalg, - rm.quality_estimates.extri, rm.quality_estimates.extriestalg, - rm.quality_estimates.extro, rm.quality_estimates.extroutestalg, - moslq_str, rm.quality_estimates.moslqestalg, - moscq_str, rm.quality_estimates.moscqestalg, - rm.quality_estimates.qoestalg); + + append_to_buffer(buffer, size, offset, "\r\nSessionDesc:"); + append_to_buffer(buffer, size, offset, " PT=%d", rm.session_description.payload_type); + APPEND_STR_TO_BUFFER(buffer, size, offset, " PD=%s", rm.session_description.payload_desc); + append_to_buffer(buffer, size, offset, " SR=%d", rm.session_description.sample_rate); + append_to_buffer(buffer, size, offset, " FD=%d", rm.session_description.frame_duration); + // append_to_buffer(buffer, size, offset, " FO=%d", rm.session_description.frame_ocets); + // append_to_buffer(buffer, size, offset, " FPP=%d", rm.session_description.frames_per_sec); + // append_to_buffer(buffer, size, offset, " PPS=%d", rm.session_description.packets_per_sec); + APPEND_STR_TO_BUFFER(buffer, size, offset, " FMTP=\"%s\"", rm.session_description.fmtp); + append_to_buffer(buffer, size, offset, " PLC=%d", rm.session_description.packet_loss_concealment); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " SSUP=%s", rm.session_description.silence_suppression_state); + + append_to_buffer(buffer, size, offset, "\r\nJitterBuffer:"); + append_to_buffer(buffer, size, offset, " JBA=%d", rm.jitter_buffer.adaptive); + append_to_buffer(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate); + append_to_buffer(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal); + append_to_buffer(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max); + append_to_buffer(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max); + + append_to_buffer(buffer, size, offset, "\r\nPacketLoss:"); + APPEND_STR_TO_BUFFER(buffer, size, offset, " NLR=%s", network_packet_loss_rate_str); + APPEND_STR_TO_BUFFER(buffer, size, offset, " JDR=%s", jitter_buffer_discard_rate_str); + + append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:"); + append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density); + append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); + APPEND_STR_TO_BUFFER(buffer, size, offset, " GLD=%s", gap_loss_density_str); + append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_Duration); + append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); + + append_to_buffer(buffer, size, offset, "\r\nDelay:"); + append_to_buffer(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay); + append_to_buffer(buffer, size, offset, " ESD=%d", rm.delay.end_system_delay); + // append_to_buffer(buffer, size, offset, " OWD=%d", rm.delay.one_way_delay); + append_to_buffer(buffer, size, offset, " SOWD=%d", rm.delay.symm_one_way_delay); + append_to_buffer(buffer, size, offset, " IAJ=%d", rm.delay.interarrival_jitter); + append_to_buffer(buffer, size, offset, " MAJ=%d", rm.delay.mean_abs_jitter); + + append_to_buffer(buffer, size, offset, "\r\nSignal:"); + append_to_buffer(buffer, size, offset, " SL=%d", rm.signal.level); + append_to_buffer(buffer, size, offset, " NL=%d", rm.signal.noise_level); + // append_to_buffer(buffer, size, offset, " RERL=%d", rm.signal.residual_echo_return_loss); + + append_to_buffer(buffer, size, offset, "\r\nQualityEst:"); + append_to_buffer(buffer, size, offset, " RLQ=%d", rm.quality_estimates.rlq); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " RLQEstAlg=%s", rm.quality_estimates.rlqestalg); + append_to_buffer(buffer, size, offset, " RCQ=%d", rm.quality_estimates.rcq); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " RCQEstAlgo=%s", rm.quality_estimates.rcqestalg); + // append_to_buffer(buffer, size, offset, " EXTRI=%d", rm.quality_estimates.extri); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " ExtRIEstAlg=%s", rm.quality_estimates.extriestalg); + // append_to_buffer(buffer, size, offset, " EXTRO=%d", rm.quality_estimates.extro); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " ExtROEstAlg=%s", rm.quality_estimates.extroutestalg); + APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSLQ=%s", moslq_str); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSLQEstAlgo=%s", rm.quality_estimates.moslqestalg); + APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSCQ=%s", moscq_str); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSCQEstAlgo=%s", rm.quality_estimates.moscqestalg); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg); + append_to_buffer(buffer, size, offset, "\r\n"); free(timpstamps_start_str); free(timpstamps_stop_str); @@ -210,17 +254,17 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off free(moscq_str); } -void linphone_quality_reporting_submit(LinphoneCall* call) { +void linphone_reporting_publish(LinphoneCall* call, int stats_type) { LinphoneContent content = {0}; LinphoneAddress *addr; int expires = 3600; - reporting_session_report_t *stats = update_stats(call); + reporting_session_report_t *report = update_report(call, stats_type); size_t offset = 0; size_t size = 2048; char * buffer; // Somehow the reporting was not created, hence no need to go further - if (stats == NULL) { + if (report == NULL) { PRINT("STATS ARE NULL!"); return; } @@ -231,25 +275,25 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { content.subtype = ms_strdup("vq-rtcpxr"); append_to_buffer(&buffer, &size, &offset, "VQSessionReport: CallTerm\r\n"); - append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", stats->info.call_id); - append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", stats->info.local_id); - append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", stats->info.remote_id); - append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", stats->info.orig_id); + append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", report->info.call_id); + append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", report->info.local_id); + append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", report->info.remote_id); + append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", report->info.orig_id); - append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", stats->info.local_group); //linphone-CALLID - append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", stats->info.remote_group); //idem - append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", stats->info.local_addr.ip, stats->info.local_addr.port, stats->info.local_addr.ssrc); - append_to_buffer(&buffer, &size, &offset, "LocalMAC: %s\r\n", stats->info.local_mac_addr); - append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", stats->info.remote_addr.ip, stats->info.remote_addr.port, stats->info.remote_addr.ssrc); - append_to_buffer(&buffer, &size, &offset, "RemoteMAC: %s\r\n", stats->info.remote_mac_addr); + if (report->info.local_group != NULL) append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", report->info.local_group); + if (report->info.remote_group != NULL) append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", report->info.remote_group); + append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.local_addr.ip, report->info.local_addr.port, report->info.local_addr.ssrc); + if (report->info.local_mac_addr != NULL) append_to_buffer(&buffer, &size, &offset, "LocalMAC: %s\r\n", report->info.local_mac_addr); + append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.remote_addr.ip, report->info.remote_addr.port, report->info.remote_addr.ssrc); + if (report->info.remote_mac_addr != NULL) append_to_buffer(&buffer, &size, &offset, "RemoteMAC: %s\r\n", report->info.remote_mac_addr); append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); - append_metrics_to_buffer(&buffer, &size, &offset, stats->local_metrics); + append_metrics_to_buffer(&buffer, &size, &offset, report->local_metrics); append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); - append_metrics_to_buffer(&buffer, &size, &offset, stats->remote_metrics); - if (stats->dialog_id != NULL) { - append_to_buffer(&buffer, &size, &offset, "DialogID: %s\r\n", stats->dialog_id); + append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics); + if (report->dialog_id != NULL) { + append_to_buffer(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id); } content.data = buffer; @@ -264,3 +308,70 @@ void linphone_quality_reporting_submit(LinphoneCall* call) { linphone_address_destroy(addr); } + +void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { + reporting_session_report_t * report = call->reports[stats_type]; + reporting_content_metrics_t * metrics = NULL; + reporting_addr_t * addr = NULL; + + LinphoneCallStats stats = call->stats[stats_type]; + mblk_t *block = NULL; + + if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { + metrics = &report->remote_metrics; + addr = &report->info.remote_addr; + if (rtcp_is_XR(stats.received_rtcp) == TRUE) { + block = stats.received_rtcp; + } + } else if (stats.updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { + metrics = &report->local_metrics; + addr = &report->info.local_addr; + if (rtcp_is_XR(stats.sent_rtcp) == TRUE) { + block = stats.sent_rtcp; + } + } + if (block != NULL) { + switch (rtcp_XR_get_block_type(block)) { + case RTCP_XR_STAT_SUMMARY: + // rtcp_XR_stat_summary_get_flags(block); + // rtcp_XR_stat_summary_get_ssrc(block); + // rtcp_XR_stat_summary_get_begin_seq(block); + // rtcp_XR_stat_summary_get_end_seq(block); + // rtcp_XR_stat_summary_get_lost_packets(block); + // rtcp_XR_stat_summary_get_dup_packets(block); + // rtcp_XR_stat_summary_get_min_jitter(block); + metrics->jitter_buffer.max = rtcp_XR_stat_summary_get_max_jitter(block); + // rtcp_XR_stat_summary_get_mean_jitter(block); + // rtcp_XR_stat_summary_get_dev_jitter(block); + // rtcp_XR_stat_summary_get_min_ttl_or_hl(block); + // rtcp_XR_stat_summary_get_max_ttl_or_hl(block); + // rtcp_XR_stat_summary_get_mean_ttl_or_hl(block); + // rtcp_XR_stat_summary_get_dev_ttl_or_hl(block); + break; + case RTCP_XR_VOIP_METRICS: + addr->ssrc = rtcp_XR_voip_metrics_get_ssrc(block); + // rtcp_XR_voip_metrics_get_loss_rate(block); + // rtcp_XR_voip_metrics_get_discard_rate(block); + // rtcp_XR_voip_metrics_get_burst_density(block); + // rtcp_XR_voip_metrics_get_gap_density(block); + // rtcp_XR_voip_metrics_get_burst_duration(block); + // rtcp_XR_voip_metrics_get_gap_duration(block); + // rtcp_XR_voip_metrics_get_round_trip_delay(block); + // rtcp_XR_voip_metrics_get_end_system_delay(block); + // rtcp_XR_voip_metrics_get_signal_level(block); + // rtcp_XR_voip_metrics_get_noise_level(block); + // rtcp_XR_voip_metrics_get_rerl(block); + // rtcp_XR_voip_metrics_get_gmin(block); + metrics->quality_estimates.rlq = rtcp_XR_voip_metrics_get_r_factor(block); + metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block); + metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block); + // rtcp_XR_voip_metrics_get_rx_config(block); + metrics->jitter_buffer.nominal = rtcp_XR_voip_metrics_get_jb_nominal(block); + metrics->jitter_buffer.max = rtcp_XR_voip_metrics_get_jb_maximum(block); + metrics->jitter_buffer.abs_max = rtcp_XR_voip_metrics_get_jb_abs_max(block); + break; + default: + break; + } + } +} diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index b8b1a42e4..7e5831212 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -45,12 +45,12 @@ typedef struct reporting_content_metrics { char * payload_desc; // mime type int sample_rate; // clock rate int frame_duration; // to check (ptime?) - audio only - int frame_ocets; // no - int frames_per_sec; // no - int packets_per_sec; // no - char * fmtp; // pt.recv_fmtp + // int frame_ocets; + // int frames_per_sec; + // int packets_per_sec; + char * fmtp; int packet_loss_concealment; // in voip metrics - audio only - char * silence_suppression_state; // no + // char * silence_suppression_state; } session_description; // jitter buffet - optional @@ -82,17 +82,17 @@ typedef struct reporting_content_metrics { struct { int round_trip_delay; // no - vary int end_system_delay; // no - not implemented yet - int one_way_delay; // no + // int one_way_delay; int symm_one_way_delay; // no - vary (depends on round_trip_delay) + not implemented (depends on end_system_delay) int interarrival_jitter; // no - not implemented yet - int mean_abs_jitter; // (no)? - to check + int mean_abs_jitter; // to check } delay; // signal - optional struct { int level; // no - vary int noise_level; // no - vary - int residual_echo_return_loss; // no + // int residual_echo_return_loss; } signal; // quality estimates - optional @@ -103,15 +103,15 @@ typedef struct reporting_content_metrics { float moscq; // no - vary or avg - voip metrics - in [0..4.9] - int extri; // no - int extro; // no - char * rlqestalg; // no to all alg - char * rcqestalg; - char * moslqestalg; - char * moscqestalg; - char * extriestalg; - char * extroutestalg; - char * qoestalg; + // int extri; + // int extro; + // char * rlqestalg; + // char * rcqestalg; + // char * moslqestalg; + // char * moscqestalg; + // char * extriestalg; + // char * extroutestalg; + // char * qoestalg; } quality_estimates; } reporting_content_metrics_t; @@ -137,8 +137,8 @@ typedef struct reporting_session_report { } reporting_session_report_t; -void linphone_quality_reporting_submit(LinphoneCall* call); - +void linphone_reporting_publish(LinphoneCall* call, int stats_type); +void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type); #ifdef __cplusplus } #endif From 23cbf843e9363961f4d91fe32b76549f52079fed Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 10 Apr 2014 16:49:03 +0200 Subject: [PATCH 17/83] Quality reporting: Remove burst gap loss since it is not implemented yet --- coreapi/linphonecore.c | 3 ++ coreapi/quality_reporting.c | 84 +++++++++++++++++++++++-------------- coreapi/quality_reporting.h | 14 +++---- 3 files changed, 63 insertions(+), 38 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 12078604b..9468189f8 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3471,6 +3471,9 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ linphone_core_stop_ringing(lc); linphone_reporting_publish(call, LINPHONE_CALL_STATS_AUDIO); + if (call->videostream!=NULL){ + linphone_reporting_publish(call, LINPHONE_CALL_STATS_VIDEO); + } linphone_call_stop_media_streams(call); diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index dc1b1c511..ff8ada7e9 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -30,18 +30,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*************************************************************************** * TODO / REMINDER LIST ****************************************************************************/ - // example at http://tools.ietf.org/html/rfc6035#section-4.7.3 - // only if this is a linphone account - // only if call succeeded - // executed AFTER BYE's "OK" response has been received - // to: collector@sip.linphone.com or not - // expires value? - // one send by stream (different ssrc) - // ex RERL 404 code différent potentiellement avec info manquante - // 3611 pour savoir les valeurs pour les champs non disponibles - // video : que se passe t-il si on arrete / resume la vidéo + // place pour appeler la fonction submit + // only if call succeeded + // executed AFTER BYE's "OK" response has been received + // si c l'autre qui raccroche on envoi pas les données là // memory leaks + char* strdup - // bouger l'appel de fonction au bon endroit (si c l'autre qui raccroche on envoi pas les données là) + // si aucune data d'une catégorie est renseigné, ne pas mettre la section dans le paquet + // stats + // valeur pour "expires" ? + // packet_loss_concealment + // jitter buffer rate / adaptive + // jitter_buffer_discard_rate; + // network_packet_loss_rate + // vérifier les valeurs par défaut etc. + // ip local potientellement vide + // remote : ip, port, timestamps, session desc + // dialog id ? + // à voir : + // video : que se passe t-il si on arrete / resume la vidéo (new stream) + // valeurs instanannées : moyenne ? valeur extreme ? + // à qui / comment on envoit ? (collector@sip.linphone.com ?) + // only if this is a linphone account? #define PRINT2(x, f) printf(#x ": " #f "\n", x) #define PRINT(x) PRINT2(x, "%s") @@ -139,9 +148,7 @@ static reporting_session_report_t * update_report(LinphoneCall * call, int stats } else { // ... } - - //report->local_metrics.session_description.packet_loss_concealment = ms_quality_indicator_get_local_late_rate(qi); - report->local_metrics.packet_loss.jitter_buffer_discard_rate = ms_quality_indicator_get_local_loss_rate(qi); + report->local_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); if (10 <= report->local_metrics.quality_estimates.rlq && report->local_metrics.quality_estimates.rlq <= 50) { @@ -169,6 +176,23 @@ static reporting_session_report_t * update_report(LinphoneCall * call, int stats report->local_metrics.timestamps.start = call->log->start_date_time; report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + + + report->remote_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); + if (10 <= report->remote_metrics.quality_estimates.rlq + && report->remote_metrics.quality_estimates.rlq <= 50) { + report->remote_metrics.quality_estimates.moslq = report->remote_metrics.quality_estimates.rlq / 10.f; + } else { + report->remote_metrics.quality_estimates.moslq = -1; + } + report->remote_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); + if (10 <= report->remote_metrics.quality_estimates.rcq + && report->remote_metrics.quality_estimates.rcq <= 50) { + report->remote_metrics.quality_estimates.moscq = report->remote_metrics.quality_estimates.rcq / 10.f; + } else { + report->remote_metrics.quality_estimates.moscq = -1; + } + return report; } @@ -179,7 +203,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off char * timpstamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop); char * network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate); char * jitter_buffer_discard_rate_str = float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate); - char * gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density); + // char * gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density); char * moslq_str = float_to_one_decimal_string(rm.quality_estimates.moslq); char * moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq); @@ -209,12 +233,12 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off APPEND_STR_TO_BUFFER(buffer, size, offset, " NLR=%s", network_packet_loss_rate_str); APPEND_STR_TO_BUFFER(buffer, size, offset, " JDR=%s", jitter_buffer_discard_rate_str); - append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:"); - append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density); - append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); - APPEND_STR_TO_BUFFER(buffer, size, offset, " GLD=%s", gap_loss_density_str); - append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_Duration); - append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); + // append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:"); + // append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density); + // append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); + // APPEND_STR_TO_BUFFER(buffer, size, offset, " GLD=%s", gap_loss_density_str); + // append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_Duration); + // append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); append_to_buffer(buffer, size, offset, "\r\nDelay:"); append_to_buffer(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay); @@ -249,7 +273,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off free(timpstamps_stop_str); free(network_packet_loss_rate_str); free(jitter_buffer_discard_rate_str); - free(gap_loss_density_str); + // free(gap_loss_density_str); free(moslq_str); free(moscq_str); } @@ -280,21 +304,19 @@ void linphone_reporting_publish(LinphoneCall* call, int stats_type) { append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", report->info.remote_id); append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", report->info.orig_id); - if (report->info.local_group != NULL) append_to_buffer(&buffer, &size, &offset, "LocalGroup: %s\r\n", report->info.local_group); - if (report->info.remote_group != NULL) append_to_buffer(&buffer, &size, &offset, "RemoteGroup: %s\r\n", report->info.remote_group); + APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "LocalGroup: %s\r\n", report->info.local_group); + APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "RemoteGroup: %s\r\n", report->info.remote_group); append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.local_addr.ip, report->info.local_addr.port, report->info.local_addr.ssrc); - if (report->info.local_mac_addr != NULL) append_to_buffer(&buffer, &size, &offset, "LocalMAC: %s\r\n", report->info.local_mac_addr); + APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "LocalMAC: %s\r\n", report->info.local_mac_addr); append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.remote_addr.ip, report->info.remote_addr.port, report->info.remote_addr.ssrc); - if (report->info.remote_mac_addr != NULL) append_to_buffer(&buffer, &size, &offset, "RemoteMAC: %s\r\n", report->info.remote_mac_addr); + APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "RemoteMAC: %s\r\n", report->info.remote_mac_addr); append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); append_metrics_to_buffer(&buffer, &size, &offset, report->local_metrics); append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics); - if (report->dialog_id != NULL) { - append_to_buffer(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id); - } + APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id); content.data = buffer; @@ -340,7 +362,7 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { // rtcp_XR_stat_summary_get_lost_packets(block); // rtcp_XR_stat_summary_get_dup_packets(block); // rtcp_XR_stat_summary_get_min_jitter(block); - metrics->jitter_buffer.max = rtcp_XR_stat_summary_get_max_jitter(block); + // rtcp_XR_stat_summary_get_max_jitter(block); // rtcp_XR_stat_summary_get_mean_jitter(block); // rtcp_XR_stat_summary_get_dev_jitter(block); // rtcp_XR_stat_summary_get_min_ttl_or_hl(block); @@ -349,7 +371,7 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { // rtcp_XR_stat_summary_get_dev_ttl_or_hl(block); break; case RTCP_XR_VOIP_METRICS: - addr->ssrc = rtcp_XR_voip_metrics_get_ssrc(block); + // rtcp_XR_voip_metrics_get_ssrc(block); // rtcp_XR_voip_metrics_get_loss_rate(block); // rtcp_XR_voip_metrics_get_discard_rate(block); // rtcp_XR_voip_metrics_get_burst_density(block); diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index 7e5831212..5b17dfec8 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -70,13 +70,13 @@ typedef struct reporting_content_metrics { // burst gap loss - optional // (no) currently not implemented - struct { - int burst_loss_density; - int burst_duration; - float gap_loss_density; - int gap_Duration; - int min_gap_threshold; - } burst_gap_loss; + // struct { + // int burst_loss_density; + // int burst_duration; + // float gap_loss_density; + // int gap_Duration; + // int min_gap_threshold; + // } burst_gap_loss; // delay - optional struct { From a9e94795f4e12f4cce88155023fd4ffe9caf135a Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 10 Apr 2014 17:13:50 +0200 Subject: [PATCH 18/83] Quality reporting: fix submit report time moment --- coreapi/linphonecall.c | 2 ++ coreapi/linphonecore.c | 4 ++-- coreapi/quality_reporting.c | 33 +++++++++++++++++++-------------- coreapi/quality_reporting.h | 6 +++--- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index d1e2d15b7..60baf03ff 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -804,6 +804,8 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const if (lc->vtable.call_state_changed) lc->vtable.call_state_changed(lc,call,cstate,message); if (cstate==LinphoneCallReleased){ + linphone_reporting_publish(call); + 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){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 9468189f8..13ab2027d 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3470,9 +3470,9 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ /*stop ringing*/ linphone_core_stop_ringing(lc); - linphone_reporting_publish(call, LINPHONE_CALL_STATS_AUDIO); + linphone_reporting_update(call, LINPHONE_CALL_STATS_AUDIO); if (call->videostream!=NULL){ - linphone_reporting_publish(call, LINPHONE_CALL_STATS_VIDEO); + linphone_reporting_update(call, LINPHONE_CALL_STATS_VIDEO); } linphone_call_stop_media_streams(call); diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index ff8ada7e9..1dd413041 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -31,10 +31,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * TODO / REMINDER LIST ****************************************************************************/ // place pour appeler la fonction submit - // only if call succeeded - // executed AFTER BYE's "OK" response has been received - // si c l'autre qui raccroche on envoi pas les données là + // only if call succeeded and ran + // TO_CHECK: executed AFTER BYE's "OK" response has been received + // memory leaks + char* strdup + // si l'autre en face a pas activé le partage de rtcp xr, on a pas de paquets du tout ? faut rien faire dans ce cas ? // si aucune data d'une catégorie est renseigné, ne pas mettre la section dans le paquet // stats // valeur pour "expires" ? @@ -99,7 +100,8 @@ static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, con va_end(args); } -static reporting_session_report_t * update_report(LinphoneCall * call, int stats_type) { +reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int stats_type) { + printf("linphone_reporting_call_stats_updated\n"); int count; reporting_session_report_t * report = call->reports[stats_type]; MediaStream stream; @@ -237,7 +239,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off // append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density); // append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); // APPEND_STR_TO_BUFFER(buffer, size, offset, " GLD=%s", gap_loss_density_str); - // append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_Duration); + // append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_duration); // append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); append_to_buffer(buffer, size, offset, "\r\nDelay:"); @@ -278,21 +280,14 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off free(moscq_str); } -void linphone_reporting_publish(LinphoneCall* call, int stats_type) { +static void reporting_publish(LinphoneCall* call, reporting_session_report_t * report) { LinphoneContent content = {0}; LinphoneAddress *addr; int expires = 3600; - reporting_session_report_t *report = update_report(call, stats_type); size_t offset = 0; size_t size = 2048; char * buffer; - // Somehow the reporting was not created, hence no need to go further - if (report == NULL) { - PRINT("STATS ARE NULL!"); - return; - } - buffer = (char *) ms_malloc(size); content.type = ms_strdup("application"); @@ -330,7 +325,6 @@ void linphone_reporting_publish(LinphoneCall* call, int stats_type) { linphone_address_destroy(addr); } - void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { reporting_session_report_t * report = call->reports[stats_type]; reporting_content_metrics_t * metrics = NULL; @@ -397,3 +391,14 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { } } } + +void linphone_reporting_publish(LinphoneCall* call) { + printf("linphone_reporting_publish\n"); + if (call->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) { + reporting_publish(call, call->reports[LINPHONE_CALL_STATS_AUDIO]); + } + + if (call->reports[LINPHONE_CALL_STATS_VIDEO] != NULL) { + reporting_publish(call, call->reports[LINPHONE_CALL_STATS_VIDEO]); + } +} diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index 5b17dfec8..1c4a3ca4d 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -74,7 +74,7 @@ typedef struct reporting_content_metrics { // int burst_loss_density; // int burst_duration; // float gap_loss_density; - // int gap_Duration; + // int gap_duration; // int min_gap_threshold; // } burst_gap_loss; @@ -136,8 +136,8 @@ typedef struct reporting_session_report { char * dialog_id; // optional } reporting_session_report_t; - -void linphone_reporting_publish(LinphoneCall* call, int stats_type); +reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int stats_type); +void linphone_reporting_publish(LinphoneCall* call); void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type); #ifdef __cplusplus } From a1c1f3013e62bb550860b8125203a5e5f383c5a5 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Fri, 11 Apr 2014 11:30:02 +0200 Subject: [PATCH 19/83] Quality reporting: verify values before adding them to the report --- coreapi/linphonecall.c | 7 +- coreapi/linphonecore.c | 5 - coreapi/private.h | 4 +- coreapi/quality_reporting.c | 318 +++++++++++++++++++++--------------- coreapi/quality_reporting.h | 1 + 5 files changed, 193 insertions(+), 142 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 60baf03ff..feb96ee1c 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -483,6 +483,9 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, call->owns_call_log=TRUE; call->camera_enabled=TRUE; + call->log->reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); + call->log->reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); + linphone_core_get_audio_port_range(call->core, &min_port, &max_port); port_config_set(call,0,min_port,max_port); @@ -1851,7 +1854,6 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna playfile=lc->play_file; recfile=lc->rec_file; call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); - call->reports[LINPHONE_CALL_STATS_AUDIO]=ms_new0(reporting_session_report_t,1); if (used_pt!=-1){ call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); @@ -1981,7 +1983,6 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,vstream->proto,SalVideo); call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt); - call->reports[LINPHONE_CALL_STATS_VIDEO]=ms_new0(reporting_session_report_t,1); if (used_pt!=-1){ VideoStreamDir dir=VideoStreamSendRecv; @@ -2206,6 +2207,7 @@ static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){ void linphone_call_stop_audio_stream(LinphoneCall *call) { if (call->audiostream!=NULL) { + linphone_reporting_update(call, LINPHONE_CALL_STATS_AUDIO); media_stream_reclaim_sessions(&call->audiostream->ms,&call->sessions[0]); rtp_session_unregister_event_queue(call->audiostream->ms.sessions.rtp_session,call->audiostream_app_evq); ortp_ev_queue_flush(call->audiostream_app_evq); @@ -2234,6 +2236,7 @@ void linphone_call_stop_audio_stream(LinphoneCall *call) { void linphone_call_stop_video_stream(LinphoneCall *call) { #ifdef VIDEO_ENABLED if (call->videostream!=NULL){ + linphone_reporting_update(call, LINPHONE_CALL_STATS_VIDEO); media_stream_reclaim_sessions(&call->videostream->ms,&call->sessions[1]); rtp_session_unregister_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq); ortp_ev_queue_flush(call->videostream_app_evq); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 13ab2027d..1d23a929a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3470,11 +3470,6 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ /*stop ringing*/ linphone_core_stop_ringing(lc); - linphone_reporting_update(call, LINPHONE_CALL_STATS_AUDIO); - if (call->videostream!=NULL){ - linphone_reporting_update(call, LINPHONE_CALL_STATS_VIDEO); - } - linphone_call_stop_media_streams(call); #ifdef BUILD_UPNP diff --git a/coreapi/private.h b/coreapi/private.h index 4d32a23e6..d92371a5a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -116,6 +116,8 @@ struct _LinphoneCallLog{ float quality; time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */ char* call_id; /**unique id of a call*/ + + reporting_session_report_t * reports[2]; bool_t video_enabled; }; @@ -193,8 +195,6 @@ struct _LinphoneCall struct _AudioStream *audiostream; /**/ struct _VideoStream *videostream; - reporting_session_report_t * reports[2]; - MSAudioEndpoint *endpoint; /*used for conferencing*/ char *refer_to; LinphoneCallParams params; diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 1dd413041..920455ac7 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // TO_CHECK: executed AFTER BYE's "OK" response has been received // memory leaks + char* strdup + // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). // si l'autre en face a pas activé le partage de rtcp xr, on a pas de paquets du tout ? faut rien faire dans ce cas ? // si aucune data d'une catégorie est renseigné, ne pas mettre la section dans le paquet // stats @@ -100,10 +101,153 @@ static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, con va_end(args); } + +#define APPEND_IF_NOT_NULL_STR(buffer, size, offset, fmt, arg) if (arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg) +#define APPEND_IF_NUM_IN_RANGE(buffer, size, offset, fmt, arg, inf, sup) if (inf <= arg && arg <= sup) append_to_buffer(buffer, size, offset, fmt, arg) +#define APPEND_IF(buffer, size, offset, fmt, arg, cond) if (cond) append_to_buffer(buffer, size, offset, fmt, arg) +#define IF_NUM_IN_RANGE(num, inf, sup, statement) if (inf <= num && num <= sup) statement + +static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, reporting_content_metrics_t rm) { + char * timestamps_start_str = NULL; + char * timestamps_stop_str = NULL; + char * network_packet_loss_rate_str = NULL; + char * jitter_buffer_discard_rate_str = NULL; + // char * gap_loss_density_str = NULL; + char * moslq_str = NULL; + char * moscq_str = NULL; + + if (rm.timestamps.start > 0) + timestamps_start_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.start); + if (rm.timestamps.stop > 0) + timestamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop); + + IF_NUM_IN_RANGE(rm.packet_loss.network_packet_loss_rate, 0, 255, network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate / 256)); + IF_NUM_IN_RANGE(rm.packet_loss.jitter_buffer_discard_rate, 0, 255, jitter_buffer_discard_rate_str = float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate / 256)); + // IF_NUM_IN_RANGE(rm.burst_gap_loss.gap_loss_density, 0, 10, gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density)); + IF_NUM_IN_RANGE(rm.quality_estimates.moslq, 1, 5, moslq_str = float_to_one_decimal_string(rm.quality_estimates.moslq)); + IF_NUM_IN_RANGE(rm.quality_estimates.moscq, 1, 5, moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq)); + + append_to_buffer(buffer, size, offset, "Timestamps:"); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " START=%s", timestamps_start_str); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " STOP=%s", timestamps_stop_str); + + append_to_buffer(buffer, size, offset, "\r\nSessionDesc:"); + APPEND_IF(buffer, size, offset, " PT=%d", rm.session_description.payload_type, rm.session_description.payload_type != -1); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " PD=%s", rm.session_description.payload_desc); + APPEND_IF(buffer, size, offset, " SR=%d", rm.session_description.sample_rate, rm.session_description.sample_rate != -1); + APPEND_IF(buffer, size, offset, " FD=%d", rm.session_description.frame_duration, rm.session_description.frame_duration != -1); + // append_to_buffer(buffer, size, offset, " FO=%d", rm.session_description.frame_ocets); + // append_to_buffer(buffer, size, offset, " FPP=%d", rm.session_description.frames_per_sec); + // append_to_buffer(buffer, size, offset, " PPS=%d", rm.session_description.packets_per_sec); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " FMTP=\"%s\"", rm.session_description.fmtp); + APPEND_IF(buffer, size, offset, " PLC=%d", rm.session_description.packet_loss_concealment, rm.session_description.packet_loss_concealment != -1); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " SSUP=%s", rm.session_description.silence_suppression_state); + + append_to_buffer(buffer, size, offset, "\r\nJitterBuffer:"); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBA=%d", rm.jitter_buffer.adaptive, 0, 3); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal, 0, 65535); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max, 0, 65535); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max, 0, 65535); + + append_to_buffer(buffer, size, offset, "\r\nPacketLoss:"); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " NLR=%s", network_packet_loss_rate_str); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " JDR=%s", jitter_buffer_discard_rate_str); + + // append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:"); + // append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density); + // append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " GLD=%s", gap_loss_density_str); + // append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_duration); + // append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); + + append_to_buffer(buffer, size, offset, "\r\nDelay:"); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay, 0, 65535); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " ESD=%d", rm.delay.end_system_delay, 0, 65535); + // APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " OWD=%d", rm.delay.one_way_delay, 0, 65535); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " SOWD=%d", rm.delay.symm_one_way_delay, 0, 65535); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " IAJ=%d", rm.delay.interarrival_jitter, 0, 65535); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " MAJ=%d", rm.delay.mean_abs_jitter, 0, 65535); + + append_to_buffer(buffer, size, offset, "\r\nSignal:"); + APPEND_IF(buffer, size, offset, " SL=%d", rm.signal.level, rm.signal.level != 127); + APPEND_IF(buffer, size, offset, " NL=%d", rm.signal.noise_level, rm.signal.noise_level != 127); + // append_to_buffer(buffer, size, offset, " RERL=%d", rm.signal.residual_echo_return_loss); + + append_to_buffer(buffer, size, offset, "\r\nQualityEst:"); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RLQ=%d", rm.quality_estimates.rlq, 1, 120); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RLQEstAlg=%s", rm.quality_estimates.rlqestalg); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RCQ=%d", rm.quality_estimates.rcq, 1, 120); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RCQEstAlgo=%s", rm.quality_estimates.rcqestalg); + // append_to_buffer(buffer, size, offset, " EXTRI=%d", rm.quality_estimates.extri); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtRIEstAlg=%s", rm.quality_estimates.extriestalg); + // append_to_buffer(buffer, size, offset, " EXTRO=%d", rm.quality_estimates.extro); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtROEstAlg=%s", rm.quality_estimates.extroutestalg); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQ=%s", moslq_str); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQEstAlgo=%s", rm.quality_estimates.moslqestalg); + APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQ=%s", moscq_str); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQEstAlgo=%s", rm.quality_estimates.moscqestalg); + // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg); + append_to_buffer(buffer, size, offset, "\r\n"); + + free(timestamps_start_str); + free(timestamps_stop_str); + free(network_packet_loss_rate_str); + free(jitter_buffer_discard_rate_str); + // free(gap_loss_density_str); + free(moslq_str); + free(moscq_str); +} + +static void reporting_publish(LinphoneCall* call, reporting_session_report_t * report) { + LinphoneContent content = {0}; + LinphoneAddress *addr; + int expires = 3600; + size_t offset = 0; + size_t size = 2048; + char * buffer; + + buffer = (char *) ms_malloc(size); + + content.type = ms_strdup("application"); + content.subtype = ms_strdup("vq-rtcpxr"); + + append_to_buffer(&buffer, &size, &offset, "VQSessionReport: CallTerm\r\n"); + append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", report->info.call_id); + append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", report->info.local_id); + append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", report->info.remote_id); + append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", report->info.orig_id); + + APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "LocalGroup: %s\r\n", report->info.local_group); + APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "RemoteGroup: %s\r\n", report->info.remote_group); + append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.local_addr.ip, report->info.local_addr.port, report->info.local_addr.ssrc); + APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "LocalMAC: %s\r\n", report->info.local_mac_addr); + append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.remote_addr.ip, report->info.remote_addr.port, report->info.remote_addr.ssrc); + APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "RemoteMAC: %s\r\n", report->info.remote_mac_addr); + + append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); + append_metrics_to_buffer(&buffer, &size, &offset, report->local_metrics); + + append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); + append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics); + APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id); + + content.data = buffer; + + // for debug purpose only + PRINT(content.data); + + content.size = strlen((char*)content.data); + + addr = linphone_address_new("sip:collector@sip.linphone.org"); + linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); + linphone_address_destroy(addr); +} + reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int stats_type) { printf("linphone_reporting_call_stats_updated\n"); int count; - reporting_session_report_t * report = call->reports[stats_type]; + reporting_session_report_t * report = call->log->reports[stats_type]; MediaStream stream; const MSQualityIndicator * qi = NULL; const PayloadType * payload; @@ -198,135 +342,8 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int return report; } -#define APPEND_STR_TO_BUFFER(buffer, size, offset, fmt, arg) if (arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg); - -static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, reporting_content_metrics_t rm) { - char * timpstamps_start_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.start); - char * timpstamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop); - char * network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate); - char * jitter_buffer_discard_rate_str = float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate); - // char * gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density); - char * moslq_str = float_to_one_decimal_string(rm.quality_estimates.moslq); - char * moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq); - - append_to_buffer(buffer, size, offset, "Timestamps:START=%s STOP=%s", - timpstamps_start_str, timpstamps_stop_str); - - append_to_buffer(buffer, size, offset, "\r\nSessionDesc:"); - append_to_buffer(buffer, size, offset, " PT=%d", rm.session_description.payload_type); - APPEND_STR_TO_BUFFER(buffer, size, offset, " PD=%s", rm.session_description.payload_desc); - append_to_buffer(buffer, size, offset, " SR=%d", rm.session_description.sample_rate); - append_to_buffer(buffer, size, offset, " FD=%d", rm.session_description.frame_duration); - // append_to_buffer(buffer, size, offset, " FO=%d", rm.session_description.frame_ocets); - // append_to_buffer(buffer, size, offset, " FPP=%d", rm.session_description.frames_per_sec); - // append_to_buffer(buffer, size, offset, " PPS=%d", rm.session_description.packets_per_sec); - APPEND_STR_TO_BUFFER(buffer, size, offset, " FMTP=\"%s\"", rm.session_description.fmtp); - append_to_buffer(buffer, size, offset, " PLC=%d", rm.session_description.packet_loss_concealment); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " SSUP=%s", rm.session_description.silence_suppression_state); - - append_to_buffer(buffer, size, offset, "\r\nJitterBuffer:"); - append_to_buffer(buffer, size, offset, " JBA=%d", rm.jitter_buffer.adaptive); - append_to_buffer(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate); - append_to_buffer(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal); - append_to_buffer(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max); - append_to_buffer(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max); - - append_to_buffer(buffer, size, offset, "\r\nPacketLoss:"); - APPEND_STR_TO_BUFFER(buffer, size, offset, " NLR=%s", network_packet_loss_rate_str); - APPEND_STR_TO_BUFFER(buffer, size, offset, " JDR=%s", jitter_buffer_discard_rate_str); - - // append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:"); - // append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density); - // append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " GLD=%s", gap_loss_density_str); - // append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_duration); - // append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); - - append_to_buffer(buffer, size, offset, "\r\nDelay:"); - append_to_buffer(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay); - append_to_buffer(buffer, size, offset, " ESD=%d", rm.delay.end_system_delay); - // append_to_buffer(buffer, size, offset, " OWD=%d", rm.delay.one_way_delay); - append_to_buffer(buffer, size, offset, " SOWD=%d", rm.delay.symm_one_way_delay); - append_to_buffer(buffer, size, offset, " IAJ=%d", rm.delay.interarrival_jitter); - append_to_buffer(buffer, size, offset, " MAJ=%d", rm.delay.mean_abs_jitter); - - append_to_buffer(buffer, size, offset, "\r\nSignal:"); - append_to_buffer(buffer, size, offset, " SL=%d", rm.signal.level); - append_to_buffer(buffer, size, offset, " NL=%d", rm.signal.noise_level); - // append_to_buffer(buffer, size, offset, " RERL=%d", rm.signal.residual_echo_return_loss); - - append_to_buffer(buffer, size, offset, "\r\nQualityEst:"); - append_to_buffer(buffer, size, offset, " RLQ=%d", rm.quality_estimates.rlq); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " RLQEstAlg=%s", rm.quality_estimates.rlqestalg); - append_to_buffer(buffer, size, offset, " RCQ=%d", rm.quality_estimates.rcq); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " RCQEstAlgo=%s", rm.quality_estimates.rcqestalg); - // append_to_buffer(buffer, size, offset, " EXTRI=%d", rm.quality_estimates.extri); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " ExtRIEstAlg=%s", rm.quality_estimates.extriestalg); - // append_to_buffer(buffer, size, offset, " EXTRO=%d", rm.quality_estimates.extro); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " ExtROEstAlg=%s", rm.quality_estimates.extroutestalg); - APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSLQ=%s", moslq_str); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSLQEstAlgo=%s", rm.quality_estimates.moslqestalg); - APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSCQ=%s", moscq_str); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " MOSCQEstAlgo=%s", rm.quality_estimates.moscqestalg); - // APPEND_STR_TO_BUFFER(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg); - append_to_buffer(buffer, size, offset, "\r\n"); - - free(timpstamps_start_str); - free(timpstamps_stop_str); - free(network_packet_loss_rate_str); - free(jitter_buffer_discard_rate_str); - // free(gap_loss_density_str); - free(moslq_str); - free(moscq_str); -} - -static void reporting_publish(LinphoneCall* call, reporting_session_report_t * report) { - LinphoneContent content = {0}; - LinphoneAddress *addr; - int expires = 3600; - size_t offset = 0; - size_t size = 2048; - char * buffer; - - buffer = (char *) ms_malloc(size); - - content.type = ms_strdup("application"); - content.subtype = ms_strdup("vq-rtcpxr"); - - append_to_buffer(&buffer, &size, &offset, "VQSessionReport: CallTerm\r\n"); - append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", report->info.call_id); - append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", report->info.local_id); - append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", report->info.remote_id); - append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", report->info.orig_id); - - APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "LocalGroup: %s\r\n", report->info.local_group); - APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "RemoteGroup: %s\r\n", report->info.remote_group); - append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.local_addr.ip, report->info.local_addr.port, report->info.local_addr.ssrc); - APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "LocalMAC: %s\r\n", report->info.local_mac_addr); - append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.remote_addr.ip, report->info.remote_addr.port, report->info.remote_addr.ssrc); - APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "RemoteMAC: %s\r\n", report->info.remote_mac_addr); - - append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); - append_metrics_to_buffer(&buffer, &size, &offset, report->local_metrics); - - append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); - append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics); - APPEND_STR_TO_BUFFER(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id); - - content.data = buffer; - - // for debug purpose only - PRINT(content.data); - - content.size = strlen((char*)content.data); - - addr = linphone_address_new("sip:collector@sip.linphone.org"); - linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); - linphone_address_destroy(addr); -} - void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { - reporting_session_report_t * report = call->reports[stats_type]; + reporting_session_report_t * report = call->log->reports[stats_type]; reporting_content_metrics_t * metrics = NULL; reporting_addr_t * addr = NULL; @@ -394,11 +411,46 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { void linphone_reporting_publish(LinphoneCall* call) { printf("linphone_reporting_publish\n"); - if (call->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) { - reporting_publish(call, call->reports[LINPHONE_CALL_STATS_AUDIO]); + if (call->log->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) { + reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO]); } - if (call->reports[LINPHONE_CALL_STATS_VIDEO] != NULL) { - reporting_publish(call, call->reports[LINPHONE_CALL_STATS_VIDEO]); + if (call->log->reports[LINPHONE_CALL_STATS_VIDEO] != NULL + && linphone_call_params_video_enabled(linphone_call_get_current_params(call))) { + reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_VIDEO]); } } + +reporting_session_report_t * linphone_reporting_new() { + int i; + reporting_session_report_t * rm = ms_new0(reporting_session_report_t,1); + + reporting_content_metrics_t * metrics[2] = {&rm->local_metrics, &rm->remote_metrics}; + for (i = 0; i < 2; i++) { + metrics[i]->session_description.payload_type = -1; + metrics[i]->session_description.sample_rate = -1; + metrics[i]->session_description.frame_duration = -1; + + metrics[i]->packet_loss.network_packet_loss_rate = -1; + metrics[i]->packet_loss.jitter_buffer_discard_rate = -1; + + metrics[i]->session_description.packet_loss_concealment = -1; + + metrics[i]->jitter_buffer.adaptive = -1; + metrics[i]->jitter_buffer.rate = -1; + metrics[i]->jitter_buffer.nominal = -1; + metrics[i]->jitter_buffer.max = -1; + metrics[i]->jitter_buffer.abs_max = -1; + + metrics[i]->delay.round_trip_delay = -1; + metrics[i]->delay.end_system_delay = -1; + // metrics[i]->delay.one_way_delay = -1; + metrics[i]->delay.symm_one_way_delay = -1; + metrics[i]->delay.interarrival_jitter = -1; + metrics[i]->delay.mean_abs_jitter = -1; + + metrics[i]->signal.level = 127; + metrics[i]->signal.noise_level = 127; + } + return rm; +} diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index 1c4a3ca4d..a59b1b8db 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -136,6 +136,7 @@ typedef struct reporting_session_report { char * dialog_id; // optional } reporting_session_report_t; +reporting_session_report_t * linphone_reporting_new(); reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int stats_type); void linphone_reporting_publish(LinphoneCall* call); void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type); From 05b75f760962f6815011b53cb089003f589a1762 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Fri, 11 Apr 2014 15:35:21 +0200 Subject: [PATCH 20/83] Quality reporting: store struct in LinphoneLog instead of LinphoneCall, and added new/destroy methods --- coreapi/linphonecall.c | 3 - coreapi/linphonecore.c | 6 ++ coreapi/quality_reporting.c | 202 ++++++++++++++++++------------------ coreapi/quality_reporting.h | 3 +- 4 files changed, 111 insertions(+), 103 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index feb96ee1c..b64cacca2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -483,9 +483,6 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, call->owns_call_log=TRUE; call->camera_enabled=TRUE; - call->log->reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); - call->log->reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); - linphone_core_get_audio_port_range(call->core, &min_port, &max_port); port_config_set(call,0,min_port,max_port); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 1d23a929a..af627ad4c 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -128,6 +128,9 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *fro cl->to=to; cl->status=LinphoneCallAborted; /*default status*/ cl->quality=-1; + + cl->reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); + cl->reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); return cl; } @@ -391,6 +394,9 @@ void linphone_call_log_destroy(LinphoneCallLog *cl){ if (cl->to!=NULL) linphone_address_destroy(cl->to); if (cl->refkey!=NULL) ms_free(cl->refkey); if (cl->call_id) ms_free(cl->call_id); + if (cl->reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reports[LINPHONE_CALL_STATS_AUDIO]); + if (cl->reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reports[LINPHONE_CALL_STATS_VIDEO]); + ms_free(cl); } diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 920455ac7..25ac63438 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -25,6 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "private.h" #include "sal/sal.h" + +#include "ortp/rtpsession.h" + #include /*************************************************************************** @@ -34,28 +37,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // only if call succeeded and ran // TO_CHECK: executed AFTER BYE's "OK" response has been received - // memory leaks + char* strdup // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). - // si l'autre en face a pas activé le partage de rtcp xr, on a pas de paquets du tout ? faut rien faire dans ce cas ? - // si aucune data d'une catégorie est renseigné, ne pas mettre la section dans le paquet - // stats - // valeur pour "expires" ? - // packet_loss_concealment - // jitter buffer rate / adaptive - // jitter_buffer_discard_rate; - // network_packet_loss_rate - // vérifier les valeurs par défaut etc. - // ip local potientellement vide - // remote : ip, port, timestamps, session desc - // dialog id ? + + // cgdb: pourquoi pas de breakpoint dans mon fichier? + // remote: session desc pourquoi c'est null + // Jehan: dialog id ? --> local / remote tag pas accessible + // à voir : + // Simon: ip remote vide + // valeur pour "expires" ? // video : que se passe t-il si on arrete / resume la vidéo (new stream) // valeurs instanannées : moyenne ? valeur extreme ? // à qui / comment on envoit ? (collector@sip.linphone.com ?) // only if this is a linphone account? - -#define PRINT2(x, f) printf(#x ": " #f "\n", x) -#define PRINT(x) PRINT2(x, "%s") + // ip local potientellement vide + // rlq: il faut un algo // since printf family functions are LOCALE dependent, float separator may differ // depending on the user's locale (LC_NUMERIC env var). @@ -145,7 +141,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off append_to_buffer(buffer, size, offset, "\r\nJitterBuffer:"); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBA=%d", rm.jitter_buffer.adaptive, 0, 3); - APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15); + // APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max, 0, 65535); @@ -235,7 +231,7 @@ static void reporting_publish(LinphoneCall* call, reporting_session_report_t * r content.data = buffer; // for debug purpose only - PRINT(content.data); + printf("%s\n", content.data); content.size = strlen((char*)content.data); @@ -250,9 +246,14 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int reporting_session_report_t * report = call->log->reports[stats_type]; MediaStream stream; const MSQualityIndicator * qi = NULL; - const PayloadType * payload; + const PayloadType * local_payload; + const PayloadType * remote_payload; RtpSession * session = NULL; + SalMediaDescription * remote_smd = NULL; + SalStreamType sal_stream_type = (stats_type == LINPHONE_CALL_STATS_AUDIO) ? SalAudio : SalVideo; + // const char* from_tag; + // const char* to_tag; if (report == NULL) { ms_warning("No reporting created for this stream"); @@ -261,83 +262,90 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int if (stats_type == LINPHONE_CALL_STATS_AUDIO) { stream = call->audiostream->ms; - payload = call->current_params.audio_codec; + local_payload = call->current_params.audio_codec; + remote_payload = linphone_call_get_remote_params(call)->audio_codec; } else { stream = call->videostream->ms; - payload = call->current_params.video_codec; + local_payload = call->current_params.video_codec; + remote_payload = linphone_call_get_remote_params(call)->video_codec; } session = stream.sessions.rtp_session; qi = media_stream_get_quality_indicator(&stream); report->info.local_addr.ssrc = rtp_session_get_send_ssrc(session); - report->info.local_addr.port = rtp_session_get_local_port(session); report->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(session); - // memcpy(report->info.remote_addr.ip, &session->rtp.rem_addr, session->rtp.rem_addrlen); - report->info.call_id = call->log->call_id; - report->info.local_group = ms_strdup_printf(_("linphone-%s"), report->info.call_id); - report->info.remote_group = ms_strdup(report->info.local_group); - for (count = 0; count < call->resultdesc->n_total_streams; ++count) { - if (call->resultdesc->streams[count].type == stats_type) { - report->info.local_addr.ip = ms_strdup(call->resultdesc->streams[count].rtp_addr); + report->info.call_id = ms_strdup(call->log->call_id); + + report->info.local_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_core_get_user_agent_name(), report->info.call_id); + report->info.remote_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_call_get_remote_user_agent(call), report->info.call_id); + for (count = 0; count < call->localdesc->n_total_streams; ++count) { + if (call->localdesc->streams[count].type == sal_stream_type) { + report->info.local_addr.ip = ms_strdup(call->localdesc->streams[count].rtp_addr); + report->info.local_addr.port = call->localdesc->streams[count].rtp_port; break; } } if (count == call->resultdesc->n_total_streams) { - ms_warning("Could not find the associated stream of type %d", stats_type); + ms_warning("Could not find the associated stream of type %d for local desc", sal_stream_type); + } + + remote_smd = sal_call_get_remote_media_description(call->op); + if (remote_smd != NULL) { + for (count = 0; count < remote_smd->n_total_streams; ++count) { + if (remote_smd->streams[count].type == sal_stream_type) { + report->info.remote_addr.ip = ms_strdup(remote_smd->streams[count].rtp_addr); + report->info.remote_addr.port = remote_smd->streams[count].rtp_port; + break; + } + } + } + if (remote_smd == NULL || count == remote_smd->n_total_streams) { + ms_warning("Could not find the associated stream of type %d for remote desc", sal_stream_type); } - if (payload != NULL) { - report->local_metrics.session_description.payload_type = payload->type; - report->local_metrics.session_description.payload_desc = ms_strdup(payload->mime_type); - report->local_metrics.session_description.sample_rate = payload->clock_rate; - report->local_metrics.session_description.fmtp = ms_strdup(payload->recv_fmtp); - } else { - // ... + if (local_payload != NULL) { + report->local_metrics.session_description.payload_type = local_payload->type; + report->local_metrics.session_description.payload_desc = ms_strdup(local_payload->mime_type); + report->local_metrics.session_description.sample_rate = local_payload->clock_rate; + report->local_metrics.session_description.fmtp = ms_strdup(local_payload->recv_fmtp); } - report->local_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); - if (10 <= report->local_metrics.quality_estimates.rlq - && report->local_metrics.quality_estimates.rlq <= 50) { - report->local_metrics.quality_estimates.moslq = report->local_metrics.quality_estimates.rlq / 10.f; - } else { - report->local_metrics.quality_estimates.moslq = -1; + if (remote_payload != NULL) { + report->remote_metrics.session_description.payload_type = remote_payload->type; + report->remote_metrics.session_description.payload_desc = ms_strdup(remote_payload->mime_type); + report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; + report->remote_metrics.session_description.fmtp = ms_strdup(remote_payload->recv_fmtp); } - report->local_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); - if (10 <= report->local_metrics.quality_estimates.rcq - && report->local_metrics.quality_estimates.rcq <= 50) { - report->local_metrics.quality_estimates.moscq = report->local_metrics.quality_estimates.rcq / 10.f; - } else { - report->local_metrics.quality_estimates.moscq = -1; - } - + if (call->dir == LinphoneCallIncoming) { report->info.remote_id = linphone_address_as_string(call->log->from); report->info.local_id = linphone_address_as_string(call->log->to); - report->info.orig_id = report->info.remote_id; + report->info.orig_id = ms_strdup(report->info.remote_id); + // from_tag=belle_sip_dialog_get_local_tag(call->op->dialog); + // to_tag=belle_sip_dialog_get_remote_tag(call->op->dialog); } else { report->info.remote_id = linphone_address_as_string(call->log->to); report->info.local_id = linphone_address_as_string(call->log->from); - report->info.orig_id = report->info.local_id; + report->info.orig_id = ms_strdup(report->info.local_id); + // to_tag=belle_sip_dialog_get_local_tag(call->op->dialog); + // from_tag=belle_sip_dialog_get_remote_tag(call->op->dialog); } + report->dialog_id = ms_strdup_printf("%s;to-tag=%s;from-tag=%s", report->info.call_id, "", ""); + report->local_metrics.timestamps.start = call->log->start_date_time; report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + //we use same timestamps for remote too + report->remote_metrics.timestamps.start = call->log->start_date_time; + report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); - report->remote_metrics.quality_estimates.rlq = ms_quality_indicator_get_lq_rating(qi); - if (10 <= report->remote_metrics.quality_estimates.rlq - && report->remote_metrics.quality_estimates.rlq <= 50) { - report->remote_metrics.quality_estimates.moslq = report->remote_metrics.quality_estimates.rlq / 10.f; - } else { - report->remote_metrics.quality_estimates.moslq = -1; - } - report->remote_metrics.quality_estimates.rcq = ms_quality_indicator_get_rating(qi); - if (10 <= report->remote_metrics.quality_estimates.rcq - && report->remote_metrics.quality_estimates.rcq <= 50) { - report->remote_metrics.quality_estimates.moscq = report->remote_metrics.quality_estimates.rcq / 10.f; - } else { - report->remote_metrics.quality_estimates.moscq = -1; - } + + // report->local_metrics.quality_estimates.rlq = + report->local_metrics.quality_estimates.moslq = ms_quality_indicator_get_average_lq_rating(qi); + + // report->local_metrics.quality_estimates.rcq = ;// + report->local_metrics.quality_estimates.moscq = ms_quality_indicator_get_average_rating(qi); return report; } @@ -365,43 +373,19 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { } if (block != NULL) { switch (rtcp_XR_get_block_type(block)) { - case RTCP_XR_STAT_SUMMARY: - // rtcp_XR_stat_summary_get_flags(block); - // rtcp_XR_stat_summary_get_ssrc(block); - // rtcp_XR_stat_summary_get_begin_seq(block); - // rtcp_XR_stat_summary_get_end_seq(block); - // rtcp_XR_stat_summary_get_lost_packets(block); - // rtcp_XR_stat_summary_get_dup_packets(block); - // rtcp_XR_stat_summary_get_min_jitter(block); - // rtcp_XR_stat_summary_get_max_jitter(block); - // rtcp_XR_stat_summary_get_mean_jitter(block); - // rtcp_XR_stat_summary_get_dev_jitter(block); - // rtcp_XR_stat_summary_get_min_ttl_or_hl(block); - // rtcp_XR_stat_summary_get_max_ttl_or_hl(block); - // rtcp_XR_stat_summary_get_mean_ttl_or_hl(block); - // rtcp_XR_stat_summary_get_dev_ttl_or_hl(block); - break; case RTCP_XR_VOIP_METRICS: - // rtcp_XR_voip_metrics_get_ssrc(block); - // rtcp_XR_voip_metrics_get_loss_rate(block); - // rtcp_XR_voip_metrics_get_discard_rate(block); - // rtcp_XR_voip_metrics_get_burst_density(block); - // rtcp_XR_voip_metrics_get_gap_density(block); - // rtcp_XR_voip_metrics_get_burst_duration(block); - // rtcp_XR_voip_metrics_get_gap_duration(block); - // rtcp_XR_voip_metrics_get_round_trip_delay(block); - // rtcp_XR_voip_metrics_get_end_system_delay(block); - // rtcp_XR_voip_metrics_get_signal_level(block); - // rtcp_XR_voip_metrics_get_noise_level(block); - // rtcp_XR_voip_metrics_get_rerl(block); - // rtcp_XR_voip_metrics_get_gmin(block); - metrics->quality_estimates.rlq = rtcp_XR_voip_metrics_get_r_factor(block); + metrics->quality_estimates.rcq = rtcp_XR_voip_metrics_get_r_factor(block); metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block); metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block); - // rtcp_XR_voip_metrics_get_rx_config(block); metrics->jitter_buffer.nominal = rtcp_XR_voip_metrics_get_jb_nominal(block); metrics->jitter_buffer.max = rtcp_XR_voip_metrics_get_jb_maximum(block); metrics->jitter_buffer.abs_max = rtcp_XR_voip_metrics_get_jb_abs_max(block); + metrics->packet_loss.network_packet_loss_rate = rtcp_XR_voip_metrics_get_loss_rate(block); + metrics->packet_loss.jitter_buffer_discard_rate = rtcp_XR_voip_metrics_get_discard_rate(block); + + uint8_t config = rtcp_XR_voip_metrics_get_rx_config(block); + metrics->session_description.packet_loss_concealment = (config >> 6) & 0x3; + metrics->jitter_buffer.adaptive = (config >> 4) & 0x3; break; default: break; @@ -437,7 +421,7 @@ reporting_session_report_t * linphone_reporting_new() { metrics[i]->session_description.packet_loss_concealment = -1; metrics[i]->jitter_buffer.adaptive = -1; - metrics[i]->jitter_buffer.rate = -1; + // metrics[i]->jitter_buffer.rate = -1; metrics[i]->jitter_buffer.nominal = -1; metrics[i]->jitter_buffer.max = -1; metrics[i]->jitter_buffer.abs_max = -1; @@ -454,3 +438,23 @@ reporting_session_report_t * linphone_reporting_new() { } return rm; } + +void linphone_reporting_destroy(reporting_session_report_t * report) { + if (report->info.call_id != NULL) ms_free(report->info.call_id); + if (report->info.local_id != NULL) ms_free(report->info.local_id); + if (report->info.remote_id != NULL) ms_free(report->info.remote_id); + if (report->info.orig_id != NULL) ms_free(report->info.orig_id); + if (report->info.local_addr.ip != NULL) ms_free(report->info.local_addr.ip); + if (report->info.remote_addr.ip != NULL) ms_free(report->info.remote_addr.ip); + if (report->info.local_group != NULL) ms_free(report->info.local_group); + if (report->info.remote_group != NULL) ms_free(report->info.remote_group); + if (report->info.local_mac_addr != NULL) ms_free(report->info.local_mac_addr); + if (report->info.remote_mac_addr != NULL) ms_free(report->info.remote_mac_addr); + if (report->dialog_id != NULL) ms_free(report->dialog_id); + if (report->local_metrics.session_description.fmtp != NULL) ms_free(report->local_metrics.session_description.fmtp); + if (report->local_metrics.session_description.payload_desc != NULL) ms_free(report->local_metrics.session_description.payload_desc); + if (report->remote_metrics.session_description.fmtp != NULL) ms_free(report->remote_metrics.session_description.fmtp); + if (report->remote_metrics.session_description.payload_desc != NULL) ms_free(report->remote_metrics.session_description.payload_desc); + + ms_free(report); +} diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index a59b1b8db..b4512d05d 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -56,7 +56,7 @@ typedef struct reporting_content_metrics { // jitter buffet - optional struct { int adaptive; // constant - int rate; // constant + // int rate; // constant int nominal; // no may vary during the call <- average? worst score? int max; // no may vary during the call <- average? int abs_max; // constant @@ -137,6 +137,7 @@ typedef struct reporting_session_report { } reporting_session_report_t; reporting_session_report_t * linphone_reporting_new(); +void linphone_reporting_destroy(reporting_session_report_t * report); reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int stats_type); void linphone_reporting_publish(LinphoneCall* call); void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type); From 1cba3da32ddf82c67e86dc1e77451d1018ed3b7e Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 14 Apr 2014 10:42:42 +0200 Subject: [PATCH 21/83] Quality reporting: fill 'from-tag' and 'to-tag' fields --- coreapi/quality_reporting.c | 19 +++++++------------ coreapi/sal.c | 4 ++++ include/sal/sal.h | 1 + 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 25ac63438..d32bd451f 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -39,7 +39,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). - // cgdb: pourquoi pas de breakpoint dans mon fichier? // remote: session desc pourquoi c'est null // Jehan: dialog id ? --> local / remote tag pas accessible @@ -252,23 +251,23 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int SalMediaDescription * remote_smd = NULL; SalStreamType sal_stream_type = (stats_type == LINPHONE_CALL_STATS_AUDIO) ? SalAudio : SalVideo; - // const char* from_tag; - // const char* to_tag; - if (report == NULL) { ms_warning("No reporting created for this stream"); return NULL; } - if (stats_type == LINPHONE_CALL_STATS_AUDIO) { + if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { stream = call->audiostream->ms; local_payload = call->current_params.audio_codec; remote_payload = linphone_call_get_remote_params(call)->audio_codec; - } else { + } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) { stream = call->videostream->ms; local_payload = call->current_params.video_codec; remote_payload = linphone_call_get_remote_params(call)->video_codec; + } else { + return NULL; } + session = stream.sessions.rtp_session; qi = media_stream_get_quality_indicator(&stream); @@ -285,7 +284,7 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int break; } } - if (count == call->resultdesc->n_total_streams) { + if (count == call->localdesc->n_total_streams) { ms_warning("Could not find the associated stream of type %d for local desc", sal_stream_type); } @@ -321,16 +320,12 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int report->info.remote_id = linphone_address_as_string(call->log->from); report->info.local_id = linphone_address_as_string(call->log->to); report->info.orig_id = ms_strdup(report->info.remote_id); - // from_tag=belle_sip_dialog_get_local_tag(call->op->dialog); - // to_tag=belle_sip_dialog_get_remote_tag(call->op->dialog); } else { report->info.remote_id = linphone_address_as_string(call->log->to); report->info.local_id = linphone_address_as_string(call->log->from); report->info.orig_id = ms_strdup(report->info.local_id); - // to_tag=belle_sip_dialog_get_local_tag(call->op->dialog); - // from_tag=belle_sip_dialog_get_remote_tag(call->op->dialog); } - report->dialog_id = ms_strdup_printf("%s;to-tag=%s;from-tag=%s", report->info.call_id, "", ""); + report->dialog_id = sal_op_get_dialog_id(call->op); report->local_metrics.timestamps.start = call->log->start_date_time; report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); diff --git a/coreapi/sal.c b/coreapi/sal.c index 6f2256ac9..d64240ef3 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -372,6 +372,10 @@ const char *sal_op_get_network_origin(const SalOp *op){ const char* sal_op_get_call_id(const SalOp *op) { return ((SalOpBase*)op)->call_id; } +char* sal_op_get_dialog_id(const SalOp *op) { + return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id, + belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog)); +} void __sal_op_init(SalOp *b, Sal *sal){ memset(b,0,sizeof(SalOpBase)); ((SalOpBase*)b)->root=sal; diff --git a/include/sal/sal.h b/include/sal/sal.h index 1dba31f90..7ec00f596 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -572,6 +572,7 @@ const SalAddress *sal_op_get_network_origin_address(const SalOp *op); const char *sal_op_get_remote_ua(const SalOp *op); void *sal_op_get_user_pointer(const SalOp *op); const char* sal_op_get_call_id(const SalOp *op); +char* sal_op_get_dialog_id(const SalOp *op); const SalAddress* sal_op_get_service_route(const SalOp *op); void sal_op_set_service_route(SalOp *op,const SalAddress* service_route); From 40d688f569406c67bac5f5c27cef530e2ca765ad Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 14 Apr 2014 11:40:55 +0200 Subject: [PATCH 22/83] Quality reporting: add security in get_dialog_id method since dialog might be null --- coreapi/quality_reporting.c | 32 ++++++++++++++++---------------- coreapi/sal.c | 8 ++++++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index d32bd451f..e9a3cc6f1 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -33,23 +33,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*************************************************************************** * TODO / REMINDER LIST ****************************************************************************/ - // place pour appeler la fonction submit - // only if call succeeded and ran - // TO_CHECK: executed AFTER BYE's "OK" response has been received + // only if call succeeded and ran (busy should NOT call this) + // TO_CHECK: executed AFTER BYE's "OK" response has been received // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). - // remote: session desc pourquoi c'est null - // Jehan: dialog id ? --> local / remote tag pas accessible - + // remote: session desc null parce que linphone_call_get_remote_params le remplit pas + // à voir : // Simon: ip remote vide + // ip local potientellement vide // valeur pour "expires" ? + // à voir ++ : // video : que se passe t-il si on arrete / resume la vidéo (new stream) // valeurs instanannées : moyenne ? valeur extreme ? // à qui / comment on envoit ? (collector@sip.linphone.com ?) // only if this is a linphone account? - // ip local potientellement vide // rlq: il faut un algo // since printf family functions are LOCALE dependent, float separator may differ @@ -244,7 +243,7 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int int count; reporting_session_report_t * report = call->log->reports[stats_type]; MediaStream stream; - const MSQualityIndicator * qi = NULL; + // const MSQualityIndicator * qi = NULL; const PayloadType * local_payload; const PayloadType * remote_payload; RtpSession * session = NULL; @@ -258,18 +257,17 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { stream = call->audiostream->ms; - local_payload = call->current_params.audio_codec; - remote_payload = linphone_call_get_remote_params(call)->audio_codec; + local_payload = linphone_call_params_get_used_audio_codec(&call->current_params); + remote_payload = linphone_call_params_get_used_audio_codec(linphone_call_get_remote_params(call)); } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) { stream = call->videostream->ms; - local_payload = call->current_params.video_codec; - remote_payload = linphone_call_get_remote_params(call)->video_codec; + local_payload = linphone_call_params_get_used_video_codec(&call->current_params); + remote_payload = linphone_call_params_get_used_video_codec(linphone_call_get_remote_params(call)); } else { return NULL; } session = stream.sessions.rtp_session; - qi = media_stream_get_quality_indicator(&stream); report->info.local_addr.ssrc = rtp_session_get_send_ssrc(session); report->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(session); @@ -325,6 +323,7 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int report->info.local_id = linphone_address_as_string(call->log->from); report->info.orig_id = ms_strdup(report->info.local_id); } + report->dialog_id = sal_op_get_dialog_id(call->op); report->local_metrics.timestamps.start = call->log->start_date_time; @@ -336,11 +335,11 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int + // qi = media_stream_get_quality_indicator(&stream); // report->local_metrics.quality_estimates.rlq = - report->local_metrics.quality_estimates.moslq = ms_quality_indicator_get_average_lq_rating(qi); - + // report->local_metrics.quality_estimates.moslq = ms_quality_indicator_get_average_lq_rating(qi); // report->local_metrics.quality_estimates.rcq = ;// - report->local_metrics.quality_estimates.moscq = ms_quality_indicator_get_average_rating(qi); + // report->local_metrics.quality_estimates.moscq = ms_quality_indicator_get_average_rating(qi); return report; } @@ -390,6 +389,7 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { void linphone_reporting_publish(LinphoneCall* call) { printf("linphone_reporting_publish\n"); + if (call->log->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) { reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO]); } diff --git a/coreapi/sal.c b/coreapi/sal.c index d64240ef3..a3ec66b45 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -373,8 +373,12 @@ const char* sal_op_get_call_id(const SalOp *op) { return ((SalOpBase*)op)->call_id; } char* sal_op_get_dialog_id(const SalOp *op) { - return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id, - belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog)); + if (op->dialog != NULL) { + return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id, + belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog)); + } + return NULL; + } void __sal_op_init(SalOp *b, Sal *sal){ memset(b,0,sizeof(SalOpBase)); From a8ba7b7993615f7adc8f05631e4066caf02616f1 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 14 Apr 2014 16:31:46 +0200 Subject: [PATCH 23/83] Quality reporting: fix IP/port fields --- coreapi/linphonecall.c | 15 ++- coreapi/quality_reporting.c | 193 ++++++++++++++++++++---------------- coreapi/quality_reporting.h | 3 +- 3 files changed, 121 insertions(+), 90 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index b64cacca2..db3b000ab 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -773,7 +773,6 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const return; } } - ms_message("Call %p: moving from state %s to %s",call,linphone_call_state_to_string(call->state), linphone_call_state_to_string(cstate)); @@ -801,10 +800,16 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const call->media_start_time=time(NULL); } + if (cstate == LinphoneCallStreamsRunning) { + linphone_reporting_update_ip(call); + } + if (lc->vtable.call_state_changed) lc->vtable.call_state_changed(lc,call,cstate,message); if (cstate==LinphoneCallReleased){ - linphone_reporting_publish(call); + + if (call->log->status == LinphoneCallSuccess) + linphone_reporting_publish(call); if (call->op!=NULL) { /*transfer the last error so that it can be obtained even in Released state*/ @@ -2754,7 +2759,8 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse evd->packet = NULL; call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); - linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); + if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) + linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { @@ -2765,7 +2771,8 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse evd->packet = NULL; call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); - linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); + if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) + linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); if (lc->vtable.call_stats_updated) lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index e9a3cc6f1..aee3d7b44 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -33,21 +33,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*************************************************************************** * TODO / REMINDER LIST ****************************************************************************/ - // only if call succeeded and ran (busy should NOT call this) + // TO_CHECK: only if call succeeded and ran (busy should NOT call this) // TO_CHECK: executed AFTER BYE's "OK" response has been received // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). // remote: session desc null parce que linphone_call_get_remote_params le remplit pas - // à voir : - // Simon: ip remote vide - // ip local potientellement vide - // valeur pour "expires" ? + // payload distant supposons que c les meme que locaux pour l'instant + // verifier char* avant assignation + // abstraction audio video + // tests liblinphonetester + // valgrind --leakcheck=full + // configurable global publish_call_statistics linphone_proxy_config_set_statistics_collector enable_collector // à voir ++ : // video : que se passe t-il si on arrete / resume la vidéo (new stream) // valeurs instanannées : moyenne ? valeur extreme ? - // à qui / comment on envoit ? (collector@sip.linphone.com ?) // only if this is a linphone account? // rlq: il faut un algo @@ -196,7 +197,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off static void reporting_publish(LinphoneCall* call, reporting_session_report_t * report) { LinphoneContent content = {0}; LinphoneAddress *addr; - int expires = 3600; + int expires = -1; size_t offset = 0; size_t size = 2048; char * buffer; @@ -229,7 +230,7 @@ static void reporting_publish(LinphoneCall* call, reporting_session_report_t * r content.data = buffer; // for debug purpose only - printf("%s\n", content.data); + printf("%s\n", (char*) content.data); content.size = strlen((char*)content.data); @@ -238,82 +239,83 @@ static void reporting_publish(LinphoneCall* call, reporting_session_report_t * r linphone_address_destroy(addr); } -reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int stats_type) { - printf("linphone_reporting_call_stats_updated\n"); - int count; - reporting_session_report_t * report = call->log->reports[stats_type]; - MediaStream stream; - // const MSQualityIndicator * qi = NULL; - const PayloadType * local_payload; - const PayloadType * remote_payload; - RtpSession * session = NULL; - SalMediaDescription * remote_smd = NULL; - SalStreamType sal_stream_type = (stats_type == LINPHONE_CALL_STATS_AUDIO) ? SalAudio : SalVideo; - if (report == NULL) { - ms_warning("No reporting created for this stream"); - return NULL; - } - - if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { - stream = call->audiostream->ms; - local_payload = linphone_call_params_get_used_audio_codec(&call->current_params); - remote_payload = linphone_call_params_get_used_audio_codec(linphone_call_get_remote_params(call)); - } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) { - stream = call->videostream->ms; - local_payload = linphone_call_params_get_used_video_codec(&call->current_params); - remote_payload = linphone_call_params_get_used_video_codec(linphone_call_get_remote_params(call)); - } else { - return NULL; - } - - session = stream.sessions.rtp_session; - - report->info.local_addr.ssrc = rtp_session_get_send_ssrc(session); - report->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(session); - report->info.call_id = ms_strdup(call->log->call_id); - - report->info.local_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_core_get_user_agent_name(), report->info.call_id); - report->info.remote_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_call_get_remote_user_agent(call), report->info.call_id); - for (count = 0; count < call->localdesc->n_total_streams; ++count) { - if (call->localdesc->streams[count].type == sal_stream_type) { - report->info.local_addr.ip = ms_strdup(call->localdesc->streams[count].rtp_addr); - report->info.local_addr.port = call->localdesc->streams[count].rtp_port; - break; - } - } - if (count == call->localdesc->n_total_streams) { - ms_warning("Could not find the associated stream of type %d for local desc", sal_stream_type); - } - - remote_smd = sal_call_get_remote_media_description(call->op); +static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDescription * remote_smd, SalStreamType sal_stream_type) { if (remote_smd != NULL) { + int count; for (count = 0; count < remote_smd->n_total_streams; ++count) { if (remote_smd->streams[count].type == sal_stream_type) { - report->info.remote_addr.ip = ms_strdup(remote_smd->streams[count].rtp_addr); - report->info.remote_addr.port = remote_smd->streams[count].rtp_port; - break; + return &remote_smd->streams[count]; + } + } + if (remote_smd == NULL || count == remote_smd->n_total_streams) { + ms_warning("Could not find the associated stream of type %d for remote desc", sal_stream_type); + } + } + + return NULL; +} + +static void reporting_update_ip(LinphoneCall * call, int stats_type) { + SalStreamType sal_stream_type = (stats_type == LINPHONE_CALL_STATS_AUDIO) ? SalAudio : SalVideo; + if (call->log->reports[stats_type] != NULL) { + const SalStreamDescription * local_desc = get_media_stream_for_desc(call->localdesc, sal_stream_type); + const SalStreamDescription * remote_desc = get_media_stream_for_desc(sal_call_get_remote_media_description(call->op), sal_stream_type); + + // local info are always up-to-date and correct + if (local_desc != NULL) { + call->log->reports[stats_type]->info.local_addr.port = local_desc->rtp_port; + call->log->reports[stats_type]->info.local_addr.ip = ms_strdup(local_desc->rtp_addr); + } + + if (remote_desc != NULL) { + // port is always stored in stream description struct + call->log->reports[stats_type]->info.remote_addr.port = remote_desc->rtp_port; + + // for IP it can be not set if we are using a direct route + if (remote_desc->rtp_addr != NULL && strlen(remote_desc->rtp_addr) > 0) { + call->log->reports[stats_type]->info.remote_addr.ip = ms_strdup(remote_desc->rtp_addr); + } else { + call->log->reports[stats_type]->info.remote_addr.ip = ms_strdup(sal_call_get_remote_media_description(call->op)->addr); } } } - if (remote_smd == NULL || count == remote_smd->n_total_streams) { - ms_warning("Could not find the associated stream of type %d for remote desc", sal_stream_type); +} + +void linphone_reporting_update_ip(LinphoneCall * call) { + printf("linphone_reporting_update_remote_ip\n"); + + // This function can be called in two different cases: + // - 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered + // - 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access + + reporting_update_ip(call, LINPHONE_CALL_STATS_AUDIO); + + if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) { + reporting_update_ip(call, LINPHONE_CALL_STATS_VIDEO); } - - if (local_payload != NULL) { - report->local_metrics.session_description.payload_type = local_payload->type; - report->local_metrics.session_description.payload_desc = ms_strdup(local_payload->mime_type); - report->local_metrics.session_description.sample_rate = local_payload->clock_rate; - report->local_metrics.session_description.fmtp = ms_strdup(local_payload->recv_fmtp); +} + +void linphone_reporting_update(LinphoneCall * call, int stats_type) { + printf("linphone_reporting_call_stats_updated type=%d\n", stats_type); + reporting_session_report_t * report = call->log->reports[stats_type]; + MediaStream * stream = NULL; + const SalMediaDescription * remote_media_desc = sal_call_get_remote_media_description(call->op); + const PayloadType * local_payload = NULL; + const PayloadType * remote_payload = NULL; + const SalStreamDescription * remote_desc = NULL; + SalStreamType sal_stream_type = (stats_type == LINPHONE_CALL_STATS_AUDIO) ? SalAudio : SalVideo; + const LinphoneCallParams * local_params = linphone_call_get_current_params(call); + const LinphoneCallParams * remote_params = linphone_call_get_remote_params(call); + if (report == NULL) { + ms_warning("No reporting created for this stream"); + return; } - if (remote_payload != NULL) { - report->remote_metrics.session_description.payload_type = remote_payload->type; - report->remote_metrics.session_description.payload_desc = ms_strdup(remote_payload->mime_type); - report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; - report->remote_metrics.session_description.fmtp = ms_strdup(remote_payload->recv_fmtp); - } - + report->info.call_id = ms_strdup(call->log->call_id); + report->info.local_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_core_get_user_agent_name(), report->info.call_id); + report->info.remote_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_call_get_remote_user_agent(call), report->info.call_id); + if (call->dir == LinphoneCallIncoming) { report->info.remote_id = linphone_address_as_string(call->log->from); report->info.local_id = linphone_address_as_string(call->log->to); @@ -332,42 +334,62 @@ reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int //we use same timestamps for remote too report->remote_metrics.timestamps.start = call->log->start_date_time; report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + + if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { + stream = &call->audiostream->ms; + local_payload = linphone_call_params_get_used_audio_codec(local_params); + if (remote_params != NULL) + remote_payload = linphone_call_params_get_used_audio_codec(remote_params); + } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) { + stream = &call->videostream->ms; + local_payload = linphone_call_params_get_used_video_codec(local_params); + if (remote_params != NULL) + remote_payload = linphone_call_params_get_used_video_codec(linphone_call_get_remote_params(call)); + } + if (stream != NULL) { + RtpSession * session = stream->sessions.rtp_session; + report->info.local_addr.ssrc = rtp_session_get_send_ssrc(session); + report->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(session); + } - // qi = media_stream_get_quality_indicator(&stream); - // report->local_metrics.quality_estimates.rlq = - // report->local_metrics.quality_estimates.moslq = ms_quality_indicator_get_average_lq_rating(qi); - // report->local_metrics.quality_estimates.rcq = ;// - // report->local_metrics.quality_estimates.moscq = ms_quality_indicator_get_average_rating(qi); + if (local_payload != NULL) { + report->local_metrics.session_description.payload_type = local_payload->type; + report->local_metrics.session_description.payload_desc = ms_strdup(local_payload->mime_type); + report->local_metrics.session_description.sample_rate = local_payload->clock_rate; + report->local_metrics.session_description.fmtp = ms_strdup(local_payload->recv_fmtp); + } - return report; + if (remote_payload != NULL) { + report->remote_metrics.session_description.payload_type = remote_payload->type; + report->remote_metrics.session_description.payload_desc = ms_strdup(remote_payload->mime_type); + report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; + report->remote_metrics.session_description.fmtp = ms_strdup(remote_payload->recv_fmtp); + } } void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { reporting_session_report_t * report = call->log->reports[stats_type]; reporting_content_metrics_t * metrics = NULL; - reporting_addr_t * addr = NULL; LinphoneCallStats stats = call->stats[stats_type]; mblk_t *block = NULL; if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { metrics = &report->remote_metrics; - addr = &report->info.remote_addr; if (rtcp_is_XR(stats.received_rtcp) == TRUE) { block = stats.received_rtcp; } } else if (stats.updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { metrics = &report->local_metrics; - addr = &report->info.local_addr; if (rtcp_is_XR(stats.sent_rtcp) == TRUE) { block = stats.sent_rtcp; } } if (block != NULL) { switch (rtcp_XR_get_block_type(block)) { - case RTCP_XR_VOIP_METRICS: + case RTCP_XR_VOIP_METRICS: { metrics->quality_estimates.rcq = rtcp_XR_voip_metrics_get_r_factor(block); metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block); metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block); @@ -381,8 +403,9 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { metrics->session_description.packet_loss_concealment = (config >> 6) & 0x3; metrics->jitter_buffer.adaptive = (config >> 4) & 0x3; break; - default: + } default: { break; + } } } } diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index b4512d05d..f3d311ad9 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -138,7 +138,8 @@ typedef struct reporting_session_report { reporting_session_report_t * linphone_reporting_new(); void linphone_reporting_destroy(reporting_session_report_t * report); -reporting_session_report_t * linphone_reporting_update(LinphoneCall * call, int stats_type); +void linphone_reporting_update(LinphoneCall * call, int stats_type); +void linphone_reporting_update_ip(LinphoneCall * call); void linphone_reporting_publish(LinphoneCall* call); void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type); #ifdef __cplusplus From 6e385691285a63e706f0dd1f7a29190aaade044e Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 14 Apr 2014 16:36:06 +0200 Subject: [PATCH 24/83] Quality reporting: remove unused variables --- coreapi/quality_reporting.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index aee3d7b44..84a14e9f5 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -300,11 +300,8 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { printf("linphone_reporting_call_stats_updated type=%d\n", stats_type); reporting_session_report_t * report = call->log->reports[stats_type]; MediaStream * stream = NULL; - const SalMediaDescription * remote_media_desc = sal_call_get_remote_media_description(call->op); const PayloadType * local_payload = NULL; const PayloadType * remote_payload = NULL; - const SalStreamDescription * remote_desc = NULL; - SalStreamType sal_stream_type = (stats_type == LINPHONE_CALL_STATS_AUDIO) ? SalAudio : SalVideo; const LinphoneCallParams * local_params = linphone_call_get_current_params(call); const LinphoneCallParams * remote_params = linphone_call_get_remote_params(call); if (report == NULL) { From 0762b56a36125e6976e5a7fefef2edb3a61a4748 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Tue, 15 Apr 2014 10:43:03 +0200 Subject: [PATCH 25/83] Quality reporting: let the config file choose if it should enable or not this feature (per account choice) --- coreapi/linphonecore.h | 11 ++++ coreapi/private.h | 4 +- coreapi/proxy.c | 43 ++++++++++++ coreapi/quality_reporting.c | 128 ++++++++++++++++++++++-------------- coreapi/sal.c | 2 +- mediastreamer2 | 2 +- 6 files changed, 137 insertions(+), 53 deletions(-) diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 7448341aa..ea03d9874 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -812,6 +812,17 @@ LINPHONE_PUBLIC void linphone_proxy_config_enable_publish(LinphoneProxyConfig *o LINPHONE_PUBLIC void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val); LINPHONE_PUBLIC void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix); +/** + * Indicates either or not, quality statistics during call should be stored and sent to a collector at termination. + * @param cfg #LinphoneProxyConfig object + * @param val if true, quality statistics publish will be stored and sent to the collector + * + */ +LINPHONE_PUBLIC void linphone_proxy_config_enable_statistics(LinphoneProxyConfig *cfg, bool_t val); +LINPHONE_PUBLIC bool_t linphone_proxy_config_send_statistics_enabled(LinphoneProxyConfig *cfg); +LINPHONE_PUBLIC void linphone_proxy_config_set_statistics_collector(LinphoneProxyConfig *cfg, const char *collector); +LINPHONE_PUBLIC const char *linphone_proxy_config_get_statistics_collector(const LinphoneProxyConfig *obj); + /** * Get the registration state of the given proxy config. * @param[in] obj #LinphoneProxyConfig object. diff --git a/coreapi/private.h b/coreapi/private.h index d92371a5a..94605e506 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -117,7 +117,7 @@ struct _LinphoneCallLog{ time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */ char* call_id; /**unique id of a call*/ - reporting_session_report_t * reports[2]; + reporting_session_report_t * reports[2]; /**config, "proxy", "reg_identity", NULL) : NULL; const char *proxy = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_proxy", NULL) : NULL; const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL; + const char *statistics_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_statistics_collector", NULL) : NULL; const char *contact_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_parameters", NULL) : NULL; const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL; @@ -59,6 +60,8 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob obj->reg_identity = identity ? ms_strdup(identity) : NULL; obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL; obj->reg_route = route ? ms_strdup(route) : NULL; + obj->reg_statistics_collector = statistics_collector ? ms_strdup(statistics_collector) : NULL; + obj->send_statistics = lc ? lp_config_get_default_int(lc->config, "proxy", "send_statistics", 0) : 0; obj->contact_params = contact_params ? ms_strdup(contact_params) : NULL; obj->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL; } @@ -93,6 +96,7 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy); if (obj->reg_identity!=NULL) ms_free(obj->reg_identity); if (obj->reg_route!=NULL) ms_free(obj->reg_route); + if (obj->reg_statistics_collector!=NULL) ms_free(obj->reg_statistics_collector); if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx); if (obj->realm!=NULL) ms_free(obj->realm); if (obj->type!=NULL) ms_free(obj->type); @@ -413,6 +417,37 @@ void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){ return cfg->dial_escape_plus; } + +void linphone_proxy_config_enable_statistics(LinphoneProxyConfig *cfg, bool_t val){ + cfg->send_statistics = val; +} + +bool_t linphone_proxy_config_send_statistics_enabled(LinphoneProxyConfig *cfg){ + // ensure that collector address is set too! + return cfg->send_statistics && cfg->reg_statistics_collector != NULL; +} + +void linphone_proxy_config_set_statistics_collector(LinphoneProxyConfig *cfg, const char *collector){ + if (collector!=NULL && strlen(collector)>0){ + LinphoneAddress *addr=linphone_address_new(collector); + if (!addr || linphone_address_get_username(addr)==NULL){ + ms_warning("Invalid sip collector identity: %s",collector); + if (addr) + linphone_address_destroy(addr); + } else { + if (cfg->reg_statistics_collector != NULL) + ms_free(cfg->reg_statistics_collector); + cfg->reg_statistics_collector = ms_strdup(collector); + linphone_address_destroy(addr); + } + } +} + +const char *linphone_proxy_config_get_statistics_collector(const LinphoneProxyConfig *cfg){ + return cfg->reg_statistics_collector; +} + + /* * http://en.wikipedia.org/wiki/Telephone_numbering_plan * http://en.wikipedia.org/wiki/Telephone_numbers_in_Europe @@ -1059,6 +1094,9 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC if (obj->reg_route!=NULL){ lp_config_set_string(config,key,"reg_route",obj->reg_route); } + if (obj->reg_statistics_collector!=NULL){ + lp_config_set_string(config,key,"reg_statistics_collector",obj->reg_statistics_collector); + } if (obj->reg_identity!=NULL){ lp_config_set_string(config,key,"reg_identity",obj->reg_identity); } @@ -1072,6 +1110,7 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister); lp_config_set_int(config,key,"publish",obj->publish); lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus); + lp_config_set_int(config,key,"send_statistics",obj->send_statistics); lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix); lp_config_set_int(config,key,"privacy",obj->privacy); } @@ -1103,6 +1142,10 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config tmp=lp_config_get_string(config,key,"reg_route",NULL); if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp); + tmp=lp_config_get_string(config,key,"reg_statistics_collector",NULL); + if (tmp!=NULL) linphone_proxy_config_set_statistics_collector(cfg,tmp); + linphone_proxy_config_enable_statistics(cfg,lp_config_get_int(config,key,"send_statistics",0)); + linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL)); linphone_proxy_config_set_contact_uri_parameters(cfg,lp_config_get_string(config,key,"contact_uri_parameters",NULL)); diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 84a14e9f5..58727acb7 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -36,21 +36,30 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // TO_CHECK: only if call succeeded and ran (busy should NOT call this) // TO_CHECK: executed AFTER BYE's "OK" response has been received + // TO_CHECK: configurable global publish_call_statistics linphone_proxy_config_set_statistics_collector enable_collector + // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). // remote: session desc null parce que linphone_call_get_remote_params le remplit pas - // payload distant supposons que c les meme que locaux pour l'instant - // verifier char* avant assignation + // range 0 - 255 au lieu de 0 - 5 metrics->quality_estimates.rcq, metrics->quality_estimates.moslq, metrics->quality_estimates.moscq); // abstraction audio video - // tests liblinphonetester // valgrind --leakcheck=full - // configurable global publish_call_statistics linphone_proxy_config_set_statistics_collector enable_collector + // tests liblinphonetester // à voir ++ : // video : que se passe t-il si on arrete / resume la vidéo (new stream) // valeurs instanannées : moyenne ? valeur extreme ? // only if this is a linphone account? // rlq: il faut un algo +/*************************************************************************** + * END OF TODO / REMINDER LIST + ****************************************************************************/ + +#define strass(dest, src) {\ + if (dest != NULL) \ + ms_free(dest); \ + dest = src; \ +} // since printf family functions are LOCALE dependent, float separator may differ // depending on the user's locale (LC_NUMERIC env var). @@ -185,18 +194,19 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg); append_to_buffer(buffer, size, offset, "\r\n"); - free(timestamps_start_str); - free(timestamps_stop_str); - free(network_packet_loss_rate_str); - free(jitter_buffer_discard_rate_str); - // free(gap_loss_density_str); - free(moslq_str); - free(moscq_str); + ms_free(timestamps_start_str); + ms_free(timestamps_stop_str); + ms_free(network_packet_loss_rate_str); + ms_free(jitter_buffer_discard_rate_str); + // ms_free(gap_loss_density_str); + ms_free(moslq_str); + ms_free(moscq_str); } static void reporting_publish(LinphoneCall* call, reporting_session_report_t * report) { LinphoneContent content = {0}; LinphoneAddress *addr; + const char * addr_str; int expires = -1; size_t offset = 0; size_t size = 2048; @@ -228,15 +238,22 @@ static void reporting_publish(LinphoneCall* call, reporting_session_report_t * r APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id); content.data = buffer; - - // for debug purpose only - printf("%s\n", (char*) content.data); - content.size = strlen((char*)content.data); - addr = linphone_address_new("sip:collector@sip.linphone.org"); - linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); - linphone_address_destroy(addr); + + + + addr_str = call->dest_proxy->reg_statistics_collector; + if (addr_str != NULL) { + addr = linphone_address_new(addr_str); + linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); + linphone_address_destroy(addr); + + // for debug purpose only + printf("%s\n", (char*) content.data); + } else { + ms_warning("Asked to submit reporting statistics but no collector address found"); + } } @@ -265,7 +282,7 @@ static void reporting_update_ip(LinphoneCall * call, int stats_type) { // local info are always up-to-date and correct if (local_desc != NULL) { call->log->reports[stats_type]->info.local_addr.port = local_desc->rtp_port; - call->log->reports[stats_type]->info.local_addr.ip = ms_strdup(local_desc->rtp_addr); + strass(call->log->reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr)); } if (remote_desc != NULL) { @@ -274,21 +291,28 @@ static void reporting_update_ip(LinphoneCall * call, int stats_type) { // for IP it can be not set if we are using a direct route if (remote_desc->rtp_addr != NULL && strlen(remote_desc->rtp_addr) > 0) { - call->log->reports[stats_type]->info.remote_addr.ip = ms_strdup(remote_desc->rtp_addr); + strass(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr)); } else { - call->log->reports[stats_type]->info.remote_addr.ip = ms_strdup(sal_call_get_remote_media_description(call->op)->addr); + strass(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(sal_call_get_remote_media_description(call->op)->addr)); } } } } -void linphone_reporting_update_ip(LinphoneCall * call) { - printf("linphone_reporting_update_remote_ip\n"); +static bool_t reporting_enabled(LinphoneCall * call) { + return (call->dest_proxy != NULL && linphone_proxy_config_send_statistics_enabled(call->dest_proxy)); +} +void linphone_reporting_update_ip(LinphoneCall * call) { // This function can be called in two different cases: // - 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered // - 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access + printf("linphone_reporting_update_remote_ip\n"); + + if (! reporting_enabled(call)) + return; + reporting_update_ip(call, LINPHONE_CALL_STATS_AUDIO); if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) { @@ -297,33 +321,32 @@ void linphone_reporting_update_ip(LinphoneCall * call) { } void linphone_reporting_update(LinphoneCall * call, int stats_type) { - printf("linphone_reporting_call_stats_updated type=%d\n", stats_type); reporting_session_report_t * report = call->log->reports[stats_type]; MediaStream * stream = NULL; const PayloadType * local_payload = NULL; const PayloadType * remote_payload = NULL; - const LinphoneCallParams * local_params = linphone_call_get_current_params(call); - const LinphoneCallParams * remote_params = linphone_call_get_remote_params(call); - if (report == NULL) { - ms_warning("No reporting created for this stream"); - return; - } + const LinphoneCallParams * current_params = linphone_call_get_current_params(call); - report->info.call_id = ms_strdup(call->log->call_id); - report->info.local_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_core_get_user_agent_name(), report->info.call_id); - report->info.remote_group = ms_strdup_printf(_("linphone-%s-%s"), linphone_call_get_remote_user_agent(call), report->info.call_id); + printf("linphone_reporting_call_stats_updated type=%d\n", stats_type); + + if (! reporting_enabled(call)) + return; + + strass(report->info.call_id, ms_strdup(call->log->call_id)); + strass(report->info.local_group, ms_strdup_printf(_("linphone-%s-%s"), linphone_core_get_user_agent_name(), report->info.call_id)); + strass(report->info.remote_group, ms_strdup_printf(_("linphone-%s-%s"), linphone_call_get_remote_user_agent(call), report->info.call_id)); if (call->dir == LinphoneCallIncoming) { - report->info.remote_id = linphone_address_as_string(call->log->from); - report->info.local_id = linphone_address_as_string(call->log->to); - report->info.orig_id = ms_strdup(report->info.remote_id); + strass(report->info.remote_id, linphone_address_as_string(call->log->from)); + strass(report->info.local_id, linphone_address_as_string(call->log->to)); + strass(report->info.orig_id, ms_strdup(report->info.remote_id)); } else { - report->info.remote_id = linphone_address_as_string(call->log->to); - report->info.local_id = linphone_address_as_string(call->log->from); - report->info.orig_id = ms_strdup(report->info.local_id); + strass(report->info.remote_id, linphone_address_as_string(call->log->to)); + strass(report->info.local_id, linphone_address_as_string(call->log->from)); + strass(report->info.orig_id, ms_strdup(report->info.local_id)); } - report->dialog_id = sal_op_get_dialog_id(call->op); + strass(report->dialog_id, sal_op_get_dialog_id(call->op)); report->local_metrics.timestamps.start = call->log->start_date_time; report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); @@ -332,16 +355,15 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { report->remote_metrics.timestamps.start = call->log->start_date_time; report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + // yet we use the same payload config for local and remote, since this is the largest case if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { stream = &call->audiostream->ms; - local_payload = linphone_call_params_get_used_audio_codec(local_params); - if (remote_params != NULL) - remote_payload = linphone_call_params_get_used_audio_codec(remote_params); + local_payload = linphone_call_params_get_used_audio_codec(current_params); + remote_payload = local_payload; } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) { stream = &call->videostream->ms; - local_payload = linphone_call_params_get_used_video_codec(local_params); - if (remote_params != NULL) - remote_payload = linphone_call_params_get_used_video_codec(linphone_call_get_remote_params(call)); + local_payload = linphone_call_params_get_used_video_codec(current_params); + remote_payload = local_payload; } if (stream != NULL) { @@ -353,16 +375,16 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { if (local_payload != NULL) { report->local_metrics.session_description.payload_type = local_payload->type; - report->local_metrics.session_description.payload_desc = ms_strdup(local_payload->mime_type); + strass(report->local_metrics.session_description.payload_desc, ms_strdup(local_payload->mime_type)); report->local_metrics.session_description.sample_rate = local_payload->clock_rate; - report->local_metrics.session_description.fmtp = ms_strdup(local_payload->recv_fmtp); + strass(report->local_metrics.session_description.fmtp, ms_strdup(local_payload->recv_fmtp)); } if (remote_payload != NULL) { report->remote_metrics.session_description.payload_type = remote_payload->type; - report->remote_metrics.session_description.payload_desc = ms_strdup(remote_payload->mime_type); + strass(report->remote_metrics.session_description.payload_desc, ms_strdup(remote_payload->mime_type)); report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; - report->remote_metrics.session_description.fmtp = ms_strdup(remote_payload->recv_fmtp); + strass(report->remote_metrics.session_description.fmtp, ms_strdup(remote_payload->recv_fmtp)); } } @@ -373,6 +395,9 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { LinphoneCallStats stats = call->stats[stats_type]; mblk_t *block = NULL; + if (! reporting_enabled(call)) + return; + if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { metrics = &report->remote_metrics; if (rtcp_is_XR(stats.received_rtcp) == TRUE) { @@ -410,6 +435,9 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { void linphone_reporting_publish(LinphoneCall* call) { printf("linphone_reporting_publish\n"); + if (! reporting_enabled(call)) + return; + if (call->log->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) { reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO]); } diff --git a/coreapi/sal.c b/coreapi/sal.c index a3ec66b45..e42c124cc 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -374,7 +374,7 @@ const char* sal_op_get_call_id(const SalOp *op) { } char* sal_op_get_dialog_id(const SalOp *op) { if (op->dialog != NULL) { - return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id, + return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id, belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog)); } return NULL; diff --git a/mediastreamer2 b/mediastreamer2 index 41db9323b..b76e3dde1 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 41db9323be6a6d136949ee5fdba1198c38a7d787 +Subproject commit b76e3dde111af0d24be4ac5f1d4f633361e654c1 From 424d75b2652b7fd57af21dd93e945437c88fbab2 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Tue, 15 Apr 2014 11:04:12 +0200 Subject: [PATCH 26/83] Quality reporting: release content after publishing it to avoid memory leaks --- coreapi/private.h | 1 + coreapi/quality_reporting.c | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coreapi/private.h b/coreapi/private.h index 94605e506..efc622b31 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -812,6 +812,7 @@ void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *d void linphone_call_create_op(LinphoneCall *call); int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer); void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body); +void linphone_content_uninit(LinphoneContent * obj); LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref); SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc); SalReason linphone_reason_to_sal(LinphoneReason reason); diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 58727acb7..075f9ebe1 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -40,11 +40,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). - // remote: session desc null parce que linphone_call_get_remote_params le remplit pas - // range 0 - 255 au lieu de 0 - 5 metrics->quality_estimates.rcq, metrics->quality_estimates.moslq, metrics->quality_estimates.moscq); // abstraction audio video - // valgrind --leakcheck=full // tests liblinphonetester // à voir ++ : // video : que se passe t-il si on arrete / resume la vidéo (new stream) @@ -254,6 +251,8 @@ static void reporting_publish(LinphoneCall* call, reporting_session_report_t * r } else { ms_warning("Asked to submit reporting statistics but no collector address found"); } + + linphone_content_uninit(&content); } From 929fbffe1a62c30766ee117f88a7d85cadfa7a9c Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Tue, 15 Apr 2014 16:54:39 +0200 Subject: [PATCH 27/83] Quality reporting: add unit tests --- coreapi/quality_reporting.c | 32 ++++++------ tester/call_tester.c | 98 ++++++++++++++++++++++++++++++++++++- tester/rcfiles/marie_rc | 2 + 3 files changed, 114 insertions(+), 18 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 075f9ebe1..ed21890f9 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -46,8 +46,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // à voir ++ : // video : que se passe t-il si on arrete / resume la vidéo (new stream) // valeurs instanannées : moyenne ? valeur extreme ? - // only if this is a linphone account? // rlq: il faut un algo + // #define PRINTF printf + #define PRINTF(...) /*************************************************************************** * END OF TODO / REMINDER LIST ****************************************************************************/ @@ -108,7 +109,7 @@ static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, con #define APPEND_IF(buffer, size, offset, fmt, arg, cond) if (cond) append_to_buffer(buffer, size, offset, fmt, arg) #define IF_NUM_IN_RANGE(num, inf, sup, statement) if (inf <= num && num <= sup) statement -static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, reporting_content_metrics_t rm) { +static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, const reporting_content_metrics_t rm) { char * timestamps_start_str = NULL; char * timestamps_stop_str = NULL; char * network_packet_loss_rate_str = NULL; @@ -200,10 +201,11 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off ms_free(moscq_str); } -static void reporting_publish(LinphoneCall* call, reporting_session_report_t * report) { +static void reporting_publish(const LinphoneCall* call, const reporting_session_report_t * report) { + PRINTF("static reporting_publish\n"); + LinphoneContent content = {0}; LinphoneAddress *addr; - const char * addr_str; int expires = -1; size_t offset = 0; size_t size = 2048; @@ -238,24 +240,21 @@ static void reporting_publish(LinphoneCall* call, reporting_session_report_t * r content.size = strlen((char*)content.data); - - - addr_str = call->dest_proxy->reg_statistics_collector; - if (addr_str != NULL) { - addr = linphone_address_new(addr_str); + addr = linphone_address_new(call->dest_proxy->reg_statistics_collector); + if (addr != NULL) { linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); linphone_address_destroy(addr); // for debug purpose only - printf("%s\n", (char*) content.data); + PRINTF("%s\n", (char*) content.data); } else { ms_warning("Asked to submit reporting statistics but no collector address found"); + PRINTF("Asked to submit reporting statistics but no collector address found\n"); } linphone_content_uninit(&content); } - static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDescription * remote_smd, SalStreamType sal_stream_type) { if (remote_smd != NULL) { int count; @@ -298,7 +297,7 @@ static void reporting_update_ip(LinphoneCall * call, int stats_type) { } } -static bool_t reporting_enabled(LinphoneCall * call) { +static bool_t reporting_enabled(const LinphoneCall * call) { return (call->dest_proxy != NULL && linphone_proxy_config_send_statistics_enabled(call->dest_proxy)); } @@ -307,7 +306,7 @@ void linphone_reporting_update_ip(LinphoneCall * call) { // - 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered // - 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access - printf("linphone_reporting_update_remote_ip\n"); + PRINTF("linphone_reporting_update_remote_ip\n"); if (! reporting_enabled(call)) return; @@ -326,7 +325,7 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { const PayloadType * remote_payload = NULL; const LinphoneCallParams * current_params = linphone_call_get_current_params(call); - printf("linphone_reporting_call_stats_updated type=%d\n", stats_type); + PRINTF("linphone_reporting_call_stats_updated type=%d\n", stats_type); if (! reporting_enabled(call)) return; @@ -432,11 +431,12 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { } void linphone_reporting_publish(LinphoneCall* call) { - printf("linphone_reporting_publish\n"); + PRINTF("linphone_reporting_publish\n"); - if (! reporting_enabled(call)) + if (! reporting_enabled(call)) return; + if (call->log->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) { reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO]); } diff --git a/tester/call_tester.c b/tester/call_tester.c index 3e8ef9475..999dc0d77 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1877,6 +1877,98 @@ static void call_rejected_without_403_because_wrong_credentials_no_auth_req_cb() call_rejected_because_wrong_credentials_with_params("tester-no-403",FALSE); } +void create_call_for_statistics_tests( + LinphoneCoreManager* marie, + LinphoneCoreManager* pauline, + LinphoneCall** call_marie, + LinphoneCall** call_pauline) { + CU_ASSERT_TRUE(call(pauline,marie)); + *call_marie = linphone_core_get_current_call(marie->lc); + *call_pauline = linphone_core_get_current_call(pauline->lc); + CU_ASSERT_PTR_NOT_NULL(*call_marie); + CU_ASSERT_PTR_NOT_NULL(*call_pauline); +} + +static void statistics_not_used_without_config() { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCall* call_marie = NULL; + LinphoneCall* call_pauline = NULL; + + create_call_for_statistics_tests(marie, pauline, &call_marie, &call_pauline); + + // marie has stats collection enabled since pauline has not + CU_ASSERT_TRUE(linphone_proxy_config_send_statistics_enabled(call_marie->dest_proxy)); + CU_ASSERT_FALSE(linphone_proxy_config_send_statistics_enabled(call_pauline->dest_proxy)); + + CU_ASSERT_EQUAL(strcmp("sip:collector@sip.linphone.org", + linphone_proxy_config_get_statistics_collector(call_marie->dest_proxy)), 0); + + // this field should be already filled + CU_ASSERT_PTR_NOT_NULL(call_marie->log->reports[0]->info.local_addr.ip); + CU_ASSERT_PTR_NULL(call_pauline->log->reports[0]->info.local_addr.ip); + + // but not this one since it is updated at the end of call + CU_ASSERT_PTR_NULL(call_marie->log->reports[0]->dialog_id); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} +static void statistics_not_sent_if_call_not_started() { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCallLog* out_call_log; + LinphoneCall* out_call; + + linphone_core_set_max_calls(pauline->lc,0); + out_call = linphone_core_invite(marie->lc,"pauline"); + linphone_call_ref(out_call); + + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallError,1)); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1); + + if (ms_list_size(linphone_core_get_call_logs(marie->lc))>0) { + CU_ASSERT_PTR_NOT_NULL(out_call_log=(LinphoneCallLog*)(linphone_core_get_call_logs(marie->lc)->data)); + CU_ASSERT_EQUAL(linphone_call_log_get_status(out_call_log),LinphoneCallAborted); + } + linphone_call_unref(out_call); + + // wait a few time... + wait_for(marie->lc,NULL,NULL,0); + // since the callee was busy, there shouldn't be no publish to do + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} +static void statistics_sent_at_call_termination() { + // int return_code = -1; + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCall* call_marie = NULL; + LinphoneCall* call_pauline = NULL; + + create_call_for_statistics_tests(marie, pauline, &call_marie, &call_pauline); + + linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1)); + + CU_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc)); + + // now dialog id should be filled + CU_ASSERT_PTR_NOT_NULL(call_marie->log->reports[0]->dialog_id); + + // PUBLISH submission to the collector should be ok + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); // failing since server side is not implemented + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + #ifdef VIDEO_ENABLED #endif @@ -1931,7 +2023,10 @@ test_t call_tests[] = { { "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite}, { "Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite }, { "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error}, - { "Call redirected by callee", call_redirect} + { "Call redirected by callee", call_redirect}, + { "Call statistics not used if no config", statistics_not_used_without_config}, + { "Call statistics not sent if call did not start", statistics_not_sent_if_call_not_started}, + { "Call statistics sent if call ended normally", statistics_sent_at_call_termination}, }; test_suite_t call_test_suite = { @@ -1941,4 +2036,3 @@ test_suite_t call_test_suite = { sizeof(call_tests) / sizeof(call_tests[0]), call_tests }; - diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc index 7b7645800..342265158 100644 --- a/tester/rcfiles/marie_rc +++ b/tester/rcfiles/marie_rc @@ -22,6 +22,8 @@ reg_expires=3600 reg_sendregister=1 publish=0 dial_escape_plus=0 +reg_statistics_collector=sip:collector@sip.linphone.org +send_statistics=1 [friend_0] url="Paupoche" From e159b4fa17746a874620ff92786e6321118f7e2a Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 17 Apr 2014 10:57:55 +0200 Subject: [PATCH 28/83] Quality reporting: do not add remote metrics if no stats are filled --- coreapi/quality_reporting.c | 51 +++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index ed21890f9..fb838c566 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -47,8 +47,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // video : que se passe t-il si on arrete / resume la vidéo (new stream) // valeurs instanannées : moyenne ? valeur extreme ? // rlq: il faut un algo - // #define PRINTF printf - #define PRINTF(...) + #define PRINTF(...) do { if (getenv("LINPHONE_QR_DEBUG") != NULL) printf(__VA_ARGS__); } while (FALSE) /*************************************************************************** * END OF TODO / REMINDER LIST ****************************************************************************/ @@ -104,10 +103,44 @@ static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, con } -#define APPEND_IF_NOT_NULL_STR(buffer, size, offset, fmt, arg) if (arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg) -#define APPEND_IF_NUM_IN_RANGE(buffer, size, offset, fmt, arg, inf, sup) if (inf <= arg && arg <= sup) append_to_buffer(buffer, size, offset, fmt, arg) -#define APPEND_IF(buffer, size, offset, fmt, arg, cond) if (cond) append_to_buffer(buffer, size, offset, fmt, arg) -#define IF_NUM_IN_RANGE(num, inf, sup, statement) if (inf <= num && num <= sup) statement +#define APPEND_IF_NOT_NULL_STR(buffer, size, offset, fmt, arg) if (FALSE &&arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg) +#define APPEND_IF_NUM_IN_RANGE(buffer, size, offset, fmt, arg, inf, sup) if (FALSE &&inf <= arg && arg <= sup) append_to_buffer(buffer, size, offset, fmt, arg) +#define APPEND_IF(buffer, size, offset, fmt, arg, cond) if (FALSE&&cond) append_to_buffer(buffer, size, offset, fmt, arg) +#define IF_NUM_IN_RANGE(num, inf, sup, statement) if (FALSE&&inf <= num && num <= sup) statement + +static bool_t are_metrics_filled(const reporting_content_metrics_t rm) { + IF_NUM_IN_RANGE(rm.packet_loss.network_packet_loss_rate, 0, 255, return TRUE); + IF_NUM_IN_RANGE(rm.packet_loss.jitter_buffer_discard_rate, 0, 255, return TRUE); + IF_NUM_IN_RANGE(rm.quality_estimates.moslq, 1, 5, return TRUE); + IF_NUM_IN_RANGE(rm.quality_estimates.moscq, 1, 5, return TRUE); + + // since these are values from local metrics, do not check them + // if (rm.session_description.payload_type != -1) return TRUE; + // if (rm.session_description.payload_desc != NULL) return TRUE; + // if (rm.session_description.sample_rate != -1) return TRUE; + if (rm.session_description.frame_duration != -1) return TRUE; + // if (rm.session_description.fmtp != NULL) return TRUE; + if (rm.session_description.packet_loss_concealment != -1) return TRUE; + + IF_NUM_IN_RANGE(rm.jitter_buffer.adaptive, 0, 3, return TRUE); + IF_NUM_IN_RANGE(rm.jitter_buffer.nominal, 0, 65535, return TRUE); + IF_NUM_IN_RANGE(rm.jitter_buffer.max, 0, 65535, return TRUE); + IF_NUM_IN_RANGE(rm.jitter_buffer.abs_max, 0, 65535, return TRUE); + + IF_NUM_IN_RANGE(rm.delay.round_trip_delay, 0, 65535, return TRUE); + IF_NUM_IN_RANGE(rm.delay.end_system_delay, 0, 65535, return TRUE); + IF_NUM_IN_RANGE(rm.delay.symm_one_way_delay, 0, 65535, return TRUE); + IF_NUM_IN_RANGE(rm.delay.interarrival_jitter, 0, 65535, return TRUE); + IF_NUM_IN_RANGE(rm.delay.mean_abs_jitter, 0, 65535, return TRUE); + + if (rm.signal.level != 127) return TRUE; + if (rm.signal.noise_level != 127) return TRUE; + + IF_NUM_IN_RANGE(rm.quality_estimates.rlq, 1, 120, return TRUE); + IF_NUM_IN_RANGE(rm.quality_estimates.rcq, 1, 120, return TRUE); + + return FALSE; +} static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, const reporting_content_metrics_t rm) { char * timestamps_start_str = NULL; @@ -232,8 +265,10 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); append_metrics_to_buffer(&buffer, &size, &offset, report->local_metrics); - append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); - append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics); + if (are_metrics_filled(report->remote_metrics)) { + append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); + append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics); + } APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id); content.data = buffer; From c94afb09587dc24f4347d0c1ff52ac2e76e192b0 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 17 Apr 2014 12:03:32 +0200 Subject: [PATCH 29/83] Quality reporting: add stream type in stats and remove debug test stuff --- coreapi/quality_reporting.c | 86 ++++++++++++++----------------------- 1 file changed, 33 insertions(+), 53 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index fb838c566..998837963 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -24,35 +24,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphonecore.h" #include "private.h" #include "sal/sal.h" - - #include "ortp/rtpsession.h" #include /*************************************************************************** * TODO / REMINDER LIST - ****************************************************************************/ - // TO_CHECK: only if call succeeded and ran (busy should NOT call this) - // TO_CHECK: executed AFTER BYE's "OK" response has been received - - // TO_CHECK: configurable global publish_call_statistics linphone_proxy_config_set_statistics_collector enable_collector - - // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). - - // range 0 - 255 au lieu de 0 - 5 metrics->quality_estimates.rcq, metrics->quality_estimates.moslq, metrics->quality_estimates.moscq); - // abstraction audio video - // tests liblinphonetester - // à voir ++ : - // video : que se passe t-il si on arrete / resume la vidéo (new stream) - // valeurs instanannées : moyenne ? valeur extreme ? - // rlq: il faut un algo - #define PRINTF(...) do { if (getenv("LINPHONE_QR_DEBUG") != NULL) printf(__VA_ARGS__); } while (FALSE) + ****************************************************************************/ + // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). + // range 0 - 255 instead of 0 - 5 for metrics->quality_estimates.rcq, metrics->quality_estimates.moslq, metrics->quality_estimates.moscq + // Know issue: if call is stopped to early, IP are invalid + // to discuss + // video: what happens if doing stop/resume? + // one time value: average? worst value? + // rlq value: need algo to compute it /*************************************************************************** * END OF TODO / REMINDER LIST ****************************************************************************/ -#define strass(dest, src) {\ +#define STR_REASSIGN(dest, src) {\ if (dest != NULL) \ ms_free(dest); \ dest = src; \ @@ -103,10 +93,10 @@ static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, con } -#define APPEND_IF_NOT_NULL_STR(buffer, size, offset, fmt, arg) if (FALSE &&arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg) -#define APPEND_IF_NUM_IN_RANGE(buffer, size, offset, fmt, arg, inf, sup) if (FALSE &&inf <= arg && arg <= sup) append_to_buffer(buffer, size, offset, fmt, arg) -#define APPEND_IF(buffer, size, offset, fmt, arg, cond) if (FALSE&&cond) append_to_buffer(buffer, size, offset, fmt, arg) -#define IF_NUM_IN_RANGE(num, inf, sup, statement) if (FALSE&&inf <= num && num <= sup) statement +#define APPEND_IF_NOT_NULL_STR(buffer, size, offset, fmt, arg) if (arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg) +#define APPEND_IF_NUM_IN_RANGE(buffer, size, offset, fmt, arg, inf, sup) if (inf <= arg && arg <= sup) append_to_buffer(buffer, size, offset, fmt, arg) +#define APPEND_IF(buffer, size, offset, fmt, arg, cond) if (cond) append_to_buffer(buffer, size, offset, fmt, arg) +#define IF_NUM_IN_RANGE(num, inf, sup, statement) if (inf <= num && num <= sup) statement static bool_t are_metrics_filled(const reporting_content_metrics_t rm) { IF_NUM_IN_RANGE(rm.packet_loss.network_packet_loss_rate, 0, 255, return TRUE); @@ -114,7 +104,7 @@ static bool_t are_metrics_filled(const reporting_content_metrics_t rm) { IF_NUM_IN_RANGE(rm.quality_estimates.moslq, 1, 5, return TRUE); IF_NUM_IN_RANGE(rm.quality_estimates.moscq, 1, 5, return TRUE); - // since these are values from local metrics, do not check them + // since these are same values than local ones, do not check them // if (rm.session_description.payload_type != -1) return TRUE; // if (rm.session_description.payload_desc != NULL) return TRUE; // if (rm.session_description.sample_rate != -1) return TRUE; @@ -235,8 +225,6 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off } static void reporting_publish(const LinphoneCall* call, const reporting_session_report_t * report) { - PRINTF("static reporting_publish\n"); - LinphoneContent content = {0}; LinphoneAddress *addr; int expires = -1; @@ -279,12 +267,8 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ if (addr != NULL) { linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); linphone_address_destroy(addr); - - // for debug purpose only - PRINTF("%s\n", (char*) content.data); } else { ms_warning("Asked to submit reporting statistics but no collector address found"); - PRINTF("Asked to submit reporting statistics but no collector address found\n"); } linphone_content_uninit(&content); @@ -315,7 +299,7 @@ static void reporting_update_ip(LinphoneCall * call, int stats_type) { // local info are always up-to-date and correct if (local_desc != NULL) { call->log->reports[stats_type]->info.local_addr.port = local_desc->rtp_port; - strass(call->log->reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr)); + STR_REASSIGN(call->log->reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr)); } if (remote_desc != NULL) { @@ -324,9 +308,9 @@ static void reporting_update_ip(LinphoneCall * call, int stats_type) { // for IP it can be not set if we are using a direct route if (remote_desc->rtp_addr != NULL && strlen(remote_desc->rtp_addr) > 0) { - strass(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr)); + STR_REASSIGN(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr)); } else { - strass(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(sal_call_get_remote_media_description(call->op)->addr)); + STR_REASSIGN(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(sal_call_get_remote_media_description(call->op)->addr)); } } } @@ -341,8 +325,6 @@ void linphone_reporting_update_ip(LinphoneCall * call) { // - 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered // - 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access - PRINTF("linphone_reporting_update_remote_ip\n"); - if (! reporting_enabled(call)) return; @@ -360,26 +342,26 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { const PayloadType * remote_payload = NULL; const LinphoneCallParams * current_params = linphone_call_get_current_params(call); - PRINTF("linphone_reporting_call_stats_updated type=%d\n", stats_type); - if (! reporting_enabled(call)) return; - strass(report->info.call_id, ms_strdup(call->log->call_id)); - strass(report->info.local_group, ms_strdup_printf(_("linphone-%s-%s"), linphone_core_get_user_agent_name(), report->info.call_id)); - strass(report->info.remote_group, ms_strdup_printf(_("linphone-%s-%s"), linphone_call_get_remote_user_agent(call), report->info.call_id)); + STR_REASSIGN(report->info.call_id, ms_strdup(call->log->call_id)); + STR_REASSIGN(report->info.local_group, ms_strdup_printf(_("linphone-%s-%s-%s"), (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"), + linphone_core_get_user_agent_name(), report->info.call_id)); + STR_REASSIGN(report->info.remote_group, ms_strdup_printf(_("linphone-%s-%s-%s"), (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"), + linphone_call_get_remote_user_agent(call), report->info.call_id)); if (call->dir == LinphoneCallIncoming) { - strass(report->info.remote_id, linphone_address_as_string(call->log->from)); - strass(report->info.local_id, linphone_address_as_string(call->log->to)); - strass(report->info.orig_id, ms_strdup(report->info.remote_id)); + STR_REASSIGN(report->info.remote_id, linphone_address_as_string(call->log->from)); + STR_REASSIGN(report->info.local_id, linphone_address_as_string(call->log->to)); + STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.remote_id)); } else { - strass(report->info.remote_id, linphone_address_as_string(call->log->to)); - strass(report->info.local_id, linphone_address_as_string(call->log->from)); - strass(report->info.orig_id, ms_strdup(report->info.local_id)); + STR_REASSIGN(report->info.remote_id, linphone_address_as_string(call->log->to)); + STR_REASSIGN(report->info.local_id, linphone_address_as_string(call->log->from)); + STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.local_id)); } - strass(report->dialog_id, sal_op_get_dialog_id(call->op)); + STR_REASSIGN(report->dialog_id, sal_op_get_dialog_id(call->op)); report->local_metrics.timestamps.start = call->log->start_date_time; report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); @@ -408,16 +390,16 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { if (local_payload != NULL) { report->local_metrics.session_description.payload_type = local_payload->type; - strass(report->local_metrics.session_description.payload_desc, ms_strdup(local_payload->mime_type)); + STR_REASSIGN(report->local_metrics.session_description.payload_desc, ms_strdup(local_payload->mime_type)); report->local_metrics.session_description.sample_rate = local_payload->clock_rate; - strass(report->local_metrics.session_description.fmtp, ms_strdup(local_payload->recv_fmtp)); + STR_REASSIGN(report->local_metrics.session_description.fmtp, ms_strdup(local_payload->recv_fmtp)); } if (remote_payload != NULL) { report->remote_metrics.session_description.payload_type = remote_payload->type; - strass(report->remote_metrics.session_description.payload_desc, ms_strdup(remote_payload->mime_type)); + STR_REASSIGN(report->remote_metrics.session_description.payload_desc, ms_strdup(remote_payload->mime_type)); report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; - strass(report->remote_metrics.session_description.fmtp, ms_strdup(remote_payload->recv_fmtp)); + STR_REASSIGN(report->remote_metrics.session_description.fmtp, ms_strdup(remote_payload->recv_fmtp)); } } @@ -466,8 +448,6 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { } void linphone_reporting_publish(LinphoneCall* call) { - PRINTF("linphone_reporting_publish\n"); - if (! reporting_enabled(call)) return; From 2551648d0dab1c759fa858edfb25f4bda746bc79 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 17 Apr 2014 15:20:20 +0200 Subject: [PATCH 30/83] Quality reporting: update collector sip address to test server instead of the production one --- tester/rcfiles/marie_rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc index 342265158..60fa3d118 100644 --- a/tester/rcfiles/marie_rc +++ b/tester/rcfiles/marie_rc @@ -22,7 +22,7 @@ reg_expires=3600 reg_sendregister=1 publish=0 dial_escape_plus=0 -reg_statistics_collector=sip:collector@sip.linphone.org +reg_statistics_collector=sip:collector@sip.example.org send_statistics=1 [friend_0] From e21cc4af9d4b6ea4056569e248f928dc30f8a5d7 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 17 Apr 2014 16:33:02 +0200 Subject: [PATCH 31/83] Quality reporting: do not publish report if we hung up too early (empty local IP address) --- coreapi/quality_reporting.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 998837963..441957736 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -232,8 +232,15 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ size_t size = 2048; char * buffer; - buffer = (char *) ms_malloc(size); + // if the call was hungup too early, we might have invalid IPs information + // in that case, we abort the report since it's not useful data + if (strlen(report->info.local_addr.ip) == 0 || strlen(report->info.remote_addr.ip) == 0) { + ms_warning("The call was hang up too early (duration: %d sec) and IP could " + "not be retrieved so dropping this report", linphone_call_get_duration(call)); + return; + } + buffer = (char *) ms_malloc(size); content.type = ms_strdup("application"); content.subtype = ms_strdup("vq-rtcpxr"); From f3efcb12864bba9c35aac38257724380f449eb9b Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Thu, 17 Apr 2014 16:58:50 +0200 Subject: [PATCH 32/83] Quality reporting: fix unit tests, and remove some trailing spaces --- coreapi/linphonecall.c | 26 +++--- coreapi/linphonecore.c | 166 ++++++++++++++++++------------------ coreapi/presence.c | 4 +- coreapi/private.h | 2 +- coreapi/proxy.c | 64 +++++++------- coreapi/quality_reporting.c | 28 +++--- coreapi/quality_reporting.h | 12 +-- coreapi/sal.c | 16 ++-- include/sal/sal.h | 4 +- tester/call_tester.c | 108 +++++++++++------------ 10 files changed, 215 insertions(+), 215 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index db3b000ab..f26ebdac9 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -399,7 +399,7 @@ static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){ int tried_port; int existing_port; bool_t already_used=FALSE; - + for(offset=0;offset<100;offset+=2){ tried_port=base_port+offset; already_used=FALSE; @@ -485,10 +485,10 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, linphone_core_get_audio_port_range(call->core, &min_port, &max_port); port_config_set(call,0,min_port,max_port); - + linphone_core_get_video_port_range(call->core, &min_port, &max_port); port_config_set(call,1,min_port,max_port); - + linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO); linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO); } @@ -781,7 +781,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const Indeed it does not change the state of the call (still paused or running)*/ call->state=cstate; } - + if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){ switch(call->non_op_error.reason){ case SalReasonDeclined: @@ -1304,7 +1304,7 @@ const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){ /** * Set the session name of the media session (ie in SDP). Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header(). * @param cp the call parameters. - * @param name the session name + * @param name the session name **/ void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){ if (cp->session_name){ @@ -1454,17 +1454,17 @@ static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ SalMediaDescription *remote; bool_t has_video=FALSE; - + if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ if (incoming_offer){ remote=sal_call_get_remote_media_description(call->op); has_video=linphone_core_media_description_contains_video_stream(remote); }else has_video=call->params.has_video; - + _linphone_call_prepare_ice_for_stream(call,0,TRUE); if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE); /*start ICE gathering*/ - if (incoming_offer) + if (incoming_offer) linphone_core_update_ice_from_remote_media_description(call,remote); if (!ice_session_candidates_gathered(call->ice_session)){ if (call->audiostream->ms.state==MSStreamInitialized) @@ -1539,7 +1539,7 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ call->audiostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(audiostream->ms.sessions.rtp_session,call->audiostream_app_evq); - + _linphone_call_prepare_ice_for_stream(call,0,FALSE); } @@ -1551,7 +1551,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){ int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0); int dscp=linphone_core_get_video_dscp(lc); const char *display_filter=linphone_core_get_video_display_filter(lc); - + if (call->sessions[1].rtp_session==NULL){ call->videostream=video_stream_new(call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port, call->af==AF_INET6); }else{ @@ -1961,7 +1961,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna #ifdef VIDEO_ENABLED LinphoneCore *lc=call->core; int used_pt=-1; - + /* look for savp stream first */ const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc, SalProtoRtpSavp,SalVideo); @@ -1983,7 +1983,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna const char *rtp_addr=vstream->rtp_addr[0]!='\0' ? vstream->rtp_addr : call->resultdesc->addr; const char *rtcp_addr=vstream->rtcp_addr[0]!='\0' ? vstream->rtcp_addr : call->resultdesc->addr; const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,vstream->proto,SalVideo); - + call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt); if (used_pt!=-1){ @@ -2147,7 +2147,7 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript SalStreamDescription *old_stream; SalStreamDescription *new_stream; const SalStreamDescription *local_st_desc; - + local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalAudio); old_stream = sal_media_description_find_stream(old_md, SalProtoRtpSavp, SalAudio); new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index af627ad4c..b0d1dff8e 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -614,7 +614,7 @@ static void sound_config_read(LinphoneCore *lc) linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC)); lc->sound_conf.latency=0; -#ifndef __ios +#ifndef __ios tmp=TRUE; #else tmp=FALSE; /* on iOS we have builtin echo cancellation.*/ @@ -633,7 +633,7 @@ static void sound_config_read(LinphoneCore *lc) /*just parse requested stream feature once at start to print out eventual errors*/ linphone_core_get_audio_features(lc); - + _linphone_core_set_tone(lc,LinphoneReasonBusy,LinphoneToneBusy,NULL); } @@ -647,7 +647,7 @@ static void certificates_config_read(LinphoneCore *lc) #endif linphone_core_set_root_ca(lc,rootca); linphone_core_verify_server_certificates(lc,lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE)); - linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE)); + linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE)); } static void sip_config_read(LinphoneCore *lc) @@ -670,12 +670,12 @@ static void sip_config_read(LinphoneCore *lc) } linphone_core_enable_ipv6(lc,ipv6); memset(&tr,0,sizeof(tr)); - + tr.udp_port=lp_config_get_int(lc->config,"sip","sip_port",5060); tr.tcp_port=lp_config_get_int(lc->config,"sip","sip_tcp_port",5060); /*we are not listening inbound connection for tls, port has no meaning*/ tr.tls_port=lp_config_get_int(lc->config,"sip","sip_tls_port",LC_SIP_TRANSPORT_RANDOM); - + certificates_config_read(lc); /*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/ sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc)); @@ -710,7 +710,7 @@ static void sip_config_read(LinphoneCore *lc) tmp=lp_config_get_int(lc->config,"sip","in_call_timeout",0); linphone_core_set_in_call_timeout(lc,tmp); - + tmp=lp_config_get_int(lc->config,"sip","delayed_timeout",4); linphone_core_set_delayed_timeout(lc,tmp); @@ -982,8 +982,8 @@ static void video_config_read(LinphoneCore *lc){ int capture, display, self_view; int automatic_video=1; #endif - const char *str; -#ifdef VIDEO_ENABLED + const char *str; +#ifdef VIDEO_ENABLED LinphoneVideoPolicy vpol; memset(&vpol, 0, sizeof(LinphoneVideoPolicy)); #endif @@ -1046,7 +1046,7 @@ bool_t linphone_core_tunnel_available(void){ /** * Enable adaptive rate control. - * + * * @ingroup media_parameters * * Adaptive rate control consists in using RTCP feedback provided information to dynamically @@ -1060,7 +1060,7 @@ void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled /** * Returns whether adaptive rate control is enabled. - * + * * @ingroup media_parameters * * See linphone_core_enable_adaptive_rate_control(). @@ -1080,7 +1080,7 @@ bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){ * calls (within SDP messages) so that the remote end can have * sufficient knowledge to properly configure its audio & video * codec output bitrate to not overflow available bandwidth. - * + * * @ingroup media_parameters * * @param lc the LinphoneCore object @@ -1166,7 +1166,7 @@ void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime){ * Set audio packetization time linphone will send (in absence of requirement from peer) * A value of 0 stands for the current codec default packetization time. * - * + * * @ingroup media_parameters **/ int linphone_core_get_upload_ptime(LinphoneCore *lc){ @@ -1187,14 +1187,14 @@ const char * linphone_core_get_version(void){ static void linphone_core_assign_payload_type(LinphoneCore *lc, PayloadType *const_pt, int number, const char *recv_fmtp){ PayloadType *pt; - + #ifdef ANDROID if (const_pt->channels==2){ ms_message("Stereo %s codec not supported on this platform.",const_pt->mime_type); return; } #endif - + pt=payload_type_clone(const_pt); if (number==-1){ /*look for a free number */ @@ -1258,10 +1258,10 @@ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const static void misc_config_read(LinphoneCore *lc) { LpConfig *config=lc->config; const char *uuid; - + lc->max_call_logs=lp_config_get_int(config,"misc","history_max_size",15); lc->max_calls=lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS); - + uuid=lp_config_get_string(config,"misc","uuid",NULL); if (!uuid){ char tmp[64]; @@ -1297,12 +1297,12 @@ static void linphone_core_start(LinphoneCore * lc) { void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) { if (lc->vtable.configuring_status) lc->vtable.configuring_status(lc, state, message); - + if (state == LinphoneConfiguringSuccessful) { if (linphone_core_is_provisioning_transient(lc) == TRUE) linphone_core_set_provisioning_uri(lc, NULL); } - + linphone_core_start(lc); } @@ -1349,7 +1349,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_core_assign_payload_type(lc,&payload_type_mp4v,99,"profile-level-id=3"); linphone_core_assign_payload_type(lc,&payload_type_h264,102,"profile-level-id=42801F"); linphone_core_assign_payload_type(lc,&payload_type_vp8,103,NULL); - + linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL); linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL); /* due to limited space in SDP, we have to disable this h264 line which is normally no more necessary */ @@ -1379,7 +1379,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; usedtx=0; cbr=1"); linphone_core_assign_payload_type(lc,&payload_type_isac,-1,NULL); linphone_core_handle_static_payloads(lc); - + ms_init(); /* create a mediastreamer2 event queue and set it as global */ /* This allows to run event's callback in linphone_core_iterate() */ @@ -1393,13 +1393,13 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab lc->network_last_check = 0; lc->network_last_status = FALSE; - + lc->http_provider = belle_sip_stack_create_http_provider(sal_get_belle_sip_stack(lc->sal), "0.0.0.0"); lc->http_verify_policy = belle_tls_verify_policy_new(); belle_http_provider_set_tls_verify_policy(lc->http_provider,lc->http_verify_policy); - + certificates_config_read(lc); - + remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); if (remote_provisioning_uri == NULL) { linphone_configuring_terminated(lc, LinphoneConfiguringSkipped, NULL); @@ -1944,7 +1944,7 @@ static int apply_transports(LinphoneCore *lc){ /*first of all invalidate all current registrations so that we can register again with new transports*/ __linphone_core_invalidate_registers(lc); - + if (lc->sip_conf.ipv6_enabled) anyaddr="::0"; else @@ -2216,7 +2216,7 @@ void linphone_core_iterate(LinphoneCore *lc){ int elapsed; bool_t one_second_elapsed=FALSE; const char *remote_provisioning_uri = NULL; - + if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) { if (sal_get_root_ca(lc->sal)) { belle_tls_verify_policy_t *tls_policy = belle_tls_verify_policy_new(); @@ -2227,7 +2227,7 @@ void linphone_core_iterate(LinphoneCore *lc){ if (lc->vtable.display_status) lc->vtable.display_status(lc, _("Configuring")); linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring"); - + remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); if (remote_provisioning_uri) { int err = linphone_remote_provisioning_download_and_apply(lc, remote_provisioning_uri); @@ -2250,7 +2250,7 @@ void linphone_core_iterate(LinphoneCore *lc){ if (ecs==LinphoneEcCalibratorDone){ int len=lp_config_get_int(lc->config,"sound","ec_tail_len",0); int margin=len/2; - + lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-margin,0)); } else if (ecs == LinphoneEcCalibratorFailed) { lp_config_set_int(lc->config, "sound", "ec_delay", -1);/*use default value from soundcard*/ @@ -2363,7 +2363,7 @@ void linphone_core_iterate(LinphoneCore *lc){ /** * Interpret a call destination as supplied by the user, and returns a fully qualified * LinphoneAddress. - * + * * @ingroup call_control * * A sip address should look like DisplayName . @@ -2382,7 +2382,7 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url) LinphoneProxyConfig *proxy=lc->default_proxy; char *tmpurl; LinphoneAddress *uri; - + if (*url=='\0') return NULL; if (is_enum(url,&enum_domain)){ @@ -2432,7 +2432,7 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url) if (uri!=NULL){ return uri; } - + return NULL; } @@ -2470,7 +2470,7 @@ const char * linphone_core_get_route(LinphoneCore *lc){ * Start a new call as a consequence of a transfer request received from a call. * This function is for advanced usage: the execution of transfers is automatically managed by the LinphoneCore. However if an application * wants to have control over the call parameters for the new call, it should call this function immediately during the LinphoneCallRefered notification. - * @see LinphoneCoreVTable::call_state_changed + * @see LinphoneCoreVTable::call_state_changed * @param lc the LinphoneCore * @param call a call that has just been notified about LinphoneCallRefered state event. * @param params the call parameters to be applied to the new call. @@ -2479,13 +2479,13 @@ const char * linphone_core_get_route(LinphoneCore *lc){ LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ LinphoneCallParams *cp=params ? linphone_call_params_copy(params) : linphone_core_create_default_call_parameters(lc); LinphoneCall *newcall; - + if (call->state!=LinphoneCallPaused){ ms_message("Automatically pausing current call to accept transfer."); _linphone_core_pause_call(lc,call); call->was_automatically_paused=TRUE; } - + if (!params){ cp->has_video = call->current_params.has_video; /*start the call to refer-target with video enabled if original call had video*/ } @@ -2525,7 +2525,7 @@ void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, L nodes with the basic SIP routing policy in order to get a workable system. */ - + static MSList *make_routes_for_proxy(LinphoneProxyConfig *proxy, const LinphoneAddress *dest){ MSList *ret=NULL; const char *local_route=linphone_proxy_config_get_route(proxy); @@ -2820,7 +2820,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const bool_t defer = FALSE; linphone_core_preempt_sound_resources(lc); - + if(!linphone_core_can_we_add_call(lc)){ if (lc->vtable.display_warning) lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); @@ -2852,7 +2852,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); call->log->start_date_time=time(NULL); linphone_call_init_media_streams(call); - + if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { /* Defer the start of the call after the ICE gathering process. */ if (linphone_call_prepare_ice(call,FALSE)==1) @@ -2884,7 +2884,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const defer = TRUE; } } - + if (defer==FALSE) linphone_core_start_invite(lc,call,NULL); if (real_url!=NULL) ms_free(real_url); @@ -2897,7 +2897,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const * @ingroup call_control * The remote endpoint is expected to issue a new call to the specified destination. * The current call remains active and thus can be later paused or terminated. - * + * * It is possible to follow the progress of the transfer provided that transferee sends notification about it. * In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party. * The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallOutgoingConnected. @@ -2929,7 +2929,7 @@ int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char * @param lc linphone core object * @param call a running call you want to transfer * @param dest a running call whose remote person will receive the transfer - * + * * @ingroup call_control * * The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately. @@ -2937,7 +2937,7 @@ int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char * This method will send a transfer request to the transfered person. The phone of the transfered is then * expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically * close the call with us (the 'dest' call). - * + * * It is possible to follow the progress of the transfer provided that transferee sends notification about it. * In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party. * The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallOutgoingConnected. @@ -2962,7 +2962,7 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){ bool_t linphone_core_media_description_has_srtp(const SalMediaDescription *md){ int i; if (md->n_active_streams==0) return FALSE; - + for(i=0;in_active_streams;i++){ const SalStreamDescription *sd=&md->streams[i]; if (sd->proto!=SalProtoRtpSavp){ @@ -3035,11 +3035,11 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ if (call->state==LinphoneCallIncomingReceived){ /*try to be best-effort in giving real local or routable contact address for 100Rel case*/ linphone_call_set_contact_op(call); - + if (propose_early_media || ringback_tone!=NULL){ linphone_core_accept_early_media(lc,call); }else sal_call_notify_ringing(call->op,FALSE); - + if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){ linphone_core_accept_call(lc,call); } @@ -3065,7 +3065,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, const LinphoneCallParams* params) { if (call->state==LinphoneCallIncomingReceived){ SalMediaDescription* md; - + /*try to be best-effort in giving real local or routable contact address for 100Rel case*/ linphone_call_set_contact_op(call); @@ -3076,7 +3076,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* sal_call_set_local_media_description ( call->op,call->localdesc ); sal_op_set_sent_custom_header ( call->op,params->custom_headers ); } - + sal_call_notify_ringing(call->op,TRUE); linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media"); @@ -3206,15 +3206,15 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho /** * @ingroup call_control * When receiving a #LinphoneCallUpdatedByRemote state notification, prevent LinphoneCore from performing an automatic answer. - * + * * When receiving a #LinphoneCallUpdatedByRemote state notification (ie an incoming reINVITE), the default behaviour of * LinphoneCore is to automatically answer the reINIVTE with call parameters unchanged. * However when for example when the remote party updated the call to propose a video stream, it can be useful - * to prompt the user before answering. This can be achieved by calling linphone_core_defer_call_update() during + * to prompt the user before answering. This can be achieved by calling linphone_core_defer_call_update() during * the call state notifiacation, to deactivate the automatic answer that would just confirm the audio but reject the video. * Then, when the user responds to dialog prompt, it becomes possible to call linphone_core_accept_call_update() to answer * the reINVITE, with eventually video enabled in the LinphoneCallParams argument. - * + * * @return 0 if successful, -1 if the linphone_core_defer_call_update() was done outside a #LinphoneCallUpdatedByRemote notification, which is illegal. **/ int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){ @@ -3420,7 +3420,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, sal_call_set_local_media_description(call->op,call->localdesc); sal_op_set_sent_custom_header(call->op,params->custom_headers); } - + /*give a chance a set card prefered sampling frequency*/ if (call->localdesc->streams[0].max_rate>0) { ms_message ("configuring prefered card sampling rate to [%i]",call->localdesc->streams[0].max_rate); @@ -3429,7 +3429,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, if (lc->sound_conf.capt_sndcard) ms_snd_card_set_preferred_sample_rate(lc->sound_conf.capt_sndcard, call->localdesc->streams[0].max_rate); } - + if (!was_ringing && call->audiostream->ms.state==MSStreamInitialized){ audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard); } @@ -3547,9 +3547,9 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call) /** * Decline a pending incoming call, with a reason. - * + * * @ingroup call_control - * + * * @param lc the linphone core * @param call the LinphoneCall, must be in the IncomingReceived state. * @param reason the reason for rejecting the call: LinphoneReasonDeclined or LinphoneReasonBusy @@ -3683,12 +3683,12 @@ int linphone_core_pause_all_calls(LinphoneCore *lc){ void linphone_core_preempt_sound_resources(LinphoneCore *lc){ LinphoneCall *current_call; - + if (linphone_core_is_in_conference(lc)){ linphone_core_leave_conference(lc); return; } - + current_call=linphone_core_get_current_call(lc); if(current_call != NULL){ ms_message("Pausing automatically the current call."); @@ -3707,7 +3707,7 @@ void linphone_core_preempt_sound_resources(LinphoneCore *lc){ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ char temp[255]={0}; const char *subject="Call resuming"; - + if(call->state!=LinphoneCallPaused ){ ms_warning("we cannot resume a call that has not been established and paused before"); return -1; @@ -3722,7 +3722,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ } call->was_automatically_paused=FALSE; - + /* Stop playing music immediately. If remote side is a conference it prevents the participants to hear it while the 200OK comes back.*/ if (call->audiostream) audio_stream_play(call->audiostream, NULL); @@ -3758,7 +3758,7 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad * @param lc * @param remote_address * @return the LinphoneCall of the call if found - * + * * @ingroup call_control */ LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){ @@ -4361,7 +4361,7 @@ const char *linphone_core_get_root_ca(LinphoneCore *lc){ /** * Specify whether the tls server certificate must be verified when connecting to a SIP/TLS server. - * + * * @ingroup initializing **/ void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){ @@ -4478,7 +4478,7 @@ void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){ if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){ audio_stream_mute_rtp(st,val); } - + } } @@ -4564,7 +4564,7 @@ void linphone_core_set_stun_server(LinphoneCore *lc, const char *server){ if (server) lc->net_conf.stun_server=ms_strdup(server); else lc->net_conf.stun_server=NULL; - + /* each time the stun server is changed, we must clean the resolved cached addrinfo*/ if (lc->net_conf.stun_addrinfo){ freeaddrinfo(lc->net_conf.stun_addrinfo); @@ -4574,7 +4574,7 @@ void linphone_core_set_stun_server(LinphoneCore *lc, const char *server){ if (lc->net_conf.stun_server){ linphone_core_resolve_stun_server(lc); } - + if (linphone_core_ready(lc)) lp_config_set_string(lc->config,"net","stun_server",lc->net_conf.stun_server); } @@ -4631,7 +4631,7 @@ const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc) char ipstring [INET6_ADDRSTRLEN]; if (lc->net_conf.nat_address==NULL) return NULL; - + if (parse_hostname_to_addr (lc->net_conf.nat_address, &ss, &ss_len, 5060)<0) { return lc->net_conf.nat_address; } @@ -5000,7 +5000,7 @@ int linphone_core_set_static_picture(LinphoneCore *lc, const char *path) { const char *linphone_core_get_static_picture(LinphoneCore *lc) { const char *path=NULL; #ifdef VIDEO_ENABLED - path=ms_static_image_get_default_image(); + path=ms_static_image_get_default_image(); #else ms_warning("Video support not compiled."); #endif @@ -5075,7 +5075,7 @@ static void unset_video_window_id(LinphoneCore *lc, bool_t preview, unsigned lon LinphoneCall *call; MSList *elem; #endif - + if (id!=0 && id!=-1) { ms_error("Invalid use of unset_video_window_id()"); return; @@ -5239,7 +5239,7 @@ static MSVideoSizeDef supported_resolutions[]={ #if !TARGET_OS_MAC || TARGET_OS_IPHONE /* OS_MAC is 1 for iPhone, but we need QVGA */ { { MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H } , "qvga" }, #endif - { { MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H } , "qcif" }, + { { MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H } , "qcif" }, { { 0,0 } , NULL } }; @@ -5484,7 +5484,7 @@ void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID toneid){ def.frequencies[0]=620; def.interval=250; def.repeat_count=3; - + break; default: ms_warning("Unhandled tone id."); @@ -5550,7 +5550,7 @@ int linphone_core_get_mtu(const LinphoneCore *lc){ * Sets the maximum transmission unit size in bytes. * This information is useful for sending RTP packets. * Default value is 1500. - * + * * @ingroup media_parameters **/ void linphone_core_set_mtu(LinphoneCore *lc, int mtu){ @@ -5644,7 +5644,7 @@ void sip_config_uninit(LinphoneCore *lc) int i; sip_config_t *config=&lc->sip_conf; bool_t still_registered=TRUE; - + lp_config_set_int(lc->config,"sip","guess_hostname",config->guess_hostname); lp_config_set_string(lc->config,"sip","contact",config->contact); lp_config_set_int(lc->config,"sip","inc_timeout",config->inc_timeout); @@ -5659,7 +5659,7 @@ void sip_config_uninit(LinphoneCore *lc) LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data); linphone_proxy_config_edit(cfg); /* to unregister */ } - + ms_message("Unregistration started."); for (i=0;i<20&&still_registered;i++){ @@ -5691,7 +5691,7 @@ void sip_config_uninit(LinphoneCore *lc) ms_message("Tunnel destroyed."); } #endif - + sal_reset_transports(lc->sal); sal_unlisten_ports(lc->sal); /*to make sure no new messages are received*/ if (lc->http_provider) { @@ -5897,7 +5897,7 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_presence_model_unref(lc->presence_model); } linphone_core_free_payload_types(lc); - + linphone_core_message_storage_close(lc); ms_exit(); linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); @@ -5906,7 +5906,7 @@ static void linphone_core_uninit(LinphoneCore *lc) static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){ // second get the list of available proxies const MSList *elem=linphone_core_get_proxy_config_list(lc); - + if (lc->network_reachable==isReachable) return; // no change, ignore. ms_message("Network state is now [%s]",isReachable?"UP":"DOWN"); @@ -5923,7 +5923,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu } lc->netup_time=curtime; lc->network_reachable=isReachable; - + if (!lc->network_reachable){ linphone_core_invalidate_friend_subscriptions(lc); sal_reset_transports(lc->sal); @@ -6397,7 +6397,7 @@ int linphone_core_set_media_encryption(LinphoneCore *lc, LinphoneMediaEncryption LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc) { const char* menc = lp_config_get_string(lc->config, "sip", "media_encryption", NULL); - + if (menc == NULL) return LinphoneMediaEncryptionNone; else if (strcmp(menc, "srtp")==0) @@ -6433,10 +6433,10 @@ const char* linphone_core_get_device_identifier(const LinphoneCore *lc) { /** * Set the DSCP field for SIP signaling channel. - * + * * @ingroup network_parameters * * The DSCP defines the quality of service in IP packets. - * + * **/ void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){ sal_set_dscp(lc->sal,dscp); @@ -6448,10 +6448,10 @@ void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){ /** * Get the DSCP field for SIP signaling channel. - * + * * @ingroup network_parameters * * The DSCP defines the quality of service in IP packets. - * + * **/ int linphone_core_get_sip_dscp(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"sip","dscp",0x1a); @@ -6462,7 +6462,7 @@ int linphone_core_get_sip_dscp(const LinphoneCore *lc){ * * @ingroup network_parameters * The DSCP defines the quality of service in IP packets. - * + * **/ void linphone_core_set_audio_dscp(LinphoneCore *lc, int dscp){ if (linphone_core_ready(lc)) @@ -6474,7 +6474,7 @@ void linphone_core_set_audio_dscp(LinphoneCore *lc, int dscp){ * * @ingroup network_parameters * The DSCP defines the quality of service in IP packets. - * + * **/ int linphone_core_get_audio_dscp(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"rtp","audio_dscp",0x2e); @@ -6485,12 +6485,12 @@ int linphone_core_get_audio_dscp(const LinphoneCore *lc){ * * @ingroup network_parameters * The DSCP defines the quality of service in IP packets. - * + * **/ void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp){ if (linphone_core_ready(lc)) lp_config_set_int_hex(lc->config,"rtp","video_dscp",dscp); - + } /** @@ -6498,7 +6498,7 @@ void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp){ * * @ingroup network_parameters * The DSCP defines the quality of service in IP packets. - * + * **/ int linphone_core_get_video_dscp(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"rtp","video_dscp",0); diff --git a/coreapi/presence.c b/coreapi/presence.c index 08996329f..fa4b97014 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1467,7 +1467,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ char *tmp; LinphoneAddress *uri; LinphoneProxyConfig *cfg; - + uri=linphone_address_new(from); linphone_address_clean(uri); tmp=linphone_address_as_string(uri); @@ -1482,7 +1482,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ } } } - + /* check if we answer to this subscription */ if (linphone_find_friend_by_address(lc->friends,uri,&lf)!=NULL){ lf->insub=op; diff --git a/coreapi/private.h b/coreapi/private.h index efc622b31..9de726b9a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -677,7 +677,7 @@ struct _LinphoneCore bool_t use_preview_window; time_t network_last_check; - + bool_t network_last_status; bool_t ringstream_autorelease; bool_t pad[2]; diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 89b61f513..a118ba50a 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -17,7 +17,7 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org) * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + #include "linphonecore.h" #include "sipsetup.h" #include "lpconfig.h" @@ -31,7 +31,7 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){ MSList *elem; int i; if (!linphone_core_ready(lc)) return; - + for(elem=lc->sip_conf.proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; linphone_proxy_config_write_to_config_file(lc->config,cfg,i); @@ -49,7 +49,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob const char *statistics_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_statistics_collector", NULL) : NULL; const char *contact_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_parameters", NULL) : NULL; const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL; - + memset(obj, 0, sizeof(LinphoneProxyConfig)); obj->magic = linphone_proxy_config_magic; obj->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600; @@ -88,7 +88,7 @@ LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) { /** * Destroys a proxy config. - * + * * @note: LinphoneProxyConfig that have been removed from LinphoneCore with * linphone_core_remove_proxy_config() must not be freed. **/ @@ -127,10 +127,10 @@ bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj){ int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr){ LinphoneAddress *addr=NULL; char *modified=NULL; - + if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy); obj->reg_proxy=NULL; - + if (server_addr!=NULL && strlen(server_addr)>0){ if (strstr(server_addr,"sip:")==NULL && strstr(server_addr,"sips:")==NULL){ modified=ms_strdup_printf("sip:%s",server_addr); @@ -153,7 +153,7 @@ int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char * /** * Sets the user identity as a SIP address. * - * This identity is normally formed with display name, username and domain, such + * This identity is normally formed with display name, username and domain, such * as: * Alice * The REGISTER messages will have from and to set to this identity. @@ -301,14 +301,14 @@ LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *obj){ LinphoneAddress *ret=NULL; LinphoneAddress *proxy=linphone_address_new(obj->reg_proxy); const char *host; - + if (proxy==NULL) return NULL; host=linphone_address_get_domain(proxy); if (host!=NULL){ int localport = -1; const char *localip = NULL; LinphoneAddress *contact=linphone_address_new(obj->reg_identity); - + linphone_address_clean(contact); if (obj->contact_params) { @@ -378,7 +378,7 @@ void linphone_proxy_config_refresh_register(LinphoneProxyConfig *obj){ /** - * Sets a dialing prefix to be automatically prepended when inviting a number with + * Sets a dialing prefix to be automatically prepended when inviting a number with * linphone_core_invite(); * This dialing prefix shall usually be the country code of the country where the user is living. * @@ -394,7 +394,7 @@ void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char /** * Returns dialing prefix. * - * + * **/ const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){ return cfg->dial_prefix; @@ -435,7 +435,7 @@ void linphone_proxy_config_set_statistics_collector(LinphoneProxyConfig *cfg, co if (addr) linphone_address_destroy(addr); } else { - if (cfg->reg_statistics_collector != NULL) + if (cfg->reg_statistics_collector != NULL) ms_free(cfg->reg_statistics_collector); cfg->reg_statistics_collector = ms_strdup(collector); linphone_address_destroy(addr); @@ -458,7 +458,7 @@ typedef struct dial_plan{ char ccc[8]; /*country calling code*/ int nnl; /*maximum national number length*/ const char * icp; /*international call prefix, ex: 00 in europe*/ - + }dial_plan_t; /* TODO: fill with information for all countries over the world*/ @@ -743,7 +743,7 @@ static void lookup_dial_plan(const char *ccc, dial_plan_t *plan){ static bool_t is_a_phone_number(const char *username){ const char *p; for(p=username;*p!='\0';++p){ - if (isdigit(*p) || + if (isdigit(*p) || *p==' ' || *p=='.' || *p=='-' || @@ -771,12 +771,12 @@ static char *flatten_number(const char *number){ static void replace_plus(const char *src, char *dest, size_t destlen, const char *icp){ int i=0; - + if (icp && src[0]=='+' && (destlen>(i=strlen(icp))) ){ src++; strcpy(dest,icp); } - + for(;(idial_prefix==NULL || proxy->dial_prefix[0]=='\0'){ /*no prefix configured, nothing else to do*/ strncpy(result,flatten,result_len); @@ -859,7 +859,7 @@ void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){ int err=0; - + if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){ if (proxy->publish_op==NULL){ proxy->publish_op=sal_op_new(proxy->lc->sal); @@ -1050,7 +1050,7 @@ void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *conf lc->default_proxy=config; if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL)); -} +} void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){ if (index<0) linphone_core_set_default_proxy(lc,NULL); @@ -1124,7 +1124,7 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config const char *proxy; LinphoneProxyConfig *cfg; char key[50]; - + sprintf(key,"proxy_%i",index); if (!lp_config_has_section(config,key)){ @@ -1133,12 +1133,12 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config cfg=linphone_proxy_config_new(); - identity=lp_config_get_string(config,key,"reg_identity",NULL); + identity=lp_config_get_string(config,key,"reg_identity",NULL); proxy=lp_config_get_string(config,key,"reg_proxy",NULL); - + linphone_proxy_config_set_identity(cfg,identity); linphone_proxy_config_set_server_addr(cfg,proxy); - + tmp=lp_config_get_string(config,key,"reg_route",NULL); if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp); @@ -1147,19 +1147,19 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config linphone_proxy_config_enable_statistics(cfg,lp_config_get_int(config,key,"send_statistics",0)); linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL)); - + linphone_proxy_config_set_contact_uri_parameters(cfg,lp_config_get_string(config,key,"contact_uri_parameters",NULL)); - + linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",lp_config_get_default_int(config,"proxy","reg_expires",600))); linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0)); - + linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0)); linphone_proxy_config_set_dial_escape_plus(cfg,lp_config_get_int(config,key,"dial_escape_plus",lp_config_get_default_int(config,"proxy","dial_escape_plus",0))); linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",lp_config_get_default_string(config,"proxy","dial_prefix",NULL))); - + tmp=lp_config_get_string(config,key,"type",NULL); - if (tmp!=NULL && strlen(tmp)>0) + if (tmp!=NULL && strlen(tmp)>0) linphone_proxy_config_set_sip_setup(cfg,tmp); linphone_proxy_config_set_privacy(cfg,lp_config_get_int(config,key,"privacy",lp_config_get_default_int(config,"proxy","privacy",LinphonePrivacyDefault))); @@ -1198,7 +1198,7 @@ static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){ ms_error("Could not retrieve proxy uri !"); } } - + } SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){ @@ -1213,7 +1213,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){ LinphoneCore *lc=cfg->lc; #ifdef BUILD_UPNP if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp){ - if(lc->sip_conf.register_only_when_upnp_is_ok && + if(lc->sip_conf.register_only_when_upnp_is_ok && (lc->upnp == NULL || !linphone_upnp_context_is_ready_for_register(lc->upnp))) { return FALSE; } @@ -1369,7 +1369,7 @@ void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) { void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){ LinphoneCore *lc=cfg->lc; bool_t update_friends=FALSE; - + if (cfg->state!=state || state==LinphoneRegistrationOk) { /*allow multiple notification of LinphoneRegistrationOk for refreshing*/ ms_message("Proxy config [%p] for identity [%s] moving from state [%s] to [%s]" , cfg, linphone_proxy_config_get_identity(cfg), @@ -1380,7 +1380,7 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat || (state!=LinphoneRegistrationOk && cfg->state==LinphoneRegistrationOk); } cfg->state=state; - + if (update_friends){ linphone_core_update_friends_subscriptions(lc,cfg,TRUE); } diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 441957736..a415824e4 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*************************************************************************** * TODO / REMINDER LIST - ****************************************************************************/ + ****************************************************************************/ // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). // range 0 - 255 instead of 0 - 5 for metrics->quality_estimates.rcq, metrics->quality_estimates.moslq, metrics->quality_estimates.moscq // Know issue: if call is stopped to early, IP are invalid @@ -115,7 +115,7 @@ static bool_t are_metrics_filled(const reporting_content_metrics_t rm) { IF_NUM_IN_RANGE(rm.jitter_buffer.adaptive, 0, 3, return TRUE); IF_NUM_IN_RANGE(rm.jitter_buffer.nominal, 0, 65535, return TRUE); IF_NUM_IN_RANGE(rm.jitter_buffer.max, 0, 65535, return TRUE); - IF_NUM_IN_RANGE(rm.jitter_buffer.abs_max, 0, 65535, return TRUE); + IF_NUM_IN_RANGE(rm.jitter_buffer.abs_max, 0, 65535, return TRUE); IF_NUM_IN_RANGE(rm.delay.round_trip_delay, 0, 65535, return TRUE); IF_NUM_IN_RANGE(rm.delay.end_system_delay, 0, 65535, return TRUE); @@ -141,9 +141,9 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off char * moslq_str = NULL; char * moscq_str = NULL; - if (rm.timestamps.start > 0) + if (rm.timestamps.start > 0) timestamps_start_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.start); - if (rm.timestamps.stop > 0) + if (rm.timestamps.stop > 0) timestamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop); IF_NUM_IN_RANGE(rm.packet_loss.network_packet_loss_rate, 0, 255, network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate / 256)); @@ -173,7 +173,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off // APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max, 0, 65535); - APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max, 0, 65535); + APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max, 0, 65535); append_to_buffer(buffer, size, offset, "\r\nPacketLoss:"); APPEND_IF_NOT_NULL_STR(buffer, size, offset, " NLR=%s", network_packet_loss_rate_str); @@ -184,7 +184,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off // append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " GLD=%s", gap_loss_density_str); // append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_duration); - // append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); + // append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); append_to_buffer(buffer, size, offset, "\r\nDelay:"); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay, 0, 65535); @@ -256,10 +256,10 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "LocalMAC: %s\r\n", report->info.local_mac_addr); append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.remote_addr.ip, report->info.remote_addr.port, report->info.remote_addr.ssrc); APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "RemoteMAC: %s\r\n", report->info.remote_mac_addr); - + append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n"); append_metrics_to_buffer(&buffer, &size, &offset, report->local_metrics); - + if (are_metrics_filled(report->remote_metrics)) { append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n"); append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics); @@ -302,7 +302,7 @@ static void reporting_update_ip(LinphoneCall * call, int stats_type) { if (call->log->reports[stats_type] != NULL) { const SalStreamDescription * local_desc = get_media_stream_for_desc(call->localdesc, sal_stream_type); const SalStreamDescription * remote_desc = get_media_stream_for_desc(sal_call_get_remote_media_description(call->op), sal_stream_type); - + // local info are always up-to-date and correct if (local_desc != NULL) { call->log->reports[stats_type]->info.local_addr.port = local_desc->rtp_port; @@ -332,7 +332,7 @@ void linphone_reporting_update_ip(LinphoneCall * call) { // - 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered // - 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access - if (! reporting_enabled(call)) + if (! reporting_enabled(call)) return; reporting_update_ip(call, LINPHONE_CALL_STATS_AUDIO); @@ -349,7 +349,7 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { const PayloadType * remote_payload = NULL; const LinphoneCallParams * current_params = linphone_call_get_current_params(call); - if (! reporting_enabled(call)) + if (! reporting_enabled(call)) return; STR_REASSIGN(report->info.call_id, ms_strdup(call->log->call_id)); @@ -376,7 +376,7 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { //we use same timestamps for remote too report->remote_metrics.timestamps.start = call->log->start_date_time; report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); - + // yet we use the same payload config for local and remote, since this is the largest case if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { stream = &call->audiostream->ms; @@ -417,7 +417,7 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { LinphoneCallStats stats = call->stats[stats_type]; mblk_t *block = NULL; - if (! reporting_enabled(call)) + if (! reporting_enabled(call)) return; if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { @@ -463,7 +463,7 @@ void linphone_reporting_publish(LinphoneCall* call) { reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO]); } - if (call->log->reports[LINPHONE_CALL_STATS_VIDEO] != NULL + if (call->log->reports[LINPHONE_CALL_STATS_VIDEO] != NULL && linphone_call_params_video_enabled(linphone_call_get_current_params(call))) { reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_VIDEO]); } diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index f3d311ad9..c817feba9 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -57,7 +57,7 @@ typedef struct reporting_content_metrics { struct { int adaptive; // constant // int rate; // constant - int nominal; // no may vary during the call <- average? worst score? + int nominal; // no may vary during the call <- average? worst score? int max; // no may vary during the call <- average? int abs_max; // constant } jitter_buffer; @@ -68,10 +68,10 @@ typedef struct reporting_content_metrics { float jitter_buffer_discard_rate; //idem } packet_loss; - // burst gap loss - optional + // burst gap loss - optional // (no) currently not implemented // struct { - // int burst_loss_density; + // int burst_loss_density; // int burst_duration; // float gap_loss_density; // int gap_duration; @@ -90,7 +90,7 @@ typedef struct reporting_content_metrics { // signal - optional struct { - int level; // no - vary + int level; // no - vary int noise_level; // no - vary // int residual_echo_return_loss; } signal; @@ -101,7 +101,7 @@ typedef struct reporting_content_metrics { int rcq; //voip metrics R factor - no - vary or avg in [0..120] float moslq; // no - vary or avg - voip metrics - in [0..4.9] float moscq; // no - vary or avg - voip metrics - in [0..4.9] - + // int extri; // int extro; @@ -114,7 +114,7 @@ typedef struct reporting_content_metrics { // char * qoestalg; } quality_estimates; } reporting_content_metrics_t; - + typedef struct reporting_session_report { struct { char * call_id; diff --git a/coreapi/sal.c b/coreapi/sal.c index e42c124cc..5404210f3 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/** +/** This header files defines the Signaling Abstraction Layer. - The purpose of this layer is too allow experiment different call signaling + The purpose of this layer is too allow experiment different call signaling protocols and implementations under linphone, for example SIP, JINGLE... **/ #ifdef HAVE_CONFIG_H @@ -39,7 +39,7 @@ const char* sal_transport_to_string(SalTransport transport) { default: { ms_fatal("Unexpected transport [%i]",transport); return NULL; - } + } } } @@ -409,17 +409,17 @@ void __sal_op_free(SalOp *op){ sal_address_destroy(b->to_address); b->to_address=NULL; } - + if (b->service_route){ sal_address_destroy(b->service_route); b->service_route=NULL; } - + if (b->origin_address){ sal_address_destroy(b->origin_address); b->origin_address=NULL; } - + if (b->from) { ms_free(b->from); b->from=NULL; @@ -624,7 +624,7 @@ static int line_get_value(const char *input, const char *key, char *value, size_ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size){ int read=0; - + do{ if (line_get_value(data,key,value,value_size,&read)) return TRUE; @@ -634,7 +634,7 @@ int sal_lines_get_value(const char *data, const char *key, char *value, size_t v } int sal_body_has_type(const SalBody *body, const char *type, const char *subtype){ - return body->type && body->subtype + return body->type && body->subtype && strcmp(body->type,type)==0 && strcmp(body->subtype,subtype)==0; } diff --git a/include/sal/sal.h b/include/sal/sal.h index 7ec00f596..b6356350a 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/** +/** This header files defines the Signaling Abstraction Layer. - The purpose of this layer is too allow experiment different call signaling + The purpose of this layer is too allow experiment different call signaling protocols and implementations under linphone, for example SIP, JINGLE... **/ diff --git a/tester/call_tester.c b/tester/call_tester.c index 999dc0d77..51fb39859 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -103,10 +103,10 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); - + CU_ASSERT_PTR_NOT_NULL(c1); CU_ASSERT_PTR_NOT_NULL(c2); - + if (!c1 || !c2) return; for (i=0; i<24 /*=12s need at least one exchange of SR to maybe 10s*/; i++) { @@ -316,7 +316,7 @@ static void cancelled_call(void) { static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime){ const MSList *elem=linphone_core_get_audio_codecs(lc); PayloadType *pt; - + for(;elem!=NULL;elem=elem->next){ pt=(PayloadType*)elem->data; linphone_core_enable_payload_type(lc,pt,FALSE); @@ -351,7 +351,7 @@ static void call_with_dns_time_out(void) { LinphoneCoreManager* marie = linphone_core_manager_new2( "empty_rc", FALSE); LCSipTransports transport = {9773,0,0,0}; int i; - + linphone_core_set_sip_transports(marie->lc,&transport); linphone_core_iterate(marie->lc); sal_set_dns_timeout(marie->lc->sal,0); @@ -359,7 +359,7 @@ static void call_with_dns_time_out(void) { for(i=0;i<10;i++){ ms_usleep(200000); linphone_core_iterate(marie->lc); - } + } CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingInit,1); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingProgress,1); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1); @@ -372,21 +372,21 @@ static void early_cancelled_call(void) { LinphoneCoreManager* pauline = linphone_core_manager_new2( "empty_rc",FALSE); LinphoneCall* out_call = linphone_core_invite_address(pauline->lc,marie->identity); - + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1)); linphone_core_terminate_call(pauline->lc,out_call); - + /*since everything is executed in a row, no response can be received from the server, thus the CANCEL cannot be sent. It will ring at Marie's side.*/ - + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); - + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallEnd,1); - + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1)); /* now the CANCEL should have been sent and the the call at marie's side should terminate*/ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); - + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1)); linphone_core_manager_destroy(marie); @@ -426,7 +426,7 @@ static void early_declined_call(void) { CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,33000)); CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallError,1); /* FIXME http://git.linphone.org/mantis/view.php?id=757 - + CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonBusy); */ if (ms_list_size(linphone_core_get_call_logs(pauline->lc))>0) { @@ -466,7 +466,7 @@ static void call_declined(void) { static void call_terminated_by_caller(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - + CU_ASSERT_TRUE(call(pauline,marie)); /*just to sleep*/ linphone_core_terminate_all_calls(pauline->lc); @@ -480,7 +480,7 @@ static void call_terminated_by_caller(void) { static void call_with_no_sdp(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - + linphone_core_enable_sdp_200_ack(marie->lc,TRUE); CU_ASSERT_TRUE(call(marie,pauline)); @@ -500,7 +500,7 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); - + CU_ASSERT_PTR_NOT_NULL(c1); CU_ASSERT_PTR_NOT_NULL(c2); @@ -522,12 +522,12 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee static void _call_with_ice(bool_t random_ports) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - + linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce); linphone_core_set_stun_server(marie->lc,"stun.linphone.org"); linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce); linphone_core_set_stun_server(pauline->lc,"stun.linphone.org"); - + if (random_ports){ linphone_core_set_audio_port(marie->lc,-1); linphone_core_set_video_port(marie->lc,-1); @@ -541,9 +541,9 @@ static void _call_with_ice(bool_t random_ports) { /*wait for the ICE reINVITE to complete*/ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); - + CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); - + liblinphone_tester_check_rtcp(marie,pauline); /*then close the call*/ linphone_core_terminate_all_calls(pauline->lc); @@ -581,17 +581,17 @@ static void call_with_custom_headers(void) { ms_free(tmp); linphone_address_destroy(marie->identity); marie->identity=marie_identity; - + params=linphone_core_create_default_call_parameters(marie->lc); linphone_call_params_add_custom_header(params,"Weather","bad"); linphone_call_params_add_custom_header(params,"Working","yes"); - + CU_ASSERT_TRUE(call_with_caller_params(pauline,marie,params)); linphone_call_params_destroy(params); - + call_marie=linphone_core_get_current_call(marie->lc); call_pauline=linphone_core_get_current_call(pauline->lc); - + CU_ASSERT_PTR_NOT_NULL(call_marie); CU_ASSERT_PTR_NOT_NULL(call_pauline); @@ -752,12 +752,12 @@ static void call_with_video_added(void) { static void call_with_video_added_random_ports(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - + linphone_core_set_audio_port(marie->lc,-1); linphone_core_set_video_port(marie->lc,-1); linphone_core_set_audio_port(pauline->lc,-1); linphone_core_set_video_port(pauline->lc,-1); - + CU_ASSERT_TRUE(call(pauline,marie)); CU_ASSERT_TRUE(add_video(pauline,marie)); @@ -848,17 +848,17 @@ static void _call_with_media_relay(bool_t random_ports) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); - + if (random_ports){ linphone_core_set_audio_port(marie->lc,-1); linphone_core_set_video_port(marie->lc,-1); linphone_core_set_audio_port(pauline->lc,-1); linphone_core_set_video_port(pauline->lc,-1); } - + CU_ASSERT_TRUE(call(pauline,marie)); liblinphone_tester_check_rtcp(pauline,marie); - + #ifdef VIDEO_ENABLED CU_ASSERT_TRUE(add_video(pauline,marie)); liblinphone_tester_check_rtcp(pauline,marie); @@ -944,7 +944,7 @@ static void call_with_privacy2(void) { LinphoneProxyConfig* pauline_proxy; params=linphone_core_create_default_call_parameters(pauline->lc); linphone_call_params_set_privacy(params,LinphonePrivacyId); - + linphone_core_get_default_proxy(pauline->lc,&pauline_proxy); linphone_proxy_config_edit(pauline_proxy); linphone_proxy_config_enable_register(pauline_proxy,FALSE); @@ -1151,7 +1151,7 @@ static void encrypted_call(LinphoneMediaEncryption mode) { CU_ASSERT_EQUAL(linphone_core_get_media_encryption(marie->lc),mode); CU_ASSERT_EQUAL(linphone_core_get_media_encryption(pauline->lc),mode); - if (linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP + if (linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP && linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP) { /*check SAS*/ CU_ASSERT_STRING_EQUAL(linphone_call_get_authentication_token(linphone_core_get_current_call(pauline->lc)) @@ -1233,7 +1233,7 @@ static void srtp_ice_call(void) { /*wait for ice to found the direct path*/ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,1)); #endif - + /*just to sleep*/ linphone_core_terminate_all_calls(marie->lc); @@ -1258,19 +1258,19 @@ static void early_media_call(void) { CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingEarlyMedia,1); CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1); - + wait_for_until(pauline->lc,marie->lc,NULL,0,1000); - + /*added because a bug related to early-media caused the Connected state to be reached two times*/ CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallConnected,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); } @@ -1287,7 +1287,7 @@ static void early_media_call_with_ringing(void){ /* Marie calls Pauline, and after the call has rung, transitions to an early_media session */ - + /*use playfile for callee to avoid locking on capture card*/ linphone_core_use_files (pauline->lc,TRUE); snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix); @@ -1323,7 +1323,7 @@ static void early_media_call_with_ringing(void){ ms_list_free(lcs); - + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -1446,9 +1446,9 @@ static void simple_call_transfer(void) { CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallPaused,1,2000)); /*marie calling laure*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingProgress,1,2000)); - + CU_ASSERT_PTR_NOT_NULL(linphone_call_get_transfer_target_call(marie_calling_pauline)); - + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneTransferCallOutgoingInit,1,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallIncomingReceived,1,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingRinging,1,2000)); @@ -1458,11 +1458,11 @@ static void simple_call_transfer(void) { CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning,1,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallConnected,1,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,2000)); - + marie_calling_laure=linphone_core_get_current_call(marie->lc); CU_ASSERT_PTR_NOT_NULL_FATAL(marie_calling_laure); CU_ASSERT_TRUE(linphone_call_get_transferer_call(marie_calling_laure)==marie_calling_pauline); - + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneTransferCallConnected,1,2000)); /*terminate marie to pauline call*/ @@ -1496,11 +1496,11 @@ static void unattended_call_transfer(void) { linphone_core_transfer_call(marie->lc,pauline_called_by_marie,laure_identity); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallRefered,1,2000)); - + /*marie ends the call */ linphone_core_terminate_call(marie->lc,pauline_called_by_marie); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,2000)); - + /*Pauline starts the transfer*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingInit,1,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingProgress,1,2000)); @@ -1537,21 +1537,21 @@ static void unattended_call_transfer_with_error(void) { linphone_core_transfer_call(marie->lc,pauline_called_by_marie,"unknown_user"); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallRefered,1,2000)); - + /*Pauline starts the transfer*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingInit,1,2000)); /* and immediately get an error*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallError,1,2000)); - + /*the error must be reported back to marie*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallError,1,2000)); /*and pauline should resume the call automatically*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallResuming,1,2000)); - + /*and call should be resumed*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,2000)); - + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); ms_list_free(lcs); @@ -1705,7 +1705,7 @@ static void call_established_with_rejected_incoming_reinvite(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); CU_ASSERT_TRUE(call(pauline,marie)); - + /*wait for ACK to be transmitted before going to reINVITE*/ wait_for_until(marie->lc,pauline->lc,NULL,0,1000); @@ -1750,7 +1750,7 @@ static void call_redirect(void){ /* Marie calls Pauline, which will redirect the call to Laure via a 302 */ - + /*use playfile for callee to avoid locking on capture card*/ linphone_core_use_files (pauline->lc,TRUE); linphone_core_use_files (laure->lc,TRUE); @@ -1788,7 +1788,7 @@ static void call_redirect(void){ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); ms_list_free(lcs); - + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(laure); @@ -1901,7 +1901,7 @@ static void statistics_not_used_without_config() { CU_ASSERT_TRUE(linphone_proxy_config_send_statistics_enabled(call_marie->dest_proxy)); CU_ASSERT_FALSE(linphone_proxy_config_send_statistics_enabled(call_pauline->dest_proxy)); - CU_ASSERT_EQUAL(strcmp("sip:collector@sip.linphone.org", + CU_ASSERT_EQUAL(strcmp("sip:collector@sip.example.org", linphone_proxy_config_get_statistics_collector(call_marie->dest_proxy)), 0); // this field should be already filled @@ -1935,7 +1935,7 @@ static void statistics_not_sent_if_call_not_started() { // wait a few time... wait_for(marie->lc,NULL,NULL,0); - // since the callee was busy, there shouldn't be no publish to do + // since the callee was busy, there shouldn't be no publish to do CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); @@ -1964,7 +1964,7 @@ static void statistics_sent_at_call_termination() { // PUBLISH submission to the collector should be ok CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); // failing since server side is not implemented - + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } From 471314ee1a30e110e061b7d76e00c6c224ff07a5 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 18 Apr 2014 09:06:11 +0200 Subject: [PATCH 33/83] preserve media encryption mode for zrtp in case of re-invite initiated by ice --- coreapi/linphonecall.c | 10 ++++++++-- mediastreamer2 | 2 +- oRTP | 2 +- tester/call_tester.c | 6 +++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index eda356c05..37d853ef3 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2639,11 +2639,17 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ int ping_time; if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) { + LinphoneCallParams params; + _linphone_call_params_copy(¶ms,&call->current_params); + if (call->params.media_encryption == LinphoneMediaEncryptionZRTP) { + /* preserve media encryption param because at that time ZRTP negociation may still be ongoing*/ + params.media_encryption=call->params.media_encryption; + } switch (ice_session_state(call->ice_session)) { case IS_Completed: ice_session_select_candidates(call->ice_session); if (ice_session_role(call->ice_session) == IR_Controlling) { - linphone_core_update_call(call->core, call, &call->current_params); + linphone_core_update_call(call->core, call, ¶ms); } break; case IS_Failed: @@ -2651,7 +2657,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ ice_session_select_candidates(call->ice_session); if (ice_session_role(call->ice_session) == IR_Controlling) { /* At least one ICE session has succeeded, so perform a call update. */ - linphone_core_update_call(call->core, call, &call->current_params); + linphone_core_update_call(call->core, call, ¶ms); } } break; diff --git a/mediastreamer2 b/mediastreamer2 index 5363f6d64..86110766b 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 5363f6d6487f44c0fa898647b7b859857db13283 +Subproject commit 86110766b0cfbd0ecfd4ab853715e0c3d681385b diff --git a/oRTP b/oRTP index 891f3da68..c09e63ddb 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 891f3da6817e30b606493840f305250f81a254bd +Subproject commit c09e63ddba599a7f7da149edf6f7b290f4cfa787 diff --git a/tester/call_tester.c b/tester/call_tester.c index 067292942..924b08950 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1312,13 +1312,13 @@ static void srtp_ice_call(void) { call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce); } static void zrtp_video_ice_call(void) { - /*encrypted_ice_call(LinphoneMediaEncryptionZRTP,TRUE,FALSE);*/ + call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyUseIce); } static void zrtp_ice_call(void) { - /*encrypted_ice_call(LinphoneMediaEncryptionZRTP,FALSE,FALSE);*/ + call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyUseIce); } static void zrtp_ice_call_with_relay(void) { - /*encrypted_ice_call(LinphoneMediaEncryptionZRTP,FALSE,TRUE);*/ + call_base(LinphoneMediaEncryptionZRTP,FALSE,TRUE,LinphonePolicyUseIce); } static void early_media_call(void) { From 0470d0523a20b66a668eddcae1cdac5e574fcbeb Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Fri, 18 Apr 2014 09:13:48 +0200 Subject: [PATCH 34/83] Quality reporting: update comments and fix mos_cq mos_lq values --- coreapi/quality_reporting.c | 30 +++++++++++++++--------------- tester/call_tester.c | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index a415824e4..fb64a4b28 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -31,10 +31,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*************************************************************************** * TODO / REMINDER LIST ****************************************************************************/ - // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). - // range 0 - 255 instead of 0 - 5 for metrics->quality_estimates.rcq, metrics->quality_estimates.moslq, metrics->quality_estimates.moscq - // Know issue: if call is stopped to early, IP are invalid // to discuss + // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). + // moslq == moscq // video: what happens if doing stop/resume? // one time value: average? worst value? // rlq value: need algo to compute it @@ -281,17 +280,17 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ linphone_content_uninit(&content); } -static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDescription * remote_smd, SalStreamType sal_stream_type) { - if (remote_smd != NULL) { - int count; - for (count = 0; count < remote_smd->n_total_streams; ++count) { - if (remote_smd->streams[count].type == sal_stream_type) { - return &remote_smd->streams[count]; +static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDescription * smd, SalStreamType sal_stream_type) { + int count; + if (smd != NULL) { + for (count = 0; count < smd->n_total_streams; ++count) { + if (smd->streams[count].type == sal_stream_type) { + return &smd->streams[count]; } } - if (remote_smd == NULL || count == remote_smd->n_total_streams) { - ms_warning("Could not find the associated stream of type %d for remote desc", sal_stream_type); - } + } + if (smd == NULL || count == smd->n_total_streams) { + ms_warning("Could not find the associated stream of type %d", sal_stream_type); } return NULL; @@ -377,7 +376,7 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { report->remote_metrics.timestamps.start = call->log->start_date_time; report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); - // yet we use the same payload config for local and remote, since this is the largest case + // yet we use the same payload config for local and remote, since this is the largest use case if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { stream = &call->audiostream->ms; local_payload = linphone_call_params_get_used_audio_codec(current_params); @@ -435,8 +434,9 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { switch (rtcp_XR_get_block_type(block)) { case RTCP_XR_VOIP_METRICS: { metrics->quality_estimates.rcq = rtcp_XR_voip_metrics_get_r_factor(block); - metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block); - metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block); + metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f; + metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block) / 10.f; + metrics->jitter_buffer.nominal = rtcp_XR_voip_metrics_get_jb_nominal(block); metrics->jitter_buffer.max = rtcp_XR_voip_metrics_get_jb_maximum(block); metrics->jitter_buffer.abs_max = rtcp_XR_voip_metrics_get_jb_abs_max(block); diff --git a/tester/call_tester.c b/tester/call_tester.c index 51fb39859..b7c6f8861 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1935,7 +1935,7 @@ static void statistics_not_sent_if_call_not_started() { // wait a few time... wait_for(marie->lc,NULL,NULL,0); - // since the callee was busy, there shouldn't be no publish to do + // since the callee was busy, there should be no publish to do CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); @@ -1963,7 +1963,7 @@ static void statistics_sent_at_call_termination() { // PUBLISH submission to the collector should be ok CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); - CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); // failing since server side is not implemented + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); From d6fef910bb543235844d6069ed3d13fa561cbd97 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 18 Apr 2014 11:02:09 +0200 Subject: [PATCH 35/83] fix crash with ICE and compilation error --- coreapi/linphonecall.c | 8 ++++---- tester/call_tester.c | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 37d853ef3..8167f2425 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -109,10 +109,10 @@ static bool_t linphone_call_are_all_streams_encrypted(LinphoneCall *call) { number_of_encrypted_stream++; } } - return number_of_active_stream>0 & number_of_active_stream==number_of_encrypted_stream; + return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream; } -void propagate_encryption_changed(LinphoneCall *call){ +static void propagate_encryption_changed(LinphoneCall *call){ LinphoneCore *lc=call->core; if (!linphone_call_are_all_streams_encrypted(call)) { ms_message("Some streams are not encrypted"); @@ -1462,8 +1462,8 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE); /*start ICE gathering*/ if (incoming_offer) - linphone_core_update_ice_from_remote_media_description(call,remote); - if (!ice_session_candidates_gathered(call->ice_session)){ + linphone_core_update_ice_from_remote_media_description(call,remote); /*this may delete the ice session*/ + if (call->ice_session && !ice_session_candidates_gathered(call->ice_session)){ if (call->audiostream->ms.state==MSStreamInitialized) audio_stream_prepare_sound(call->audiostream, NULL, NULL); #ifdef VIDEO_ENABLED diff --git a/tester/call_tester.c b/tester/call_tester.c index 924b08950..1616ae649 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -553,14 +553,18 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee return success; } -static void _call_with_ice(bool_t random_ports) { +static void _call_with_ice(bool_t caller_with_ice, bool_t callee_with_ice, bool_t random_ports) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce); - linphone_core_set_stun_server(marie->lc,"stun.linphone.org"); - linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce); - linphone_core_set_stun_server(pauline->lc,"stun.linphone.org"); + if (callee_with_ice){ + linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce); + linphone_core_set_stun_server(marie->lc,"stun.linphone.org"); + } + if (caller_with_ice){ + linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce); + linphone_core_set_stun_server(pauline->lc,"stun.linphone.org"); + } if (random_ports){ linphone_core_set_audio_port(marie->lc,-1); @@ -571,12 +575,14 @@ static void _call_with_ice(bool_t random_ports) { CU_ASSERT_TRUE(call(pauline,marie)); - CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); - /*wait for the ICE reINVITE to complete*/ - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); + if (callee_with_ice && caller_with_ice) { + check_ice(pauline,marie,LinphoneIceStateHostConnection); + /*wait for the ICE reINVITE to complete*/ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); - CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); + CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); + } liblinphone_tester_check_rtcp(marie,pauline); /*then close the call*/ @@ -589,11 +595,19 @@ static void _call_with_ice(bool_t random_ports) { } static void call_with_ice(void){ - _call_with_ice(FALSE); + _call_with_ice(TRUE,TRUE,FALSE); } static void call_with_ice_random_ports(void){ - _call_with_ice(TRUE); + _call_with_ice(TRUE,TRUE,TRUE); +} + +static void ice_to_not_ice(void){ + _call_with_ice(TRUE,FALSE,FALSE); +} + +static void not_ice_to_ice(void){ + _call_with_ice(FALSE,TRUE,FALSE); } static void call_with_custom_headers(void) { @@ -2000,6 +2014,8 @@ test_t call_tests[] = { { "Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call }, { "Call with ICE", call_with_ice }, { "Call with ICE (random ports)", call_with_ice_random_ports }, + { "Call from ICE to not ICE",ice_to_not_ice}, + { "Call from not ICE to ICE",not_ice_to_ice}, { "Call with custom headers",call_with_custom_headers}, { "Call established with rejected INFO",call_established_with_rejected_info}, { "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite}, From ce7a483183be66062d6a8cd3479e61c802c867f7 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 18 Apr 2014 11:15:13 +0200 Subject: [PATCH 36/83] Fix local remote provisioning test for android --- tester/rcfiles/marie_remote_localfile_android_rc | 3 +++ tester/remote_provisioning_tester.c | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tester/rcfiles/marie_remote_localfile_android_rc diff --git a/tester/rcfiles/marie_remote_localfile_android_rc b/tester/rcfiles/marie_remote_localfile_android_rc new file mode 100644 index 000000000..ef0a321ce --- /dev/null +++ b/tester/rcfiles/marie_remote_localfile_android_rc @@ -0,0 +1,3 @@ +[misc] +config-uri=file:///data/data/org.linphone.tester/files/config_files/rcfiles/marie_remote_localfile2_rc + diff --git a/tester/remote_provisioning_tester.c b/tester/remote_provisioning_tester.c index 99bfbcc6a..365673ff6 100644 --- a/tester/remote_provisioning_tester.c +++ b/tester/remote_provisioning_tester.c @@ -90,8 +90,13 @@ static void remote_provisioning_default_values(void) { } static void remote_provisioning_file(void) { - LinphoneCoreManager* marie = linphone_core_manager_new2("marie_remote_localfile_rc", FALSE); + LinphoneCoreManager* marie; const LpConfig* conf; +#if ANDROID + marie = linphone_core_manager_new2("marie_remote_localfile_android_rc", FALSE); +#else + marie = linphone_core_manager_new2("marie_remote_localfile_rc", FALSE); +#endif CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringSuccessful,1)); conf = linphone_core_get_config( marie->lc ); From 62365a41199da5e0c1e2685c0082f873a2e7ec85 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 18 Apr 2014 11:20:26 +0200 Subject: [PATCH 37/83] Fix compil of tester for android --- tester/call_tester.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tester/call_tester.c b/tester/call_tester.c index 1616ae649..928ce6484 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1286,6 +1286,7 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e if (policy == LinphonePolicyUseIce) CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); +#ifdef VIDEO_ENABLED if (enable_video) { if (linphone_core_video_supported(marie->lc)) { for (i=0;i<100;i++) { /*fixme to workaround a crash*/ @@ -1306,6 +1307,7 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e } } +#endif /*just to sleep*/ From 9f68674a4b10aa6a6907cebf65b941997719e9e7 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 18 Apr 2014 11:36:06 +0200 Subject: [PATCH 38/83] ms2:fix opus traces --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 86110766b..a66959cdc 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 86110766b0cfbd0ecfd4ab853715e0c3d681385b +Subproject commit a66959cdc9ffa2eb2736c465dfe942ce8a74dbda From c1ef06eb8f2a7c88d6e54943930a838085d11e9e Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 18 Apr 2014 16:05:04 +0200 Subject: [PATCH 39/83] add refcounting to LpConfig --- coreapi/linphonecore.c | 7 +++++-- coreapi/lpconfig.c | 21 +++++++++++++++++++-- coreapi/lpconfig.h | 19 ++++++++++++++++--- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index bd852968e..bc52d67fa 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1304,7 +1304,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab const char *remote_provisioning_uri = NULL; ms_message("Initializing LinphoneCore %s", linphone_core_get_version()); memset (lc, 0, sizeof (LinphoneCore)); - lc->config=config; + lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; @@ -1421,8 +1421,11 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable, const char *config_path, const char *factory_config_path, void * userdata) { + LinphoneCore *lc; LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path); - return linphone_core_new_with_config(vtable, config, userdata); + lc=linphone_core_new_with_config(vtable, config, userdata); + lp_config_unref(config); + return lc; } LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, struct _LpConfig *config, void *userdata) diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 6e51d257c..d6ccea612 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -63,6 +63,7 @@ typedef struct _LpSection{ } LpSection; struct _LpConfig{ + int refcnt; FILE *file; char *filename; MSList *sections; @@ -287,6 +288,7 @@ LpConfig * lp_config_new(const char *filename){ LpConfig * lp_config_new_from_buffer(const char *buffer){ LpConfig* conf = lp_new0(LpConfig,1); + conf->refcnt=1; LpSection* current_section = NULL; char* ptr = ms_strdup(buffer); @@ -305,7 +307,7 @@ LpConfig * lp_config_new_from_buffer(const char *buffer){ LpConfig *lp_config_new_with_factory(const char *config_filename, const char *factory_config_filename) { LpConfig *lpconfig=lp_new0(LpConfig,1); - + lpconfig->refcnt=1; if (config_filename!=NULL){ ms_message("Using (r/w) config information from %s", config_filename); lpconfig->filename=ortp_strdup(config_filename); @@ -354,13 +356,28 @@ void lp_item_set_value(LpItem *item, const char *value){ } -void lp_config_destroy(LpConfig *lpconfig){ +static void _lp_config_destroy(LpConfig *lpconfig){ if (lpconfig->filename!=NULL) ortp_free(lpconfig->filename); ms_list_for_each(lpconfig->sections,(void (*)(void*))lp_section_destroy); ms_list_free(lpconfig->sections); free(lpconfig); } +LpConfig *lp_config_ref(LpConfig *lpconfig){ + lpconfig->refcnt++; + return lpconfig; +} + +void lp_config_unref(LpConfig *lpconfig){ + lpconfig->refcnt--; + if (lpconfig->refcnt==0) + _lp_config_destroy(lpconfig); +} + +void lp_config_destroy(LpConfig *lpconfig){ + lp_config_unref(lpconfig); +} + void lp_section_remove_item(LpSection *sec, LpItem *item){ sec->items=ms_list_remove(sec->items,(void *)item); lp_item_destroy(item); diff --git a/coreapi/lpconfig.h b/coreapi/lpconfig.h index f0f330c18..bd229803e 100644 --- a/coreapi/lpconfig.h +++ b/coreapi/lpconfig.h @@ -57,7 +57,7 @@ extern "C" { /** * Instantiates a LpConfig object from a user config file. - * + * The caller of this constructor owns a reference. lp_config_unref() must be called when this object is no longer needed. * @ingroup misc * @param filename the filename of the config file to read to fill the instantiated LpConfig * @see lp_config_new_with_factory @@ -66,7 +66,7 @@ LINPHONE_PUBLIC LpConfig * lp_config_new(const char *filename); /** * Instantiates a LpConfig object from a user provided buffer. - * + * The caller of this constructor owns a reference. lp_config_unref() must be called when this object is no longer needed. * @ingroup misc * @param buffer the buffer from which the lpconfig will be retrieved. We expect the buffer to be null-terminated. * @see lp_config_new_with_factory @@ -76,7 +76,7 @@ LINPHONE_PUBLIC LpConfig * lp_config_new_from_buffer(const char *buffer); /** * Instantiates a LpConfig object from a user config file and a factory config file. - * + * The caller of this constructor owns a reference. lp_config_unref() must be called when this object is no longer needed. * @ingroup misc * @param config_filename the filename of the user config file to read to fill the instantiated LpConfig * @param factory_config_filename the filename of the factory config file to read to fill the instantiated LpConfig @@ -259,6 +259,19 @@ LINPHONE_PUBLIC const char* lp_config_get_default_string(const LpConfig *lpconfi **/ LINPHONE_PUBLIC const char* lp_config_get_section_param_string(const LpConfig *lpconfig, const char *section, const char *key, const char *default_value); + +/** + * increment reference count + * @ingroup misc +**/ +LINPHONE_PUBLIC LpConfig *lp_config_ref(LpConfig *lpconfig); + +/** + * Decrement reference count, which will eventually free the object. + * @ingroup misc +**/ +LINPHONE_PUBLIC void lp_config_unref(LpConfig *lpconfig); + #ifdef __cplusplus } #endif From e0ee323dd02febc94511f6546085c330bbe47d1c Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 21 Apr 2014 10:27:18 +0200 Subject: [PATCH 40/83] give more time in tests --- README.mingw | 10 +++++++++- tester/flexisip_tester.c | 18 +++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/README.mingw b/README.mingw index 9e9e78075..79e8ce547 100644 --- a/README.mingw +++ b/README.mingw @@ -118,8 +118,8 @@ linphone-deps packages. List of software included in linphone-deps: antlr3c (compiled) +bzrtp (compiled) polarssl (compiled -belle-sip (compiled) libsrtp (compiled) libavcodec, libavutil, libavformat, libavdevice, libswscale (compiled, all these from ffmpeg) libtheora (from the web) @@ -167,6 +167,14 @@ When running "make install DESTDIR=", somepath must be absolute and sh $ make install $ make install DESTDIR=/home//libsrtp-install +- building bzrtp + * download the sources with msys-git shell using the following command: + $ git clone git://git.linphone.org/bzrtp.git + * compile and install + $ ./autogen.sh + $ ./configure --prefix=/usr --enable-shared --disable-static + $ make && make install + - building sqlite3 * download the sources on the following website: http://www.sqlite.org/download.html (choose the sqlite-autoconf-3XXX.tar.gz) diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 4218c1009..1a75cdd97 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -43,7 +43,7 @@ static void subscribe_forking(void) { 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)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline2->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,1000)); @@ -71,7 +71,7 @@ static void message_forking(void) { lcs=ms_list_append(lcs,marie2->lc); linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneMessageReceived,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneMessageDelivered,1,1000)); CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); @@ -101,7 +101,7 @@ static void message_forking_with_unreachable_recipients(void) { linphone_core_set_network_reachable(marie3->lc,FALSE); linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneMessageDelivered,1,1000)); CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); CU_ASSERT_TRUE( marie2->stat.number_of_LinphoneMessageReceived==0); @@ -192,7 +192,7 @@ static void call_forking(void){ linphone_core_invite_address(pauline->lc,marie->identity); /*pauline should hear ringback*/ - CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); /*all devices from Marie should be ringing*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,1000)); @@ -400,7 +400,7 @@ static void call_forking_with_push_notification_single(void){ linphone_core_set_network_reachable(marie->lc,TRUE); /*Marie shall receive the call immediately*/ - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,5000)); /*pauline should hear ringback as well*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); @@ -450,7 +450,7 @@ static void call_forking_with_push_notification_multiple(void){ linphone_core_invite_address(pauline->lc,marie->identity); /*marie1 will ring*/ - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,5000)); /*pauline should hear ringback as well*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); @@ -458,7 +458,7 @@ static void call_forking_with_push_notification_multiple(void){ linphone_core_set_network_reachable(marie2->lc,TRUE); /*Marie shall receive the call immediately*/ - CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,5000)); /*marie2 accepts the call*/ linphone_core_accept_call(marie2->lc,linphone_core_get_current_call(marie2->lc)); @@ -500,7 +500,7 @@ void call_forking_not_responded(void){ linphone_core_invite_address(pauline->lc,marie->identity); /*pauline should hear ringback*/ - CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); /*all devices from Marie should be ringing*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,1000)); @@ -568,7 +568,7 @@ static void early_media_call_forking(void) { linphone_core_invite_address_with_params(pauline->lc,marie1->identity,params); linphone_call_params_destroy(params); - CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingEarlyMedia,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingEarlyMedia,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingEarlyMedia,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,1000)); From b74aa1f56a6c209e9679cb40431892189fcb722c Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 21 Apr 2014 10:35:47 +0200 Subject: [PATCH 41/83] fix audio-only build --- coreapi/linphonecore.c | 2 +- tester/call_tester.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index bc52d67fa..dbd8eb07a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3277,7 +3277,7 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ SalMediaDescription *remote_desc; bool_t keep_sdp_version; -#ifdef VIDEO_ENABLED +#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) bool_t old_has_video = call->params.has_video; #endif diff --git a/tester/call_tester.c b/tester/call_tester.c index 928ce6484..facec8769 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1245,7 +1245,6 @@ static void call_with_declined_srtp(void) { } static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy) { - int i=0; LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); if (enable_relay) { @@ -1288,6 +1287,7 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); #ifdef VIDEO_ENABLED if (enable_video) { + int i=0; if (linphone_core_video_supported(marie->lc)) { for (i=0;i<100;i++) { /*fixme to workaround a crash*/ ms_usleep(20000); @@ -1321,15 +1321,19 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e linphone_core_manager_destroy(pauline); } +#ifdef VIDEO_ENABLED static void srtp_video_ice_call(void) { call_base(LinphoneMediaEncryptionSRTP,TRUE,FALSE,LinphonePolicyUseIce); } -static void srtp_ice_call(void) { - call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce); -} static void zrtp_video_ice_call(void) { call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyUseIce); } +#endif + +static void srtp_ice_call(void) { + call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce); +} + static void zrtp_ice_call(void) { call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyUseIce); } From 5f9dc1c5d8221ddef8a2f4637053f26ddfeb64c0 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 22 Apr 2014 16:07:00 +0200 Subject: [PATCH 42/83] Fix compilation with Visual Studio. --- coreapi/remote_provisioning.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/coreapi/remote_provisioning.c b/coreapi/remote_provisioning.c index 7b5d6367d..3eb848b71 100644 --- a/coreapi/remote_provisioning.c +++ b/coreapi/remote_provisioning.c @@ -57,11 +57,14 @@ static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* FILE* f = fopen(file_path, "r"); if( f ){ + long fsize; + char* provisioning; + fseek(f, 0, SEEK_END); - long fsize = ftell(f); + fsize = ftell(f); fseek(f, 0, SEEK_SET); - char* provisioning = ms_malloc(fsize + 1); + provisioning = ms_malloc(fsize + 1); provisioning[fsize]='\0'; if (fread(provisioning, fsize, 1, f)==0){ ms_error("Could not read xml provisioning file from %s",file_path); From e47167217043efe3f59e5c52fd5c89c87cd5d318 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Tue, 22 Apr 2014 16:26:07 +0200 Subject: [PATCH 43/83] remove unimplemented function from header file --- coreapi/linphonecore.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index ea03d9874..eff26c794 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -177,7 +177,7 @@ enum _LinphoneReason{ LinphoneReasonNotAcceptable, /** Date: Tue, 22 Apr 2014 16:26:40 +0200 Subject: [PATCH 44/83] Quality reporting: add some extra delay (3s->10s) to avoid false positive fails --- tester/call_tester.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tester/call_tester.c b/tester/call_tester.c index 391893951..655281550 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -2013,7 +2013,7 @@ static void statistics_not_sent_if_call_not_started() { out_call = linphone_core_invite(marie->lc,"pauline"); linphone_call_ref(out_call); - CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallError,1)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallError,1, 10000)); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1); if (ms_list_size(linphone_core_get_call_logs(marie->lc))>0) { @@ -2041,8 +2041,8 @@ static void statistics_sent_at_call_termination() { create_call_for_statistics_tests(marie, pauline, &call_marie, &call_pauline); linphone_core_terminate_all_calls(marie->lc); - CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1)); - CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000)); + CU_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000)); CU_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc)); CU_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc)); From 28e99d08e189d2a34283dd044c4ddc9cabcf3f16 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 22 Apr 2014 16:34:43 +0200 Subject: [PATCH 45/83] Fix compilation with Visual Studio. --- coreapi/lpconfig.c | 3 ++- coreapi/quality_reporting.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index d6ccea612..0ac692cde 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -288,13 +288,14 @@ LpConfig * lp_config_new(const char *filename){ LpConfig * lp_config_new_from_buffer(const char *buffer){ LpConfig* conf = lp_new0(LpConfig,1); - conf->refcnt=1; LpSection* current_section = NULL; char* ptr = ms_strdup(buffer); char* strtok_storage = NULL; char* line = strtok_r(ptr, "\n", &strtok_storage); + conf->refcnt=1; + while( line != NULL ){ current_section = lp_config_parse_line(conf,line,current_section); line = strtok_r(NULL, "\n", &strtok_storage); diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index fb64a4b28..325ba7985 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -433,6 +433,8 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { if (block != NULL) { switch (rtcp_XR_get_block_type(block)) { case RTCP_XR_VOIP_METRICS: { + uint8_t config; + metrics->quality_estimates.rcq = rtcp_XR_voip_metrics_get_r_factor(block); metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f; metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block) / 10.f; @@ -443,7 +445,7 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { metrics->packet_loss.network_packet_loss_rate = rtcp_XR_voip_metrics_get_loss_rate(block); metrics->packet_loss.jitter_buffer_discard_rate = rtcp_XR_voip_metrics_get_discard_rate(block); - uint8_t config = rtcp_XR_voip_metrics_get_rx_config(block); + config = rtcp_XR_voip_metrics_get_rx_config(block); metrics->session_description.packet_loss_concealment = (config >> 6) & 0x3; metrics->jitter_buffer.adaptive = (config >> 4) & 0x3; break; From ee6d1e5087e5e64e2c4d131febb489ee9a7fae82 Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Tue, 22 Apr 2014 17:08:51 +0200 Subject: [PATCH 46/83] Add system sound preferences button in audio wizard --- gtk/audio_assistant.c | 61 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c index 431fa9995..c394b02fa 100644 --- a/gtk/audio_assistant.c +++ b/gtk/audio_assistant.c @@ -268,6 +268,49 @@ void linphone_gtk_start_play_record_sound(GtkWidget *w,gpointer data){ } } +void display_popup(GtkMessageType type,const gchar *message){ + GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(audio_assistant), + GTK_DIALOG_DESTROY_WITH_PARENT, + type, + GTK_BUTTONS_CLOSE, + "%s", + (const gchar*)message); + /* Destroy the dialog when the user responds to it (e.g. clicks a button) */ + g_signal_connect_swapped (G_OBJECT (dialog), "response", + G_CALLBACK (gtk_widget_destroy), + G_OBJECT (dialog)); + gtk_widget_show(dialog); +} + +static void open_mixer(){ + GError *error = NULL; + +#ifdef WIN32 + if(!g_spawn_command_line_async("control mmsys.cpl",&error)){ + display_popup(GTK_MESSAGE_WARNING,"Sound preferences not found "); + g_error_free(error); + } +#elif __APPLE__ + if(!g_spawn_command_line_async("open /System/Library/PreferencePanes/Sound.prefPane",&error)){ + display_popup(GTK_MESSAGE_WARNING,"Sound preferences not found "); + g_error_free(error); + } +#else + if(!g_spawn_command_line_async("gnome-volume-control",&error)){ + if(!g_spawn_command_line_async("gnome-control-center sound",&error)){ + if(!g_spawn_command_line_async("kmix",&error)){ + if(!g_spawn_command_line_async("mate-volume-control",&error)){ + if(!g_spawn_command_line_async("xterm alsamixer",&error)){ + display_popup(GTK_MESSAGE_WARNING,"Cannot launch system sound control "); + g_error_free(error); + } + } + } + } + } +#endif +} + static GtkWidget *create_intro(){ GtkWidget *vbox=gtk_vbox_new(FALSE,2); GtkWidget *label=gtk_label_new(_("Welcome !\nThis assistant will help you to configure audio settings for Linphone")); @@ -286,6 +329,11 @@ static GtkWidget *create_mic_page(){ GtkWidget *capture_device=gtk_combo_box_new(); GtkWidget *box = gtk_vbox_new(FALSE,0); GtkWidget *label_audiolevel=gtk_label_new(_("No voice")); + GtkWidget *mixer_button=gtk_button_new_with_label("System sound preferences"); + GtkWidget *image; + + image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU); + gtk_button_set_image(GTK_BUTTON(mixer_button),image); gtk_box_pack_start(GTK_BOX(box),mic_audiolevel,TRUE,TRUE,1); gtk_box_pack_start(GTK_BOX(box),label_audiolevel,FALSE,FALSE,1); @@ -294,6 +342,7 @@ static GtkWidget *create_mic_page(){ gtk_table_attach_defaults(GTK_TABLE(vbox), capture_device, 1, 2, 0, 1); gtk_table_attach_defaults(GTK_TABLE(vbox), labelMicLevel, 0, 1, 1, 2); gtk_table_attach_defaults(GTK_TABLE(vbox), box, 1, 2, 1, 2); + gtk_table_attach(GTK_TABLE(vbox), mixer_button, 0, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0,0); gtk_table_set_row_spacings(GTK_TABLE(vbox),10); @@ -306,23 +355,30 @@ static GtkWidget *create_mic_page(){ gtk_widget_show_all(vbox); g_signal_connect(G_OBJECT(capture_device),"changed",(GCallback)capture_device_changed,capture_device); + g_signal_connect(G_OBJECT(mixer_button),"clicked",(GCallback)open_mixer,vbox); return vbox; } static GtkWidget *create_speaker_page(){ - GtkWidget *vbox=gtk_table_new(2,2,FALSE); + GtkWidget *vbox=gtk_table_new(3,2,FALSE); LinphoneCore *lc=linphone_gtk_get_core(); GtkWidget *labelSpeakerChoice=gtk_label_new(_("Playback device")); GtkWidget *labelSpeakerLevel=gtk_label_new(_("Play three beeps")); GtkWidget *spk_button=gtk_button_new_from_stock(GTK_STOCK_MEDIA_PLAY); GtkWidget *playback_device=gtk_combo_box_new(); + GtkWidget *mixer_button=gtk_button_new_with_label("System sound preferences"); + GtkWidget *image; + + image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU); + gtk_button_set_image(GTK_BUTTON(mixer_button),image); gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerChoice, 0, 1, 0, 1); - gtk_table_attach_defaults(GTK_TABLE(vbox), playback_device, 1, 2, 0, 1); + gtk_table_attach(GTK_TABLE(vbox), playback_device, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0,0); gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerLevel, 0, 1, 1, 2); gtk_table_attach(GTK_TABLE(vbox), spk_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0); + gtk_table_attach(GTK_TABLE(vbox), mixer_button, 0, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0,0); gtk_table_set_row_spacings(GTK_TABLE(vbox),10); @@ -334,6 +390,7 @@ static GtkWidget *create_speaker_page(){ set_widget_to_assistant("speaker_page",vbox); g_signal_connect(G_OBJECT(playback_device),"changed",(GCallback)playback_device_changed,playback_device); g_signal_connect(G_OBJECT(spk_button),"clicked",(GCallback)linphone_gtk_start_sound,vbox); + g_signal_connect(G_OBJECT(mixer_button),"clicked",(GCallback)open_mixer,vbox); return vbox; } From 4386f18b2170445855147f417e6a7d4f04ce728d Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Tue, 22 Apr 2014 17:21:22 +0200 Subject: [PATCH 47/83] replace tabs with spaces and remove trailing spaces --- coreapi/bellesip_sal/sal_impl.c | 36 +++++----- coreapi/bellesip_sal/sal_op_call.c | 32 ++++----- coreapi/bellesip_sal/sal_op_impl.c | 48 ++++++------- coreapi/chat.c | 32 ++++----- coreapi/friend.c | 24 +++---- coreapi/linphone_tunnel_stubs.c | 4 +- coreapi/linphonecore.c | 32 ++++----- coreapi/misc.c | 50 ++++++------- coreapi/offeranswer.c | 34 ++++----- coreapi/offeranswer.h | 8 +-- coreapi/quality_reporting.c | 78 ++++++++++---------- coreapi/sal.c | 4 +- coreapi/upnp.c | 110 ++++++++++++++--------------- coreapi/xml2lpc.c | 62 ++++++++-------- 14 files changed, 277 insertions(+), 277 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index e4d72e834..5bc256bea 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -117,7 +117,7 @@ void sal_process_authentication(SalOp *op) { belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction); belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t); belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from); - + if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){ /*prefer using the from from the SalOp*/ from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)sal_op_get_from_address(op)); @@ -137,7 +137,7 @@ void sal_process_authentication(SalOp *op) { ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op); return; } - + if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) { if (is_within_dialog) { sal_op_send_request(op,new_request); @@ -308,7 +308,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even 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); int response_code = belle_sip_response_get_status_code(response); - + if (!client_transaction) { ms_warning("Discarding stateless response [%i]",response_code); return; @@ -334,11 +334,11 @@ 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 && op->callbacks->process_response_event) { /*handle authorization*/ switch (response_code) { - case 200: + case 200: break; case 401: case 407: @@ -677,10 +677,10 @@ static void set_tls_properties(Sal *ctx){ if (lp){ belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp); int verify_exceptions=0; - + if (!ctx->tls_verify) verify_exceptions=BELLE_SIP_TLS_LISTENING_POINT_BADCERT_ANY_REASON; else if (!ctx->tls_verify_cn) verify_exceptions=BELLE_SIP_TLS_LISTENING_POINT_BADCERT_CN_MISMATCH; - + belle_sip_tls_listening_point_set_root_ca(tlp,ctx->root_ca); /*root_ca might be NULL */ belle_sip_tls_listening_point_set_verify_exceptions(tlp,verify_exceptions); } @@ -802,7 +802,7 @@ void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode) { auth_inf void sal_certificates_chain_delete(SalCertificatesChain *chain) { belle_sip_object_unref((belle_sip_object_t *)chain); } -void sal_signing_key_delete(SalSigningKey *key) { +void sal_signing_key_delete(SalSigningKey *key) { belle_sip_object_unref((belle_sip_object_t *)key); } @@ -829,7 +829,7 @@ int sal_auth_compute_ha1(const char* userid,const char* realm,const char* passwo SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value){ belle_sip_message_t *msg=(belle_sip_message_t*)ch; belle_sip_header_t *h; - + if (msg==NULL){ msg=(belle_sip_message_t*)belle_sip_request_new(); belle_sip_object_ref(msg); @@ -846,7 +846,7 @@ SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name){ if (ch){ belle_sip_header_t *h=belle_sip_message_get_header((belle_sip_message_t*)ch,name); - + if (h){ return belle_sip_header_get_unparsed_value(h); } @@ -879,12 +879,12 @@ void sal_set_uuid(Sal *sal, const char *uuid){ } typedef struct { - unsigned int time_low; - unsigned short time_mid; - unsigned short time_hi_and_version; - unsigned char clock_seq_hi_and_reserved; - unsigned char clock_seq_low; - unsigned char node[6]; + unsigned int time_low; + unsigned short time_mid; + unsigned short time_hi_and_version; + unsigned char clock_seq_hi_and_reserved; + unsigned char clock_seq_low; + unsigned char node[6]; } sal_uuid_t; @@ -892,7 +892,7 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){ sal_uuid_t uuid_struct; int i; int written; - + if (len==0) return -1; /*create an UUID as described in RFC4122, 4.4 */ belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t)); @@ -900,7 +900,7 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){ uuid_struct.clock_seq_hi_and_reserved|=1<<7; uuid_struct.time_hi_and_version&=~(0xf<<12); uuid_struct.time_hi_and_version|=4<<12; - + written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.time_low, uuid_struct.time_mid, uuid_struct.time_hi_and_version, uuid_struct.clock_seq_hi_and_reserved, uuid_struct.clock_seq_low); diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index e6262c60a..610815802 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -111,9 +111,9 @@ static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription } static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ SalOp* op=(SalOp*)user_ctx; - + if (op->state==SalOpStateTerminated) return; - + if (!op->dialog) { /*call terminated very early*/ sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO error",NULL); @@ -129,7 +129,7 @@ static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminat if (op->dialog && op->dialog==belle_sip_dialog_terminated_event_get_dialog(event)) { /*belle_sip_transaction_t* trans=belle_sip_dialog_get_last_transaction(op->dialog);*/ ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op); - + switch(belle_sip_dialog_get_previous_state(op->dialog)) { case BELLE_SIP_DIALOG_CONFIRMED: if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) { @@ -192,7 +192,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); set_or_update_dialog(op,belle_sip_response_event_get_dialog(event)); dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; - + ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,op->dialog,belle_sip_dialog_state_to_string(dialog_state)); switch(dialog_state) { @@ -290,9 +290,9 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { SalOp* op=(SalOp*)user_ctx; - + if (op->state==SalOpStateTerminated) return; - + if (!op->dialog) { /*call terminated very early*/ sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL); @@ -342,7 +342,7 @@ static void unsupported_method(belle_sip_server_transaction_t* server_transactio * Extract the sdp from a sip message. * If there is no body in the message, the session_desc is set to null, 0 is returned. * If body was present is not a SDP or parsing of SDP failed, -1 is returned and SalReason is set appropriately. - * + * **/ static int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) { belle_sip_header_content_type_t* content_type=belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t); @@ -388,7 +388,7 @@ static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { belle_sip_object_unref(sdp); }else op->sdp_offering=TRUE; /*INVITE without SDP*/ }else err=-1; - + if (err==-1){ sal_call_decline(op,reason,NULL); } @@ -582,7 +582,7 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ if (op->base.local_media) sal_media_description_unref(op->base.local_media); op->base.local_media=desc; - + if (op->base.remote_media){ /*case of an incoming call where we modify the local capabilities between the time * the call is ringing and it is accepted (for example if you want to accept without video*/ @@ -597,7 +597,7 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ static belle_sip_header_allow_t *create_allow(){ belle_sip_header_allow_t* header_allow; - header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE"); + header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE"); return header_allow; } @@ -633,7 +633,7 @@ int sal_call(SalOp *op, const char *from, const char *to){ } if (op->referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->referred_by)); - + return sal_op_send_request(op,invite); } @@ -679,7 +679,7 @@ int sal_call_notify_ringing(SalOp *op, bool_t early_media){ belle_sip_response_t* ringing_response = sal_op_create_response_from_request(op,req,status_code); belle_sip_header_t *require; const char *tags=NULL; - + if (early_media){ handle_offer_answer_response(op,ringing_response); } @@ -692,7 +692,7 @@ int sal_call_notify_ringing(SalOp *op, bool_t early_media){ } #ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING - if (tags && strstr(tags,"100rel")!=0) + if (tags && strstr(tags,"100rel")!=0) #endif { belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op); @@ -740,7 +740,7 @@ int sal_call_accept(SalOp*h){ if ((contact_header=sal_op_create_contact(h))) { belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header)); } - + _sal_op_add_custom_headers(h, BELLE_SIP_MESSAGE(response)); handle_offer_answer_response(h,response); @@ -757,7 +757,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); - + if (reason==SalReasonRedirect){ if (redirection!=NULL) { if (strstr(redirection,"sip:")!=0) status=302; @@ -812,7 +812,7 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){ if (req){ int bodylen; char dtmf_body[128]={0}; - + snprintf(dtmf_body, sizeof(dtmf_body)-1, "Signal=%c\r\nDuration=250\r\n", dtmf); bodylen=strlen(dtmf_body); belle_sip_message_set_body((belle_sip_message_t*)req,dtmf_body,bodylen); diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index a6020791e..251420977 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -90,19 +90,19 @@ SalAuthInfo * sal_op_get_auth_requested(SalOp *op){ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){ belle_sip_header_contact_t* contact_header; belle_sip_uri_t* contact_uri; - + if (sal_op_get_contact_address(op)) { contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op))); } else { contact_header= belle_sip_header_contact_new(); } - + if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) { /*no uri, just creating a new one*/ contact_uri=belle_sip_uri_new(); belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri); } - + belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op)); if (op->privacy!=SalPrivacyNone){ belle_sip_uri_set_user(contact_uri,NULL); @@ -213,7 +213,7 @@ void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) { } static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *msg){ - + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){ belle_sip_header_contact_t* newct; /*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/ @@ -224,7 +224,7 @@ static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *m } /*if a header already exists in the message, replace it*/ belle_sip_message_set_header(msg,h); - + } void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){ @@ -246,20 +246,20 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req belle_sip_header_contact_t* contact; int result =-1; belle_sip_uri_t *next_hop_uri=NULL; - + if (add_contact) { contact = sal_op_create_contact(op); belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact)); } - + _sal_op_add_custom_headers(op, (belle_sip_message_t*)request); - + if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) { /*don't put route header if dialog is in confirmed state*/ const MSList *elem=sal_op_get_route_addresses(op); const char *transport; const char *method=belle_sip_request_get_method(request); - + if (elem) { outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data); next_hop_uri=outbound_proxy; @@ -284,7 +284,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req } } } - if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport && + if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport && (strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){ /*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/ belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t); @@ -307,12 +307,12 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL); } result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); - + /*update call id if not set yet for this OP*/ if (result == 0 && !op->base.call_id) { op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t)))); } - + return result; } @@ -323,9 +323,9 @@ int sal_op_send_request(SalOp* op, belle_sip_request_t* request) { return -1; /*sanity check*/ } /* - Header field where proxy ACK BYE CAN INV OPT REG - ___________________________________________________________ - Contact R o - - m o o + Header field where proxy ACK BYE CAN INV OPT REG + ___________________________________________________________ + Contact R o - - m o o */ if (strcmp(belle_sip_request_get_method(request),"INVITE")==0 ||strcmp(belle_sip_request_get_method(request),"REGISTER")==0 @@ -415,7 +415,7 @@ SalReason sal_reason_to_sip_code(SalReason r){ SalReason _sal_reason_from_sip_code(int code) { if (code>=100 && code<300) return SalReasonNone; - + switch(code) { case 0: return SalReasonIOError; @@ -490,7 +490,7 @@ void sal_error_info_reset(SalErrorInfo *ei){ if (ei->warnings){ ms_free(ei->warnings); ei->warnings=NULL; - + } if (ei->full_string){ ms_free(ei->full_string); @@ -522,7 +522,7 @@ void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *respon 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); @@ -618,7 +618,7 @@ void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){ } const char *sal_op_get_remote_contact(const SalOp *op){ - /* + /* * remote contact is filled in process_response * return sal_custom_header_find(op->base.recv_custom_headers,"Contact"); */ @@ -649,16 +649,16 @@ bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){ belle_sip_header_content_type_t *content_type; belle_sip_header_content_length_t *clen=NULL; belle_sip_header_t *content_encoding; - + content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t); if (content_type){ body=belle_sip_message_get_body(msg); clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t); } content_encoding=belle_sip_message_get_header(msg,"Content-encoding"); - + memset(salbody,0,sizeof(SalBody)); - + if (content_type && body && clen) { salbody->type=belle_sip_header_content_type_get_type(content_type); salbody->subtype=belle_sip_header_content_type_get_subtype(content_type); @@ -693,7 +693,7 @@ bool_t sal_op_is_ipv6(SalOp *op){ belle_sip_transaction_t *tr=NULL; belle_sip_header_address_t *contact; belle_sip_request_t *req; - + if (op->refresher) tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(op->refresher); @@ -701,7 +701,7 @@ bool_t sal_op_is_ipv6(SalOp *op){ tr=(belle_sip_transaction_t *)op->pending_client_trans; if (tr==NULL) tr=(belle_sip_transaction_t *)op->pending_server_trans; - + if (tr==NULL){ ms_error("Unable to determine IP version from signaling operation."); return FALSE; diff --git a/coreapi/chat.c b/coreapi/chat.c index fe0370afe..1c97389fe 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -21,7 +21,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + #include "linphonecore.h" #include "private.h" #include "lpconfig.h" @@ -116,7 +116,7 @@ bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *f LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) { LinphoneAddress *to_addr=linphone_core_interpret_url(lc,to); LinphoneChatRoom *ret; - + if (to_addr==NULL){ ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s",to); return NULL; @@ -176,7 +176,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM char* content_type; const char *identity=NULL; time_t t=time(NULL); - + if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",0)){ if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){ if (call->state==LinphoneCallConnected || @@ -266,7 +266,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag char *from; LinphoneChatMessage* msg; const SalCustomHeader *ch; - + addr=linphone_address_new(sal_msg->from); linphone_address_clean(addr); cr=linphone_core_get_chat_room(lc,addr); @@ -278,20 +278,20 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag } msg = linphone_chat_room_create_message(cr, sal_msg->text); linphone_chat_message_set_from(msg, cr->peer_url); - + { LinphoneAddress *to; to=sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc)); msg->to=to; } - + msg->time=sal_msg->time; msg->state=LinphoneChatMessageStateDelivered; msg->is_read=FALSE; msg->dir=LinphoneChatMessageIncoming; ch=sal_op_get_recv_custom_header(op); if (ch) msg->custom_headers=sal_custom_header_clone(ch); - + if (sal_msg->url) { linphone_chat_message_set_external_body_url(msg, sal_msg->url); } @@ -437,8 +437,8 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con * @return a new #LinphoneChatMessage */ LinphoneChatMessage* linphone_chat_room_create_message_2( - LinphoneChatRoom *cr, const char* message, const char* external_body_url, - LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming) { + LinphoneChatRoom *cr, const char* message, const char* external_body_url, + LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming) { LinphoneCore *lc=linphone_chat_room_get_lc(cr); LinphoneChatMessage* msg = belle_sip_object_new(LinphoneChatMessage); @@ -605,13 +605,13 @@ void linphone_chat_room_compose(LinphoneChatRoom *cr) { */ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state) { switch (state) { - case LinphoneChatMessageStateIdle:return "LinphoneChatMessageStateIdle"; + case LinphoneChatMessageStateIdle:return "LinphoneChatMessageStateIdle"; case LinphoneChatMessageStateInProgress:return "LinphoneChatMessageStateInProgress"; case LinphoneChatMessageStateDelivered:return "LinphoneChatMessageStateDelivered"; case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered"; default: return "Unknown state"; } - + } /** @@ -653,8 +653,8 @@ const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessag /** * Linphone message can carry external body as defined by rfc2017 - * - * @param message a LinphoneChatMessage + * + * @param message a LinphoneChatMessage * @param url ex: access-type=URL; URL="http://www.foo.com/file" */ void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url) { @@ -675,7 +675,7 @@ void linphone_chat_message_set_from(LinphoneChatMessage* message, const Linphone } /** - * Get origin of the message + * Get origin of the message *@param message #LinphoneChatMessage obj *@return #LinphoneAddress */ @@ -694,7 +694,7 @@ void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAd } /** - * Get destination of the message + * Get destination of the message *@param message #LinphoneChatMessage obj *@return #LinphoneAddress */ @@ -780,7 +780,7 @@ bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage* message) { * @return the id */ unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage* message) { - return message->storage_id; + return message->storage_id; } /** diff --git a/coreapi/friend.c b/coreapi/friend.c index a51ee7891..a287b7e90 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -62,8 +62,8 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){ case LinphoneStatusPending: str=_("Pending"); break; - case LinphoneStatusVacation: - str=_("Vacation"); + case LinphoneStatusVacation: + str=_("Vacation"); default: str=_("Unknown-bug"); } @@ -109,7 +109,7 @@ LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ LinphoneCore *lc=fr->lc; - + if (fr->outsub==NULL){ /* people for which we don't have yet an answer should appear as offline */ fr->presence=NULL; @@ -132,7 +132,7 @@ LinphoneFriend * linphone_friend_new(){ obj->pol=LinphoneSPAccept; obj->presence=NULL; obj->subscribe=TRUE; - return obj; + return obj; } LinphoneFriend *linphone_friend_new_with_address(const char *addr){ @@ -255,7 +255,7 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf){ linphone_friend_unsubscribe(lf); if (lf->insub){ sal_notify_presence_close(lf->insub); - + } } @@ -388,7 +388,7 @@ BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){ **/ void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *proxy, bool_t only_when_registered){ int can_subscribe=1; - + if (only_when_registered && (fr->subscribe || fr->subscribe_active)){ LinphoneProxyConfig *cfg=linphone_core_lookup_known_proxy(fr->lc,fr->uri); if (proxy && proxy!=cfg) return; @@ -592,13 +592,13 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde int a; LinphoneFriend *lf; LpConfig *config=lc->config; - + sprintf(item,"friend_%i",index); - + if (!lp_config_has_section(config,item)){ return NULL; } - + tmp=lp_config_get_string(config,item,"url",NULL); if (tmp==NULL) { return NULL; @@ -614,7 +614,7 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde } a=lp_config_get_int(config,item,"subscribe",0); linphone_friend_send_subscribe(lf,a); - + linphone_friend_set_ref_key(lf,lp_config_get_string(config,item,"refkey",NULL)); return lf; } @@ -639,9 +639,9 @@ void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf, char key[50]; char *tmp; const char *refkey; - + sprintf(key,"friend_%i",index); - + if (lf==NULL){ lp_config_clean_section(config,key); return; diff --git a/coreapi/linphone_tunnel_stubs.c b/coreapi/linphone_tunnel_stubs.c index 0865704a0..c208dd249 100644 --- a/coreapi/linphone_tunnel_stubs.c +++ b/coreapi/linphone_tunnel_stubs.c @@ -46,7 +46,7 @@ void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig } const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ - return NULL; + return NULL; } void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){ @@ -56,7 +56,7 @@ void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){ } bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){ - return FALSE; + return FALSE; } bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 0697e349f..dc69310a3 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -680,7 +680,7 @@ static void sip_config_read(LinphoneCore *lc) /*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/ sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc)); /*start listening on ports*/ - linphone_core_set_sip_transports(lc,&tr); + linphone_core_set_sip_transports(lc,&tr); tmpstr=lp_config_get_string(lc->config,"sip","contact",NULL); if (tmpstr==NULL || linphone_core_set_primary_contact(lc,tmpstr)==-1) { @@ -844,7 +844,7 @@ static bool_t get_codec(LinphoneCore *lc, const char* type, int index, PayloadTy if (pt && enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED; //ms_message("Found codec %s/%i",pt->mime_type,pt->clock_rate); if (pt==NULL) ms_warning("Ignoring codec config %s/%i with fmtp=%s because unsupported", - mime,rate,fmtp ? fmtp : ""); + mime,rate,fmtp ? fmtp : ""); *ret=pt; return TRUE; } @@ -902,7 +902,7 @@ static MSList *add_missing_codecs(LinphoneCore *lc, SalStreamType mtype, MSList if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO) pt=NULL; else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED - && pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){ + && pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){ pt=NULL; } if (pt && ms_filter_codec_supported(pt->mime_type)){ @@ -912,7 +912,7 @@ static MSList *add_missing_codecs(LinphoneCore *lc, SalStreamType mtype, MSList payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED); } ms_message("Adding new codec %s/%i with fmtp %s", - pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : ""); + pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : ""); l=ms_list_insert_sorted(l,pt,(int (*)(const void *, const void *))codec_compare); } } @@ -1391,8 +1391,8 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab sal_set_user_pointer(lc->sal,lc); sal_set_callbacks(lc->sal,&linphone_sal_callbacks); - lc->network_last_check = 0; - lc->network_last_status = FALSE; + lc->network_last_check = 0; + lc->network_last_status = FALSE; lc->http_provider = belle_sip_stack_create_http_provider(sal_get_belle_sip_stack(lc->sal), "0.0.0.0"); lc->http_verify_policy = belle_tls_verify_policy_new(); @@ -1501,7 +1501,7 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact) void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){ const char *ip; if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress - && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){ + && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){ strncpy(result,ip,LINPHONE_IPADDR_SIZE); return; } @@ -2273,7 +2273,7 @@ void linphone_core_iterate(LinphoneCore *lc){ } if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0 - && (curtime-lc->dmfs_playing_start_time)>5){ + && (curtime-lc->dmfs_playing_start_time)>5){ MSPlayerState state; bool_t stop=TRUE; if (lc->ringstream->source && ms_filter_call_method(lc->ringstream->source,MS_PLAYER_GET_STATE,&state)==0){ @@ -2426,7 +2426,7 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url) } linphone_address_set_display_name(uri,NULL); linphone_proxy_config_normalize_number(proxy,url,normalized_username, - sizeof(normalized_username)); + sizeof(normalized_username)); linphone_address_set_username(uri,normalized_username); return uri; }else return NULL; @@ -3005,10 +3005,10 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ tmp=linphone_address_as_string(from_parsed); linphone_address_destroy(from_parsed); barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"), - (sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_(".")); + (sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_(".")); if (lc->vtable.show) lc->vtable.show(lc); if (lc->vtable.display_status) - lc->vtable.display_status(lc,barmesg); + lc->vtable.display_status(lc,barmesg); /* play the ring if this is the only call*/ if (ms_list_size(lc->calls)==1){ @@ -3275,7 +3275,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call) int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ if (call->state!=LinphoneCallUpdatedByRemote){ ms_error("linphone_core_accept_update(): invalid state %s to call this function.", - linphone_call_state_to_string(call->state)); + linphone_call_state_to_string(call->state)); return -1; } return _linphone_core_accept_call_update(lc, call, params); @@ -3391,7 +3391,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *rc=(LinphoneCall*)sal_op_get_user_pointer (replaced); if (rc){ ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.", - call,rc); + call,rc); linphone_core_terminate_call(lc,rc); } } @@ -3772,7 +3772,7 @@ LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const c } int linphone_core_send_publish(LinphoneCore *lc, - LinphonePresenceModel *presence) + LinphonePresenceModel *presence) { const MSList *elem; for (elem=linphone_core_get_proxy_config_list(lc);elem!=NULL;elem=ms_list_next(elem)){ @@ -4129,7 +4129,7 @@ static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap){ if (sndcard==NULL){/*looks like a bug! take the first one !*/ const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get()); if (elem) sndcard=(MSSndCard*)elem->data; - } + } } if (sndcard==NULL) ms_error("Could not find a suitable soundcard !"); return sndcard; @@ -5040,7 +5040,7 @@ float linphone_core_get_static_picture_fps(LinphoneCore *lc) { if (vs && vs->source) { if (ms_filter_get_id(vs->source) == MS_STATIC_IMAGE_ID) { - float fps; + float fps; ms_filter_call_method(vs->source, MS_FILTER_GET_FPS,(void *)&fps); return fps; diff --git a/coreapi/misc.c b/coreapi/misc.c index 37198490e..b1e9f2235 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -88,7 +88,7 @@ int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t } int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt){ - return payload_type_get_number(pt); + return payload_type_get_number(pt); } const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){ @@ -129,7 +129,7 @@ static double get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *p /*special case of aac 44K because ptime= 10ms*/ npacket=100; } - + bitrate=get_codec_bitrate(lc,pt); packet_size= (((double)bitrate)/(npacket*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ; return packet_size*8.0*npacket; @@ -162,7 +162,7 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl { double codec_band; bool_t ret=FALSE; - + switch (pt->type){ case PAYLOAD_AUDIO_CONTINUOUS: case PAYLOAD_AUDIO_PACKETIZED: @@ -278,7 +278,7 @@ static int sendStunRequest(int sock, const struct sockaddr *server, socklen_t ad char buf[STUN_MAX_MESSAGE_SIZE]; int len = STUN_MAX_MESSAGE_SIZE; StunAtrString username; - StunAtrString password; + StunAtrString password; StunMessage req; int err; memset(&req, 0, sizeof(StunMessage)); @@ -301,9 +301,9 @@ static int sendStunRequest(int sock, const struct sockaddr *server, socklen_t ad int linphone_parse_host_port(const char *input, char *host, size_t hostlen, int *port){ char tmphost[NI_MAXHOST]={0}; char *p1, *p2; - + if ((sscanf(input, "[%64[^]]]:%d", tmphost, port) == 2) || (sscanf(input, "[%64[^]]]", tmphost) == 1)) { - + } else { p1 = strchr(input, ':'); p2 = strrchr(input, ':'); @@ -324,9 +324,9 @@ int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, sock char host[NI_MAXHOST]; int port_int=default_port; int ret; - + linphone_parse_host_port(server,host,sizeof(host),&port_int); - + snprintf(port, sizeof(port), "%d", port_int); memset(&hints,0,sizeof(hints)); hints.ai_family=AF_UNSPEC; @@ -346,7 +346,7 @@ int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, sock static int recvStunResponse(ortp_socket_t sock, char *ipaddr, int *port, int *id){ char buf[STUN_MAX_MESSAGE_SIZE]; - int len = STUN_MAX_MESSAGE_SIZE; + int len = STUN_MAX_MESSAGE_SIZE; StunMessage resp; len=recv(sock,buf,len,0); if (len>0){ @@ -370,7 +370,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ const char *server=linphone_core_get_stun_server(lc); StunCandidate *ac=&call->ac; StunCandidate *vc=&call->vc; - + if (lc->sip_conf.ipv6_enabled){ ms_warning("stun support is not implemented for ipv6"); return -1; @@ -389,7 +389,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ struct timeval init,cur; double elapsed; int ret=0; - + if (ai==NULL){ ms_error("Could not obtain stun server addrinfo."); return -1; @@ -408,7 +408,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ got_video=FALSE; ortp_gettimeofday(&init,NULL); do{ - + int id; if (loops%20==0){ ms_message("Sending stun requests..."); @@ -487,7 +487,7 @@ void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, Linphone if (ping_time_ms>0 && lp_config_get_int(lc->config,"net","activate_edge_workarounds",0)==1){ ms_message("Stun server ping time is %i ms",ping_time_ms); threshold=lp_config_get_int(lc->config,"net","edge_ping_time",500); - + if (ping_time_ms>threshold){ /* we might be in a 2G network*/ params->low_bandwidth=TRUE; @@ -536,7 +536,7 @@ void linphone_core_resolve_stun_server(LinphoneCore *lc){ * - have a cache of the stun server addrinfo * - this cached value is returned when it is non-null * - an asynchronous resolution is asked each time this function is called to ensure frequent refreshes of the cached value. - * - if no cached value exists, block for a short time; this case must be unprobable because the resolution will be asked each time the stun server value is + * - if no cached value exists, block for a short time; this case must be unprobable because the resolution will be asked each time the stun server value is * changed. **/ const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc){ @@ -957,7 +957,7 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){ p=n; } }else ret=AUDIO_STREAM_FEATURE_ALL; - + if (ret==AUDIO_STREAM_FEATURE_ALL){ /*since call recording is specified before creation of the stream in linphonecore, * it will be requested on demand. It is not necessary to include it all the time*/ @@ -987,7 +987,7 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size) #else #define UP_FLAG IFF_RUNNING /* resources allocated */ #endif - + for (ifp = ifpstart; ifp != NULL; ifp = ifp->ifa_next) { if (ifp->ifa_addr && ifp->ifa_addr->sa_family == type && (ifp->ifa_flags & UP_FLAG) && !(ifp->ifa_flags & IFF_LOOPBACK)) @@ -1042,8 +1042,8 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul if (err<0) { /*the network isn't reachable*/ if (getSocketErrorCode()!=ENETUNREACH) ms_error("Error in connect: %s",strerror(errno)); - freeaddrinfo(res); - close_socket(sock); + freeaddrinfo(res); + close_socket(sock); return -1; } freeaddrinfo(res); @@ -1078,19 +1078,19 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ int err; - strcpy(result,type==AF_INET ? "127.0.0.1" : "::1"); - + strcpy(result,type==AF_INET ? "127.0.0.1" : "::1"); + if (dest==NULL){ if (type==AF_INET) dest="87.98.157.38"; /*a public IP address*/ else dest="2a00:1450:8002::68"; } - err=get_local_ip_for_with_connect(type,dest,result); + err=get_local_ip_for_with_connect(type,dest,result); if (err==0) return 0; - - /* if the connect method failed, which happens when no default route is set, + + /* if the connect method failed, which happens when no default route is set, * try to find 'the' running interface with getifaddrs*/ - + #ifdef HAVE_GETIFADDRS /*we use getifaddrs for lookup of default interface */ int found_ifs; @@ -1103,7 +1103,7 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ return -1; } #endif - return 0; + return 0; } SalReason linphone_reason_to_sal(LinphoneReason reason){ diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index caece9835..df4e7507d 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -42,7 +42,7 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload /* the compare between G729 and G729A is for some stupid uncompliant phone*/ if ( pt->mime_type && refpt->mime_type && (strcasecmp(pt->mime_type,refpt->mime_type)==0 || - (strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 )) + (strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 )) && pt->clock_rate==refpt->clock_rate){ candidate=pt; /*good candidate, check fmtp for H264 */ @@ -56,7 +56,7 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload mode2=atoi(value); } if (mode1==mode2) - break; /*exact match */ + break; /*exact match */ } }else break; } @@ -69,7 +69,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t MSList *res=NULL; PayloadType *matched; bool_t found_codec=FALSE; - + for(e2=remote;e2!=NULL;e2=e2->next){ PayloadType *p2=(PayloadType*)e2->data; matched=find_payload_type_best_match(local,p2); @@ -85,7 +85,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t }else found_codec=TRUE; } } - + newp=payload_type_clone(matched); if (p2->send_fmtp) payload_type_set_send_fmtp(newp,p2->send_fmtp); @@ -95,7 +95,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t payload_type_set_number(newp,remote_number); if (reading_response && remote_number!=local_number){ ms_warning("For payload type %s, proposed number was %i but the remote phone answered %i", - newp->mime_type, local_number, remote_number); + newp->mime_type, local_number, remote_number); /* We must add this payload type with our local numbering in order to be able to receive it. Indeed despite we must sent with the remote numbering, we must be able to receive with @@ -132,28 +132,28 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t return res; } -static bool_t match_crypto_algo(const SalSrtpCryptoAlgo* local, const SalSrtpCryptoAlgo* remote, +static bool_t match_crypto_algo(const SalSrtpCryptoAlgo* local, const SalSrtpCryptoAlgo* remote, SalSrtpCryptoAlgo* result, unsigned int* choosen_local_tag, bool_t use_local_key) { int i,j; for(i=0; ialgo = remote[i].algo; - /* We're answering an SDP offer. Supply our master key, associated with the remote supplied tag */ + /* We're answering an SDP offer. Supply our master key, associated with the remote supplied tag */ if (use_local_key) { strncpy(result->master_key, local[j].master_key, 41); result->tag = remote[i].tag; - *choosen_local_tag = local[j].tag; + *choosen_local_tag = local[j].tag; } /* We received an answer to our SDP crypto proposal. Copy matching algo remote master key to result, and memorize local tag */ - else { + else { strncpy(result->master_key, remote[i].master_key, 41); result->tag = local[j].tag; - *choosen_local_tag = local[j].tag; + *choosen_local_tag = local[j].tag; } result->master_key[40] = '\0'; return TRUE; @@ -205,8 +205,8 @@ static SalStreamDir compute_dir_incoming(SalStreamDir local, SalStreamDir offere } static void initiate_outgoing(const SalStreamDescription *local_offer, - const SalStreamDescription *remote_answer, - SalStreamDescription *result){ + const SalStreamDescription *remote_answer, + SalStreamDescription *result){ if (remote_answer->rtp_port!=0) result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE); result->proto=remote_answer->proto; @@ -233,8 +233,8 @@ static void initiate_outgoing(const SalStreamDescription *local_offer, static void initiate_incoming(const SalStreamDescription *local_cap, - const SalStreamDescription *remote_offer, - SalStreamDescription *result, bool_t one_matching_codec){ + const SalStreamDescription *remote_offer, + SalStreamDescription *result, bool_t one_matching_codec){ result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec); result->proto=remote_offer->proto; result->type=local_cap->type; @@ -254,7 +254,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap, memset(result->crypto, 0, sizeof(result->crypto)); if (!match_crypto_algo(local_cap->crypto, remote_offer->crypto, &result->crypto[0], &result->crypto_local_tag, TRUE)) result->rtp_port = 0; - + } strcpy(result->ice_pwd, local_cap->ice_pwd); strcpy(result->ice_ufrag, local_cap->ice_ufrag); @@ -388,7 +388,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities strcpy(result->ice_ufrag, local_capabilities->ice_ufrag); result->ice_lite = local_capabilities->ice_lite; result->ice_completed = local_capabilities->ice_completed; - + strcpy(result->name,local_capabilities->name); // Handle session RTCP XR attribute diff --git a/coreapi/offeranswer.h b/coreapi/offeranswer.h index 5aa658ae6..0c8ebd7b1 100644 --- a/coreapi/offeranswer.h +++ b/coreapi/offeranswer.h @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef offeranswer_h #define offeranswer_h -/** +/** This header files defines the SDP offer answer API. It can be used by implementations of SAL directly. **/ @@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. **/ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, const SalMediaDescription *remote_answer, - SalMediaDescription *result); + SalMediaDescription *result); /** * Returns a media description to run the streams with, based on the local capabilities and @@ -41,7 +41,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, **/ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities, const SalMediaDescription *remote_offer, - SalMediaDescription *result, bool_t one_matching_codec); - + SalMediaDescription *result, bool_t one_matching_codec); + #endif diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 325ba7985..c5107b4e1 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -31,12 +31,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*************************************************************************** * TODO / REMINDER LIST ****************************************************************************/ - // to discuss + // to discuss // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). // moslq == moscq // video: what happens if doing stop/resume? - // one time value: average? worst value? - // rlq value: need algo to compute it + // one time value: average? worst value? + // rlq value: need algo to compute it /*************************************************************************** * END OF TODO / REMINDER LIST ****************************************************************************/ @@ -63,10 +63,10 @@ static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offs size_t prevoffset = *offset; #ifndef WIN32 - va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/ - va_copy(cap,args); + va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/ + va_copy(cap,args); ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, cap); - va_end(cap); + va_end(cap); #else ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, args); #endif @@ -225,7 +225,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off static void reporting_publish(const LinphoneCall* call, const reporting_session_report_t * report) { LinphoneContent content = {0}; - LinphoneAddress *addr; + LinphoneAddress *addr; int expires = -1; size_t offset = 0; size_t size = 2048; @@ -414,46 +414,46 @@ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) { reporting_content_metrics_t * metrics = NULL; LinphoneCallStats stats = call->stats[stats_type]; - mblk_t *block = NULL; + mblk_t *block = NULL; - if (! reporting_enabled(call)) + if (! reporting_enabled(call)) return; - if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { + if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { metrics = &report->remote_metrics; - if (rtcp_is_XR(stats.received_rtcp) == TRUE) { - block = stats.received_rtcp; - } - } else if (stats.updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { + if (rtcp_is_XR(stats.received_rtcp) == TRUE) { + block = stats.received_rtcp; + } + } else if (stats.updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { metrics = &report->local_metrics; - if (rtcp_is_XR(stats.sent_rtcp) == TRUE) { - block = stats.sent_rtcp; - } - } - if (block != NULL) { - switch (rtcp_XR_get_block_type(block)) { - case RTCP_XR_VOIP_METRICS: { - uint8_t config; + if (rtcp_is_XR(stats.sent_rtcp) == TRUE) { + block = stats.sent_rtcp; + } + } + if (block != NULL) { + switch (rtcp_XR_get_block_type(block)) { + case RTCP_XR_VOIP_METRICS: { + uint8_t config; - metrics->quality_estimates.rcq = rtcp_XR_voip_metrics_get_r_factor(block); - metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f; - metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block) / 10.f; + metrics->quality_estimates.rcq = rtcp_XR_voip_metrics_get_r_factor(block); + metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f; + metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block) / 10.f; - metrics->jitter_buffer.nominal = rtcp_XR_voip_metrics_get_jb_nominal(block); - metrics->jitter_buffer.max = rtcp_XR_voip_metrics_get_jb_maximum(block); - metrics->jitter_buffer.abs_max = rtcp_XR_voip_metrics_get_jb_abs_max(block); - metrics->packet_loss.network_packet_loss_rate = rtcp_XR_voip_metrics_get_loss_rate(block); - metrics->packet_loss.jitter_buffer_discard_rate = rtcp_XR_voip_metrics_get_discard_rate(block); + metrics->jitter_buffer.nominal = rtcp_XR_voip_metrics_get_jb_nominal(block); + metrics->jitter_buffer.max = rtcp_XR_voip_metrics_get_jb_maximum(block); + metrics->jitter_buffer.abs_max = rtcp_XR_voip_metrics_get_jb_abs_max(block); + metrics->packet_loss.network_packet_loss_rate = rtcp_XR_voip_metrics_get_loss_rate(block); + metrics->packet_loss.jitter_buffer_discard_rate = rtcp_XR_voip_metrics_get_discard_rate(block); - config = rtcp_XR_voip_metrics_get_rx_config(block); - metrics->session_description.packet_loss_concealment = (config >> 6) & 0x3; - metrics->jitter_buffer.adaptive = (config >> 4) & 0x3; - break; - } default: { - break; - } - } - } + config = rtcp_XR_voip_metrics_get_rx_config(block); + metrics->session_description.packet_loss_concealment = (config >> 6) & 0x3; + metrics->jitter_buffer.adaptive = (config >> 4) & 0x3; + break; + } default: { + break; + } + } + } } void linphone_reporting_publish(LinphoneCall* call) { diff --git a/coreapi/sal.c b/coreapi/sal.c index 5404210f3..cb94d675c 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -82,7 +82,7 @@ void sal_media_description_unref(SalMediaDescription *md){ } SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, - SalMediaProto proto, SalStreamType type){ + SalMediaProto proto, SalStreamType type){ int i; for(i=0;in_active_streams;++i){ SalStreamDescription *ss=&md->streams[i]; @@ -161,7 +161,7 @@ static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){ */ /* if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) || - !fmtp_equals(p1->send_fmtp,p2->send_fmtp)) + !fmtp_equals(p1->send_fmtp,p2->send_fmtp)) return FALSE; */ return TRUE; diff --git a/coreapi/upnp.c b/coreapi/upnp.c index 741e44529..7feaaa30c 100644 --- a/coreapi/upnp.c +++ b/coreapi/upnp.c @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define UPNP_ADD_MAX_RETRY 4 #define UPNP_REMOVE_MAX_RETRY 4 #define UPNP_SECTION_NAME "uPnP" -#define UPNP_CORE_READY_CHECK 1 +#define UPNP_CORE_READY_CHECK 1 #define UPNP_CORE_RETRY_DELAY 10 #define UPNP_CALL_RETRY_DELAY 3 #define UPNP_UUID_LEN 128 @@ -79,7 +79,7 @@ struct _UpnpContext { ms_mutex_t mutex; ms_cond_t empty_cond; - + time_t last_ready_check; LinphoneUpnpState last_ready_state; }; @@ -91,13 +91,13 @@ bool_t linphone_upnp_is_blacklisted(UpnpContext *ctx); UpnpPortBinding *linphone_upnp_port_binding_new(); UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_protocol protocol, int local_port, int external_port); -UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port); +UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port); UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port); void linphone_upnp_port_binding_set_device_id(UpnpPortBinding *port, const char * device_id); bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2); UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(MSList *list, const UpnpPortBinding *port); UpnpPortBinding *linphone_upnp_port_binding_retain(UpnpPortBinding *port); -void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay); +void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay); void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port); void linphone_upnp_port_binding_release(UpnpPortBinding *port); void linphone_upnp_update_config(UpnpContext *lupnp); @@ -108,7 +108,7 @@ MSList *linphone_upnp_config_list_port_bindings(struct _LpConfig *lpc, const cha void linphone_upnp_config_add_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port); void linphone_upnp_config_remove_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port); -// uPnP +// uPnP int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry); int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry); @@ -141,7 +141,7 @@ char * linphone_upnp_format_device_id(const char *device_id) { char *ret = NULL; char *tmp; char tchar; - bool_t copy; + bool_t copy; if(device_id == NULL) { return ret; } @@ -366,7 +366,7 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) { linphone_core_remove_iterate_hook(lupnp->lc, linphone_core_upnp_hook, lupnp); ms_mutex_lock(&lupnp->mutex); - + if(lupnp->lc->network_reachable) { /* Send port binding removes */ if(lupnp->sip_udp != NULL) { @@ -391,7 +391,7 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) { upnp_igd_destroy(lupnp->upnp_igd_ctxt); lupnp->upnp_igd_ctxt = NULL; } - + /* No more multi threading here */ /* Run one more time configuration update and proxy */ @@ -419,7 +419,7 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) { lupnp->removing_configs = ms_list_free(lupnp->removing_configs); ms_list_for_each(lupnp->pending_bindings,(void (*)(void*))linphone_upnp_port_binding_release); lupnp->pending_bindings = ms_list_free(lupnp->pending_bindings); - + ms_mutex_destroy(&lupnp->mutex); ms_cond_destroy(&lupnp->empty_cond); @@ -439,17 +439,17 @@ LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *lupnp) { bool_t _linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { bool_t ready = TRUE; - + // 1 Check global uPnP state ready = (lupnp->state == LinphoneUpnpStateOk); - + // 2 Check external ip address if(ready) { if (upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt) == NULL) { ready = FALSE; } } - + // 3 Check sip ports bindings if(ready) { if(lupnp->sip_udp != NULL) { @@ -468,7 +468,7 @@ bool_t _linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { ready = FALSE; } } - + return ready; } @@ -486,7 +486,7 @@ int linphone_upnp_context_get_external_port(UpnpContext *lupnp) { int port = -1; if(lupnp != NULL) { ms_mutex_lock(&lupnp->mutex); - + if(lupnp->sip_udp != NULL) { if(lupnp->sip_udp->state == LinphoneUpnpStateOk) { port = lupnp->sip_udp->external_port; @@ -500,7 +500,7 @@ int linphone_upnp_context_get_external_port(UpnpContext *lupnp) { port = lupnp->sip_tls->external_port; } } - + ms_mutex_unlock(&lupnp->mutex); } return port; @@ -508,7 +508,7 @@ int linphone_upnp_context_get_external_port(UpnpContext *lupnp) { bool_t linphone_upnp_is_blacklisted(UpnpContext *lupnp) { const char * device_model_name = upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt); - const char * device_model_number = upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt); + const char * device_model_number = upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt); const char * blacklist = lp_config_get_string(lupnp->lc->config, "net", "upnp_blacklist", NULL); bool_t blacklisted = FALSE; char *str; @@ -521,7 +521,7 @@ bool_t linphone_upnp_is_blacklisted(UpnpContext *lupnp) { return FALSE; } - // Find in the list + // Find in the list str = strdup(blacklist); pch = strtok(str, ";"); while (pch != NULL && !blacklisted) { @@ -537,7 +537,7 @@ bool_t linphone_upnp_is_blacklisted(UpnpContext *lupnp) { if(model_number == NULL || strcmp(model_number, device_model_number) == 0) { blacklisted = TRUE; } - } + } pch = strtok(NULL, ";"); } free(str); @@ -563,7 +563,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind upnp_igd_port_mapping mapping; char description[128]; int ret; - + if(lupnp->state != LinphoneUpnpStateOk) { return -2; } @@ -587,7 +587,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind return 0; } } - + // No retry if specified if(port->retry != 0 && !retry) { return -1; @@ -626,7 +626,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry) { upnp_igd_port_mapping mapping; int ret; - + if(lupnp->state != LinphoneUpnpStateOk) { return -2; } @@ -649,7 +649,7 @@ int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortB return 0; } } - + // No retry if specified if(port->retry != 0 && !retry) { return 1; @@ -697,19 +697,19 @@ int linphone_core_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool /* * Audio part */ - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtp, + linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtp, UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[0].rtp_port:0, UPNP_CALL_RETRY_DELAY); - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtcp, + linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtcp, UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[0].rtcp_port:0, UPNP_CALL_RETRY_DELAY); - + /* * Video part */ - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtp, + linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtp, UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[1].rtp_port:0, UPNP_CALL_RETRY_DELAY); - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtcp, + linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtcp, UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[1].rtcp_port:0, UPNP_CALL_RETRY_DELAY); } @@ -756,16 +756,16 @@ void linphone_upnp_update_stream_state(UpnpStream *stream) { if((stream->rtp == NULL || stream->rtp->state == LinphoneUpnpStateOk || stream->rtp->state == LinphoneUpnpStateIdle) && (stream->rtcp == NULL || stream->rtcp->state == LinphoneUpnpStateOk || stream->rtcp->state == LinphoneUpnpStateIdle)) { stream->state = LinphoneUpnpStateOk; - } else if((stream->rtp != NULL && - (stream->rtp->state == LinphoneUpnpStateAdding || stream->rtp->state == LinphoneUpnpStateRemoving)) || - (stream->rtcp != NULL && - (stream->rtcp->state == LinphoneUpnpStateAdding || stream->rtcp->state == LinphoneUpnpStateRemoving))) { + } else if((stream->rtp != NULL && + (stream->rtp->state == LinphoneUpnpStateAdding || stream->rtp->state == LinphoneUpnpStateRemoving)) || + (stream->rtcp != NULL && + (stream->rtcp->state == LinphoneUpnpStateAdding || stream->rtcp->state == LinphoneUpnpStateRemoving))) { stream->state = LinphoneUpnpStatePending; } else if((stream->rtp != NULL && stream->rtp->state == LinphoneUpnpStateKo) || (stream->rtcp != NULL && stream->rtcp->state == LinphoneUpnpStateKo)) { stream->state = LinphoneUpnpStateKo; } else { - ms_error("Invalid stream %p state", stream); + ms_error("Invalid stream %p state", stream); } } @@ -799,7 +799,7 @@ int linphone_upnp_call_process(LinphoneCall *call) { * Update stat */ linphone_core_update_upnp_state_in_call_stats(call); - + /* * Update session state */ @@ -820,7 +820,7 @@ int linphone_upnp_call_process(LinphoneCall *call) { } ms_mutex_unlock(&lupnp->mutex); - + /* When change is done proceed update */ if(oldState != LinphoneUpnpStateOk && oldState != LinphoneUpnpStateKo && (newState == LinphoneUpnpStateOk || newState == LinphoneUpnpStateKo)) { @@ -865,9 +865,9 @@ void linphone_upnp_update(UpnpContext *lupnp) { UpnpPortBinding *port_mapping, *port_mapping2; ms_message("uPnP IGD: Name:%s", linphone_core_upnp_get_charptr_null(upnp_igd_get_device_name(lupnp->upnp_igd_ctxt))); - ms_message("uPnP IGD: Device:%s %s", - linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt)), - linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt))); + ms_message("uPnP IGD: Device:%s %s", + linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt)), + linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt))); ms_message("uPnP IGD: Refresh mappings"); if(lupnp->sip_udp != NULL) { @@ -939,7 +939,7 @@ void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **por if(*port_mapping == NULL) { *port_mapping = linphone_upnp_port_binding_new_or_collect(lupnp->pending_bindings, protocol, port, port); } - + // Get addresses local_addr = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt); external_addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt); @@ -972,7 +972,7 @@ void linphone_upnp_update_config(UpnpContext* lupnp) { char key[64]; const MSList *item; UpnpPortBinding *port_mapping; - + /* Add configs */ for(item = lupnp->adding_configs;item!=NULL;item=item->next) { port_mapping = (UpnpPortBinding *)item->data; @@ -1006,7 +1006,7 @@ void linphone_upnp_update_proxy(UpnpContext* lupnp, bool_t force) { LinphoneUpnpState ready_state; const MSList *item; time_t now = (force)? (lupnp->last_ready_check + UPNP_CORE_READY_CHECK) : time(NULL); - + /* Refresh registers if we are ready */ if(now - lupnp->last_ready_check >= UPNP_CORE_READY_CHECK) { lupnp->last_ready_check = now; @@ -1046,7 +1046,7 @@ bool_t linphone_core_upnp_hook(void *data) { linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tls, UPNP_IGD_IP_PROTOCOL_TCP, transport.tls_port, UPNP_CORE_RETRY_DELAY); } - linphone_upnp_update_proxy(lupnp, FALSE); + linphone_upnp_update_proxy(lupnp, FALSE); linphone_upnp_update_config(lupnp); ms_mutex_unlock(&lupnp->mutex); @@ -1090,7 +1090,7 @@ UpnpPortBinding *linphone_upnp_port_binding_new() { port = ms_new0(UpnpPortBinding,1); ms_mutex_init(&port->mutex, NULL); port->state = LinphoneUpnpStateIdle; - port->protocol = UPNP_IGD_IP_PROTOCOL_UDP; + port->protocol = UPNP_IGD_IP_PROTOCOL_UDP; port->device_id = NULL; port->local_addr[0] = '\0'; port->local_port = -1; @@ -1114,20 +1114,20 @@ UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_prot UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port) { UpnpPortBinding *tmp_binding; UpnpPortBinding *end_binding; - + // Seek an binding with same protocol and local port end_binding = linphone_upnp_port_binding_new_with_parameters(protocol, local_port, -1); tmp_binding = linphone_upnp_port_binding_equivalent_in_list(list, end_binding); - - // Must be not attached to any struct + + // Must be not attached to any struct if(tmp_binding != NULL && tmp_binding->ref == 1) { linphone_upnp_port_binding_release(end_binding); end_binding = linphone_upnp_port_binding_retain(tmp_binding); } else { end_binding->external_port = external_port; } - return end_binding; -} + return end_binding; +} UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port) { UpnpPortBinding *new_port = NULL; @@ -1174,8 +1174,8 @@ void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBi // Return true if the binding are equivalent. (Note external_port == -1 means "don't care") bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2) { return port1->protocol == port2->protocol && - port1->local_port == port2->local_port && - (port1->external_port == -1 || port2->external_port == -1 || port1->external_port == port2->external_port); + port1->local_port == port2->local_port && + (port1->external_port == -1 || port2->external_port == -1 || port1->external_port == port2->external_port); } UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(MSList *list, const UpnpPortBinding *port) { @@ -1220,7 +1220,7 @@ void linphone_upnp_port_binding_release(UpnpPortBinding *port) { UpnpStream* linphone_upnp_stream_new() { UpnpStream *stream = ms_new0(UpnpStream,1); stream->state = LinphoneUpnpStateIdle; - stream->rtp = NULL; + stream->rtp = NULL; stream->rtcp = NULL; return stream; } @@ -1269,10 +1269,10 @@ void linphone_upnp_session_destroy(UpnpSession *session) { linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtcp, TRUE); } } - + session->call->stats[LINPHONE_CALL_STATS_AUDIO].upnp_state = LinphoneUpnpStateKo; session->call->stats[LINPHONE_CALL_STATS_VIDEO].upnp_state = LinphoneUpnpStateKo; - + linphone_upnp_stream_destroy(session->audio); linphone_upnp_stream_destroy(session->video); ms_free(session); @@ -1302,12 +1302,12 @@ static void linphone_upnp_config_list_port_bindings_cb(const char *entry, struct int ret; bool_t valid = TRUE; UpnpPortBinding *port; - + ret = sscanf(entry, "%"UPNP_UUID_LEN_STR"[^-]-%3s-%i-%i", device_id, protocol_str, &external_port, &local_port); if(ret == 4) { // Handle only wanted device bindings if(device_id != NULL && strcmp(cookie->device_id, device_id) != 0) { - return; + return; } if(linphone_upnp_strncmpi(protocol_str, "TCP", 3) == 0) { protocol = UPNP_IGD_IP_PROTOCOL_TCP; @@ -1344,7 +1344,7 @@ MSList *linphone_upnp_config_list_port_bindings(struct _LpConfig *lpc, const cha void linphone_upnp_config_add_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port) { MSList *list; UpnpPortBinding *list_port; - + if(port->device_id == NULL) { ms_error("Can't remove port binding without device_id"); return; diff --git a/coreapi/xml2lpc.c b/coreapi/xml2lpc.c index bacc7d4ba..57380bcd2 100644 --- a/coreapi/xml2lpc.c +++ b/coreapi/xml2lpc.c @@ -29,7 +29,7 @@ struct _xml2lpc_context { LpConfig *lpc; xml2lpc_function cbf; void *ctx; - + xmlDoc *doc; xmlDoc *xsd; char errorBuffer[XML2LPC_BZ]; @@ -43,7 +43,7 @@ xml2lpc_context* xml2lpc_context_new(xml2lpc_function cbf, void *ctx) { xmlCtx->lpc = NULL; xmlCtx->cbf = cbf; xmlCtx->ctx = ctx; - + xmlCtx->doc = NULL; xmlCtx->xsd = NULL; xmlCtx->errorBuffer[0]='\0'; @@ -70,19 +70,19 @@ static void xml2lpc_context_clear_logs(xml2lpc_context *ctx) { } static void xml2lpc_log(xml2lpc_context *xmlCtx, int level, const char *fmt, ...) { - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); if(xmlCtx->cbf != NULL) { xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args); } - va_end(args); + va_end(args); } static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) { xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx; int sl = strlen(xmlCtx->errorBuffer); - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); vsnprintf(xmlCtx->errorBuffer + sl, XML2LPC_BZ-sl, fmt, args); va_end(args); } @@ -90,25 +90,25 @@ static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) { static void xml2lpc_genericxml_warning(void *ctx, const char *fmt, ...) { xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx; int sl = strlen(xmlCtx->warningBuffer); - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); vsnprintf(xmlCtx->warningBuffer + sl, XML2LPC_BZ-sl, fmt, args); va_end(args); } #if 0 static void dumpNodes(int level, xmlNode * a_node, xml2lpc_context *ctx) { - xmlNode *cur_node = NULL; + xmlNode *cur_node = NULL; - for (cur_node = a_node; cur_node; cur_node = cur_node->next) { - if (cur_node->type == XML_ELEMENT_NODE) { - xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: Element, name: %s", level, cur_node->name); - } else { - xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: %d, name: %s", level, cur_node->type, cur_node->name); - } + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: Element, name: %s", level, cur_node->name); + } else { + xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: %d, name: %s", level, cur_node->type, cur_node->name); + } - dumpNodes(level + 1, cur_node->children, ctx); - } + dumpNodes(level + 1, cur_node->children, ctx); + } } #endif @@ -162,7 +162,7 @@ static int processEntry(xmlElement *element, const char *sectionName, xml2lpc_co } else { xml2lpc_log(ctx, XML2LPC_WARNING, "ignored entry with no \"name\" attribute line:%d",xmlGetLineNo((xmlNode*)element)); } - return 0; + return 0; } static int processSection(xmlElement *element, xml2lpc_context *ctx) { @@ -185,13 +185,13 @@ static int processSection(xmlElement *element, xml2lpc_context *ctx) { processEntry((xmlElement*)cur_node, name, ctx); } } - - } - } else { - xml2lpc_log(ctx, XML2LPC_WARNING, "ignored section with no \"name\" attribute, line:%d", xmlGetLineNo((xmlNode*)element)); - } - return 0; + } + } else { + xml2lpc_log(ctx, XML2LPC_WARNING, "ignored section with no \"name\" attribute, line:%d", xmlGetLineNo((xmlNode*)element)); + } + + return 0; } static int processConfig(xmlElement *element, xml2lpc_context *ctx) { @@ -199,19 +199,19 @@ static int processConfig(xmlElement *element, xml2lpc_context *ctx) { for (cur_node = element->children; cur_node; cur_node = cur_node->next) { dumpNode(cur_node, ctx); - if (cur_node->type == XML_ELEMENT_NODE && + if (cur_node->type == XML_ELEMENT_NODE && strcmp((const char*)cur_node->name, "section") == 0 ) { processSection((xmlElement*)cur_node, ctx); - } - - } + } + + } return 0; } static int processDoc(xmlNode *node, xml2lpc_context *ctx) { dumpNode(node, ctx); - - if (node->type == XML_ELEMENT_NODE && + + if (node->type == XML_ELEMENT_NODE && strcmp((const char*)node->name, "config") == 0 ) { processConfig((xmlElement*)node, ctx); } else { From 02918fba1be1c9ab601d1be70ebf1e6dd70892eb Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 23 Apr 2014 00:54:59 +0200 Subject: [PATCH 48/83] factorize call stats filling --- coreapi/linphonecall.c | 189 ++++++++++++++++-------------------- coreapi/private.h | 2 +- coreapi/proxy.c | 22 ++--- coreapi/quality_reporting.c | 2 +- mediastreamer2 | 2 +- tester/rcfiles/marie_rc | 2 +- 6 files changed, 100 insertions(+), 119 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 2519bc687..6ac45de4f 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -127,13 +127,6 @@ static void propagate_encryption_changed(LinphoneCall *call){ } } -#ifdef VIDEO_ENABLED -static void linphone_call_videostream_encryption_changed(void *data, bool_t encrypted){ - LinphoneCall *call = (LinphoneCall *)data; - propagate_encryption_changed(call); -} -#endif - static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) { char status[255]={0}; LinphoneCall *call; @@ -2720,8 +2713,90 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ } } +void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){ + OrtpEventType evt=ortp_event_get_type(ev); + OrtpEventData *evd=ortp_event_get_data(ev); + + if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { + stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session); + if(stats->received_rtcp != NULL) + freemsg(stats->received_rtcp); + stats->received_rtcp = evd->packet; + evd->packet = NULL; + stats->updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; + update_local_stats(stats,ms); + } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { + memcpy(&stats->jitter_stats, rtp_session_get_jitter_stats(ms->sessions.rtp_session), sizeof(jitter_stats_t)); + if (stats->sent_rtcp != NULL) + freemsg(stats->sent_rtcp); + stats->sent_rtcp = evd->packet; + evd->packet = NULL; + stats->updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; + update_local_stats(stats,ms); + } +} + +void linphone_call_notify_stats_updated(LinphoneCall *call, int stream_index){ + LinphoneCallStats *stats=&call->stats[stream_index]; + LinphoneCore *lc=call->core; + if (stats->updated){ + linphone_reporting_call_stats_updated(call, stream_index); + if (lc->vtable.call_stats_updated) + lc->vtable.call_stats_updated(lc, call, stats); + stats->updated = 0; + } +} + +void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ + MediaStream *ms=stream_index==0 ? (MediaStream *)call->audiostream : (MediaStream *)call->videostream; /*assumption to remove*/ + OrtpEvQueue *evq; + OrtpEvent *ev; + + if (ms==NULL) return; + /* Ensure there is no dangling ICE check list. */ + if (call->ice_session == NULL) ms->ice_check_list = NULL; + + switch(ms->type){ + case AudioStreamType: + audio_stream_iterate((AudioStream*)ms); + break; + case VideoStreamType: +#ifdef VIDEO_ENABLED + video_stream_iterate((VideoStream*)ms); +#endif + break; + default: + ms_error("linphone_call_handle_stream_events(): unsupported stream type."); + return; + break; + } + /*yes the event queue has to be taken at each iteration, because ice events may perform operations re-creating the streams*/ + while ((evq=stream_index==0 ? call->audiostream_app_evq : call->videostream_app_evq) && (NULL != (ev=ortp_ev_queue_get(evq)))){ + OrtpEventType evt=ortp_event_get_type(ev); + OrtpEventData *evd=ortp_event_get_data(ev); + + linphone_call_stats_fill(&call->stats[stream_index],ms,ev); + linphone_call_notify_stats_updated(call,stream_index); + + if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ + if (ms->type==AudioStreamType) + linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted); + else if (ms->type==VideoStreamType) + propagate_encryption_changed(call); + } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) { + if (ms->type==AudioStreamType) + linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified); + } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) + || (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) { + handle_ice_events(call, ev); + } else if (evt==ORTP_EVENT_TELEPHONE_EVENT){ + linphone_core_dtmf_received(call->core,evd->info.telephone_event); + } + ortp_event_destroy(ev); + } +} + void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){ - LinphoneCore* lc = call->core; int disconnect_timeout = linphone_core_get_nortp_timeout(call->core); bool_t disconnected=FALSE; @@ -2743,102 +2818,8 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse linphone_upnp_call_process(call); #endif //BUILD_UPNP -#ifdef VIDEO_ENABLED - if (call->videostream!=NULL) { - OrtpEvent *ev; - - /* Ensure there is no dangling ICE check list. */ - if (call->ice_session == NULL) call->videostream->ms.ice_check_list = NULL; - - // Beware that the application queue should not depend on treatments fron the - // mediastreamer queue. - video_stream_iterate(call->videostream); - - while (call->videostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq)))){ - OrtpEventType evt=ortp_event_get_type(ev); - OrtpEventData *evd=ortp_event_get_data(ev); - if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ - linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted); - } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { - call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->ms.sessions.rtp_session); - if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL) - freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp); - call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet; - evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; - update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); - if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) - linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); - if (lc->vtable.call_stats_updated) - lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); - } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { - memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->ms.sessions.rtp_session), sizeof(jitter_stats_t)); - if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL) - freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp); - call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet; - evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; - update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream); - if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) - linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_VIDEO); - if (lc->vtable.call_stats_updated) - lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]); - } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) - || (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) { - handle_ice_events(call, ev); - } - ortp_event_destroy(ev); - } - } -#endif - if (call->audiostream!=NULL) { - OrtpEvent *ev; - - /* Ensure there is no dangling ICE check list. */ - if (call->ice_session == NULL) call->audiostream->ms.ice_check_list = NULL; - - // Beware that the application queue should not depend on treatments fron the - // mediastreamer queue. - audio_stream_iterate(call->audiostream); - - while (call->audiostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq)))){ - OrtpEventType evt=ortp_event_get_type(ev); - OrtpEventData *evd=ortp_event_get_data(ev); - if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ - linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted); - } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) { - linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified); - } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { - call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->ms.sessions.rtp_session); - if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL) - freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp); - call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet; - evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; - update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); - linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_AUDIO); - if (lc->vtable.call_stats_updated) - lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); - } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { - memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->ms.sessions.rtp_session), sizeof(jitter_stats_t)); - if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL) - freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp); - call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet; - evd->packet = NULL; - call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; - update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream); - linphone_reporting_call_stats_updated(call, LINPHONE_CALL_STATS_AUDIO); - if (lc->vtable.call_stats_updated) - lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]); - } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) - || (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) { - handle_ice_events(call, ev); - } else if (evt==ORTP_EVENT_TELEPHONE_EVENT){ - linphone_core_dtmf_received(lc,evd->info.telephone_event); - } - ortp_event_destroy(ev); - } - } + linphone_call_handle_stream_events(call,0); + linphone_call_handle_stream_events(call,1); if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 ) disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout); if (disconnected) diff --git a/coreapi/private.h b/coreapi/private.h index 2d2d9fb21..003af30f1 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -403,7 +403,7 @@ struct _LinphoneProxyConfig char *reg_proxy; char *reg_identity; char *reg_route; - char *reg_statistics_collector; + char *statistics_collector; char *realm; char *contact_params; char *contact_uri_params; diff --git a/coreapi/proxy.c b/coreapi/proxy.c index a118ba50a..30f29f3bc 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -46,7 +46,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob const char *identity = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_identity", NULL) : NULL; const char *proxy = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_proxy", NULL) : NULL; const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL; - const char *statistics_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_statistics_collector", NULL) : NULL; + const char *statistics_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "statistics_collector", NULL) : NULL; const char *contact_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_parameters", NULL) : NULL; const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL; @@ -60,7 +60,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob obj->reg_identity = identity ? ms_strdup(identity) : NULL; obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL; obj->reg_route = route ? ms_strdup(route) : NULL; - obj->reg_statistics_collector = statistics_collector ? ms_strdup(statistics_collector) : NULL; + obj->statistics_collector = statistics_collector ? ms_strdup(statistics_collector) : NULL; obj->send_statistics = lc ? lp_config_get_default_int(lc->config, "proxy", "send_statistics", 0) : 0; obj->contact_params = contact_params ? ms_strdup(contact_params) : NULL; obj->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL; @@ -96,7 +96,7 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy); if (obj->reg_identity!=NULL) ms_free(obj->reg_identity); if (obj->reg_route!=NULL) ms_free(obj->reg_route); - if (obj->reg_statistics_collector!=NULL) ms_free(obj->reg_statistics_collector); + if (obj->statistics_collector!=NULL) ms_free(obj->statistics_collector); if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx); if (obj->realm!=NULL) ms_free(obj->realm); if (obj->type!=NULL) ms_free(obj->type); @@ -424,7 +424,7 @@ void linphone_proxy_config_enable_statistics(LinphoneProxyConfig *cfg, bool_t va bool_t linphone_proxy_config_send_statistics_enabled(LinphoneProxyConfig *cfg){ // ensure that collector address is set too! - return cfg->send_statistics && cfg->reg_statistics_collector != NULL; + return cfg->send_statistics && cfg->statistics_collector != NULL; } void linphone_proxy_config_set_statistics_collector(LinphoneProxyConfig *cfg, const char *collector){ @@ -435,16 +435,16 @@ void linphone_proxy_config_set_statistics_collector(LinphoneProxyConfig *cfg, co if (addr) linphone_address_destroy(addr); } else { - if (cfg->reg_statistics_collector != NULL) - ms_free(cfg->reg_statistics_collector); - cfg->reg_statistics_collector = ms_strdup(collector); + if (cfg->statistics_collector != NULL) + ms_free(cfg->statistics_collector); + cfg->statistics_collector = ms_strdup(collector); linphone_address_destroy(addr); } } } const char *linphone_proxy_config_get_statistics_collector(const LinphoneProxyConfig *cfg){ - return cfg->reg_statistics_collector; + return cfg->statistics_collector; } @@ -1094,8 +1094,8 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC if (obj->reg_route!=NULL){ lp_config_set_string(config,key,"reg_route",obj->reg_route); } - if (obj->reg_statistics_collector!=NULL){ - lp_config_set_string(config,key,"reg_statistics_collector",obj->reg_statistics_collector); + if (obj->statistics_collector!=NULL){ + lp_config_set_string(config,key,"statistics_collector",obj->statistics_collector); } if (obj->reg_identity!=NULL){ lp_config_set_string(config,key,"reg_identity",obj->reg_identity); @@ -1142,7 +1142,7 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config tmp=lp_config_get_string(config,key,"reg_route",NULL); if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp); - tmp=lp_config_get_string(config,key,"reg_statistics_collector",NULL); + tmp=lp_config_get_string(config,key,"statistics_collector",NULL); if (tmp!=NULL) linphone_proxy_config_set_statistics_collector(cfg,tmp); linphone_proxy_config_enable_statistics(cfg,lp_config_get_int(config,key,"send_statistics",0)); diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index c5107b4e1..595db24d2 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -269,7 +269,7 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ content.size = strlen((char*)content.data); - addr = linphone_address_new(call->dest_proxy->reg_statistics_collector); + addr = linphone_address_new(call->dest_proxy->statistics_collector); if (addr != NULL) { linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content); linphone_address_destroy(addr); diff --git a/mediastreamer2 b/mediastreamer2 index a66959cdc..69cf3ba35 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit a66959cdc9ffa2eb2736c465dfe942ce8a74dbda +Subproject commit 69cf3ba35c3533f8092b177bdc854a6fb45ceaa3 diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc index 60fa3d118..e5cd7a3b5 100644 --- a/tester/rcfiles/marie_rc +++ b/tester/rcfiles/marie_rc @@ -22,7 +22,7 @@ reg_expires=3600 reg_sendregister=1 publish=0 dial_escape_plus=0 -reg_statistics_collector=sip:collector@sip.example.org +statistics_collector=sip:collector@sip.example.org send_statistics=1 [friend_0] From ff7d1a7091131858fe68e0aa65c0330c303bee8f Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Wed, 23 Apr 2014 09:15:41 +0200 Subject: [PATCH 49/83] Value uninitialized --- coreapi/linphonecall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 6ac45de4f..cbb6624d4 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1450,7 +1450,7 @@ static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream } int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ - SalMediaDescription *remote; + SalMediaDescription *remote = NULL; bool_t has_video=FALSE; if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ From 95b0718a4a2911080ef2d88708b518ddf4f96e90 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Wed, 23 Apr 2014 10:07:12 +0200 Subject: [PATCH 50/83] cast size_t to unsigned long when using printf since some compilers complain about bad format conversion --- coreapi/quality_reporting.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 595db24d2..c9aaf331c 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -73,7 +73,9 @@ static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offs // if we are out of memory, we add some size to buffer if (ret == BELLE_SIP_BUFFER_OVERFLOW) { - ms_warning("Buffer was too small to contain the whole report - doubling its size from %lu to %lu", *buff_size, 2 * *buff_size); + // some compilers complain that size_t cannot be formatted as unsigned long, hence forcing cast + ms_warning("Buffer was too small to contain the whole report - doubling its size from %lu to %lu", + (unsigned long)*buff_size, (unsigned long)2 * *buff_size); *buff_size += 2048; *buff = (char *) ms_realloc(*buff, *buff_size); From 25a3df806080f4f0eb90a2af8e947b873fbaac87 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Wed, 23 Apr 2014 10:39:42 +0200 Subject: [PATCH 51/83] Link against libgcc and libmingwex when compiling for Windows with CMake. --- coreapi/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 05ae3d811..1fb5f2add 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -1,3 +1,7 @@ +if(MSVC) + find_library(LIBGCC NAMES gcc) + find_library(LIBMINGWEX NAMES mingwex) +endif() find_library(LIBORTP NAMES ortp) find_library(LIBMEDIASTREAMER_BASE NAMES mediastreamer_base) find_library(LIBMEDIASTREAMER_VOIP NAMES mediastreamer_voip) @@ -119,7 +123,7 @@ add_definitions( set(LIBS ws2_32) endif(WIN32) -set(LIBS ${LIBS} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2}) +set(LIBS ${LIBS} ${LIBGCC} ${LIBMINGWEX} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2}) add_library(linphone SHARED ${SOURCE_FILES}) set_target_properties(linphone PROPERTIES VERSION 3.7.0 SOVERSION 5) From 2d1c999fc514ea613f3c7020459065fdb4930bc3 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 23 Apr 2014 12:50:09 +0200 Subject: [PATCH 52/83] add proxy config setter for publish expiration --- coreapi/linphonecore.h | 16 ++++++++++++++++ coreapi/private.h | 1 + coreapi/proxy.c | 18 +++++++++++++++++- tester/Makefile.am | 4 +++- tester/eventapi_tester.c | 4 ++++ tester/presence_tester.c | 14 +++++++++++++- 6 files changed, 54 insertions(+), 3 deletions(-) diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index eff26c794..7194bbf2c 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -789,6 +789,7 @@ LINPHONE_PUBLIC int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *o LINPHONE_PUBLIC int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity); LINPHONE_PUBLIC int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route); LINPHONE_PUBLIC void linphone_proxy_config_set_expires(LinphoneProxyConfig *obj, int expires); + #define linphone_proxy_config_expires linphone_proxy_config_set_expires /** * Indicates either or not, REGISTRATION must be issued for this #LinphoneProxyConfig . @@ -808,6 +809,21 @@ LINPHONE_PUBLIC int linphone_proxy_config_done(LinphoneProxyConfig *obj); * */ LINPHONE_PUBLIC void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val); +/** + * Set the publish expiration time in second. + * @param obj proxy config + * @param exires in second + * */ + +LINPHONE_PUBLIC void linphone_proxy_config_set_publish_expires(LinphoneProxyConfig *obj, int expires); +/** + * get the publish expiration time in second. Default value is the registration expiration value. + * @param obj proxy config + * @return expires in second + * */ + +LINPHONE_PUBLIC int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *obj); + LINPHONE_PUBLIC void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val); LINPHONE_PUBLIC void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix); diff --git a/coreapi/private.h b/coreapi/private.h index 003af30f1..fa19c431e 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -408,6 +408,7 @@ struct _LinphoneProxyConfig char *contact_params; char *contact_uri_params; int expires; + int publish_expires; SalOp *op; char *type; struct _SipSetupContext *ssctx; diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 30f29f3bc..7827dcb82 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -64,6 +64,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob obj->send_statistics = lc ? lp_config_get_default_int(lc->config, "proxy", "send_statistics", 0) : 0; obj->contact_params = contact_params ? ms_strdup(contact_params) : NULL; obj->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL; + obj->publish_expires=-1; } /** @@ -872,7 +873,11 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese sal_address_unref(addr); } } - err=sal_publish_presence(proxy->publish_op,NULL,NULL,proxy->expires,(SalPresenceModel *)presence); + err=sal_publish_presence(proxy->publish_op + ,NULL + ,NULL + ,linphone_proxy_config_get_publish_expires(proxy) + ,(SalPresenceModel *)presence); }else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/ return err; } @@ -1456,3 +1461,14 @@ void linphone_proxy_config_set_privacy(LinphoneProxyConfig *params, LinphonePriv LinphonePrivacyMask linphone_proxy_config_get_privacy(const LinphoneProxyConfig *params) { return params->privacy; } +void linphone_proxy_config_set_publish_expires(LinphoneProxyConfig *obj, int expires) { + obj->publish_expires=expires; +} +int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *obj) { + if (obj->publish_expires<0) { + return obj->expires; /*default value is same as register*/ + } else { + return obj->publish_expires; + } + +} diff --git a/tester/Makefile.am b/tester/Makefile.am index 3896dc77c..1cda152c7 100644 --- a/tester/Makefile.am +++ b/tester/Makefile.am @@ -22,6 +22,8 @@ liblinphonetester_la_SOURCES = tester.c \ stun_tester.c \ remote_provisioning_tester.c +liblinphonetester_la_LDFLAGS= -no-undefined +liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS) AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/coreapi AM_CFLAGS = $(STRICT_OPTIONS) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS) @@ -31,7 +33,7 @@ if !BUILD_IOS noinst_PROGRAMS = liblinphone_tester liblinphone_tester_SOURCES = liblinphone_tester.c -liblinphone_tester_LDADD = $(top_builddir)/coreapi/liblinphone.la liblinphonetester.la $(SIPSTACK_LIBS) $(LIBXML2_LIBS) $(CUNIT_LIBS) +liblinphone_tester_LDADD = $(top_builddir)/coreapi/liblinphone.la liblinphonetester.la endif diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 9ed221667..75bd963d4 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -95,6 +95,10 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state){ stats* counters = get_stats(lc); + const LinphoneAddress* from_addr = linphone_event_get_from(ev); + char* from = linphone_address_as_string(from_addr); + ms_message("Publish state [%s] from [%s]",linphone_publish_state_to_string(state),from); + ms_free(from); switch(state){ case LinphonePublishProgress: counters->number_of_LinphonePublishProgress++; break; case LinphonePublishOk: diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 57b638c34..a1a1b6b63 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -123,13 +123,16 @@ static void wait_core(LinphoneCore *core) { } } -static void simple_publish(void) { +static void simple_publish_with_expire(int expires) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneProxyConfig* proxy; LinphonePresenceModel* presence; linphone_core_get_default_proxy(marie->lc,&proxy); linphone_proxy_config_edit(proxy); + if (expires >0) { + linphone_proxy_config_set_publish_expires(proxy,expires); + } linphone_proxy_config_enable_publish(proxy,TRUE); linphone_proxy_config_done(proxy); wait_core(marie->lc); @@ -139,6 +142,14 @@ static void simple_publish(void) { linphone_core_manager_destroy(marie); } +static void simple_publish() { + simple_publish_with_expire(-1); +} + +static void publish_with_expires() { + simple_publish_with_expire(1); +} + static bool_t subscribe_to_callee_presence(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) { stats initial_caller=caller_mgr->stat; stats initial_callee=callee_mgr->stat; @@ -340,6 +351,7 @@ static void presence_information(void) { test_t presence_tests[] = { { "Simple Subscribe", simple_subscribe }, { "Simple Publish", simple_publish }, + { "Simple Publish with expires", publish_with_expires }, /*{ "Call with presence", call_with_presence },*/ { "Unsubscribe while subscribing", unsubscribe_while_subscribing }, { "Presence information", presence_information }, From 811223d35f6ae1f7831f7b918cb95b1e1e7bcf0d Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 23 Apr 2014 16:56:24 +0200 Subject: [PATCH 53/83] reset error_info in case of success --- coreapi/bellesip_sal/sal_op_registration.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index 17a3861b4..0f011d308 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -32,6 +32,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher /*only take first one for now*/ op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data)); } + sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); if(status_code == 200) { /*check service route rfc3608*/ belle_sip_header_service_route_t* service_route; @@ -41,7 +42,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher } sal_op_set_service_route(op,(const SalAddress*)service_route_address); if (service_route_address) belle_sip_object_unref(service_route_address); - + sal_remove_pending_auth(op->base.root,op); /*just in case*/ op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0); } else if (status_code>=400) { @@ -55,7 +56,6 @@ 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_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*/ From d38ec1eebe2ae98a6ffbb1dc7405940b4a5ae19c Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Wed, 23 Apr 2014 11:26:07 +0200 Subject: [PATCH 54/83] Add missing file in Makefile --- coreapi/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 5edc54059..0beea01a4 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -56,7 +56,7 @@ liblinphone_la_SOURCES=\ xml2lpc.c \ lpc2xml.c \ remote_provisioning.c \ - quality_reporting.c \ + quality_reporting.c quality_reporting.h\ $(GITVERSION_FILE) if BUILD_UPNP From 0e9a92ef5adf0a0a12fdb237c49f1b483f23b836 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 24 Apr 2014 19:04:20 +0200 Subject: [PATCH 55/83] declare prototype --- coreapi/linphonecall.c | 2 ++ coreapi/private.h | 1 + 2 files changed, 3 insertions(+) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index cbb6624d4..a4903ed1a 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2713,6 +2713,8 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ } } + +/*do not change the prototype of this function, it is also used internally in linphone-daemon.*/ void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); diff --git a/coreapi/private.h b/coreapi/private.h index fa19c431e..ee980edf4 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -329,6 +329,7 @@ const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc); void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, LinphoneCallParams *params); int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call); void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call); +void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev); void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session); void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md); bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md); From 078e2d461daf29e9c7b97d6fdcc383ee8d901fad Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 25 Apr 2014 15:07:32 +0200 Subject: [PATCH 56/83] change LinphoneEvent from/to management to only use op --- coreapi/callbacks.c | 2 +- coreapi/event.c | 32 ++++++++++++++++++-------------- coreapi/private.h | 7 +++++-- tester/call_tester.c | 29 +++++++++++++++-------------- tester/eventapi_tester.c | 6 +++++- 5 files changed, 44 insertions(+), 32 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 2bbea45b2..94d7f17d2 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -1075,7 +1075,7 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons if (lev==NULL) { /*out of subscribe notify */ - lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionOutgoing,eventname); + lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname); } if (lc->vtable.notify_received){ const LinphoneContent *ct=linphone_content_from_sal_body(&content,body); diff --git a/coreapi/event.c b/coreapi/event.c index e95f7d454..b1c7b110d 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -74,17 +74,17 @@ LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, return lev; } -LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name){ +static LinphoneEvent *linphone_event_new_with_op_base(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name, bool_t is_out_of_dialog){ LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, op); - if (dir==LinphoneSubscriptionIncoming){ - lev->resource_addr=linphone_address_clone((LinphoneAddress*)sal_op_get_to_address(op)); - lev->from=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(lev->op)); - }else{ - lev->resource_addr=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(op)); - } + lev->is_out_of_dialog_op=is_out_of_dialog; return lev; } - +LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) { + return linphone_event_new_with_op_base(lc,op,dir,name,FALSE); +} +LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) { + return linphone_event_new_with_op_base(lc,op,dir,name,TRUE); +} void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){ LinphoneCore *lc=lev->lc; if (lev->subscription_state!=state){ @@ -129,8 +129,6 @@ LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, const LinphoneAd LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionOutgoing, event, expires); linphone_configure_op(lc,lev->op,resource,NULL,TRUE); sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_subscribe",1)); - lev->resource_addr=linphone_address_clone(resource); - lev->from=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(lev->op)); return lev; } @@ -318,8 +316,6 @@ static void linphone_event_destroy(LinphoneEvent *lev){ if (lev->op) sal_op_release(lev->op); ms_free(lev->name); - if (lev->resource_addr) linphone_address_destroy(lev->resource_addr); - if (lev->from) linphone_address_destroy(lev->from); ms_free(lev); } @@ -341,11 +337,19 @@ const char *linphone_event_get_name(const LinphoneEvent *lev){ } const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev){ - return lev->from; + if (lev->is_out_of_dialog_op){ + return (LinphoneAddress*)sal_op_get_to_address(lev->op); + }else{ + return (LinphoneAddress*)sal_op_get_from_address(lev->op); + } } const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){ - return lev->resource_addr; + if (lev->is_out_of_dialog_op){ + return (LinphoneAddress*)sal_op_get_from_address(lev->op); + }else{ + return (LinphoneAddress*)sal_op_get_to_address(lev->op); + } } LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev){ diff --git a/coreapi/private.h b/coreapi/private.h index ee980edf4..08cd1a3f3 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -710,10 +710,9 @@ struct _LinphoneEvent{ void *userdata; int refcnt; char *name; - LinphoneAddress *from; - LinphoneAddress *resource_addr; int expires; bool_t terminating; + bool_t is_out_of_dialog_op; /*used for out of dialog notify*/ }; @@ -819,6 +818,10 @@ SalReason linphone_reason_to_sal(LinphoneReason reason); LinphoneReason linphone_reason_from_sal(SalReason reason); LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires); LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); +/** + * Useful for out of dialog notify + * */ +LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state); LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); diff --git a/tester/call_tester.c b/tester/call_tester.c index 655281550..a6dc8c4ae 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1388,31 +1388,32 @@ static void early_media_call_with_ringing(void){ CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); - /* send a 183 to initiate the early media */ + if (linphone_core_inc_invite_pending(pauline->lc)) { + /* send a 183 to initiate the early media */ - linphone_core_accept_early_media(pauline->lc, linphone_core_get_current_call(pauline->lc)); + linphone_core_accept_early_media(pauline->lc, linphone_core_get_current_call(pauline->lc)); - CU_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000) ); - CU_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000) ); + CU_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000) ); + CU_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000) ); - liblinphone_tester_check_rtcp(marie, pauline); + liblinphone_tester_check_rtcp(marie, pauline); - linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc)); + linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc)); - CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); - CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); + CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); - liblinphone_tester_check_rtcp(marie, pauline); + liblinphone_tester_check_rtcp(marie, pauline); - linphone_core_terminate_all_calls(pauline->lc); + linphone_core_terminate_all_calls(pauline->lc); - CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); - ms_list_free(lcs); - + ms_list_free(lcs); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 75bd963d4..ea1bb69a4 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -48,12 +48,16 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li stats* counters = get_stats(lc); LinphoneCoreManager *mgr=get_manager(lc); LinphoneContent content={0}; - + const LinphoneAddress* from_addr = linphone_event_get_from(lev); + char* from = linphone_address_as_string(from_addr); content.type="application"; content.subtype="somexml2"; content.data=(void*)notify_content; content.size=strlen(notify_content); + ms_message("Subscription state [%s] from [%s]",linphone_subscription_state_to_string(state),from); + ms_free(from); + switch(state){ case LinphoneSubscriptionNone: break; From 7553aa6492f1df0106ca42bbfb9cea49c5dd656e Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 25 Apr 2014 23:10:12 +0200 Subject: [PATCH 57/83] - linphone now puts Route headers in requests (except register) for outbound proxy configurations, according to RFC3261 This behavior can be reverted by putting [sip]->use_no_initial_route=1 in the configuration file. - accept presence NOTIFY without bodies, instead of replying 415 - remove belle-sip warning at start due to stack not created early enough. --- coreapi/bellesip_sal/sal_impl.c | 12 +++++++++-- coreapi/bellesip_sal/sal_impl.h | 1 + coreapi/bellesip_sal/sal_op_impl.c | 17 +++++++++++++++- coreapi/bellesip_sal/sal_op_presence.c | 28 +++++++++++--------------- coreapi/linphonecore.c | 1 + include/sal/sal.h | 1 + 6 files changed, 41 insertions(+), 19 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 5bc256bea..a35d85822 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -424,14 +424,18 @@ Sal * sal_init(){ belle_sip_listener_callbacks_t listener_callbacks; Sal * sal=ms_new0(Sal,1); sal->auto_contacts=TRUE; + + /*first create the stack, which initializes the belle-sip object's pool for this thread*/ + belle_sip_set_log_handler(_belle_sip_log); + sal->stack = belle_sip_stack_new(NULL); + sal->user_agent=belle_sip_header_user_agent_new(); #if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION) belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION); #endif sal_append_stack_string_to_user_agent(sal); belle_sip_object_ref(sal->user_agent); - belle_sip_set_log_handler(_belle_sip_log); - sal->stack = belle_sip_stack_new(NULL); + sal->prov = belle_sip_stack_create_provider(sal->stack,NULL); sal_nat_helper_enable(sal,TRUE); memset(&listener_callbacks,0,sizeof(listener_callbacks)); @@ -938,6 +942,10 @@ void sal_enable_test_features(Sal*ctx, bool_t enabled){ ctx->enable_test_features=enabled; } +void sal_use_no_initial_route(Sal *ctx, bool_t enabled){ + ctx->no_initial_route=enabled; +} + SalResolverContext * sal_resolve_a(Sal* sal, const char *name, int port, int family, SalResolverCallback cb, void *data){ return (SalResolverContext*)belle_sip_stack_resolve_a(sal->stack,name,port,family,(belle_sip_resolver_callback_t)cb,data); } diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index c203c9cb1..b6e18d76a 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -47,6 +47,7 @@ struct Sal{ bool_t use_dates; bool_t auto_contacts; bool_t enable_test_features; + bool_t no_initial_route; }; typedef enum SalOpState { diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 251420977..1b90487e0 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -122,15 +122,25 @@ belle_sip_header_t * sal_make_supported_header(Sal *sal){ return belle_sip_header_create("Supported","replaces, outbound"); } +static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){ + for (;list!=NULL;list=list->next){ + SalAddress *addr=(SalAddress*)list->data; + belle_sip_header_route_t *route=belle_sip_header_route_create((belle_sip_header_address_t*)addr); + belle_sip_uri_t *uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route); + belle_sip_uri_set_lr_param(uri,1); + belle_sip_message_add_header((belle_sip_message_t*)request,(belle_sip_header_t*)route); + } +} + belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_header_from_t* from_header; belle_sip_header_to_t* to_header; belle_sip_provider_t* prov=op->base.root->prov; belle_sip_request_t *req; belle_sip_uri_t* req_uri; + const MSList *elem=sal_op_get_route_addresses(op); char token[10]; - if (strcmp("REGISTER",method)==0 || op->privacy==SalPrivacyNone) { from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)) ,belle_sip_random_token(token,sizeof(token))); @@ -157,6 +167,11 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity)); } + + if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){ + add_initial_route_set(req,elem); + } + if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){ belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new(); if (op->privacy&SalPrivacyCritical) diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index ca526fd5d..3be52c051 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -164,6 +164,8 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req return NULL; if (belle_sip_header_content_length_get_content_length(content_length) == 0) return NULL; + + if (body==NULL) return NULL; op->base.root->callbacks.parse_presence_requested(op, belle_sip_header_content_type_get_type(content_type), @@ -183,28 +185,22 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){ if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { SalPresenceModel *presence_model = NULL; const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); - if (body==NULL){ - ms_error("No body in NOTIFY received from [%s]",sal_op_get_from(op)); - resp = sal_op_create_response_from_request(op, req, 415); - belle_sip_server_transaction_send_response(server_transaction,resp); - return; + if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { + sub_state=SalSubscribeTerminated; + ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); + } else { + sub_state=SalSubscribeActive; } presence_model = process_presence_notification(op, req); - if (presence_model != NULL) { + if (presence_model != NULL || body==NULL) { /* Presence notification body parsed successfully. */ - if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { - sub_state=SalSubscribeTerminated; - ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); - } else { - sub_state=SalSubscribeActive; - } + resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */ op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL); - - } else { + } else if (body){ /* Formatting error in presence notification body. */ - ms_error("Wrongly formatted presence notification received"); - resp = sal_op_create_response_from_request(op, req, 400); + ms_warning("Wrongly formatted presence document."); + resp = sal_op_create_response_from_request(op, req, 488); } belle_sip_server_transaction_send_response(server_transaction,resp); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index dc69310a3..c31d1c181 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -662,6 +662,7 @@ static void sip_config_read(LinphoneCore *lc) sal_use_session_timers(lc->sal,200); } + sal_use_no_initial_route(lc->sal,lp_config_get_int(lc->config,"sip","use_no_initial_route",0)); sal_use_rport(lc->sal,lp_config_get_int(lc->config,"sip","use_rport",1)); ipv6=lp_config_get_int(lc->config,"sip","use_ipv6",-1); diff --git a/include/sal/sal.h b/include/sal/sal.h index 0d5cea3cc..2d7e4eec8 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -530,6 +530,7 @@ void sal_verify_server_cn(Sal *ctx, bool_t verify); void sal_set_uuid(Sal*ctx, const char *uuid); int sal_create_uuid(Sal*ctx, char *uuid, size_t len); void sal_enable_test_features(Sal*ctx, bool_t enabled); +void sal_use_no_initial_route(Sal *ctx, bool_t enabled); int sal_iterate(Sal *sal); MSList * sal_get_pending_auths(Sal *sal); From 2b5e2f2a81bbfd722dc42d33be04ed4f3defb1e3 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 28 Apr 2014 11:27:29 +0200 Subject: [PATCH 58/83] submit quality report on call end instead of on call release and add doxygen documentation --- coreapi/linphonecall.c | 14 ++++--- coreapi/quality_reporting.h | 75 ++++++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index a4903ed1a..70fe1656a 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -794,11 +794,13 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const if (lc->vtable.call_state_changed) lc->vtable.call_state_changed(lc,call,cstate,message); - if (cstate==LinphoneCallReleased){ + if (cstate==LinphoneCallEnd){ if (call->log->status == LinphoneCallSuccess) linphone_reporting_publish(call); + } + 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){ @@ -2718,7 +2720,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); - + if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session); if(stats->received_rtcp != NULL) @@ -2753,11 +2755,11 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ MediaStream *ms=stream_index==0 ? (MediaStream *)call->audiostream : (MediaStream *)call->videostream; /*assumption to remove*/ OrtpEvQueue *evq; OrtpEvent *ev; - + if (ms==NULL) return; /* Ensure there is no dangling ICE check list. */ if (call->ice_session == NULL) ms->ice_check_list = NULL; - + switch(ms->type){ case AudioStreamType: audio_stream_iterate((AudioStream*)ms); @@ -2776,10 +2778,10 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ while ((evq=stream_index==0 ? call->audiostream_app_evq : call->videostream_app_evq) && (NULL != (ev=ortp_ev_queue_get(evq)))){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); - + linphone_call_stats_fill(&call->stats[stream_index],ms,ev); linphone_call_notify_stats_updated(call,stream_index); - + if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ if (ms->type==AudioStreamType) linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted); diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index c817feba9..c182a4210 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -26,12 +26,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern "C"{ #endif + +/** + * Linphone quality report sub object storing address related information (ip / port / MAC). + */ typedef struct reporting_addr { char * ip; int port; uint32_t ssrc; } reporting_addr_t; +/** + * Linphone quality report sub object storing media metrics information as required by RFC035. + */ + typedef struct reporting_content_metrics { // timestamps - mandatory struct { @@ -45,18 +53,13 @@ typedef struct reporting_content_metrics { char * payload_desc; // mime type int sample_rate; // clock rate int frame_duration; // to check (ptime?) - audio only - // int frame_ocets; - // int frames_per_sec; - // int packets_per_sec; char * fmtp; int packet_loss_concealment; // in voip metrics - audio only - // char * silence_suppression_state; } session_description; // jitter buffet - optional struct { int adaptive; // constant - // int rate; // constant int nominal; // no may vary during the call <- average? worst score? int max; // no may vary during the call <- average? int abs_max; // constant @@ -64,25 +67,14 @@ typedef struct reporting_content_metrics { // packet loss - optional struct { - float network_packet_loss_rate; // voip metrics (loss rate) + conversion - float jitter_buffer_discard_rate; //idem + float network_packet_loss_rate; + float jitter_buffer_discard_rate; } packet_loss; - // burst gap loss - optional - // (no) currently not implemented - // struct { - // int burst_loss_density; - // int burst_duration; - // float gap_loss_density; - // int gap_duration; - // int min_gap_threshold; - // } burst_gap_loss; - // delay - optional struct { int round_trip_delay; // no - vary int end_system_delay; // no - not implemented yet - // int one_way_delay; int symm_one_way_delay; // no - vary (depends on round_trip_delay) + not implemented (depends on end_system_delay) int interarrival_jitter; // no - not implemented yet int mean_abs_jitter; // to check @@ -92,7 +84,6 @@ typedef struct reporting_content_metrics { struct { int level; // no - vary int noise_level; // no - vary - // int residual_echo_return_loss; } signal; // quality estimates - optional @@ -101,20 +92,14 @@ typedef struct reporting_content_metrics { int rcq; //voip metrics R factor - no - vary or avg in [0..120] float moslq; // no - vary or avg - voip metrics - in [0..4.9] float moscq; // no - vary or avg - voip metrics - in [0..4.9] - - - // int extri; - // int extro; - // char * rlqestalg; - // char * rcqestalg; - // char * moslqestalg; - // char * moscqestalg; - // char * extriestalg; - // char * extroutestalg; - // char * qoestalg; } quality_estimates; } reporting_content_metrics_t; + +/** + * Linphone quality report main object created by function linphone_reporting_new(). + * It contains all fields required by RFC6035 + */ typedef struct reporting_session_report { struct { char * call_id; @@ -138,10 +123,40 @@ typedef struct reporting_session_report { reporting_session_report_t * linphone_reporting_new(); void linphone_reporting_destroy(reporting_session_report_t * report); + +/** + * Fill media information about a given call. This function must be called before + * stopping the media stream. + * @param call #LinphoneCall object to consider + * @param stats_type the media type (LINPHONE_CALL_STATS_AUDIO or LINPHONE_CALL_STATS_VIDEO) + * + */ void linphone_reporting_update(LinphoneCall * call, int stats_type); + +/** + * Fill IP information about a given call. This function must be called each + * time state is 'LinphoneCallStreamsRunning' since IP might be updated (if we + * found a direct route between caller and callee for example). + * @param call #LinphoneCall object to consider + * + */ void linphone_reporting_update_ip(LinphoneCall * call); + +/** + * Publish the report on the call end. + * @param call #LinphoneCall object to consider + * + */ void linphone_reporting_publish(LinphoneCall* call); + +/** + * Update publish report data with fresh RTCP stats, if needed. + * @param call #LinphoneCall object to consider + * @param stats_type the media type (LINPHONE_CALL_STATS_AUDIO or LINPHONE_CALL_STATS_VIDEO) + * + */ void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type); + #ifdef __cplusplus } #endif From 037859f83ac2c48d1c7c8cca5f8c443d5fcfb9f8 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 28 Apr 2014 12:00:49 +0200 Subject: [PATCH 59/83] do not use _() macro for quality reporting data since this macro is used for localized text (gettext) --- coreapi/quality_reporting.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index c9aaf331c..58484cad7 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -55,7 +55,7 @@ static char * float_to_one_decimal_string(float f) { int floor_part = (int) rounded_f; int one_decimal_part = floorf (10 * (rounded_f - floor_part) + .5f); - return ms_strdup_printf(_("%d.%d"), floor_part, one_decimal_part); + return ms_strdup_printf("%d.%d", floor_part, one_decimal_part); } static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offset, const char *fmt, va_list args) { @@ -354,9 +354,9 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { return; STR_REASSIGN(report->info.call_id, ms_strdup(call->log->call_id)); - STR_REASSIGN(report->info.local_group, ms_strdup_printf(_("linphone-%s-%s-%s"), (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"), + STR_REASSIGN(report->info.local_group, ms_strdup_printf("linphone-%s-%s-%s", (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"), linphone_core_get_user_agent_name(), report->info.call_id)); - STR_REASSIGN(report->info.remote_group, ms_strdup_printf(_("linphone-%s-%s-%s"), (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"), + STR_REASSIGN(report->info.remote_group, ms_strdup_printf("linphone-%s-%s-%s", (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"), linphone_call_get_remote_user_agent(call), report->info.call_id)); if (call->dir == LinphoneCallIncoming) { From 1d7d5f47ebdee02616854d52979739cfa075e635 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 28 Apr 2014 17:53:53 +0200 Subject: [PATCH 60/83] fix crash in quality reporting if ip was not valid on call end --- coreapi/quality_reporting.c | 3 ++- mediastreamer2 | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 58484cad7..df19240d8 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -235,7 +235,8 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ // if the call was hungup too early, we might have invalid IPs information // in that case, we abort the report since it's not useful data - if (strlen(report->info.local_addr.ip) == 0 || strlen(report->info.remote_addr.ip) == 0) { + if (report->info.local_addr.ip == NULL || strlen(report->info.local_addr.ip) == 0 + || report->info.remote_addr.ip == NULL || strlen(report->info.remote_addr.ip) == 0) { ms_warning("The call was hang up too early (duration: %d sec) and IP could " "not be retrieved so dropping this report", linphone_call_get_duration(call)); return; diff --git a/mediastreamer2 b/mediastreamer2 index 69cf3ba35..f6c6813f0 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 69cf3ba35c3533f8092b177bdc854a6fb45ceaa3 +Subproject commit f6c6813f0cdffaaa290d3933b7f6a92d586bae72 From c987f1a002b79eb4609d2ac01da72874566fe102 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 1 May 2014 11:41:40 +0200 Subject: [PATCH 61/83] increase wait time in subscribe tests --- tester/eventapi_tester.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index ea1bb69a4..e5c459489 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -140,7 +140,7 @@ static void subscribe_test_declined(void) { linphone_event_ref(lev); 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)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionError,1,21000));/*yes flexisip may wait 20 secs in case of forking*/ ei=linphone_event_get_error_info(lev); CU_ASSERT_PTR_NOT_NULL(ei); @@ -183,8 +183,8 @@ static void subscribe_test_with_args(bool_t terminated_by_subscriber, RefreshTes 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)); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,3000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,1000)); /*make sure marie receives first notification before terminating*/ @@ -238,7 +238,7 @@ static void subscribe_test_with_args2(bool_t terminated_by_subscriber, RefreshTe linphone_event_send_subscribe(lev,&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)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); /*check good receipt of custom headers*/ CU_ASSERT_STRING_EQUAL(linphone_event_get_custom_header(pauline->lev,"My-Header"),"pouet"); From f6d63524d3589c388506c9069d4dcb7d3727f702 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 1 May 2014 12:14:05 +0200 Subject: [PATCH 62/83] fix declared number of channels in SDP for opus codec, to follow opus-rtp draft. add ugly hack to allow older versions of linphone to call new versions with opus. --- coreapi/bellesip_sal/sal_sdp.c | 2 +- coreapi/linphonecore.c | 2 +- coreapi/misc.c | 6 ------ coreapi/offeranswer.c | 15 +++++++++++++-- mediastreamer2 | 2 +- oRTP | 2 +- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 0ee29e6da..50e3504a5 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -117,7 +117,7 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session mime_param= belle_sdp_mime_parameter_create ( pt->mime_type , payload_type_get_number ( pt ) , pt->clock_rate - ,stream->type==SalAudio?1:-1 ); + , pt->channels>0 ? pt->channels : -1 ); belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp ); if ( stream->ptime>0 ) { belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime ); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c31d1c181..b15bd71b4 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1377,7 +1377,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_core_assign_payload_type(lc,&payload_type_g729,18,"annexb=no"); linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,"config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"); linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,"config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5"); - linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; usedtx=0; cbr=1"); + linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; stereo=0; sprop-stereo=0"); linphone_core_assign_payload_type(lc,&payload_type_isac,-1,NULL); linphone_core_handle_static_payloads(lc); diff --git a/coreapi/misc.c b/coreapi/misc.c index b1e9f2235..fed8191b4 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -168,12 +168,6 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl case PAYLOAD_AUDIO_PACKETIZED: codec_band=get_audio_payload_bandwidth(lc,pt); ret=bandwidth_is_greater(bandwidth_limit*1000,codec_band); - /*hack to avoid using uwb codecs when having low bitrate and video*/ - if (bandwidth_is_greater(199,bandwidth_limit)){ - if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){ - ret=FALSE; - } - } //ms_message("Payload %s: %g",pt->mime_type,codec_band); break; case PAYLOAD_VIDEO: diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index df4e7507d..db2a28b76 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -39,11 +39,20 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload for (elem=l;elem!=NULL;elem=elem->next){ pt=(PayloadType*)elem->data; + + /*workaround a bug in earlier versions of linphone where opus/48000/1 is offered, which is uncompliant with opus rtp draft*/ + if (refpt->mime_type && strcasecmp(refpt->mime_type,"opus")==0 && refpt->channels==1 + && strcasecmp(pt->mime_type,refpt->mime_type)==0){ + pt->channels=1; /*so that we respond with same number of channels */ + candidate=pt; + break; + } + /* the compare between G729 and G729A is for some stupid uncompliant phone*/ if ( pt->mime_type && refpt->mime_type && (strcasecmp(pt->mime_type,refpt->mime_type)==0 || (strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 )) - && pt->clock_rate==refpt->clock_rate){ + && pt->clock_rate==refpt->clock_rate && pt->channels==refpt->channels){ candidate=pt; /*good candidate, check fmtp for H264 */ if (strcasecmp(pt->mime_type,"H264")==0){ @@ -106,7 +115,9 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t res=ms_list_append(res,newp); } }else{ - ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate); + if (p2->channels>0) + ms_message("No match for %s/%i/%i",p2->mime_type,p2->clock_rate,p2->channels); + else ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate); } } if (reading_response){ diff --git a/mediastreamer2 b/mediastreamer2 index f6c6813f0..7f97a5c70 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit f6c6813f0cdffaaa290d3933b7f6a92d586bae72 +Subproject commit 7f97a5c7046589f4de0a742a686308ad5770348d diff --git a/oRTP b/oRTP index c09e63ddb..c329c3a47 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit c09e63ddba599a7f7da149edf6f7b290f4cfa787 +Subproject commit c329c3a478011ed4c10ffca79b8624ec6b60450c From c5f702ede74a2f724f6f5d0635a4d332e22c14e0 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 2 May 2014 11:25:59 +0200 Subject: [PATCH 63/83] update ms2 --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 7f97a5c70..f8658d427 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 7f97a5c7046589f4de0a742a686308ad5770348d +Subproject commit f8658d42780c966c7e2cd683c1ee445688e5d465 From 3a6aa9f08d233b7acfb0707cec55b007474fb17a Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 2 May 2014 20:24:51 +0200 Subject: [PATCH 64/83] deep modifications about audio & video codec bitrates are handled. - vbr codecs can automatically have different output bitrates depending on whether video is used and/or allowed total output bandwidth - application can specify an output IP bitrate for a given codec, which allows to control the quality of vbr codecs. Note: a belle-sip upgrade is required to fix a bug around channels parsing in rtpmap. --- coreapi/bellesip_sal/sal_op_call.c | 2 +- coreapi/linphonecall.c | 83 +++++++++++----- coreapi/linphonecore.h | 29 +++++- coreapi/misc.c | 152 +++++++++++++++++------------ coreapi/private.h | 9 +- gtk/propertybox.c | 6 +- tester/call_tester.c | 35 +++++++ 7 files changed, 222 insertions(+), 94 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 610815802..6f886d336 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -597,7 +597,7 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ static belle_sip_header_allow_t *create_allow(){ belle_sip_header_allow_t* header_allow; - header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE"); + header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO"); return header_allow; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 70fe1656a..bb0e8c619 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1693,17 +1693,65 @@ static void post_configure_audio_streams(LinphoneCall*call){ linphone_call_start_recording(call); } -static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){ +static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){ + int remote_bw=0; + int upload_bw; + int total_upload_bw=linphone_core_get_upload_bandwidth(call->core); + const LinphoneCallParams *params=&call->params; + bool_t will_use_video=linphone_core_media_description_contains_video_stream(md); + bool_t forced=FALSE; + + if (desc->bandwidth>0) remote_bw=desc->bandwidth; + else if (md->bandwidth>0) { + /*case where b=AS is given globally, not per stream*/ + remote_bw=md->bandwidth; + } + if (params->up_bw>0){ + forced=TRUE; + upload_bw=params->up_bw; + }else upload_bw=total_upload_bw; + upload_bw=get_min_bandwidth(upload_bw,remote_bw); + if (!will_use_video || forced) return upload_bw; + + if (bandwidth_is_greater(upload_bw,512)){ + upload_bw=100; + }else if (bandwidth_is_greater(upload_bw,256)){ + upload_bw=64; + }else if (bandwidth_is_greater(upload_bw,128)){ + upload_bw=40; + }else if (bandwidth_is_greater(upload_bw,0)){ + upload_bw=24; + } + return upload_bw; +} + +static int get_video_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){ + int remote_bw=0; int bw; + if (desc->bandwidth>0) remote_bw=desc->bandwidth; + else if (md->bandwidth>0) { + /*case where b=AS is given globally, not per stream*/ + remote_bw=get_remaining_bandwidth_for_video(md->bandwidth,call->audio_bw); + } + bw=get_min_bandwidth(get_remaining_bandwidth_for_video(linphone_core_get_upload_bandwidth(call->core),call->audio_bw),remote_bw); + return bw; +} + +static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){ + int bw=0; const MSList *elem; RtpProfile *prof=rtp_profile_new("Call profile"); bool_t first=TRUE; - int remote_bw=0; LinphoneCore *lc=call->core; int up_ptime=0; const LinphoneCallParams *params=&call->params; + *used_pt=-1; - + if (desc->type==SalAudio) + bw=get_ideal_audio_bw(call,md,desc); + else if (desc->type==SalVideo) + bw=get_video_bw(call,md,desc); + for(elem=desc->payloads;elem!=NULL;elem=elem->next){ PayloadType *pt=(PayloadType*)elem->data; int number; @@ -1712,8 +1760,11 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m pt=payload_type_clone(pt); if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) { + /*first codec in list is the selected one*/ if (desc->type==SalAudio){ - linphone_core_update_allocated_audio_bandwidth_in_call(call,pt); + /*this will update call->audio_bw*/ + linphone_core_update_allocated_audio_bandwidth_in_call(call,pt,bw); + bw=call->audio_bw; if (params->up_ptime) up_ptime=params->up_ptime; else up_ptime=linphone_core_get_upload_ptime(lc); @@ -1721,27 +1772,9 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m *used_pt=payload_type_get_number(pt); first=FALSE; } - if (desc->bandwidth>0) remote_bw=desc->bandwidth; - else if (md->bandwidth>0) { - /*case where b=AS is given globally, not per stream*/ - remote_bw=md->bandwidth; - if (desc->type==SalVideo){ - remote_bw=get_video_bandwidth(remote_bw,call->audio_bw); - } - } - - if (desc->type==SalAudio){ - int audio_bw=call->audio_bw; - if (params->up_bw){ - if (params->up_bw< audio_bw) - audio_bw=params->up_bw; - } - bw=get_min_bandwidth(audio_bw,remote_bw); - }else bw=get_min_bandwidth(get_video_bandwidth(linphone_core_get_upload_bandwidth (lc),call->audio_bw),remote_bw); - if (bw>0) pt->normal_bitrate=bw*1000; - else if (desc->type==SalAudio){ - pt->normal_bitrate=-1; - } + if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){ + pt->normal_bitrate=get_min_bandwidth(pt->normal_bitrate,bw*1000); + } else pt->normal_bitrate=bw*1000; if (desc->ptime>0){ up_ptime=desc->ptime; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 7194bbf2c..fc02cbb23 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1580,6 +1580,33 @@ LINPHONE_PUBLIC int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *cod */ LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt); +/** + * Tells whether the specified payload type represents a variable bitrate codec. + * @param[in] lc #LinphoneCore object. + * @param[in] pt The #PayloadType we want to know + * @returns TRUE if the payload type represents a VBR codec, FALSE if disabled. + * @ingroup media_parameters + */ +LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt); + +/** + * Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s. + * @param[in] lc the #LinphoneCore object + * @param[in] pt the #PayloadType to modify. + * @param[in] bitrate the IP bitrate in kbit/s. + * @ingroup media_parameters +**/ +LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate); + +/** + * Get the bitrate explicitely set with linphone_core_set_payload_type_bitrate(). + * @param[in] lc the #LinphoneCore object + * @param[in] pt the #PayloadType to modify. + * @return bitrate the IP bitrate in kbit/s, or -1 if an error occured. + * @ingroup media_parameters +**/ +LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt); + /** * Enable or disable the use of the specified payload type. * @param[in] lc #LinphoneCore object. @@ -1616,7 +1643,7 @@ LINPHONE_PUBLIC int linphone_core_get_payload_type_number(LinphoneCore *lc, cons LINPHONE_PUBLIC const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt); -LINPHONE_PUBLIC bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt); +LINPHONE_PUBLIC bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const PayloadType *pt); /** * Create a proxy config with default values from Linphone core. diff --git a/coreapi/misc.c b/coreapi/misc.c index fed8191b4..f46ec403b 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -77,6 +77,11 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *p return FALSE; } +bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt){ + if (pt->type==PAYLOAD_VIDEO) return TRUE; + return !!(pt->flags & PAYLOAD_TYPE_IS_VBR); +} + int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){ if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){ payload_type_set_enable(pt,enabled); @@ -103,62 +108,124 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload return NULL; } - -/*this function makes a special case for speex/8000. -This codec is variable bitrate. The 8kbit/s mode is interesting when having a low upload bandwidth, but its quality -is not very good. We 'd better use its 15kbt/s mode when we have enough bandwidth*/ -static int get_codec_bitrate(LinphoneCore *lc, const PayloadType *pt){ - int upload_bw=linphone_core_get_upload_bandwidth(lc); - if (bandwidth_is_greater(upload_bw,129) || (bandwidth_is_greater(upload_bw,33) && !linphone_core_video_enabled(lc)) ) { - if (strcmp(pt->mime_type,"speex")==0 && pt->clock_rate==8000){ - return 15000; +void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate){ + if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){ + if (pt->flags & PAYLOAD_TYPE_IS_VBR){ + pt->normal_bitrate=bitrate*1000; + pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE; + }else{ + ms_error("Cannot set an explicit bitrate for codec %s/%i, because it is not VBR.",pt->mime_type,pt->clock_rate); } } - return pt->normal_bitrate; + ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !"); } + /* *((codec-birate*ptime/8) + RTP header + UDP header + IP header)*8/ptime; *ptime=1/npacket */ -static double get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt){ + +static double get_audio_payload_bandwidth_from_codec_bitrate(const PayloadType *pt){ double npacket=50; double packet_size; int bitrate; + if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt))==0) { /*special case of aac 44K because ptime= 10ms*/ npacket=100; + }else if (strcmp(payload_type_get_mime(&payload_type_ilbc), payload_type_get_mime(pt))==0) { + npacket=1000/30.0; } - bitrate=get_codec_bitrate(lc,pt); + bitrate=pt->normal_bitrate; packet_size= (((double)bitrate)/(npacket*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ; return packet_size*8.0*npacket; } -void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt){ - call->audio_bw=(int)(ceil(get_audio_payload_bandwidth(call->core,pt)/1000.0)); /*rounding codec bandwidth should be avoid, specially for AMR*/ +typedef struct vbr_codec_bitrate{ + int max_avail_bitrate; + int min_rate; + int recomended_bitrate; +}vbr_codec_bitrate_t; + +static vbr_codec_bitrate_t defauls_vbr[]={ + //{ 100, 44100, 100 }, + { 64, 44100, 50 }, + { 64, 16000, 40 }, + { 32, 16000, 32 }, + { 32, 8000, 32 }, + { 0 , 8000, 24 }, + { 0 , 0, 0 } +}; + +static int lookup_vbr_typical_bitrate(int maxbw, int clock_rate){ + vbr_codec_bitrate_t *it; + if (maxbw<=0) maxbw=defauls_vbr[0].max_avail_bitrate; + for(it=defauls_vbr;it->min_rate!=0;it++){ + if (maxbw>=it->max_avail_bitrate && clock_rate>=it->min_rate) + return it->recomended_bitrate; + } + ms_error("lookup_vbr_typical_bitrate(): should not happen."); + return 32; +} + +static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt, int maxbw){ + if (linphone_core_payload_type_is_vbr(lc,pt)){ + if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){ + ms_message("PayloadType %s/%i has bitrate override",pt->mime_type,pt->clock_rate); + return pt->normal_bitrate/1000; + } + return lookup_vbr_typical_bitrate(maxbw,pt->clock_rate); + }else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/ +} + +int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt){ + int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), + linphone_core_get_upload_bandwidth(lc)); + if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){ + return get_audio_payload_bandwidth(lc,pt,maxbw); + }else if (pt->type==PAYLOAD_VIDEO){ + int video_bw; + linphone_core_update_allocated_audio_bandwidth(lc); + if (maxbw<=0) { + video_bw=1500; /*default bitrate for video stream when no bandwidth limit is set, around 1.5 Mbit/s*/ + }else{ + video_bw=get_remaining_bandwidth_for_video(maxbw,lc->audio_bw); + } + return video_bw; + } + return 0; +} + +void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt, int maxbw){ + call->audio_bw=get_audio_payload_bandwidth(call->core,pt,maxbw); ms_message("Audio bandwidth for this call is %i",call->audio_bw); } void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){ const MSList *elem; - PayloadType *max=NULL; + int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), + linphone_core_get_upload_bandwidth(lc)); + int max_codec_bitrate=0; + for(elem=linphone_core_get_audio_codecs(lc);elem!=NULL;elem=elem->next){ PayloadType *pt=(PayloadType*)elem->data; if (payload_type_enabled(pt)){ - int pt_bitrate=get_codec_bitrate(lc,pt); - if (max==NULL) max=pt; - else if (max->normal_bitrateaudio_bw=(int)(get_audio_payload_bandwidth(lc,max)/1000.0); + if (max_codec_bitrate) { + lc->audio_bw=max_codec_bitrate; } } -bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, PayloadType *pt, int bandwidth_limit) +bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit) { double codec_band; bool_t ret=FALSE; @@ -166,7 +233,7 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl switch (pt->type){ case PAYLOAD_AUDIO_CONTINUOUS: case PAYLOAD_AUDIO_PACKETIZED: - codec_band=get_audio_payload_bandwidth(lc,pt); + codec_band=get_audio_payload_bandwidth(lc,pt,bandwidth_limit); ret=bandwidth_is_greater(bandwidth_limit*1000,codec_band); //ms_message("Payload %s: %g",pt->mime_type,codec_band); break; @@ -181,43 +248,8 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl } /* return TRUE if codec can be used with bandwidth, FALSE else*/ -bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt) -{ - double codec_band; - int allowed_bw,video_bw; - bool_t ret=FALSE; - - linphone_core_update_allocated_audio_bandwidth(lc); - allowed_bw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), - linphone_core_get_upload_bandwidth(lc)); - if (allowed_bw==0) { - allowed_bw=-1; - video_bw=1500; /*around 1.5 Mbit/s*/ - }else - video_bw=get_video_bandwidth(allowed_bw,lc->audio_bw); - - switch (pt->type){ - case PAYLOAD_AUDIO_CONTINUOUS: - case PAYLOAD_AUDIO_PACKETIZED: - codec_band=get_audio_payload_bandwidth(lc,pt); - ret=bandwidth_is_greater(allowed_bw*1000,codec_band); - /*hack to avoid using uwb codecs when having low bitrate and video*/ - if (bandwidth_is_greater(199,allowed_bw)){ - if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){ - ret=FALSE; - } - } - //ms_message("Payload %s: %g",pt->mime_type,codec_band); - break; - case PAYLOAD_VIDEO: - if (video_bw>0){ - pt->normal_bitrate=video_bw*1000; - ret=TRUE; - } - else ret=FALSE; - break; - } - return ret; +bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const PayloadType *pt){ + return linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, linphone_core_get_payload_type_bitrate(lc,pt)); } bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){ diff --git a/coreapi/private.h b/coreapi/private.h index 08cd1a3f3..3553ca353 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -292,7 +292,7 @@ static inline bool_t bandwidth_is_greater(int bw1, int bw2){ else return bw1>=bw2; } -static inline int get_video_bandwidth(int total, int audio){ +static inline int get_remaining_bandwidth_for_video(int total, int audio){ if (total<=0) return 0; return total-audio-10; } @@ -307,6 +307,7 @@ static inline void set_string(char **dest, const char *src){ } #define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0 +#define PAYLOAD_TYPE_BITRATE_OVERRIDE PAYLOAD_TYPE_USER_FLAG_3 void linphone_process_authentication(LinphoneCore* lc, SalOp *op); void linphone_authentication_ok(LinphoneCore *lc, SalOp *op); @@ -321,7 +322,7 @@ void linphone_subscription_answered(LinphoneCore *lc, SalOp *op); void linphone_subscription_closed(LinphoneCore *lc, SalOp *op); void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc); -void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt); +void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt, int maxbw); int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call); void linphone_core_resolve_stun_server(LinphoneCore *lc); @@ -655,7 +656,7 @@ struct _LinphoneCore char *play_file; char *rec_file; time_t prevtime; - int audio_bw; + int audio_bw; /*IP bw consumed by audio codec, set as soon as used codec is known, its purpose is to know the remaining bw for video*/ LinphoneCoreWaitingCallback wait_cb; void *wait_ctx; unsigned long video_window_id; @@ -731,7 +732,7 @@ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call); void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md); -bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, PayloadType *pt, int bandwidth_limit); +bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit); #define linphone_core_ready(lc) ((lc)->state==LinphoneGlobalOn || (lc)->state==LinphoneGlobalShutdown) void _linphone_core_configure_resolver(); diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 86356a97b..598e2f384 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -565,7 +565,7 @@ static void linphone_gtk_init_codec_list(GtkTreeView *listview){ "foreground",CODEC_COLOR, NULL); gtk_tree_view_append_column (listview, column); - column = gtk_tree_view_column_new_with_attributes (_("Bitrate (kbit/s)"), + column = gtk_tree_view_column_new_with_attributes (_("IP Bitrate (kbit/s)"), renderer, "text", CODEC_BITRATE, "foreground",CODEC_COLOR, @@ -621,7 +621,7 @@ static void linphone_gtk_show_codecs(GtkTreeView *listview, const MSList *codecl } /* get an iterator */ gtk_list_store_append(store,&iter); - bitrate=payload_type_get_bitrate(pt)/1000.0; + bitrate=linphone_core_get_payload_type_bitrate(linphone_gtk_get_core(),pt); rate=payload_type_get_rate(pt); if (pt->recv_fmtp!=NULL) params=pt->recv_fmtp; gtk_list_store_set(store,&iter, CODEC_NAME,payload_type_get_mime(pt), @@ -657,7 +657,7 @@ static void linphone_gtk_check_codec_bandwidth(GtkTreeView *v){ gfloat bitrate; gtk_tree_model_get(model,&iter,CODEC_PRIVDATA,&pt,-1); - bitrate=payload_type_get_bitrate(pt)/1000.0; + bitrate=linphone_core_get_payload_type_bitrate(linphone_gtk_get_core(),pt); gtk_list_store_set(GTK_LIST_STORE(model),&iter,CODEC_COLOR, (gpointer)get_codec_color(linphone_gtk_get_core(),pt), CODEC_BITRATE, bitrate,-1); }while(gtk_tree_model_iter_next(model,&iter)); diff --git a/tester/call_tester.c b/tester/call_tester.c index a6dc8c4ae..1fd301fb4 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -25,6 +25,7 @@ #include "liblinphone_tester.h" static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy); +static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime); void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){ char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); @@ -249,6 +250,39 @@ static void simple_call(void) { linphone_core_manager_destroy(pauline); } +static void call_with_specified_codec_bitrate(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + const LinphoneCallStats *pauline_stats,*marie_stats; + bool_t call_ok; + if (linphone_core_find_payload_type(marie->lc,"opus",48000,-1)==NULL){ + ms_warning("opus codec not supported, test skipped."); + goto end; + } + + disable_all_codecs_except_one(marie->lc,"opus"); + disable_all_codecs_except_one(pauline->lc,"opus"); + + linphone_core_set_payload_type_bitrate(marie->lc, + linphone_core_find_payload_type(marie->lc,"opus",48000,-1), + 50); + linphone_core_set_payload_type_bitrate(pauline->lc, + linphone_core_find_payload_type(pauline->lc,"opus",48000,-1), + 24); + + CU_ASSERT_TRUE((call_ok=call(pauline,marie))); + if (!call_ok) goto end; + liblinphone_tester_check_rtcp(marie,pauline); + marie_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc)); + pauline_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); + CU_ASSERT_TRUE(marie_stats->download_bandwidth<30); + CU_ASSERT_TRUE(pauline_stats->download_bandwidth>45); + +end: + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void simple_call_compatibility_mode(void) { char route[256]; LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); @@ -2122,6 +2156,7 @@ test_t call_tests[] = { { "Call statistics not used if no config", statistics_not_used_without_config}, { "Call statistics not sent if call did not start", statistics_not_sent_if_call_not_started}, { "Call statistics sent if call ended normally", statistics_sent_at_call_termination}, + { "Call with specified codec bitrate", call_with_specified_codec_bitrate} }; test_suite_t call_test_suite = { From 9968ac1b8a344287bf182defde8fe1afcd229b30 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 2 May 2014 20:31:29 +0200 Subject: [PATCH 65/83] forgot to update oRTP --- oRTP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oRTP b/oRTP index c329c3a47..bc9f28bea 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit c329c3a478011ed4c10ffca79b8624ec6b60450c +Subproject commit bc9f28beadf9336552eaa091c06bf72fd1d5e491 From 4296c3945c47602e9a3e9daea6b35a85cb2513a8 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 2 May 2014 23:22:36 +0200 Subject: [PATCH 66/83] update oRTP, fix bad error output, and restore UPDATE method in allow header (removed by mistake) --- coreapi/bellesip_sal/sal_op_call.c | 6 +++--- coreapi/misc.c | 1 + oRTP | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 6f886d336..1b0f63949 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -597,7 +597,7 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ static belle_sip_header_allow_t *create_allow(){ belle_sip_header_allow_t* header_allow; - header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO"); + header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE"); return header_allow; } @@ -609,8 +609,8 @@ static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) { belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer")); } if (op->base.local_media){ - op->sdp_offering=TRUE; - set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media); + op->sdp_offering=TRUE; + set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media); }else op->sdp_offering=FALSE; return; } diff --git a/coreapi/misc.c b/coreapi/misc.c index f46ec403b..82f089152 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -115,6 +115,7 @@ void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, i pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE; }else{ ms_error("Cannot set an explicit bitrate for codec %s/%i, because it is not VBR.",pt->mime_type,pt->clock_rate); + return; } } ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !"); diff --git a/oRTP b/oRTP index bc9f28bea..fb53b3dd2 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit bc9f28beadf9336552eaa091c06bf72fd1d5e491 +Subproject commit fb53b3dd2bcc5e889f7026bdd42b151ef7217249 From e942c6590ba23a1d544790a7026a4398c6b81862 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 5 May 2014 11:03:46 +0200 Subject: [PATCH 67/83] fix clang warning --- coreapi/bellesip_sal/sal_op_presence.c | 4 ++-- mediastreamer2 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index 3be52c051..e1ab054aa 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -177,7 +177,7 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req } static void handle_notify(SalOp *op, belle_sip_request_t *req){ - belle_sip_response_t* resp; + belle_sip_response_t* resp=NULL; belle_sip_server_transaction_t* server_transaction=op->pending_server_trans; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); SalSubscribeStatus sub_state; @@ -202,7 +202,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){ ms_warning("Wrongly formatted presence document."); resp = sal_op_create_response_from_request(op, req, 488); } - belle_sip_server_transaction_send_response(server_transaction,resp); + if (resp) belle_sip_server_transaction_send_response(server_transaction,resp); } } diff --git a/mediastreamer2 b/mediastreamer2 index f8658d427..cc4c03ad5 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit f8658d42780c966c7e2cd683c1ee445688e5d465 +Subproject commit cc4c03ad5e80afc3f0f518618f061e024c6eba64 From eba52ef155b2d945db51daada777e016bce9e550 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 5 May 2014 11:27:35 +0200 Subject: [PATCH 68/83] fix bad handling of link-local ipv6 addresses --- coreapi/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/misc.c b/coreapi/misc.c index 82f089152..38f72bfe3 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -1094,7 +1094,7 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul ms_error("getnameinfo error: %s",strerror(errno)); } /*avoid ipv6 link-local addresses*/ - if (type==AF_INET6 && strchr(result,'%')!=NULL){ + if (p_addr->sa_family==AF_INET6 && strchr(result,'%')!=NULL){ strcpy(result,"::1"); close_socket(sock); return -1; From fb2b7ee40df1954235d64d7c69899997f5ea3dfc Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 5 May 2014 11:47:19 +0200 Subject: [PATCH 69/83] ipv6 detection fix --- coreapi/linphonecore.c | 4 +++- coreapi/misc.c | 17 +++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index b15bd71b4..edd8a0c47 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1527,7 +1527,9 @@ void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){ strncpy(result,"::1",LINPHONE_IPADDR_SIZE); return; } - }else af=AF_INET; + } + /*in all other cases use IPv4*/ + af=AF_INET; } if (linphone_core_get_local_ip_for(af,NULL,result)==0) return; diff --git a/coreapi/misc.c b/coreapi/misc.c index 38f72bfe3..e3fef7c59 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -1000,12 +1000,12 @@ bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc){ #ifdef HAVE_GETIFADDRS #include -static int get_local_ip_with_getifaddrs(int type, char *address, int size) -{ +static int get_local_ip_with_getifaddrs(int type, char *address, int size){ struct ifaddrs *ifp; struct ifaddrs *ifpstart; - int ret = 0; - + char retaddr[LINPHONE_IPADDR_SIZE]={0}; + bool_t found=FALSE; + if (getifaddrs(&ifpstart) < 0) { return -1; } @@ -1022,17 +1022,18 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size) if(getnameinfo(ifp->ifa_addr, (type == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in), - address, size, NULL, 0, NI_NUMERICHOST) == 0) { - if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */ + retaddr, size, NULL, 0, NI_NUMERICHOST) == 0) { + if (strchr(retaddr, '%') == NULL) { /*avoid ipv6 link-local addresses */ /*ms_message("getifaddrs() found %s",address);*/ - ret++; + found=TRUE; break; } } } } freeifaddrs(ifpstart); - return ret; + if (found) strncpy(address,retaddr,size); + return found; } #endif From b5117cf71e467fae267a452c8f5a6f0b68d78bac Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Mon, 5 May 2014 12:03:29 +0200 Subject: [PATCH 70/83] Answer 504 to UPDADE requests received in a confirmed dialog --- coreapi/bellesip_sal/sal_op_call.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 1b0f63949..9a2474b37 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -560,6 +560,18 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481)); } else if (strcmp("MESSAGE",method)==0){ sal_process_incoming_message(op,event); + } else if (strcmp("UPDATE",method)==0) { + /*rfc 3311 + * 5.2 Receiving an UPDATE + * ... + * If the UAS cannot change the session parameters without prompting the user, it SHOULD reject + * the request with a 504 response. + */ + resp=sal_op_create_response_from_request(op,req,504); + belle_sip_message_add_header( BELLE_SIP_MESSAGE(resp) + ,belle_sip_header_create( "Warning", "Cannot change the session parameters without prompting the user")); + belle_sip_server_transaction_send_response(server_transaction,resp); + return; }else{ ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); unsupported_method(server_transaction,req); From b4cda536530f49eab71c45badc6af4941b07c039 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 5 May 2014 12:11:09 +0200 Subject: [PATCH 71/83] relax time in test suite --- tester/flexisip_tester.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 1a75cdd97..e295b61eb 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -352,11 +352,11 @@ static void call_forking_declined(bool_t declined_globaly){ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallStreamsRunning,1,2000)); liblinphone_tester_check_rtcp(pauline,marie2); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallEnd,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,3000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallEnd,1,3000)); linphone_core_terminate_call(marie2->lc,linphone_core_get_current_call(marie2->lc)); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,3000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,3000)); } linphone_core_manager_destroy(pauline); From ad32d0f58c6ac895eed0938fccb76e3fbe49ffb4 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 5 May 2014 12:58:06 +0200 Subject: [PATCH 72/83] remove check for android, not true for opus --- coreapi/linphonecore.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index edd8a0c47..2b860816f 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1189,13 +1189,6 @@ const char * linphone_core_get_version(void){ static void linphone_core_assign_payload_type(LinphoneCore *lc, PayloadType *const_pt, int number, const char *recv_fmtp){ PayloadType *pt; -#ifdef ANDROID - if (const_pt->channels==2){ - ms_message("Stereo %s codec not supported on this platform.",const_pt->mime_type); - return; - } -#endif - pt=payload_type_clone(const_pt); if (number==-1){ /*look for a free number */ From c8cdbdd5436dcecdf585abb344432b09d787389a Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 7 May 2014 12:04:53 +0200 Subject: [PATCH 73/83] allow setting explicit bitrate for video codecs --- coreapi/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/misc.c b/coreapi/misc.c index e3fef7c59..56383fa58 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -110,7 +110,7 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate){ if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){ - if (pt->flags & PAYLOAD_TYPE_IS_VBR){ + if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){ pt->normal_bitrate=bitrate*1000; pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE; }else{ From 610f31c95f0cf3475d218a5819d9049cfcf9b9bb Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 7 May 2014 12:06:32 +0200 Subject: [PATCH 74/83] add java bindings for new payload type related API --- coreapi/linphonecore_jni.cc | 16 ++++++++++++++++ java/common/org/linphone/core/LinphoneCore.java | 14 ++++++++++++++ .../impl/org/linphone/core/LinphoneCoreImpl.java | 10 ++++++++++ 3 files changed, 40 insertions(+) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index bb94573f5..4124f3092 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -1240,6 +1240,22 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isPayloadTypeEnabled ,jlong pt) { return (jboolean) linphone_core_payload_type_enabled((LinphoneCore*)lc, (PayloadType*)pt); } + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPayloadTypeBitrate(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jlong pt + ,jint bitrate) { + linphone_core_set_payload_type_bitrate((LinphoneCore*)lc,(PayloadType*)pt,bitrate); +} + +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getPayloadTypeBitrate(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jlong pt) { + return (jint)linphone_core_get_payload_type_bitrate((LinphoneCore*)lc,(PayloadType*)pt); +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableEchoCancellation(JNIEnv* env ,jobject thiz ,jlong lc diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index 3d22e10ba..332a85be0 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -693,6 +693,20 @@ public interface LinphoneCore { */ boolean isPayloadTypeEnabled(PayloadType pt); + /** + * Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s. + * @param pt the payload type + * @param bitrate target IP bitrate in kbit/s + */ + void setPayloadTypeBitrate(PayloadType pt, int bitrate); + + /** + * Get target bitrate previously set by setPayloadTypeBitrate(). + * @param pt + * @return IP bitrate in kbit/s + */ + int getPayloadTypeBitrate(PayloadType pt); + /** * Enables or disable echo cancellation. * @param enable diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 66597ca81..8cd5fe79e 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -1188,5 +1188,15 @@ class LinphoneCoreImpl implements LinphoneCore { public void stopRinging() { stopRinging(nativePtr); } + private native void setPayloadTypeBitrate(long coreptr, long payload_ptr, int bitrate); + @Override + public void setPayloadTypeBitrate(PayloadType pt, int bitrate) { + setPayloadTypeBitrate(nativePtr, ((PayloadTypeImpl)pt).nativePtr, bitrate); + } + private native int getPayloadTypeBitrate(long coreptr, long payload_ptr); + @Override + public int getPayloadTypeBitrate(PayloadType pt) { + return getPayloadTypeBitrate(nativePtr, ((PayloadTypeImpl)pt).nativePtr); + } } From 77ff00acbc834fb365cc32af1c4a08a602ca671d Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 7 May 2014 21:41:56 +0200 Subject: [PATCH 75/83] improve network state monitor so that it can take into account IP address changes. --- coreapi/linphonecore.c | 21 +++++++++++++++------ coreapi/private.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 2b860816f..cd1534723 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2089,23 +2089,32 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ - char result[LINPHONE_IPADDR_SIZE]; bool_t new_status=lc->network_last_status; + char newip[LINPHONE_IPADDR_SIZE]; /* only do the network up checking every five seconds */ if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){ - linphone_core_get_local_ip(lc,AF_UNSPEC,result); - if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){ + linphone_core_get_local_ip(lc,AF_UNSPEC,newip); + if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){ new_status=TRUE; - }else new_status=FALSE; - lc->network_last_check=curtime; + }else new_status=FALSE; /*no network*/ + + if (new_status==lc->network_last_status && new_status==TRUE && strcmp(newip,lc->localip)!=0){ + /*IP address change detected*/ + ms_message("IP address change detected."); + set_network_reachable(lc,FALSE,curtime); + lc->network_last_status=FALSE; + } + strncpy(lc->localip,newip,sizeof(lc->localip)); + if (new_status!=lc->network_last_status) { if (new_status){ - ms_message("New local ip address is %s",result); + ms_message("New local ip address is %s",lc->localip); } set_network_reachable(lc,new_status, curtime); lc->network_last_status=new_status; } + lc->network_last_check=curtime; } } diff --git a/coreapi/private.h b/coreapi/private.h index 3553ca353..e8294620b 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -682,6 +682,7 @@ struct _LinphoneCore bool_t network_last_status; bool_t ringstream_autorelease; bool_t pad[2]; + char localip[LINPHONE_IPADDR_SIZE]; int device_rotation; int max_calls; LinphoneTunnel *tunnel; From 77e0fede43424ea526329f20f1cf24595f0af04a Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Fri, 9 May 2014 12:48:51 +0200 Subject: [PATCH 76/83] use C comment style '/* ... */' instead of C++ '// ...' one --- coreapi/quality_reporting.c | 108 ++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index df19240d8..7da31f3d1 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -31,12 +31,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*************************************************************************** * TODO / REMINDER LIST ****************************************************************************/ - // to discuss - // For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). - // moslq == moscq - // video: what happens if doing stop/resume? - // one time value: average? worst value? - // rlq value: need algo to compute it +/*For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000). +moslq == moscq +video: what happens if doing stop/resume? +one time value: average? worst value? +rlq value: need algo to compute it*/ /*************************************************************************** * END OF TODO / REMINDER LIST ****************************************************************************/ @@ -47,8 +46,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. dest = src; \ } -// since printf family functions are LOCALE dependent, float separator may differ -// depending on the user's locale (LC_NUMERIC env var). +/*since printf family functions are LOCALE dependent, float separator may differ +depending on the user's locale (LC_NUMERIC environment var).*/ static char * float_to_one_decimal_string(float f) { float rounded_f = floorf(f * 10 + .5f) / 10; @@ -71,17 +70,17 @@ static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offs ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, args); #endif - // if we are out of memory, we add some size to buffer + /*if we are out of memory, we add some size to buffer*/ if (ret == BELLE_SIP_BUFFER_OVERFLOW) { - // some compilers complain that size_t cannot be formatted as unsigned long, hence forcing cast + /*some compilers complain that size_t cannot be formatted as unsigned long, hence forcing cast*/ ms_warning("Buffer was too small to contain the whole report - doubling its size from %lu to %lu", (unsigned long)*buff_size, (unsigned long)2 * *buff_size); *buff_size += 2048; *buff = (char *) ms_realloc(*buff, *buff_size); *offset = prevoffset; - // recall myself since we did not write all things into the buffer but - // only a part of it + /*recall myself since we did not write all things into the buffer but + only a part of it*/ append_to_buffer_valist(buff, buff_size, offset, fmt, args); } } @@ -105,12 +104,12 @@ static bool_t are_metrics_filled(const reporting_content_metrics_t rm) { IF_NUM_IN_RANGE(rm.quality_estimates.moslq, 1, 5, return TRUE); IF_NUM_IN_RANGE(rm.quality_estimates.moscq, 1, 5, return TRUE); - // since these are same values than local ones, do not check them - // if (rm.session_description.payload_type != -1) return TRUE; - // if (rm.session_description.payload_desc != NULL) return TRUE; - // if (rm.session_description.sample_rate != -1) return TRUE; + /*since these are same values than local ones, do not check them*/ + /*if (rm.session_description.payload_type != -1) return TRUE;*/ + /*if (rm.session_description.payload_desc != NULL) return TRUE;*/ + /*if (rm.session_description.sample_rate != -1) return TRUE;*/ if (rm.session_description.frame_duration != -1) return TRUE; - // if (rm.session_description.fmtp != NULL) return TRUE; + /*if (rm.session_description.fmtp != NULL) return TRUE;*/ if (rm.session_description.packet_loss_concealment != -1) return TRUE; IF_NUM_IN_RANGE(rm.jitter_buffer.adaptive, 0, 3, return TRUE); @@ -138,7 +137,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off char * timestamps_stop_str = NULL; char * network_packet_loss_rate_str = NULL; char * jitter_buffer_discard_rate_str = NULL; - // char * gap_loss_density_str = NULL; + /*char * gap_loss_density_str = NULL;*/ char * moslq_str = NULL; char * moscq_str = NULL; @@ -149,7 +148,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off IF_NUM_IN_RANGE(rm.packet_loss.network_packet_loss_rate, 0, 255, network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate / 256)); IF_NUM_IN_RANGE(rm.packet_loss.jitter_buffer_discard_rate, 0, 255, jitter_buffer_discard_rate_str = float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate / 256)); - // IF_NUM_IN_RANGE(rm.burst_gap_loss.gap_loss_density, 0, 10, gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density)); + /*IF_NUM_IN_RANGE(rm.burst_gap_loss.gap_loss_density, 0, 10, gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density));*/ IF_NUM_IN_RANGE(rm.quality_estimates.moslq, 1, 5, moslq_str = float_to_one_decimal_string(rm.quality_estimates.moslq)); IF_NUM_IN_RANGE(rm.quality_estimates.moscq, 1, 5, moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq)); @@ -162,16 +161,16 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off APPEND_IF_NOT_NULL_STR(buffer, size, offset, " PD=%s", rm.session_description.payload_desc); APPEND_IF(buffer, size, offset, " SR=%d", rm.session_description.sample_rate, rm.session_description.sample_rate != -1); APPEND_IF(buffer, size, offset, " FD=%d", rm.session_description.frame_duration, rm.session_description.frame_duration != -1); - // append_to_buffer(buffer, size, offset, " FO=%d", rm.session_description.frame_ocets); - // append_to_buffer(buffer, size, offset, " FPP=%d", rm.session_description.frames_per_sec); - // append_to_buffer(buffer, size, offset, " PPS=%d", rm.session_description.packets_per_sec); + /*append_to_buffer(buffer, size, offset, " FO=%d", rm.session_description.frame_ocets);*/ + /*append_to_buffer(buffer, size, offset, " FPP=%d", rm.session_description.frames_per_sec);*/ + /*append_to_buffer(buffer, size, offset, " PPS=%d", rm.session_description.packets_per_sec);*/ APPEND_IF_NOT_NULL_STR(buffer, size, offset, " FMTP=\"%s\"", rm.session_description.fmtp); APPEND_IF(buffer, size, offset, " PLC=%d", rm.session_description.packet_loss_concealment, rm.session_description.packet_loss_concealment != -1); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " SSUP=%s", rm.session_description.silence_suppression_state); + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " SSUP=%s", rm.session_description.silence_suppression_state);*/ append_to_buffer(buffer, size, offset, "\r\nJitterBuffer:"); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBA=%d", rm.jitter_buffer.adaptive, 0, 3); - // APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15); + /*APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15);*/ APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max, 0, 65535); @@ -180,17 +179,17 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off APPEND_IF_NOT_NULL_STR(buffer, size, offset, " NLR=%s", network_packet_loss_rate_str); APPEND_IF_NOT_NULL_STR(buffer, size, offset, " JDR=%s", jitter_buffer_discard_rate_str); - // append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:"); - // append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density); - // append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " GLD=%s", gap_loss_density_str); - // append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_duration); - // append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold); + /*append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:");*/ + /* append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density);*/ + /* append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration);*/ + /* APPEND_IF_NOT_NULL_STR(buffer, size, offset, " GLD=%s", gap_loss_density_str);*/ + /* append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_duration);*/ + /* append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold);*/ append_to_buffer(buffer, size, offset, "\r\nDelay:"); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " ESD=%d", rm.delay.end_system_delay, 0, 65535); - // APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " OWD=%d", rm.delay.one_way_delay, 0, 65535); + /*APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " OWD=%d", rm.delay.one_way_delay, 0, 65535);*/ APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " SOWD=%d", rm.delay.symm_one_way_delay, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " IAJ=%d", rm.delay.interarrival_jitter, 0, 65535); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " MAJ=%d", rm.delay.mean_abs_jitter, 0, 65535); @@ -198,29 +197,29 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off append_to_buffer(buffer, size, offset, "\r\nSignal:"); APPEND_IF(buffer, size, offset, " SL=%d", rm.signal.level, rm.signal.level != 127); APPEND_IF(buffer, size, offset, " NL=%d", rm.signal.noise_level, rm.signal.noise_level != 127); - // append_to_buffer(buffer, size, offset, " RERL=%d", rm.signal.residual_echo_return_loss); + /*append_to_buffer(buffer, size, offset, " RERL=%d", rm.signal.residual_echo_return_loss);*/ append_to_buffer(buffer, size, offset, "\r\nQualityEst:"); APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RLQ=%d", rm.quality_estimates.rlq, 1, 120); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RLQEstAlg=%s", rm.quality_estimates.rlqestalg); + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RLQEstAlg=%s", rm.quality_estimates.rlqestalg);*/ APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RCQ=%d", rm.quality_estimates.rcq, 1, 120); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RCQEstAlgo=%s", rm.quality_estimates.rcqestalg); - // append_to_buffer(buffer, size, offset, " EXTRI=%d", rm.quality_estimates.extri); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtRIEstAlg=%s", rm.quality_estimates.extriestalg); - // append_to_buffer(buffer, size, offset, " EXTRO=%d", rm.quality_estimates.extro); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtROEstAlg=%s", rm.quality_estimates.extroutestalg); + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RCQEstAlgo=%s", rm.quality_estimates.rcqestalg);*/ + /*append_to_buffer(buffer, size, offset, " EXTRI=%d", rm.quality_estimates.extri);*/ + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtRIEstAlg=%s", rm.quality_estimates.extriestalg);*/ + /*append_to_buffer(buffer, size, offset, " EXTRO=%d", rm.quality_estimates.extro);*/ + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtROEstAlg=%s", rm.quality_estimates.extroutestalg);*/ APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQ=%s", moslq_str); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQEstAlgo=%s", rm.quality_estimates.moslqestalg); + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQEstAlgo=%s", rm.quality_estimates.moslqestalg);*/ APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQ=%s", moscq_str); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQEstAlgo=%s", rm.quality_estimates.moscqestalg); - // APPEND_IF_NOT_NULL_STR(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg); + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQEstAlgo=%s", rm.quality_estimates.moscqestalg);*/ + /*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg);*/ append_to_buffer(buffer, size, offset, "\r\n"); ms_free(timestamps_start_str); ms_free(timestamps_stop_str); ms_free(network_packet_loss_rate_str); ms_free(jitter_buffer_discard_rate_str); - // ms_free(gap_loss_density_str); + /*ms_free(gap_loss_density_str);*/ ms_free(moslq_str); ms_free(moscq_str); } @@ -233,8 +232,8 @@ static void reporting_publish(const LinphoneCall* call, const reporting_session_ size_t size = 2048; char * buffer; - // if the call was hungup too early, we might have invalid IPs information - // in that case, we abort the report since it's not useful data + /*if the call was hung up too early, we might have invalid IPs information + in that case, we abort the report since it's not useful data*/ if (report->info.local_addr.ip == NULL || strlen(report->info.local_addr.ip) == 0 || report->info.remote_addr.ip == NULL || strlen(report->info.remote_addr.ip) == 0) { ms_warning("The call was hang up too early (duration: %d sec) and IP could " @@ -305,17 +304,17 @@ static void reporting_update_ip(LinphoneCall * call, int stats_type) { const SalStreamDescription * local_desc = get_media_stream_for_desc(call->localdesc, sal_stream_type); const SalStreamDescription * remote_desc = get_media_stream_for_desc(sal_call_get_remote_media_description(call->op), sal_stream_type); - // local info are always up-to-date and correct + /*local info are always up-to-date and correct*/ if (local_desc != NULL) { call->log->reports[stats_type]->info.local_addr.port = local_desc->rtp_port; STR_REASSIGN(call->log->reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr)); } if (remote_desc != NULL) { - // port is always stored in stream description struct + /*port is always stored in stream description struct*/ call->log->reports[stats_type]->info.remote_addr.port = remote_desc->rtp_port; - // for IP it can be not set if we are using a direct route + /*for IP it can be not set if we are using a direct route*/ if (remote_desc->rtp_addr != NULL && strlen(remote_desc->rtp_addr) > 0) { STR_REASSIGN(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr)); } else { @@ -330,10 +329,9 @@ static bool_t reporting_enabled(const LinphoneCall * call) { } void linphone_reporting_update_ip(LinphoneCall * call) { - // This function can be called in two different cases: - // - 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered - // - 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access - + /*This function can be called in two different cases: + - 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered + - 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access*/ if (! reporting_enabled(call)) return; @@ -375,11 +373,11 @@ void linphone_reporting_update(LinphoneCall * call, int stats_type) { report->local_metrics.timestamps.start = call->log->start_date_time; report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); - //we use same timestamps for remote too + /*we use same timestamps for remote too*/ report->remote_metrics.timestamps.start = call->log->start_date_time; report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); - // yet we use the same payload config for local and remote, since this is the largest use case + /*yet we use the same payload config for local and remote, since this is the largest use case*/ if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { stream = &call->audiostream->ms; local_payload = linphone_call_params_get_used_audio_codec(current_params); @@ -490,14 +488,14 @@ reporting_session_report_t * linphone_reporting_new() { metrics[i]->session_description.packet_loss_concealment = -1; metrics[i]->jitter_buffer.adaptive = -1; - // metrics[i]->jitter_buffer.rate = -1; + /*metrics[i]->jitter_buffer.rate = -1;*/ metrics[i]->jitter_buffer.nominal = -1; metrics[i]->jitter_buffer.max = -1; metrics[i]->jitter_buffer.abs_max = -1; metrics[i]->delay.round_trip_delay = -1; metrics[i]->delay.end_system_delay = -1; - // metrics[i]->delay.one_way_delay = -1; + /*metrics[i]->delay.one_way_delay = -1;*/ metrics[i]->delay.symm_one_way_delay = -1; metrics[i]->delay.interarrival_jitter = -1; metrics[i]->delay.mean_abs_jitter = -1; From a63a3f59cde3910e41a2cb2c10ba0cbb16c7c7a9 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 9 May 2014 15:19:50 +0200 Subject: [PATCH 77/83] avoid sending dummy route headers as much as possible --- coreapi/bellesip_sal/sal_op_impl.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 1b90487e0..a364ce324 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -123,10 +123,23 @@ belle_sip_header_t * sal_make_supported_header(Sal *sal){ } static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){ - for (;list!=NULL;list=list->next){ - SalAddress *addr=(SalAddress*)list->data; - belle_sip_header_route_t *route=belle_sip_header_route_create((belle_sip_header_address_t*)addr); - belle_sip_uri_t *uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route); + const MSList *elem; + for (elem=list;elem!=NULL;elem=elem->next){ + SalAddress *addr=(SalAddress*)elem->data; + belle_sip_header_route_t *route; + belle_sip_uri_t *uri; + /*Optimization: if the initial route set only contains one URI which is the same as the request URI, ommit it*/ + if (elem==list && list->next==NULL){ + belle_sip_uri_t *requri=belle_sip_request_get_uri(request); + /*skip the first route it is the same as the request uri*/ + if (strcmp(sal_address_get_domain(addr),belle_sip_uri_get_host(requri))==0 ){ + ms_message("Skipping top route of initial route-set because same as request-uri."); + continue; + } + } + + route=belle_sip_header_route_create((belle_sip_header_address_t*)addr); + uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route); belle_sip_uri_set_lr_param(uri,1); belle_sip_message_add_header((belle_sip_message_t*)request,(belle_sip_header_t*)route); } From 24a208100a173d1b769e830c26f89bd7d2d7df8e Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 12 May 2014 12:41:32 +0200 Subject: [PATCH 78/83] * notify friend status to offline when network goes unreachable * relax timeouts of tests again * always install linphone_tunnel.h --- coreapi/Makefile.am | 10 +++------- coreapi/friend.c | 8 ++++++++ tester/call_tester.c | 2 +- tester/flexisip_tester.c | 8 ++++---- tester/tester.c | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 0beea01a4..e2db1d2c1 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -18,11 +18,7 @@ CLEANFILES=$(GITVERSION_FILE) ## Process this file with automake to produce Makefile.in linphone_includedir=$(includedir)/linphone -linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h - -if BUILD_TUNNEL -linphone_include_HEADERS+=linphone_tunnel.h -endif +linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h lib_LTLIBRARIES=liblinphone.la @@ -82,9 +78,9 @@ endif liblinphone_la_SOURCES+=linphone_tunnel_config.c if BUILD_TUNNEL -liblinphone_la_SOURCES+=linphone_tunnel.cc TunnelManager.cc TunnelManager.hh +liblinphone_la_SOURCES+=linphone_tunnel.cc TunnelManager.cc TunnelManager.hh linphone_tunnel.h else -liblinphone_la_SOURCES+=linphone_tunnel_stubs.c +liblinphone_la_SOURCES+=linphone_tunnel_stubs.c linphone_tunnel.h endif diff --git a/coreapi/friend.c b/coreapi/friend.c index a287b7e90..7b0ddd816 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -244,9 +244,17 @@ static void linphone_friend_unsubscribe(LinphoneFriend *lf){ static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ if (lf->outsub!=NULL) { + LinphoneCore *lc=lf->lc; sal_op_release(lf->outsub); lf->outsub=NULL; lf->subscribe_active=FALSE; + /*notify application that we no longer know the presence activity */ + if (lf->presence != NULL) { + linphone_presence_model_unref(lf->presence); + } + lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity"); + if (lc->vtable.notify_presence_received) + lc->vtable.notify_presence_received(lc,lf); } lf->initial_subscribes_sent=FALSE; } diff --git a/tester/call_tester.c b/tester/call_tester.c index 1fd301fb4..fb9571205 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1347,7 +1347,7 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e 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)); } else { - ms_warning ("not tested because srtp not available"); + ms_warning ("not tested because %s not available", linphone_media_encryption_to_string(mode)); } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index e295b61eb..89c2dfe4b 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -569,8 +569,8 @@ static void early_media_call_forking(void) { linphone_call_params_destroy(params); CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingEarlyMedia,1,3000)); - CU_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingEarlyMedia,1,1000)); - CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingEarlyMedia,1,3000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,3000)); pauline_call=linphone_core_get_current_call(pauline->lc); marie1_call=linphone_core_get_current_call(marie1->lc); @@ -583,8 +583,8 @@ static void early_media_call_forking(void) { CU_ASSERT_TRUE(linphone_call_get_audio_stats(marie2_call)->download_bandwidth>70); linphone_core_accept_call(marie1->lc,linphone_core_get_current_call(marie1->lc)); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneCallStreamsRunning,1,1000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneCallStreamsRunning,1,3000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,3000)); /*marie2 should get her call terminated*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000)); diff --git a/tester/tester.c b/tester/tester.c index 2d734b074..3623073e4 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -141,7 +141,7 @@ bool_t wait_for_until(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int va } bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value) { - return wait_for_until(lc_1, lc_2,counter,value,3000); + return wait_for_until(lc_1, lc_2,counter,value,10000); } bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) { From fc6472f49faabe8505dd8fb816a70ad4f863a1c3 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 13 May 2014 15:07:47 +0200 Subject: [PATCH 79/83] Update oRTP and ms2 submodules for work on AVPF. --- mediastreamer2 | 2 +- oRTP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediastreamer2 b/mediastreamer2 index cc4c03ad5..4290b6c8f 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit cc4c03ad5e80afc3f0f518618f061e024c6eba64 +Subproject commit 4290b6c8f39855ef7a99e71574567597b9a4d923 diff --git a/oRTP b/oRTP index fb53b3dd2..d7661ae03 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit fb53b3dd2bcc5e889f7026bdd42b151ef7217249 +Subproject commit d7661ae0350fe4ba4c712cad8a4b2e1bbf1b884c From 0554cc4cee868b3903ee3292cd454d2be0ef0784 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 13 May 2014 15:32:46 +0200 Subject: [PATCH 80/83] Update ms2 submodule. --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index 4290b6c8f..2f942b812 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 4290b6c8f39855ef7a99e71574567597b9a4d923 +Subproject commit 2f942b81247ec49050200e8f631ee87d868edfba From b8c3eed489b9739927af1b418124d02cb5f6ca04 Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Tue, 13 May 2014 16:42:43 +0200 Subject: [PATCH 81/83] Don't return on failure to bind UDP, so that subsequent channels are still available --- coreapi/linphonecore.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index cd1534723..a77d550ae 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1953,7 +1953,6 @@ static int apply_transports(LinphoneCore *lc){ if (tr->udp_port!=0){ if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){ transport_error(lc,"udp",tr->udp_port); - return -1; } } if (tr->tcp_port!=0){ @@ -2098,7 +2097,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){ new_status=TRUE; }else new_status=FALSE; /*no network*/ - + if (new_status==lc->network_last_status && new_status==TRUE && strcmp(newip,lc->localip)!=0){ /*IP address change detected*/ ms_message("IP address change detected."); @@ -2106,7 +2105,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ lc->network_last_status=FALSE; } strncpy(lc->localip,newip,sizeof(lc->localip)); - + if (new_status!=lc->network_last_status) { if (new_status){ ms_message("New local ip address is %s",lc->localip); From 131c00b9ee22f0d171f8db0de13b096f3451c920 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 13 May 2014 16:56:39 +0200 Subject: [PATCH 82/83] Limit the sending of VFU request if a lot of video decoding errors are reported. --- coreapi/linphonecall.c | 5 ++++- mediastreamer2 | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index bb0e8c619..c80810ba4 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1404,7 +1404,10 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u switch (event_id) { case MS_VIDEO_DECODER_DECODING_ERRORS: ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS"); - linphone_call_send_vfu_request(call); + if (call->videostream && (video_stream_is_decoding_error_to_be_reported(call->videostream, 5000) == TRUE)) { + video_stream_decoding_error_reported(call->videostream); + linphone_call_send_vfu_request(call); + } break; case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED: ms_message("First video frame decoded successfully"); diff --git a/mediastreamer2 b/mediastreamer2 index 2f942b812..a090ff068 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 2f942b81247ec49050200e8f631ee87d868edfba +Subproject commit a090ff06894bcb1487b53c39714593aad9d3f77d From 191d6e2f065ec84c5c1c46d83cdd87d59d134e88 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 13 May 2014 18:00:26 +0200 Subject: [PATCH 83/83] Update oRTP and ms2 submodules. --- mediastreamer2 | 2 +- oRTP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediastreamer2 b/mediastreamer2 index a090ff068..d51333b63 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit a090ff06894bcb1487b53c39714593aad9d3f77d +Subproject commit d51333b63b6f61c96bb861ad07e8165321c50f59 diff --git a/oRTP b/oRTP index d7661ae03..c93363ac0 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit d7661ae0350fe4ba4c712cad8a4b2e1bbf1b884c +Subproject commit c93363ac023c2122bfdfb8b0d99b811dffbad827