Commit 0762b56a authored by Gautier Pelloux-Prayer's avatar Gautier Pelloux-Prayer
Browse files

Quality reporting: let the config file choose if it should enable or not this...

Quality reporting: let the config file choose if it should enable or not this feature (per account choice)
parent 6e385691
......@@ -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.
......
......@@ -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]; /**<Quality statistics of the call (rfc6035) */
bool_t video_enabled;
};
......@@ -405,6 +405,7 @@ struct _LinphoneProxyConfig
char *reg_proxy;
char *reg_identity;
char *reg_route;
char *reg_statistics_collector;
char *realm;
char *contact_params;
char *contact_uri_params;
......@@ -421,6 +422,7 @@ struct _LinphoneProxyConfig
bool_t publish;
bool_t dial_escape_plus;
bool_t send_publish;
bool_t send_statistics;
bool_t pad[3];
void* user_data;
time_t deletion_date;
......
......@@ -46,6 +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 *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));
......
......@@ -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;
content.size = strlen((char*)content.data);
// 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");
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;
}
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);
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]);
}
......
......@@ -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;
......
mediastreamer2 @ b76e3dde
Subproject commit 41db9323be6a6d136949ee5fdba1198c38a7d787
Subproject commit b76e3dde111af0d24be4ac5f1d4f633361e654c1
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment