mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-02-07 14:18:25 +00:00
Quality reporting: add possibility to send interval reports to a given spacing interval during a call
This commit is contained in:
parent
22e2cb518f
commit
ce7a644616
6 changed files with 114 additions and 22 deletions
|
|
@ -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 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
|
||||
* @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 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_on_call_term(LinphoneCall* 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_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_on_call_term(LinphoneCall* call);
|
||||
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_interval_report(LinphoneCall* call);
|
||||
|
||||
/**
|
||||
* Update publish report data with fresh RTCP stats, if needed.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue