stats->type = type;
stats->received_rtcp = NULL;
stats->sent_rtcp = NULL;
+ stats->ice_state = LinphoneIceStateNotActivated;
}
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
call->ice_session = NULL;
if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL;
if (call->videostream != NULL) call->videostream->ice_check_list = NULL;
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated;
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated;
}
}
if (ice_session_role(call->ice_session) == IR_Controlling) {
ice_session_select_candidates(call->ice_session);
linphone_core_update_call(call->core, call, &call->current_params);
+ linphone_core_update_ice_state_in_call_stats(call);
}
break;
case IS_Failed:
/* At least one ICE session has succeeded, so perform a call update. */
ice_session_select_candidates(call->ice_session);
linphone_core_update_call(call->core, call, &call->current_params);
+ linphone_core_update_ice_state_in_call_stats(call);
}
}
break;
#define LINPHONE_CALL_STATS_AUDIO 0
#define LINPHONE_CALL_STATS_VIDEO 1
+/**
+ * Enum describing ICE states.
+ * @ingroup initializing
+**/
+enum _LinphoneIceState{
+ LinphoneIceStateNotActivated, /**< ICE has not been activated for this call */
+ LinphoneIceStateInProgress, /**< ICE process is in progress */
+ LinphoneIceStateHostConnection, /**< ICE has established a direct connection to the remote host */
+ LinphoneIceStateReflexiveConnection, /**< ICE has established a connection to the remote host through one or several NATs */
+ LinphoneIceStateRelayConnection /**< ICE has established a connection through a relay */
+};
+
+/**
+ * Enum describing Ice states.
+ * @ingroup initializing
+**/
+typedef enum _LinphoneIceState LinphoneIceState;
+
/**
* The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams.
*
mblk_t* received_rtcp; /**<Last RTCP packet received, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
mblk_t* sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
+ LinphoneIceState ice_state; /**< State of ICE processing. */
};
/**
}
ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port, 1, NULL);
ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port + 1, 2, NULL);
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress;
if (call->params.has_video && (video_check_list != NULL)) {
ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port, 1, NULL);
ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port + 1, 2, NULL);
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress;
}
ms_message("ICE: gathering candidate from [%s]",server);
return 0;
}
+void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
+{
+ IceCheckList *audio_check_list;
+ IceCheckList *video_check_list;
+
+ if (call->ice_session == NULL) return;
+ audio_check_list = ice_session_check_list(call->ice_session, 0);
+ video_check_list = ice_session_check_list(call->ice_session, 1);
+ if (audio_check_list == NULL) return;
+
+ switch (ice_check_list_selected_valid_candidate_type(audio_check_list)) {
+ case ICT_HostCandidate:
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateHostConnection;
+ break;
+ case ICT_ServerReflexiveCandidate:
+ case ICT_PeerReflexiveCandidate:
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateReflexiveConnection;
+ break;
+ case ICT_RelayedCandidate:
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateRelayConnection;
+ break;
+ }
+ if (call->params.has_video && (video_check_list != NULL)) {
+ switch (ice_check_list_selected_valid_candidate_type(video_check_list)) {
+ case ICT_HostCandidate:
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateHostConnection;
+ break;
+ case ICT_ServerReflexiveCandidate:
+ case ICT_PeerReflexiveCandidate:
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateReflexiveConnection;
+ break;
+ case ICT_RelayedCandidate:
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateRelayConnection;
+ break;
+ }
+ }
+}
+
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session)
{
const char *rtp_addr, *rtcp_addr;
int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call, StunCandidate *ac, StunCandidate *vc);
void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, LinphoneCallParams *params);
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call);
+void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call);
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
void linphone_core_deactivate_ice_for_deactivated_media_streams(LinphoneCall *call, const SalMediaDescription *md);