Quality reporting: add possibility to send interval reports to a given spacing...

Quality reporting: add possibility to send interval reports to a given spacing interval during a call
parent 22e2cb51
......@@ -907,7 +907,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
if (cstate==LinphoneCallEnd){
if (call->log->status == LinphoneCallSuccess)
linphone_reporting_publish_on_call_term(call);
linphone_reporting_publish_session_report(call);
}
if (cstate==LinphoneCallReleased){
......
......@@ -834,16 +834,54 @@ LINPHONE_PUBLIC int linphone_proxy_config_get_publish_expires(const LinphoneProx
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 whether quality statistics during call should be stored and sent to a collector according to RFC 6035.
* @param[in] cfg #LinphoneProxyConfig object
* @param[in] enable True to sotre quality statistics and sent them to the collector, false to disable it.
*/
LINPHONE_PUBLIC void linphone_proxy_config_enable_quality_reporting(LinphoneProxyConfig *cfg, bool_t enable);
/**
* 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
*
* Indicates whether quality statistics during call should be stored and sent to a collector according to RFC 6035.
* @param[in] cfg #LinphoneProxyConfig object
* @return True if quality repotring is enabled, false otherwise.
*/
LINPHONE_PUBLIC void linphone_proxy_config_enable_quality_reporting(LinphoneProxyConfig *cfg, bool_t val);
LINPHONE_PUBLIC bool_t linphone_proxy_config_quality_reporting_enabled(LinphoneProxyConfig *cfg);
/**
* Set the SIP address of the collector end-point when using quality reporting. This SIP address
* should be used on server-side to process packets directly then discard packets. Collector address
* should be a non existing account and should not received any packets.
* @param[in] cfg #LinphoneProxyConfig object
* @param[in] collector SIP address of the collector end-point.
*/
LINPHONE_PUBLIC void linphone_proxy_config_set_quality_reporting_collector(LinphoneProxyConfig *cfg, const char *collector);
LINPHONE_PUBLIC const char *linphone_proxy_config_get_quality_reporting_collector(const LinphoneProxyConfig *obj);
/**
* Get the SIP address of the collector end-point when using quality reporting. This SIP address
* should be used on server-side to process packets directly then discard packets. Collector address
* should be a non existing account and should not received any packets.
* @param[in] cfg #LinphoneProxyConfig object
* @return The SIP address of the collector end-point.
*/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_quality_reporting_collector(const LinphoneProxyConfig *cfg);
/**
* Set the interval between 2 interval reports sending when using quality reporting. If call exceed interval size, an
* interval report will be sent to the collector. On call termination, a session report will be sent
* for the remaining period.
* @param[in] cfg #LinphoneProxyConfig object
* @param[in] interval The interval in seconds.
*/
void linphone_proxy_config_set_quality_reporting_interval(LinphoneProxyConfig *cfg, uint8_t interval);
/**
* Get the interval between interval reports when using quality reporting.
* @param[in] cfg #LinphoneProxyConfig object
* @return The interval in seconds.
*/
int linphone_proxy_config_get_quality_reporting_interval(LinphoneProxyConfig *cfg);
/**
* Get the registration state of the given proxy config.
......
......@@ -437,6 +437,7 @@ struct _LinphoneProxyConfig
bool_t avpf_enabled;
bool_t pad;
uint8_t avpf_rr_interval;
uint8_t quality_reporting_interval;
void* user_data;
time_t deletion_date;
LinphonePrivacyMask privacy;
......
......@@ -108,8 +108,9 @@ 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->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL;
obj->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0;
obj->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL;
obj->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 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->avpf_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", 0) : 0;
......@@ -489,6 +490,14 @@ bool_t linphone_proxy_config_quality_reporting_enabled(LinphoneProxyConfig *cfg)
return cfg->quality_reporting_enabled && cfg->quality_reporting_collector != NULL;
}
void linphone_proxy_config_set_quality_reporting_interval(LinphoneProxyConfig *cfg, uint8_t interval) {
cfg->quality_reporting_interval = interval;
}
int linphone_proxy_config_get_quality_reporting_interval(LinphoneProxyConfig *cfg) {
return cfg->quality_reporting_interval;
}
void linphone_proxy_config_set_quality_reporting_collector(LinphoneProxyConfig *cfg, const char *collector){
if (collector!=NULL && strlen(collector)>0){
LinphoneAddress *addr=linphone_address_new(collector);
......@@ -1174,9 +1183,6 @@ 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->quality_reporting_collector!=NULL){
lp_config_set_string(config,key,"quality_reporting_collector",obj->quality_reporting_collector);
}
if (obj->reg_identity!=NULL){
lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
}
......@@ -1186,13 +1192,17 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC
if (obj->contact_uri_params!=NULL){
lp_config_set_string(config,key,"contact_uri_parameters",obj->contact_uri_params);
}
if (obj->quality_reporting_collector!=NULL){
lp_config_set_string(config,key,"quality_reporting_collector",obj->quality_reporting_collector);
}
lp_config_set_int(config,key,"quality_reporting_enabled",obj->quality_reporting_enabled);
lp_config_set_int(config,key,"quality_reporting_interval",obj->quality_reporting_interval);
lp_config_set_int(config,key,"reg_expires",obj->expires);
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, "avpf", obj->avpf_enabled);
lp_config_set_int(config, key, "avpf_rr_interval", obj->avpf_rr_interval);
lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus);
lp_config_set_int(config,key,"quality_reporting_enabled",obj->quality_reporting_enabled);
lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix);
lp_config_set_int(config,key,"privacy",obj->privacy);
}
......@@ -1224,9 +1234,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);
linphone_proxy_config_enable_quality_reporting(cfg,lp_config_get_int(config,key,"quality_reporting_enabled",0));
tmp=lp_config_get_string(config,key,"quality_reporting_collector",NULL);
if (tmp!=NULL) linphone_proxy_config_set_quality_reporting_collector(cfg,tmp);
linphone_proxy_config_enable_quality_reporting(cfg,lp_config_get_int(config,key,"quality_reporting_enabled",0));
linphone_proxy_config_set_quality_reporting_interval(cfg, lp_config_get_int(config, key, "quality_reporting_interval", 5));
linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL));
......
......@@ -33,8 +33,10 @@ 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).
moslq == moscq
valgrind
video: what happens if doing stop/resume?
rlq value: need algo to compute it
3.4 overload avoidance?
- The Session report when session terminates, media change (codec change or a session fork), session terminates due to no media packets being received
- The Interval report SHOULD be used for periodic or interval reporting
......@@ -282,7 +284,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off
ms_free(moscq_str);
}
static void send_report(const LinphoneCall* call, reporting_session_report_t * report) {
static void send_report(const LinphoneCall* call, reporting_session_report_t * report, const char * report_event) {
LinphoneContent content = {0};
LinphoneAddress *addr;
int expires = -1;
......@@ -295,7 +297,15 @@ static void send_report(const LinphoneCall* call, reporting_session_report_t * r
if (report->info.local_addr.ip == NULL || strlen(report->info.local_addr.ip) == 0
|| report->info.remote_addr.ip == NULL || strlen(report->info.remote_addr.ip) == 0) {
ms_warning("The call was hang up too early (duration: %d sec) and IP could "
"not be retrieved so dropping this report", linphone_call_get_duration(call));
"not be retrieved so dropping this report"
, linphone_call_get_duration(call));
return;
}
/*do not send report if the previous one was sent less than 30seconds ago*/
if (ms_time(NULL) - report->last_report_date < 30){
ms_warning("Already sent a report %ld sec ago. Cancel sending this report"
, ms_time(NULL) - report->last_report_date);
return;
}
......@@ -309,7 +319,7 @@ static void send_report(const LinphoneCall* call, reporting_session_report_t * r
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, "%s\r\n", report_event);
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);
......@@ -339,6 +349,8 @@ static void send_report(const LinphoneCall* call, reporting_session_report_t * r
reset_avg_metrics(report);
linphone_content_uninit(&content);
report->last_report_date = ms_time(NULL);
}
static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDescription * smd, SalStreamType sal_stream_type) {
......@@ -533,20 +545,39 @@ void linphone_reporting_on_rtcp_received(LinphoneCall *call, int stats_type) {
}
}
}
/* check if we should send an interval report */
if (ms_time(NULL) - report->last_report_date > linphone_proxy_config_get_quality_reporting_interval(call->dest_proxy)){
linphone_reporting_publish_interval_report(call);
}
}
void linphone_reporting_publish_session_report(LinphoneCall* call) {
if (! is_reporting_enabled(call))
return;
if (call->log->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) {
send_report(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO], "VQSessionReport: CallTerm");
}
if (call->log->reports[LINPHONE_CALL_STATS_VIDEO] != NULL
&& linphone_call_params_video_enabled(linphone_call_get_current_params(call))) {
send_report(call, call->log->reports[LINPHONE_CALL_STATS_VIDEO], "VQSessionReport: CallTerm");
}
}
void linphone_reporting_publish_on_call_term(LinphoneCall* call) {
void linphone_reporting_publish_interval_report(LinphoneCall* call) {
if (! is_reporting_enabled(call))
return;
if (call->log->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) {
send_report(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO]);
send_report(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO], "VQIntervalReport");
}
if (call->log->reports[LINPHONE_CALL_STATS_VIDEO] != NULL
&& linphone_call_params_video_enabled(linphone_call_get_current_params(call))) {
send_report(call, call->log->reports[LINPHONE_CALL_STATS_VIDEO]);
send_report(call, call->log->reports[LINPHONE_CALL_STATS_VIDEO], "VQIntervalReport");
}
}
......
......@@ -129,6 +129,9 @@ typedef struct reporting_session_report {
reporting_content_metrics_t remote_metrics; // optional
char * dialog_id; // optional
// for internal processing
time_t last_report_date;
} reporting_session_report_t;
reporting_session_report_t * linphone_reporting_new();
......@@ -154,11 +157,19 @@ void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type);
void linphone_reporting_update_ip(LinphoneCall * call);
/**
* Publish the report on the call end.
* Publish a session report. This function should be called when session terminates,
* media change (codec change or session fork), session terminates due to no media packets being received.
* @param call #LinphoneCall object to consider
*
*/
void linphone_reporting_publish_session_report(LinphoneCall* call);
/**
* Publish an interval report. This function should be used for periodic interval
* @param call #LinphoneCall object to consider
*
*/
void linphone_reporting_publish_on_call_term(LinphoneCall* call);
void linphone_reporting_publish_interval_report(LinphoneCall* call);
/**
* Update publish report data with fresh RTCP stats, if needed.
......
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