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.
This commit is contained in:
Simon Morlat 2016-03-04 22:57:01 +01:00
parent 3644599159
commit 34a1e616b2
5 changed files with 99 additions and 33 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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)
};