diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 98ab0b47d..c0afd17a5 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2532,6 +2532,27 @@ const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) { return stats; } +static bool_t ice_in_progress(LinphoneCallStats *stats){ + return stats->ice_state==LinphoneIceStateInProgress; +} + +/** + * Indicates whether an operation is in progress at the media side. + * It can a bad idea to initiate signaling operations (adding video, pausing the call, removing video, changing video parameters) while + * the media is busy in establishing the connection (typically ICE connectivity checks). It can result in failures generating loss of time + * in future operations in the call. + * Applications are invited to check this function after each call state change to decide whether certain operations are permitted or not. + * @param call the call + * @return TRUE if media is busy in establishing the connection, FALSE otherwise. +**/ +bool_t linphone_call_media_in_progress(LinphoneCall *call){ + bool_t ret=FALSE; + if (ice_in_progress(&call->stats[LINPHONE_CALL_STATS_AUDIO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_VIDEO])) + ret=TRUE; + /*TODO: could check zrtp state, upnp state*/ + return ret; +} + /** * Get the local loss rate since last report * @return The sender loss rate diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index af9f61f0f..0832fc947 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2295,9 +2295,11 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){ if (lc->sip_conf.ipv6_enabled!=val){ lc->sip_conf.ipv6_enabled=val; if (lc->sal){ - /* we need to restart eXosip */ + /* we need to update the sip stack */ apply_transports(lc); } + /*update the localip immediately for the network monitor to avoid to "discover" later that we switched to ipv6*/ + linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,lc->localip); } } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 666872865..0be4be5b0 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -481,7 +481,7 @@ typedef struct _LinphoneVideoPolicy LinphoneVideoPolicy; * @ingroup initializing **/ enum _LinphoneIceState{ - LinphoneIceStateNotActivated, /**< ICE has not been activated for this call */ + LinphoneIceStateNotActivated, /**< ICE has not been activated for this call or stream*/ LinphoneIceStateFailed, /**< ICE processing has failed */ LinphoneIceStateInProgress, /**< ICE process is in progress */ LinphoneIceStateHostConnection, /**< ICE has established a direct connection to the remote host */ @@ -730,6 +730,7 @@ LINPHONE_PUBLIC void linphone_call_zoom_video(LinphoneCall* call, float zoom_fac LINPHONE_PUBLIC void linphone_call_start_recording(LinphoneCall *call); LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call); LINPHONE_PUBLIC LinphonePlayer * linphone_call_get_player(LinphoneCall *call); +LINPHONE_PUBLIC bool_t linphone_call_media_in_progress(LinphoneCall *call); /** * Return TRUE if this call is currently part of a conference diff --git a/coreapi/misc.c b/coreapi/misc.c index 6a9141ea1..f762bb537 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -686,7 +686,7 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call) } else { call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed; } - } + }else call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated; } else if (session_state == IS_Running) { call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; if (call->params->has_video && (video_check_list != NULL)) { diff --git a/gtk/incall_view.c b/gtk/incall_view.c index 5329508b6..4fa0bd66b 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -426,7 +426,9 @@ void linphone_gtk_update_video_button(LinphoneCall *call){ GtkWidget *conf_frame; const LinphoneCallParams *params=linphone_call_get_current_params(call); gboolean has_video=linphone_call_params_video_enabled(params); + gboolean button_sensitive=FALSE; if (call_view==NULL) return; + button=linphone_gtk_get_widget(call_view,"video_button"); gtk_button_set_image(GTK_BUTTON(button), @@ -436,12 +438,20 @@ void linphone_gtk_update_video_button(LinphoneCall *call){ gtk_widget_set_sensitive(button,FALSE); return; } + switch(linphone_call_get_state(call)){ + case LinphoneCallStreamsRunning: + button_sensitive=!linphone_call_media_in_progress(call); + break; + default: + button_sensitive=FALSE; + break; + } + gtk_widget_set_sensitive(button,button_sensitive); if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"signal_connected"))==0){ g_signal_connect(G_OBJECT(button),"clicked",(GCallback)video_button_clicked,call); g_object_set_data(G_OBJECT(button),"signal_connected",GINT_TO_POINTER(1)); } conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); - gtk_widget_set_sensitive(button,linphone_call_get_state(call)==LinphoneCallStreamsRunning); if(conf_frame!=NULL){ gtk_widget_set_sensitive(button,FALSE); } diff --git a/tester/call_tester.c b/tester/call_tester.c index 37b28ddfd..9918e526d 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -336,6 +336,31 @@ static void simple_call(void) { } } +static void direct_call_over_ipv6(){ + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + + if (liblinphone_tester_ipv6_available()){ + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new( "pauline_tcp_rc"); + linphone_core_enable_ipv6(marie->lc,TRUE); + linphone_core_enable_ipv6(pauline->lc,TRUE); + linphone_core_set_default_proxy_config(marie->lc,NULL); + linphone_core_invite(marie->lc,"sip:[::1]:12002;transport=tcp"); + + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallOutgoingRinging,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallIncomingReceived,1)); + linphone_core_accept_call(pauline->lc,linphone_core_get_current_call(pauline->lc)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,1)); + + liblinphone_tester_check_rtcp(marie,pauline); + end_call(marie,pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + }else ms_warning("Test skipped, no ipv6 available"); +} + static void call_outbound_with_multiple_proxy() { LinphoneCoreManager* pauline = linphone_core_manager_new2( "pauline_rc", FALSE); LinphoneCoreManager* marie = linphone_core_manager_new2( "marie_rc", FALSE); @@ -3354,6 +3379,7 @@ test_t call_tests[] = { { "Cancelled ringing call", cancelled_ringing_call }, { "Call failed because of codecs", call_failed_because_of_codecs }, { "Simple call", simple_call }, + { "Direct call over IPv6", direct_call_over_ipv6}, { "Outbound call with multiple proxy possible", call_outbound_with_multiple_proxy }, { "Audio call recording", audio_call_recording_test }, #if 0 /* not yet activated because not implemented */ diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 5d68bc2cf..26f3521ec 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -115,7 +115,23 @@ static void liblinphone_tester_qnx_log_handler(OrtpLogLevel lev, const char *fmt } #endif /* __QNX__ */ - +int liblinphone_tester_ipv6_available(void){ + struct addrinfo *ai=belle_sip_ip_address_to_addrinfo(AF_INET6,"2a01:e00::2",53); + if (ai){ + struct sockaddr_storage ss; + struct addrinfo src; + socklen_t slen=sizeof(ss); + char localip[128]; + int port=0; + belle_sip_get_src_addr_for(ai->ai_addr,ai->ai_addrlen,(struct sockaddr*) &ss,&slen,4444); + src.ai_addr=(struct sockaddr*) &ss; + src.ai_addrlen=slen; + belle_sip_addrinfo_to_ip(&src,localip, sizeof(localip),&port); + freeaddrinfo(ai); + return strcmp(localip,"::1")!=0; + } + return FALSE; +} void helper(const char *name) { liblinphone_tester_fprintf(stderr,"%s --help\n" diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index d8ecb1987..464926707 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -76,6 +76,7 @@ extern void liblinphone_tester_uninit(void); extern int liblinphone_tester_run_tests(const char *suite_name, const char *test_name); extern void liblinphone_tester_set_fileprefix(const char* file_prefix); extern void liblinphone_tester_set_writable_dir_prefix(const char* writable_dir_prefix); +extern int liblinphone_tester_ipv6_available(void); #ifdef __cplusplus }; diff --git a/tester/rcfiles/pauline_tcp_rc b/tester/rcfiles/pauline_tcp_rc index 809c1ace6..11cdb64cd 100644 --- a/tester/rcfiles/pauline_tcp_rc +++ b/tester/rcfiles/pauline_tcp_rc @@ -1,6 +1,6 @@ [sip] sip_port=-1 -sip_tcp_port=-1 +sip_tcp_port=12002 sip_tls_port=-1 default_proxy=0 ping_with_options=0