forked from mirrors/linphone-iphone
implement independant controls for media and sip network reachabilities.
This commit is contained in:
parent
b689c4bc4e
commit
c329b10669
6 changed files with 155 additions and 33 deletions
|
|
@ -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 isReachable, time_t curtime){
|
||||
static void set_sip_network_reachable(LinphoneCore* lc,bool_t is_sip_reachable, time_t curtime){
|
||||
// second get the list of available proxies
|
||||
const MSList *elem=linphone_core_get_proxy_config_list(lc);
|
||||
|
||||
if (lc->network_reachable==isReachable) return; // no change, ignore.
|
||||
if (lc->sip_network_reachable==is_sip_reachable) return; // no change, ignore.
|
||||
lc->network_reachable_to_be_notified=TRUE;
|
||||
ms_message("Network state is now [%s]",isReachable?"UP":"DOWN");
|
||||
ms_message("SIP network reachability state is now [%s]",is_sip_reachable?"UP":"DOWN");
|
||||
for(;elem!=NULL;elem=elem->next){
|
||||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
|
||||
if (linphone_proxy_config_register_enabled(cfg) ) {
|
||||
if (!isReachable) {
|
||||
if (!is_sip_reachable) {
|
||||
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=isReachable;
|
||||
lc->sip_network_reachable=is_sip_reachable;
|
||||
|
||||
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(isReachable && linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) {
|
||||
if(is_sip_reachable && linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) {
|
||||
lc->upnp = linphone_upnp_context_new(lc);
|
||||
}
|
||||
} else {
|
||||
if(!isReachable && linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) {
|
||||
if(!is_sip_reachable && 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue