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
c329b106
Commit
c329b106
authored
Jan 22, 2016
by
Simon Morlat
Browse files
implement independant controls for media and sip network reachabilities.
parent
b689c4bc
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
155 additions
and
33 deletions
+155
-33
coreapi/linphonecore.c
coreapi/linphonecore.c
+59
-19
coreapi/linphonecore.h
coreapi/linphonecore.h
+16
-0
coreapi/private.h
coreapi/private.h
+6
-2
coreapi/proxy.c
coreapi/proxy.c
+2
-6
coreapi/upnp.c
coreapi/upnp.c
+1
-1
tester/call_tester.c
tester/call_tester.c
+71
-5
No files found.
coreapi/linphonecore.c
View file @
c329b106
...
...
@@ -102,6 +102,8 @@ static FILE * liblinphone_log_collection_file = NULL;
static
size_t
liblinphone_log_collection_file_size
=
0
;
static
bool_t
liblinphone_serialize_logs
=
FALSE
;
static
void
set_network_reachable
(
LinphoneCore
*
lc
,
bool_t
isReachable
,
time_t
curtime
);
static
void
set_sip_network_reachable
(
LinphoneCore
*
lc
,
bool_t
isReachable
,
time_t
curtime
);
static
void
set_media_network_reachable
(
LinphoneCore
*
lc
,
bool_t
isReachable
);
static
void
linphone_core_run_hooks
(
LinphoneCore
*
lc
);
#include "enum.h"
...
...
@@ -2556,7 +2558,7 @@ void linphone_core_iterate(LinphoneCore *lc){
if
(
lc
->
network_reachable_to_be_notified
)
{
lc
->
network_reachable_to_be_notified
=
FALSE
;
linphone_core_notify_network_reachable
(
lc
,
lc
->
network_reachable
);
linphone_core_notify_network_reachable
(
lc
,
lc
->
sip_
network_reachable
);
}
if
(
linphone_core_get_global_state
(
lc
)
==
LinphoneGlobalStartup
)
{
if
(
sal_get_root_ca
(
lc
->
sal
))
{
...
...
@@ -2696,7 +2698,7 @@ void linphone_core_iterate(LinphoneCore *lc){
linphone_core_run_hooks
(
lc
);
linphone_core_do_plugin_tasks
(
lc
);
if
(
lc
->
network_reachable
&&
lc
->
netup_time
!=
0
&&
(
current_real_time
-
lc
->
netup_time
)
>
3
){
if
(
lc
->
sip_
network_reachable
&&
lc
->
netup_time
!=
0
&&
(
current_real_time
-
lc
->
netup_time
)
>
3
){
/*not do that immediately, take your time.*/
linphone_core_send_initial_subscribes
(
lc
);
}
...
...
@@ -6166,7 +6168,7 @@ void sip_config_uninit(LinphoneCore *lc)
lp_config_set_int
(
lc
->
config
,
"sip"
,
"register_only_when_network_is_up"
,
config
->
register_only_when_network_is_up
);
lp_config_set_int
(
lc
->
config
,
"sip"
,
"register_only_when_upnp_is_ok"
,
config
->
register_only_when_upnp_is_ok
);
if
(
lc
->
network_reachable
)
{
if
(
lc
->
sip_
network_reachable
)
{
for
(
elem
=
config
->
proxies
;
elem
!=
NULL
;
elem
=
ms_list_next
(
elem
)){
LinphoneProxyConfig
*
cfg
=
(
LinphoneProxyConfig
*
)(
elem
->
data
);
_linphone_proxy_config_unregister
(
cfg
);
/* to unregister without changing the stored flag enable_register */
...
...
@@ -6431,17 +6433,17 @@ static void linphone_core_uninit(LinphoneCore *lc)
ms_list_free_with_data
(
lc
->
vtable_refs
,(
void
(
*
)(
void
*
))
v_table_reference_destroy
);
}
static
void
set_network_reachable
(
LinphoneCore
*
lc
,
bool_t
is
R
eachable
,
time_t
curtime
){
static
void
set_
sip_
network_reachable
(
LinphoneCore
*
lc
,
bool_t
is
_sip_r
eachable
,
time_t
curtime
){
// second get the list of available proxies
const
MSList
*
elem
=
linphone_core_get_proxy_config_list
(
lc
);
if
(
lc
->
network_reachable
==
is
R
eachable
)
return
;
// no change, ignore.
if
(
lc
->
sip_
network_reachable
==
is
_sip_r
eachable
)
return
;
// no change, ignore.
lc
->
network_reachable_to_be_notified
=
TRUE
;
ms_message
(
"
N
etwork state is now [%s]"
,
is
R
eachable
?
"UP"
:
"DOWN"
);
ms_message
(
"
SIP n
etwork
reachability
state is now [%s]"
,
is
_sip_r
eachable
?
"UP"
:
"DOWN"
);
for
(;
elem
!=
NULL
;
elem
=
elem
->
next
){
LinphoneProxyConfig
*
cfg
=
(
LinphoneProxyConfig
*
)
elem
->
data
;
if
(
linphone_proxy_config_register_enabled
(
cfg
)
)
{
if
(
!
is
R
eachable
)
{
if
(
!
is
_sip_r
eachable
)
{
linphone_proxy_config_stop_refreshing
(
cfg
);
linphone_proxy_config_set_state
(
cfg
,
LinphoneRegistrationNone
,
"Registration impossible (network down)"
);
}
else
{
...
...
@@ -6450,26 +6452,23 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu
}
}
lc
->
netup_time
=
curtime
;
lc
->
network_reachable
=
is
R
eachable
;
lc
->
sip_
network_reachable
=
is
_sip_r
eachable
;
if
(
!
lc
->
network_reachable
){
if
(
!
lc
->
sip_
network_reachable
){
linphone_core_invalidate_friend_subscriptions
(
lc
);
sal_reset_transports
(
lc
->
sal
);
/*mark all calls as broken, so that they can be either dropped immediately or restaured when network will be back*/
ms_list_for_each
(
lc
->
calls
,
(
MSIterateFunc
)
linphone_call_set_broken
);
}
else
{
linphone_core_resolve_stun_server
(
lc
);
if
(
lp_config_get_int
(
lc
->
config
,
"net"
,
"recreate_sockets_when_network_is_up"
,
0
)){
ms_list_for_each
(
lc
->
calls
,
(
MSIterateFunc
)
linphone_call_refresh_sockets
);
}
}
#ifdef BUILD_UPNP
if
(
lc
->
upnp
==
NULL
)
{
if
(
is
R
eachable
&&
linphone_core_get_firewall_policy
(
lc
)
==
LinphonePolicyUseUpnp
)
{
if
(
is
_sip_r
eachable
&&
linphone_core_get_firewall_policy
(
lc
)
==
LinphonePolicyUseUpnp
)
{
lc
->
upnp
=
linphone_upnp_context_new
(
lc
);
}
}
else
{
if
(
!
is
R
eachable
&&
linphone_core_get_firewall_policy
(
lc
)
==
LinphonePolicyUseUpnp
)
{
if
(
!
is
_sip_r
eachable
&&
linphone_core_get_firewall_policy
(
lc
)
==
LinphonePolicyUseUpnp
)
{
linphone_upnp_context_destroy
(
lc
->
upnp
);
lc
->
upnp
=
NULL
;
}
...
...
@@ -6477,9 +6476,37 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu
#endif
}
void
linphone_core_repair_calls
(
LinphoneCore
*
lc
){
if
(
lc
->
calls
&&
lp_config_get_int
(
lc
->
config
,
"sip"
,
"repair_broken_calls"
,
1
)
&&
lc
->
media_network_reachable
){
/*if we are registered and there were broken calls due to a past network disconnection, attempt to repair them*/
ms_list_for_each
(
lc
->
calls
,
(
MSIterateFunc
)
linphone_call_repair_if_broken
);
}
}
static
void
set_media_network_reachable
(
LinphoneCore
*
lc
,
bool_t
is_media_reachable
){
if
(
lc
->
media_network_reachable
==
is_media_reachable
)
return
;
// no change, ignore.
ms_message
(
"Media network reachability state is now [%s]"
,
is_media_reachable
?
"UP"
:
"DOWN"
);
lc
->
media_network_reachable
=
is_media_reachable
;
if
(
!
lc
->
media_network_reachable
){
/*mark all calls as broken, so that they can be either dropped immediately or restaured when network will be back*/
ms_list_for_each
(
lc
->
calls
,
(
MSIterateFunc
)
linphone_call_set_broken
);
}
else
{
if
(
lp_config_get_int
(
lc
->
config
,
"net"
,
"recreate_sockets_when_network_is_up"
,
0
)){
ms_list_for_each
(
lc
->
calls
,
(
MSIterateFunc
)
linphone_call_refresh_sockets
);
}
linphone_core_repair_calls
(
lc
);
}
}
static
void
set_network_reachable
(
LinphoneCore
*
lc
,
bool_t
is_network_reachable
,
time_t
curtime
){
set_sip_network_reachable
(
lc
,
is_network_reachable
,
curtime
);
set_media_network_reachable
(
lc
,
is_network_reachable
);
}
void
linphone_core_refresh_registers
(
LinphoneCore
*
lc
)
{
const
MSList
*
elem
;
if
(
!
lc
->
network_reachable
)
{
if
(
!
lc
->
sip_
network_reachable
)
{
ms_warning
(
"Refresh register operation not available (network unreachable)"
);
return
;
}
...
...
@@ -6503,17 +6530,30 @@ void __linphone_core_invalidate_registers(LinphoneCore* lc){
}
}
void
linphone_core_set_network_reachable
(
LinphoneCore
*
lc
,
bool_t
isReachable
)
{
//first disable automatic mode
static
void
disable_internal_network_reachability_detection
(
LinphoneCore
*
lc
){
if
(
lc
->
auto_net_state_mon
)
{
ms_message
(
"Disabling automatic network state monitoring"
);
lc
->
auto_net_state_mon
=
FALSE
;
}
set_network_reachable
(
lc
,
isReachable
,
ms_time
(
NULL
));
}
void
linphone_core_set_network_reachable
(
LinphoneCore
*
lc
,
bool_t
isReachable
)
{
disable_internal_network_reachability_detection
(
lc
);
set_network_reachable
(
lc
,
isReachable
,
ms_time
(
NULL
));
}
void
linphone_core_set_media_network_reachable
(
LinphoneCore
*
lc
,
bool_t
is_reachable
){
disable_internal_network_reachability_detection
(
lc
);
set_media_network_reachable
(
lc
,
is_reachable
);
}
void
linphone_core_set_sip_network_reachable
(
LinphoneCore
*
lc
,
bool_t
is_reachable
){
disable_internal_network_reachability_detection
(
lc
);
set_sip_network_reachable
(
lc
,
is_reachable
,
ms_time
(
NULL
));
}
bool_t
linphone_core_is_network_reachable
(
LinphoneCore
*
lc
)
{
return
lc
->
network_reachable
;
return
lc
->
sip_
network_reachable
;
}
ortp_socket_t
linphone_core_get_sip_socket
(
LinphoneCore
*
lc
){
return
sal_get_socket
(
lc
->
sal
);
...
...
coreapi/linphonecore.h
View file @
c329b106
...
...
@@ -3743,6 +3743,22 @@ LINPHONE_PUBLIC void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t
*/
LINPHONE_PUBLIC
bool_t
linphone_core_is_network_reachable
(
LinphoneCore
*
lc
);
/**
* @ingroup network_parameters
* This method is called by the application to notify the linphone core library when the SIP network is reachable.
* This is for advanced usage, when SIP and RTP layers are required to use different interfaces.
* Most applications just need linphone_core_set_network_reachable().
*/
LINPHONE_PUBLIC
void
linphone_core_set_sip_network_reachable
(
LinphoneCore
*
lc
,
bool_t
value
);
/**
* @ingroup network_parameters
* This method is called by the application to notify the linphone core library when the media (RTP) network is reachable.
* This is for advanced usage, when SIP and RTP layers are required to use different interfaces.
* Most applications just need linphone_core_set_network_reachable().
*/
LINPHONE_PUBLIC
void
linphone_core_set_media_network_reachable
(
LinphoneCore
*
lc
,
bool_t
value
);
/**
* @ingroup network_parameters
* enable signaling keep alive. small udp packet sent periodically to keep udp NAT association
...
...
coreapi/private.h
View file @
c329b106
...
...
@@ -921,13 +921,16 @@ struct _LinphoneCore
bool_t
preview_finished
;
bool_t
auto_net_state_mon
;
bool_t
network_reachable
;
bool_t
sip_network_reachable
;
bool_t
media_network_reachable
;
bool_t
network_reachable_to_be_notified
;
/*set to true when state must be notified in next iterate*/
bool_t
use_preview_window
;
bool_t
network_last_status
;
bool_t
ringstream_autorelease
;
bool_t
vtables_running
;
bool_t
pad
[
3
];
char
localip
[
LINPHONE_IPADDR_SIZE
];
int
device_rotation
;
int
max_calls
;
...
...
@@ -1037,6 +1040,7 @@ void ec_calibrator_destroy(EcCalibrator *ecc);
void
linphone_call_background_tasks
(
LinphoneCall
*
call
,
bool_t
one_second_elapsed
);
void
linphone_call_set_broken
(
LinphoneCall
*
call
);
void
linphone_call_repair_if_broken
(
LinphoneCall
*
call
);
void
linphone_core_repair_calls
(
LinphoneCore
*
lc
);
void
linphone_core_preempt_sound_resources
(
LinphoneCore
*
lc
);
int
_linphone_core_pause_call
(
LinphoneCore
*
lc
,
LinphoneCall
*
call
);
...
...
coreapi/proxy.c
View file @
c329b106
...
...
@@ -1362,7 +1362,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){
}
#endif //BUILD_UPNP
if
(
lc
->
sip_conf
.
register_only_when_network_is_up
){
return
lc
->
network_reachable
;
return
lc
->
sip_
network_reachable
;
}
return
TRUE
;
}
...
...
@@ -1434,13 +1434,9 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat
cfg
->
state
=
state
;
}
if
(
lc
){
linphone_core_notify_registration_state_changed
(
lc
,
cfg
,
state
,
message
);
if
(
lc
->
calls
&&
lp_config_get_int
(
lc
->
config
,
"sip"
,
"repair_broken_calls"
,
1
)){
/*if we are registered and there were broken calls due to a past network disconnection, attempt to repair them*/
ms_list_for_each
(
lc
->
calls
,
(
MSIterateFunc
)
linphone_call_repair_if_broken
);
}
linphone_core_repair_calls
(
lc
);
}
}
else
{
/*state already reported*/
...
...
coreapi/upnp.c
View file @
c329b106
...
...
@@ -367,7 +367,7 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) {
ms_mutex_lock
(
&
lupnp
->
mutex
);
if
(
lupnp
->
lc
->
network_reachable
)
{
if
(
lupnp
->
lc
->
sip_
network_reachable
)
{
/* Send port binding removes */
if
(
lupnp
->
sip_udp
!=
NULL
)
{
linphone_upnp_context_send_remove_port_binding
(
lupnp
,
lupnp
->
sip_udp
,
TRUE
);
...
...
tester/call_tester.c
View file @
c329b106
...
...
@@ -5474,6 +5474,7 @@ static void _call_with_network_switch(bool_t use_ice, bool_t with_socket_refresh
LinphoneCoreManager
*
marie
=
linphone_core_manager_new
(
"marie_rc"
);
LinphoneCoreManager
*
pauline
=
linphone_core_manager_new
(
transport_supported
(
LinphoneTransportTls
)
?
"pauline_rc"
:
"pauline_tcp_rc"
);
MSList
*
lcs
=
NULL
;
int
ice_reinvite
=
use_ice
?
1
:
0
;
bool_t
call_ok
;
lcs
=
ms_list_append
(
lcs
,
marie
->
lc
);
...
...
@@ -5503,9 +5504,10 @@ static void _call_with_network_switch(bool_t use_ice, bool_t with_socket_refresh
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
marie
->
stat
.
number_of_LinphoneRegistrationOk
,
2
));
/*pauline shall receive a reINVITE to update the session*/
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
pauline
->
stat
.
number_of_LinphoneCallUpdatedByRemote
,
1
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
pauline
->
stat
.
number_of_LinphoneCallStreamsRunning
,
2
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
marie
->
stat
.
number_of_LinphoneCallStreamsRunning
,
2
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
marie
->
stat
.
number_of_LinphoneCallUpdating
,
1
+
ice_reinvite
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
pauline
->
stat
.
number_of_LinphoneCallUpdatedByRemote
,
1
+
ice_reinvite
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
pauline
->
stat
.
number_of_LinphoneCallStreamsRunning
,
2
+
ice_reinvite
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
marie
->
stat
.
number_of_LinphoneCallStreamsRunning
,
2
+
ice_reinvite
));
/*check that media is back*/
check_media_direction
(
marie
,
linphone_core_get_current_call
(
marie
->
lc
),
lcs
,
LinphoneMediaDirectionSendRecv
,
LinphoneMediaDirectionInvalid
);
...
...
@@ -5532,6 +5534,69 @@ static void call_with_network_switch_and_socket_refresh(void){
_call_with_network_switch
(
TRUE
,
TRUE
);
}
static
void
call_with_sip_and_rtp_independant_switches
(){
LinphoneCoreManager
*
marie
=
linphone_core_manager_new
(
"marie_rc"
);
LinphoneCoreManager
*
pauline
=
linphone_core_manager_new
(
transport_supported
(
LinphoneTransportTls
)
?
"pauline_rc"
:
"pauline_tcp_rc"
);
MSList
*
lcs
=
NULL
;
bool_t
call_ok
;
bool_t
use_ice
=
TRUE
;
bool_t
with_socket_refresh
=
TRUE
;
lcs
=
ms_list_append
(
lcs
,
marie
->
lc
);
lcs
=
ms_list_append
(
lcs
,
pauline
->
lc
);
if
(
use_ice
){
linphone_core_set_firewall_policy
(
marie
->
lc
,
LinphonePolicyUseIce
);
linphone_core_set_firewall_policy
(
pauline
->
lc
,
LinphonePolicyUseIce
);
}
if
(
with_socket_refresh
){
lp_config_set_int
(
linphone_core_get_config
(
marie
->
lc
),
"net"
,
"recreate_sockets_when_network_is_up"
,
1
);
lp_config_set_int
(
linphone_core_get_config
(
pauline
->
lc
),
"net"
,
"recreate_sockets_when_network_is_up"
,
1
);
}
linphone_core_set_media_network_reachable
(
marie
->
lc
,
TRUE
);
BC_ASSERT_TRUE
((
call_ok
=
call
(
pauline
,
marie
)));
if
(
!
call_ok
)
goto
end
;
wait_for_until
(
marie
->
lc
,
pauline
->
lc
,
NULL
,
0
,
2000
);
if
(
use_ice
)
BC_ASSERT_TRUE
(
check_ice
(
pauline
,
marie
,
LinphoneIceStateHostConnection
));
/*marie looses the SIP network and reconnects*/
linphone_core_set_sip_network_reachable
(
marie
->
lc
,
FALSE
);
wait_for_until
(
marie
->
lc
,
pauline
->
lc
,
NULL
,
0
,
1000
);
/*marie will reconnect and register*/
linphone_core_set_sip_network_reachable
(
marie
->
lc
,
TRUE
);
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
marie
->
stat
.
number_of_LinphoneRegistrationOk
,
2
));
wait_for_until
(
marie
->
lc
,
pauline
->
lc
,
NULL
,
0
,
1000
);
/*at this stage, no reINVITE is expected to be send*/
BC_ASSERT_EQUAL
(
marie
->
stat
.
number_of_LinphoneCallUpdating
,
1
,
int
,
"%i"
);
/*1: because of ICE reinvite*/
/*now we notify the a reconnection of media network*/
linphone_core_set_media_network_reachable
(
marie
->
lc
,
FALSE
);
linphone_core_set_media_network_reachable
(
marie
->
lc
,
TRUE
);
/*pauline shall receive a reINVITE to update the session*/
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
marie
->
stat
.
number_of_LinphoneCallUpdating
,
2
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
pauline
->
stat
.
number_of_LinphoneCallUpdatedByRemote
,
2
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
pauline
->
stat
.
number_of_LinphoneCallStreamsRunning
,
3
));
BC_ASSERT_TRUE
(
wait_for
(
marie
->
lc
,
pauline
->
lc
,
&
marie
->
stat
.
number_of_LinphoneCallStreamsRunning
,
3
));
/*check that media is back*/
check_media_direction
(
marie
,
linphone_core_get_current_call
(
marie
->
lc
),
lcs
,
LinphoneMediaDirectionSendRecv
,
LinphoneMediaDirectionInvalid
);
liblinphone_tester_check_rtcp
(
pauline
,
marie
);
if
(
use_ice
)
BC_ASSERT_TRUE
(
check_ice
(
pauline
,
marie
,
LinphoneIceStateHostConnection
));
/*pauline shall be able to end the call without problem now*/
end_call
(
pauline
,
marie
);
end:
ms_list_free
(
lcs
);
linphone_core_manager_destroy
(
marie
);
linphone_core_manager_destroy
(
pauline
);
}
#ifdef CALL_LOGS_STORAGE_ENABLED
static
void
call_logs_if_no_db_set
(
void
)
{
...
...
@@ -5987,8 +6052,8 @@ test_t call_tests[] = {
{
"Call established with rejected info during re-invite"
,
call_established_with_rejected_info_during_reinvite
},
{
"Call redirected by callee"
,
call_redirect
},
{
"Call with specified codec bitrate"
,
call_with_specified_codec_bitrate
},
{
"Call with no audio codec"
,
call_with_no_audio_codec
},
{
"Video call with no audio and no video codec"
,
video_call_with_no_audio_and_no_video_codec
},
{
"Call with no audio codec"
,
call_with_no_audio_codec
},
{
"Video call with no audio and no video codec"
,
video_call_with_no_audio_and_no_video_codec
},
{
"Call with in-dialog UPDATE request"
,
call_with_in_dialog_update
},
{
"Call with in-dialog codec change"
,
call_with_in_dialog_codec_change
},
{
"Call with in-dialog codec change no sdp"
,
call_with_in_dialog_codec_change_no_sdp
},
...
...
@@ -6025,6 +6090,7 @@ test_t call_tests[] = {
{
"Call with network switch in early state 2"
,
call_with_network_switch_in_early_state_2
},
{
"Call with network switch and ICE"
,
call_with_network_switch_and_ice
},
{
"Call with network switch with socket refresh"
,
call_with_network_switch_and_socket_refresh
},
{
"Call with SIP and RTP independant switches"
,
call_with_sip_and_rtp_independant_switches
},
{
"Call with rtcp-mux"
,
call_with_rtcp_mux
},
{
"Call with rtcp-mux not accepted"
,
call_with_rtcp_mux_not_accepted
},
{
"Call with ICE and rtcp-mux"
,
call_with_ice_and_rtcp_mux
},
...
...
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