From 8417c0b18d8f5d6575e3d64a06dce8dc44009fb4 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Mon, 7 Apr 2014 16:50:27 +0200 Subject: [PATCH 01/38] 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 02/38] 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 03/38] 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 04/38] 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 05/38] 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 06/38] 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 07/38] 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 08/38] 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 09/38] 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 10/38] 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 11/38] 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 12/38] 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 13/38] 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 14/38] 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 15/38] 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 16/38] 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 17/38] 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 18/38] 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 19/38] 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 20/38] 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 21/38] 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 22/38] 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 23/38] 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 24/38] 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 0470d0523a20b66a668eddcae1cdac5e574fcbeb Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Fri, 18 Apr 2014 09:13:48 +0200 Subject: [PATCH 25/38] 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 5f9dc1c5d8221ddef8a2f4637053f26ddfeb64c0 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 22 Apr 2014 16:07:00 +0200 Subject: [PATCH 26/38] 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 27/38] 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 28/38] 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 29/38] 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 30/38] 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 31/38] 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 32/38] 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 33/38] 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 34/38] 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 35/38] 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 36/38] 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 37/38] 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 38/38] 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