Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
liblinphone
Commits
e2a35a71
Commit
e2a35a71
authored
Jun 09, 2014
by
Gautier Pelloux-Prayer
Browse files
Quality reporting: send session reports when video is disabled
parent
99594853
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
101 additions
and
43 deletions
+101
-43
coreapi/linphonecall.c
coreapi/linphonecall.c
+2
-8
coreapi/linphonecore.c
coreapi/linphonecore.c
+4
-5
coreapi/private.h
coreapi/private.h
+8
-1
coreapi/quality_reporting.c
coreapi/quality_reporting.c
+70
-22
coreapi/quality_reporting.h
coreapi/quality_reporting.h
+13
-3
tester/call_tester.c
tester/call_tester.c
+4
-4
No files found.
coreapi/linphonecall.c
View file @
e2a35a71
...
...
@@ -819,6 +819,7 @@ static void linphone_call_set_terminated(LinphoneCall *call){
void
linphone_call_fix_call_parameters
(
LinphoneCall
*
call
){
call
->
params
.
has_video
=
call
->
current_params
.
has_video
;
if
(
call
->
params
.
media_encryption
!=
LinphoneMediaEncryptionZRTP
)
/*in case of ZRTP call parameter are handle after zrtp negociation*/
call
->
params
.
media_encryption
=
call
->
current_params
.
media_encryption
;
}
...
...
@@ -906,17 +907,10 @@ 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
==
LinphoneCallEnd
){
if
(
call
->
log
->
status
==
LinphoneCallSuccess
)
linphone_reporting_publish_session_report
(
call
);
}
linphone_reporting_call_state_updated
(
call
);
if
(
cstate
==
LinphoneCallReleased
){
if
(
call
->
op
!=
NULL
)
{
...
...
coreapi/linphonecore.c
View file @
e2a35a71
...
...
@@ -129,8 +129,8 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *fro
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
();
cl
->
reporting
.
reports
[
LINPHONE_CALL_STATS_AUDIO
]
=
linphone_reporting_new
();
cl
->
reporting
.
reports
[
LINPHONE_CALL_STATS_VIDEO
]
=
linphone_reporting_new
();
return
cl
;
}
...
...
@@ -394,8 +394,8 @@ 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
]);
if
(
cl
->
reporting
.
reports
[
LINPHONE_CALL_STATS_AUDIO
]
!=
NULL
)
linphone_reporting_destroy
(
cl
->
reporting
.
reports
[
LINPHONE_CALL_STATS_AUDIO
]);
if
(
cl
->
reporting
.
reports
[
LINPHONE_CALL_STATS_VIDEO
]
!=
NULL
)
linphone_reporting_destroy
(
cl
->
reporting
.
reports
[
LINPHONE_CALL_STATS_VIDEO
]);
ms_free
(
cl
);
}
...
...
@@ -3257,7 +3257,6 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call)
linphone_core_update_streams
(
lc
,
call
,
md
);
linphone_call_fix_call_parameters
(
call
);
}
if
(
call
->
state
!=
LinphoneCallOutgoingEarlyMedia
)
/*don't change the state in case of outgoing early (SIP UPDATE)*/
linphone_call_set_state
(
call
,
LinphoneCallStreamsRunning
,
"Connected (streams running)"
);
return
0
;
...
...
coreapi/private.h
View file @
e2a35a71
...
...
@@ -103,6 +103,11 @@ struct _LinphoneCallParams{
uint8_t
avpf_rr_interval
;
};
struct
_LinphoneQualityReporting
{
reporting_session_report_t
*
reports
[
2
];
/**Store information on audio and video media streams (RFC 6035) */
bool_t
was_video_running
;
/*Keep video state since last check in order to detect its (de)activation*/
};
struct
_LinphoneCallLog
{
struct
_LinphoneCore
*
lc
;
LinphoneCallDir
dir
;
/**< The direction of the call*/
...
...
@@ -119,10 +124,12 @@ 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
];
/**<Quality statistics of the call (rfc6035) */
struct
_LinphoneQualityReporting
reporting
;
bool_t
video_enabled
;
};
typedef
struct
_CallCallbackObj
{
LinphoneCallCbFunc
_func
;
...
...
coreapi/quality_reporting.c
View file @
e2a35a71
...
...
@@ -85,7 +85,7 @@ 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
)
{
/*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 - increasing its size from %lu to %lu"
,
ms_warning
(
"
QualityReporting:
Buffer was too small to contain the whole report - increasing its size from %lu to %lu"
,
(
unsigned
long
)
*
buff_size
,
(
unsigned
long
)
*
buff_size
+
2048
);
*
buff_size
+=
2048
;
*
buff
=
(
char
*
)
ms_realloc
(
*
buff
,
*
buff_size
);
...
...
@@ -187,7 +187,7 @@ static bool_t media_report_enabled(LinphoneCall * call, int stats_type){
if
(
stats_type
==
LINPHONE_CALL_STATS_VIDEO
&&
!
linphone_call_params_video_enabled
(
linphone_call_get_current_params
(
call
)))
return
FALSE
;
return
(
call
->
log
->
reports
[
stats_type
]
!=
NULL
);
return
(
call
->
log
->
reporting
.
reports
[
stats_type
]
!=
NULL
);
}
static
void
append_metrics_to_buffer
(
char
**
buffer
,
size_t
*
size
,
size_t
*
offset
,
const
reporting_content_metrics_t
rm
)
{
...
...
@@ -308,28 +308,30 @@ 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
,
const
char
*
report_event
)
{
static
int
send_report
(
const
LinphoneCall
*
call
,
reporting_session_report_t
*
report
,
const
char
*
report_event
)
{
LinphoneContent
content
=
{
0
};
LinphoneAddress
*
addr
;
int
expires
=
-
1
;
size_t
offset
=
0
;
size_t
size
=
2048
;
char
*
buffer
;
int
ret
=
0
;
/*if the call was hung up too early, we might have invalid IPs information
in that case, we abort the report since it's not useful data*/
if
(
report
->
info
.
local_addr
.
ip
==
NULL
||
strlen
(
report
->
info
.
local_addr
.
ip
)
==
0
||
report
->
info
.
remote_addr
.
ip
==
NULL
||
strlen
(
report
->
info
.
remote_addr
.
ip
)
==
0
)
{
ms_warning
(
"
The call was hang up
too early (duration: %d sec) and IP could "
ms_warning
(
"
QualityReporting: Trying to submit a %s
too early (
call
duration: %d sec) and IP could "
"not be retrieved so dropping this report"
,
report_event
,
linphone_call_get_duration
(
call
));
return
;
return
1
;
}
addr
=
linphone_address_new
(
linphone_proxy_config_get_quality_reporting_collector
(
call
->
dest_proxy
));
if
(
addr
==
NULL
)
{
ms_warning
(
"Asked to submit reporting statistics but no collector address found"
);
return
;
ms_warning
(
"
QualityReporting:
Asked to submit reporting statistics but no collector address found"
);
return
2
;
}
buffer
=
(
char
*
)
ms_malloc
(
size
);
...
...
@@ -362,11 +364,14 @@ static void send_report(const LinphoneCall* call, reporting_session_report_t * r
content
.
size
=
strlen
(
buffer
);
/*(WIP) Memory leak: PUBLISH message is never freed (issue 1283)*/
linphone_core_publish
(
call
->
core
,
addr
,
"vq-rtcpxr"
,
expires
,
&
content
);
if
(
!
linphone_core_publish
(
call
->
core
,
addr
,
"vq-rtcpxr"
,
expires
,
&
content
)){
ret
=
3
;
}
linphone_address_destroy
(
addr
);
reset_avg_metrics
(
report
);
linphone_content_uninit
(
&
content
);
return
ret
;
}
static
const
SalStreamDescription
*
get_media_stream_for_desc
(
const
SalMediaDescription
*
smd
,
SalStreamType
sal_stream_type
)
{
...
...
@@ -379,7 +384,7 @@ static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDesc
}
}
ms_warning
(
"Could not find the associated stream of type %d"
,
sal_stream_type
);
ms_warning
(
"
QualityReporting:
Could not find the associated stream of type %d"
,
sal_stream_type
);
return
NULL
;
}
...
...
@@ -391,19 +396,19 @@ static void 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
;
STR_REASSIGN
(
call
->
log
->
reports
[
stats_type
]
->
info
.
local_addr
.
ip
,
ms_strdup
(
local_desc
->
rtp_addr
));
call
->
log
->
reporting
.
reports
[
stats_type
]
->
info
.
local_addr
.
port
=
local_desc
->
rtp_port
;
STR_REASSIGN
(
call
->
log
->
reporting
.
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
;
call
->
log
->
reporting
.
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
)
{
STR_REASSIGN
(
call
->
log
->
reports
[
stats_type
]
->
info
.
remote_addr
.
ip
,
ms_strdup
(
remote_desc
->
rtp_addr
));
STR_REASSIGN
(
call
->
log
->
reporting
.
reports
[
stats_type
]
->
info
.
remote_addr
.
ip
,
ms_strdup
(
remote_desc
->
rtp_addr
));
}
else
{
STR_REASSIGN
(
call
->
log
->
reports
[
stats_type
]
->
info
.
remote_addr
.
ip
,
ms_strdup
(
sal_call_get_remote_media_description
(
call
->
op
)
->
addr
));
STR_REASSIGN
(
call
->
log
->
reporting
.
reports
[
stats_type
]
->
info
.
remote_addr
.
ip
,
ms_strdup
(
sal_call_get_remote_media_description
(
call
->
op
)
->
addr
));
}
}
}
...
...
@@ -432,11 +437,12 @@ void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type) {
const
PayloadType
*
local_payload
=
NULL
;
const
PayloadType
*
remote_payload
=
NULL
;
const
LinphoneCallParams
*
current_params
=
linphone_call_get_current_params
(
call
);
reporting_session_report_t
*
report
=
call
->
log
->
reports
[
stats_type
];
reporting_session_report_t
*
report
=
call
->
log
->
reporting
.
reports
[
stats_type
];
if
(
!
media_report_enabled
(
call
,
stats_type
))
return
;
STR_REASSIGN
(
report
->
info
.
call_id
,
ms_strdup
(
call
->
log
->
call_id
));
STR_REASSIGN
(
report
->
info
.
local_group
,
ms_strdup_printf
(
"linphone-%s-%s-%s"
,
(
stats_type
==
LINPHONE_CALL_STATS_AUDIO
?
"audio"
:
"video"
),
linphone_core_get_user_agent_name
(),
report
->
info
.
call_id
));
...
...
@@ -496,7 +502,7 @@ void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type) {
}
void
linphone_reporting_on_rtcp_received
(
LinphoneCall
*
call
,
int
stats_type
)
{
reporting_session_report_t
*
report
=
call
->
log
->
reports
[
stats_type
];
reporting_session_report_t
*
report
=
call
->
log
->
reporting
.
reports
[
stats_type
];
reporting_content_metrics_t
*
metrics
=
NULL
;
MSQosAnalyzer
*
analyzer
=
NULL
;
LinphoneCallStats
stats
=
call
->
stats
[
stats_type
];
...
...
@@ -554,21 +560,31 @@ void linphone_reporting_on_rtcp_received(LinphoneCall *call, int stats_type) {
}
}
static
void
publish_report
(
LinphoneCall
*
call
,
const
char
*
event_type
){
static
int
publish_report
(
LinphoneCall
*
call
,
const
char
*
event_type
){
int
ret
=
0
;
int
i
;
for
(
i
=
0
;
i
<
2
;
i
++
){
if
(
media_report_enabled
(
call
,
i
)){
int
sndret
;
linphone_reporting_update_media_info
(
call
,
i
);
send_report
(
call
,
call
->
log
->
reports
[
i
],
event_type
);
sndret
=
send_report
(
call
,
call
->
log
->
reporting
.
reports
[
i
],
event_type
);
if
(
sndret
>
0
){
ret
+=
10
+
(
i
+
1
)
*
sndret
;
}
}
else
{
ret
+=
i
+
1
;
}
}
return
ret
;
}
void
linphone_reporting_publish_session_report
(
LinphoneCall
*
call
)
{
publish_report
(
call
,
"VQSessionReport: CallTerm"
);
int
linphone_reporting_publish_session_report
(
LinphoneCall
*
call
,
bool_t
call_term
)
{
char
*
session_type
=
call_term
?
"VQSessionReport: CallTerm"
:
"VQSessionReport"
;
return
publish_report
(
call
,
session_type
);
}
void
linphone_reporting_publish_interval_report
(
LinphoneCall
*
call
)
{
publish_report
(
call
,
"VQIntervalReport"
);
int
linphone_reporting_publish_interval_report
(
LinphoneCall
*
call
)
{
return
publish_report
(
call
,
"VQIntervalReport"
);
}
reporting_session_report_t
*
linphone_reporting_new
()
{
...
...
@@ -628,3 +644,35 @@ void linphone_reporting_destroy(reporting_session_report_t * report) {
ms_free
(
report
);
}
void
linphone_reporting_call_state_updated
(
LinphoneCall
*
call
){
LinphoneCallState
state
=
linphone_call_get_state
(
call
);
bool_t
enabled
=
media_report_enabled
(
call
,
LINPHONE_CALL_STATS_VIDEO
);
switch
(
state
){
case
LinphoneCallStreamsRunning
:
if
(
enabled
!=
call
->
log
->
reporting
.
was_video_running
){
if
(
enabled
){
linphone_reporting_update_ip
(
call
);
}
else
{
ms_message
(
"Send midterm report with status %d"
,
send_report
(
call
,
call
->
log
->
reporting
.
reports
[
LINPHONE_CALL_STATS_VIDEO
],
"VQSessionReport"
)
);
}
}
else
{
linphone_reporting_update_ip
(
call
);
}
call
->
log
->
reporting
.
was_video_running
=
enabled
;
break
;
case
LinphoneCallEnd
:
if
(
call
->
log
->
status
==
LinphoneCallSuccess
||
call
->
log
->
status
==
LinphoneCallAborted
){
ms_message
(
"Send report with status %d"
,
linphone_reporting_publish_session_report
(
call
,
TRUE
)
);
}
break
;
default:
break
;
}
}
coreapi/quality_reporting.h
View file @
e2a35a71
...
...
@@ -164,25 +164,35 @@ void linphone_reporting_update_ip(LinphoneCall * call);
* 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
* @param call_term whether the call has ended or is continuing
*
* @return error code. 0 for success, positive value otherwise.
*/
void
linphone_reporting_publish_session_report
(
LinphoneCall
*
call
);
int
linphone_reporting_publish_session_report
(
LinphoneCall
*
call
,
bool_t
call_term
);
/**
* Publish an interval report. This function should be used for periodic interval
* @param call #LinphoneCall object to consider
* @return error code. 0 for success, positive value otherwise.
*
*/
void
linphone_reporting_publish_interval_report
(
LinphoneCall
*
call
);
int
linphone_reporting_publish_interval_report
(
LinphoneCall
*
call
);
/**
* Update publish report
data
with
fresh RTCP stats, if needed
.
* Update publish report
s
with
newly received RTCP-XR packets (if available)
.
* @param call #LinphoneCall object to consider
* @param stats_type the media type (LINPHONE_CALL_STATS_AUDIO or LINPHONE_CALL_STATS_VIDEO)
*
*/
void
linphone_reporting_on_rtcp_received
(
LinphoneCall
*
call
,
int
stats_type
);
/**
* Update publish reports on call state change.
* @param call #LinphoneCall object to consider
*
*/
void
linphone_reporting_call_state_updated
(
LinphoneCall
*
call
);
#ifdef __cplusplus
}
#endif
...
...
tester/call_tester.c
View file @
e2a35a71
...
...
@@ -2199,11 +2199,11 @@ static void quality_reporting_not_used_without_config() {
linphone_proxy_config_get_quality_reporting_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
);
CU_ASSERT_PTR_NOT_NULL
(
call_marie
->
log
->
reporting
.
reports
[
0
]
->
info
.
local_addr
.
ip
);
CU_ASSERT_PTR_NULL
(
call_pauline
->
log
->
reporting
.
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
);
CU_ASSERT_PTR_NULL
(
call_marie
->
log
->
reporting
.
reports
[
0
]
->
dialog_id
);
linphone_core_manager_destroy
(
marie
);
linphone_core_manager_destroy
(
pauline
);
...
...
@@ -2247,7 +2247,7 @@ static void quality_reporting_at_call_termination() {
linphone_core_terminate_all_calls
(
marie
->
lc
);
// now dialog id should be filled
CU_ASSERT_PTR_NOT_NULL
(
call_marie
->
log
->
reports
[
0
]
->
dialog_id
);
CU_ASSERT_PTR_NOT_NULL
(
call_marie
->
log
->
reporting
.
reports
[
0
]
->
dialog_id
);
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
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment