Commit 3d744d40 authored by Simon Morlat's avatar Simon Morlat
Browse files

* add test for ipv6 calls

add linphone_call_media_in_progress() method for app to easily check that ice has finished or not its processing.
Update GTK app accordingly, so that adding video is no longer possible while ICE is in progress.
parent a12c07a3
......@@ -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
......
......@@ -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);
}
}
......
......@@ -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
......
......@@ -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)) {
......
......@@ -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);
}
......
......@@ -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 */
......
......@@ -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"
......
......@@ -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
};
......
[sip]
sip_port=-1
sip_tcp_port=-1
sip_tcp_port=12002
sip_tls_port=-1
default_proxy=0
ping_with_options=0
......
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