Commit 34a1e616 authored by Simon Morlat's avatar Simon Morlat
Browse files

implement ice mode where the c= line is left to host candidate instead of stun...

implement ice mode where the c= line is left to host candidate instead of stun (this is useful to interoperate with non-ice servers).
also, start to enable the use of ice without stun, though it is not working yet because of internal problems in the ice session.
parent 36445991
......@@ -336,7 +336,7 @@ static void call_received(SalOp *h){
call->bg_task_id=sal_begin_background_task("liblinphone call notification", NULL, NULL);
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
if (call->defer_notify_incoming) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather ICE candidates");
return;
......
......@@ -585,7 +585,7 @@ void linphone_call_increment_local_media_description(LinphoneCall *call){
void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call){
LinphoneCore *lc = call->core;
if (call->ice_session != NULL) {
/*set this to FALSE once flexisip are updated*/
/*set this to FALSE once flexisip are updated everywhere, let's say in December 2016.*/
bool_t use_nortpproxy = lp_config_get_int(lc->config, "sip", "ice_uses_nortpproxy", TRUE);
_update_local_media_description_from_ice(call->localdesc, call->ice_session, use_nortpproxy);
linphone_core_update_ice_state_in_call_stats(call);
......@@ -1091,6 +1091,21 @@ void linphone_call_fill_media_multicast_addr(LinphoneCall *call) {
call->media_ports[call->main_video_stream_index].multicast_ip[0]='\0';
}
static void linphone_call_create_ice_session(LinphoneCall *call, IceRole role){
call->ice_session = ice_session_new();
/*for backward compatibility purposes, shall be enabled by default in futur*/
ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(call->core->config,"net","ice_session_enable_message_integrity_check",1));
if (lp_config_get_int(call->core->config, "net", "dont_default_to_stun_candidates", 0)){
IceCandidateType types[ICT_CandidateTypeMax];
types[0] = ICT_RelayedCandidate;
types[1] = ICT_HostCandidate;
types[2] = ICT_CandidateInvalid;
ice_session_set_default_candidates_types(call->ice_session, types);
}
ice_session_set_role(call->ice_session, role);
}
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
LinphoneCall *call = belle_sip_object_new(LinphoneCall);
......@@ -1106,10 +1121,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
linphone_call_fill_media_multicast_addr(call);
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
call->ice_session = ice_session_new();
/*for backward compatibility purposes, shall be enabled by default in futur*/
ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(lc->config,"net","ice_session_enable_message_integrity_check",1));
ice_session_set_role(call->ice_session, IR_Controlling);
linphone_call_create_ice_session(call, IR_Controlling);
}
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
call->ping_time=linphone_core_run_stun_tests(call->core,call);
......@@ -1338,10 +1350,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
/*create the ice session now if ICE is required*/
if (fpol==LinphonePolicyUseIce){
if (md){
call->ice_session = ice_session_new();
/*for backward compatibility purposes, shall be enabled by default in futur*/
ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(lc->config,"net","ice_session_enable_message_integrity_check",1));
ice_session_set_role(call->ice_session, IR_Controlled);
linphone_call_create_ice_session(call, IR_Controlled);
}else{
fpol=LinphonePolicyNoFirewall;
ms_warning("ICE not supported for incoming INVITE without SDP.");
......@@ -1352,7 +1361,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
linphone_call_init_media_streams(call);
switch (fpol) {
case LinphonePolicyUseIce:
linphone_call_prepare_ice(call,TRUE);
call->defer_notify_incoming = linphone_call_prepare_ice(call,TRUE) == 1;
break;
case LinphonePolicyUseStun:
call->ping_time=linphone_core_run_stun_tests(call->core,call);
......@@ -2225,6 +2234,7 @@ static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream
int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
SalMediaDescription *remote = NULL;
int err;
bool_t has_video=FALSE;
if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
......@@ -2251,13 +2261,12 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
text_stream_prepare_text(call->textstream);
}
if (linphone_core_gather_ice_candidates(call->core,call)<0) {
if ((err=linphone_core_gather_ice_candidates(call->core,call))<0) {
/* Ice candidates gathering failed, proceed with the call anyway. */
linphone_call_delete_ice_session(call);
linphone_call_stop_media_streams_for_ice_gathering(call);
return -1;
}
return 1;/*gathering in progress, wait*/
return err;/* 1= gathering in progress, wait; 0=proceed*/
}
}
return 0;
......@@ -4282,12 +4291,10 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
linphone_call_params_unref(params);
} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
if (evd->info.ice_processing_successful==TRUE) {
linphone_call_on_ice_gathering_finished(call);
} else {
ms_warning("No STUN answer from [%s], disabling ICE",linphone_core_get_stun_server(call->core));
linphone_call_delete_ice_session(call);
if (! evd->info.ice_processing_successful==TRUE) {
ms_warning("No STUN answer from [%s], continuing without STUN",linphone_core_get_stun_server(call->core));
}
linphone_call_on_ice_gathering_finished(call);
switch (call->state) {
case LinphoneCallUpdating:
linphone_core_start_update_call(call->core, call);
......
......@@ -628,16 +628,15 @@ void linphone_core_enable_forced_ice_relay(LinphoneCore *lc, bool_t enable) {
lc->forced_ice_relay = enable;
}
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
{
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call){
char local_addr[64];
const struct addrinfo *ai;
const struct addrinfo *ai = NULL;
IceCheckList *audio_check_list;
IceCheckList *video_check_list;
IceCheckList *text_check_list;
const char *server = linphone_core_get_stun_server(lc);
if ((server == NULL) || (call->ice_session == NULL)) return -1;
if (call->ice_session == NULL) return -1;
audio_check_list = ice_session_check_list(call->ice_session, call->main_audio_stream_index);
video_check_list = ice_session_check_list(call->ice_session, call->main_video_stream_index);
text_check_list = ice_session_check_list(call->ice_session, call->main_text_stream_index);
......@@ -647,10 +646,13 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
ms_warning("Ice gathering is not implemented for ipv6");
return -1;
}
ai=linphone_core_get_stun_server_addrinfo(lc);
if (ai==NULL){
ms_warning("Fail to resolve STUN server for ICE gathering.");
return -1;
if (server){
ai=linphone_core_get_stun_server_addrinfo(lc);
if (ai==NULL){
ms_warning("Fail to resolve STUN server for ICE gathering, continuing without stun.");
}
}else{
ms_warning("Ice is used without stun server.");
}
linphone_core_notify_display_status(lc, _("ICE local candidates gathering in progress..."));
......@@ -678,10 +680,12 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
ice_add_local_candidate(text_check_list, "host", local_addr, call->media_ports[call->main_text_stream_index].rtcp_port, 2, NULL);
call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateInProgress;
}
ms_message("ICE: gathering candidate from [%s]",server);
/* Gather local srflx candidates. */
ice_session_gather_candidates(call->ice_session, ai->ai_addr, (socklen_t)ai->ai_addrlen);
if (ai){
ms_message("ICE: gathering candidate from [%s]",server);
/* Gather local srflx candidates. */
ice_session_gather_candidates(call->ice_session, ai->ai_addr, (socklen_t)ai->ai_addrlen);
return 1;
}
return 0;
}
......@@ -731,6 +735,10 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
case ICT_RelayedCandidate:
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateRelayConnection;
break;
case ICT_CandidateInvalid:
case ICT_CandidateTypeMax:
/*shall not happen*/
break;
}
} else {
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed;
......@@ -750,6 +758,10 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
case ICT_RelayedCandidate:
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateRelayConnection;
break;
case ICT_CandidateInvalid:
case ICT_CandidateTypeMax:
/*shall not happen*/
break;
}
} else {
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed;
......@@ -769,6 +781,10 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
case ICT_RelayedCandidate:
call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateRelayConnection;
break;
case ICT_CandidateInvalid:
case ICT_CandidateTypeMax:
/*shall not happen*/
break;
}
} else {
call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateFailed;
......
......@@ -340,6 +340,7 @@ struct _LinphoneCall{
char *dtls_certificate_fingerprint; /**> This fingerprint is computed during stream init and is stored in call to be used when making local media description */
char *onhold_file; /*set if a on-hold file is to be played*/
LinphoneChatRoom *chat_room;
LinphoneConference *conf_ref; /**> Point on the associated conference if this call is part of a conference. NULL instead. */
bool_t refer_pending;
bool_t expect_media_in_ack;
bool_t audio_muted;
......@@ -357,8 +358,7 @@ struct _LinphoneCall{
bool_t paused_by_app;
bool_t broken; /*set to TRUE when the call is in broken state due to network disconnection or transport */
LinphoneConference *conf_ref; /**> Point on the associated conference if this call is part of a conference. NULL instead. */
bool_t defer_notify_incoming;
};
BELLE_SIP_DECLARE_VPTR(LinphoneCall);
......
......@@ -6003,6 +6003,47 @@ static void call_with_zrtp_configured_calling_base(LinphoneCoreManager *marie, L
end_call(pauline, marie);
}
/*
* this test checks the 'dont_default_to_stun_candidates' mode, where the c= line is left to host
* ip instead of stun candidate when ice is enabled*/
static void call_with_ice_with_default_candidate_not_stun(void){
LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
char localip[LINPHONE_IPADDR_SIZE];
bool_t call_ok;
lp_config_set_int(marie->lc->config, "net", "dont_default_to_stun_candidates", 1);
linphone_core_set_firewall_policy(marie->lc, LinphonePolicyUseIce);
linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce);
linphone_core_get_local_ip(marie->lc, AF_INET, NULL, localip);
call_ok = call(marie, pauline);
if (call_ok){
check_ice(marie, pauline, LinphoneIceStateHostConnection);
BC_ASSERT_STRING_EQUAL(marie->lc->current_call->localdesc->addr, localip);
BC_ASSERT_STRING_EQUAL(pauline->lc->current_call->resultdesc->addr, localip);
BC_ASSERT_STRING_EQUAL(marie->lc->current_call->localdesc->streams[0].rtp_addr, localip);
BC_ASSERT_STRING_EQUAL(pauline->lc->current_call->resultdesc->streams[0].rtp_addr, "");
}
end_call(marie, pauline);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_with_ice_without_stun(void){
#if GHISLAIN_CAN_MAKE_THIS_TEST_TO_WORK
LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_core_set_stun_server(marie->lc, NULL);
linphone_core_set_stun_server(pauline->lc, NULL);
_call_with_ice_base(marie, pauline, TRUE, TRUE, TRUE, FALSE);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
#endif
}
static void call_with_zrtp_configured_calling_side(void) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
......@@ -6198,6 +6239,8 @@ test_t call_tests[] = {
TEST_NO_TAG("Call with rtcp-mux not accepted", call_with_rtcp_mux_not_accepted),
TEST_ONE_TAG("Call with ICE and rtcp-mux", call_with_ice_and_rtcp_mux, "ICE"),
TEST_ONE_TAG("Call with ICE and rtcp-mux without ICE re-invite", call_with_ice_and_rtcp_mux_without_reinvite, "ICE"),
TEST_ONE_TAG("Call with ICE with default candidate not stun", call_with_ice_with_default_candidate_not_stun, "ICE"),
TEST_ONE_TAG("Call with ICE without stun server", call_with_ice_without_stun, "ICE"),
TEST_NO_TAG("call with ZRTP configured calling side only", call_with_zrtp_configured_calling_side)
};
......
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