Esempio n. 1
0
void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
{
	IceCheckList *audio_check_list;
	IceCheckList *video_check_list;
	IceSessionState session_state;

	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;

	session_state = ice_session_state(call->ice_session);
	if ((session_state == IS_Completed) || ((session_state == IS_Failed) && (ice_session_has_completed_check_list(call->ice_session) == TRUE))) {
		if (ice_check_list_state(audio_check_list) == ICL_Completed) {
			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;
			}
		} else {
			call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed;
		}
		if (call->params.has_video && (video_check_list != NULL)) {
			if (ice_check_list_state(video_check_list) == ICL_Completed) {
				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;
				}
			} else {
				call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed;
			}
		}
	} else if (session_state == IS_Running) {
		call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress;
		if (call->params.has_video && (video_check_list != NULL)) {
			call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress;
		}
	} else {
		call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed;
		if (call->params.has_video && (video_check_list != NULL)) {
			call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed;
		}
	}
}
Esempio n. 2
0
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
{
	char local_addr[64];
	sockaddr_x ss;
	socklen_t ss_len;
	IceCheckList *audio_check_list;
	IceCheckList *video_check_list;
	const char *server = linphone_core_get_stun_server(lc);

	if ((server == NULL) || (call->ice_session == NULL)) return -1;
	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 -1;

	if (lc->sip_conf.ipv6_enabled){
		ms_warning("stun support is not implemented for ipv6");
		return -1;
	}

	if (parse_hostname_to_addr(server, &ss, &ss_len) < 0) {
		ms_error("Fail to parser stun server address: %s", server);
		return -1;
	}
	if (lc->vtable.display_status != NULL)
		lc->vtable.display_status(lc, _("ICE local candidates gathering in progress..."));

	/* Gather local host candidates. */
	if (linphone_core_get_local_ip_for(AF_INET, server, local_addr) < 0) {
		ms_error("Fail to get local ip");
		return -1;
	}
	if ((ice_check_list_state(audio_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_check_list) == FALSE)) {
		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_check_list_state(video_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(video_check_list) == FALSE)) {
		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);
	/* Gather local srflx candidates. */
	/* ice_session_gather_candidates(call->ice_session, ss, ss_len); */
	return 0;
}
Esempio n. 3
0
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
{
	char local_addr[64];
	const struct addrinfo *ai;
	IceCheckList *audio_check_list;
	IceCheckList *video_check_list;
	const char *server = linphone_core_get_stun_server(lc);

	if ((server == NULL) || (call->ice_session == NULL)) return -1;
	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 -1;

	if (call->af==AF_INET6){
		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 (lc->vtable.display_status != NULL)
		lc->vtable.display_status(lc, _("ICE local candidates gathering in progress..."));

	/* Gather local host candidates. */
	if (linphone_core_get_local_ip_for(AF_INET, NULL, local_addr) < 0) {
		ms_error("Fail to get local ip");
		return -1;
	}
	if ((ice_check_list_state(audio_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_check_list) == FALSE)) {
		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_check_list_state(video_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(video_check_list) == FALSE)) {
		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);
	/* Gather local srflx candidates. */
	ice_session_gather_candidates(call->ice_session, ai->ai_addr, ai->ai_addrlen);
	return 0;
}
Esempio n. 4
0
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session)
{
	const char *rtp_addr, *rtcp_addr;
	IceSessionState session_state = ice_session_state(session);
	int nb_candidates;
	int i, j;
	bool_t result;

	if (session_state == IS_Completed) {
		desc->ice_completed = TRUE;
		result = ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, 0), &rtp_addr, NULL, NULL, NULL);
		if (result == TRUE) {
			strncpy(desc->addr, rtp_addr, sizeof(desc->addr));
		} else {
			ms_warning("If ICE has completed successfully, rtp_addr should be set!");
		}
	}
	else {
		desc->ice_completed = FALSE;
	}
	strncpy(desc->ice_pwd, ice_session_local_pwd(session), sizeof(desc->ice_pwd));
	strncpy(desc->ice_ufrag, ice_session_local_ufrag(session), sizeof(desc->ice_ufrag));
	for (i = 0; i < desc->n_active_streams; i++) {
		SalStreamDescription *stream = &desc->streams[i];
		IceCheckList *cl = ice_session_check_list(session, i);
		nb_candidates = 0;
		if (cl == NULL) continue;
		if (ice_check_list_state(cl) == ICL_Completed) {
			stream->ice_completed = TRUE;
			result = ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, i), &rtp_addr, &stream->rtp_port, &rtcp_addr, &stream->rtcp_port);
		} else {
			stream->ice_completed = FALSE;
			result = ice_check_list_default_local_candidate(ice_session_check_list(session, i), &rtp_addr, &stream->rtp_port, &rtcp_addr, &stream->rtcp_port);
		}
		if (result == TRUE) {
			strncpy(stream->rtp_addr, rtp_addr, sizeof(stream->rtp_addr));
			strncpy(stream->rtcp_addr, rtcp_addr, sizeof(stream->rtcp_addr));
		} else {
			memset(stream->rtp_addr, 0, sizeof(stream->rtp_addr));
			memset(stream->rtcp_addr, 0, sizeof(stream->rtcp_addr));
		}
		if ((strlen(ice_check_list_local_pwd(cl)) != strlen(desc->ice_pwd)) || (strcmp(ice_check_list_local_pwd(cl), desc->ice_pwd)))
			strncpy(stream->ice_pwd, ice_check_list_local_pwd(cl), sizeof(stream->ice_pwd));
		else
			memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd));
		if ((strlen(ice_check_list_local_ufrag(cl)) != strlen(desc->ice_ufrag)) || (strcmp(ice_check_list_local_ufrag(cl), desc->ice_ufrag)))
			strncpy(stream->ice_ufrag, ice_check_list_local_ufrag(cl), sizeof(stream->ice_ufrag));
		else
			memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd));
		stream->ice_mismatch = ice_check_list_is_mismatch(cl);
		if ((ice_check_list_state(cl) == ICL_Running) || (ice_check_list_state(cl) == ICL_Completed)) {
			memset(stream->ice_candidates, 0, sizeof(stream->ice_candidates));
			for (j = 0; j < MIN(ms_list_size(cl->local_candidates), SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES); j++) {
				SalIceCandidate *sal_candidate = &stream->ice_candidates[nb_candidates];
				IceCandidate *ice_candidate = ms_list_nth_data(cl->local_candidates, j);
				const char *default_addr = NULL;
				int default_port = 0;
				if (ice_candidate->componentID == 1) {
					default_addr = stream->rtp_addr;
					default_port = stream->rtp_port;
				} else if (ice_candidate->componentID == 2) {
					default_addr = stream->rtcp_addr;
					default_port = stream->rtcp_port;
				} else continue;
				if (default_addr[0] == '\0') default_addr = desc->addr;
				/* Only include the candidates matching the default destination for each component of the stream if the state is Completed as specified in RFC5245 section 9.1.2.2. */
				if ((ice_check_list_state(cl) == ICL_Completed)
					&& !((ice_candidate->taddr.port == default_port) && (strlen(ice_candidate->taddr.ip) == strlen(default_addr)) && (strcmp(ice_candidate->taddr.ip, default_addr) == 0)))
					continue;
				strncpy(sal_candidate->foundation, ice_candidate->foundation, sizeof(sal_candidate->foundation));
				sal_candidate->componentID = ice_candidate->componentID;
				sal_candidate->priority = ice_candidate->priority;
				strncpy(sal_candidate->type, ice_candidate_type(ice_candidate), sizeof(sal_candidate->type));
				strncpy(sal_candidate->addr, ice_candidate->taddr.ip, sizeof(sal_candidate->addr));
				sal_candidate->port = ice_candidate->taddr.port;
				if ((ice_candidate->base != NULL) && (ice_candidate->base != ice_candidate)) {
					strncpy(sal_candidate->raddr, ice_candidate->base->taddr.ip, sizeof(sal_candidate->raddr));
					sal_candidate->rport = ice_candidate->base->taddr.port;
				}
				nb_candidates++;
			}
		}
		if ((ice_check_list_state(cl) == ICL_Completed) && (ice_session_role(session) == IR_Controlling)) {
			int rtp_port, rtcp_port;
			memset(stream->ice_remote_candidates, 0, sizeof(stream->ice_remote_candidates));
			if (ice_check_list_selected_valid_remote_candidate(cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port) == TRUE) {
				strncpy(stream->ice_remote_candidates[0].addr, rtp_addr, sizeof(stream->ice_remote_candidates[0].addr));
				stream->ice_remote_candidates[0].port = rtp_port;
				strncpy(stream->ice_remote_candidates[1].addr, rtcp_addr, sizeof(stream->ice_remote_candidates[1].addr));
				stream->ice_remote_candidates[1].port = rtcp_port;
			} else {
				ms_error("ice: Selected valid remote candidates should be present if the check list is in the Completed state");
			}
		} else {
			for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) {
				stream->ice_remote_candidates[j].addr[0] = '\0';
				stream->ice_remote_candidates[j].port = 0;
			}
		}
	}
}