示例#1
0
struct tsip_transac_dst_s* tsip_transac_dst_dialog_create(tsip_dialog_t *dlg)
{
	struct tsip_transac_dst_s* dst;
	if((dst =  tsip_transac_dst_create(tsip_transac_dst_type_dialog, TSIP_DIALOG_GET_STACK(dlg)))){
		dst->dialog.dlg = tsk_object_ref(dlg);
	}
	return dst;
}
/* ======================== conds ======================== */
static tsk_bool_t _fsm_cond_not_served_here(tsip_dialog_register_t* dialog, tsip_message_t* message)
{
	if(message && TSIP_REQUEST_IS_REGISTER(message)){
		if(tsk_object_cmp(TSIP_DIALOG_GET_STACK(dialog)->network.realm, message->line.request.uri) != 0){
			tsip_dialog_register_send_RESPONSE(dialog, TSIP_MESSAGE_AS_REQUEST(message), 404, "Domain not served here");
			return tsk_true;
		}
	}
	return tsk_false;
}
static int tsip_dialog_invite_ice_create_ctx(tsip_dialog_invite_t * self, tmedia_type_t media_type)
{
	int32_t transport_idx;
	int ret = 0;
	if(!self){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}
	transport_idx = TSIP_DIALOG_GET_STACK(self)->network.transport_idx_default;
	if (!self->ice.ctx_audio && (media_type & tmedia_audio)) {
		self->ice.ctx_audio = tnet_ice_ctx_create(self->ice.is_jingle, TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type[transport_idx]), 
					self->use_rtcp, tsk_false, tsip_dialog_invite_ice_audio_callback, self);
		if (!self->ice.ctx_audio) {
			TSK_DEBUG_ERROR("Failed to create ICE audio context");
			return -2;
		}
		ret = tnet_ice_ctx_set_stun(self->ice.ctx_audio, TSIP_DIALOG_GET_SS(self)->media.stun.hostname, TSIP_DIALOG_GET_SS(self)->media.stun.port, kStunSoftware, TSIP_DIALOG_GET_SS(self)->media.stun.username, TSIP_DIALOG_GET_SS(self)->media.stun.password);
		ret = tnet_ice_ctx_set_stun_enabled(self->ice.ctx_audio, TSIP_DIALOG_GET_SS(self)->media.enable_icestun);
		ret = tnet_ice_ctx_set_turn_enabled(self->ice.ctx_audio, TSIP_DIALOG_GET_SS(self)->media.enable_iceturn);
		ret = tnet_ice_ctx_set_rtcpmux(self->ice.ctx_audio, self->use_rtcpmux);
	}
	if (!self->ice.ctx_video && (media_type & tmedia_video)) {
		self->ice.ctx_video = tnet_ice_ctx_create(self->ice.is_jingle, TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type[transport_idx]), 
					self->use_rtcp, tsk_true, tsip_dialog_invite_ice_video_callback, self);
		if (!self->ice.ctx_video) {
			TSK_DEBUG_ERROR("Failed to create ICE video context");
			return -2;
		}
		ret = tnet_ice_ctx_set_stun(self->ice.ctx_video, TSIP_DIALOG_GET_SS(self)->media.stun.hostname, TSIP_DIALOG_GET_SS(self)->media.stun.port, kStunSoftware, TSIP_DIALOG_GET_SS(self)->media.stun.username, TSIP_DIALOG_GET_SS(self)->media.stun.password);
		ret = tnet_ice_ctx_set_stun_enabled(self->ice.ctx_video, TSIP_DIALOG_GET_SS(self)->media.enable_icestun);
		ret = tnet_ice_ctx_set_turn_enabled(self->ice.ctx_video, TSIP_DIALOG_GET_SS(self)->media.enable_iceturn);
		ret = tnet_ice_ctx_set_rtcpmux(self->ice.ctx_video, self->use_rtcpmux);
	}

	// set media type
	ret = tsip_dialog_invite_ice_set_media_type(self, media_type);

	// update session manager with the right ICE contexts
	if (self->msession_mgr) {
		ret = tmedia_session_mgr_set_ice_ctx(self->msession_mgr, self->ice.ctx_audio, self->ice.ctx_video);
	}

	return ret;
}
/* Started -> (oINVITE) -> Outgoing
*/
int c0000_Started_2_Outgoing_X_oINVITE(va_list *app)
{
	int ret;
	tsip_dialog_invite_t *self;
	const tsip_action_t* action;

	self = va_arg(*app, tsip_dialog_invite_t *);
	va_arg(*app, const tsip_message_t *);
	action = va_arg(*app, const tsip_action_t *);
	
	/* This is the first FSM transaction when you try to make an audio/video/msrp call */
	if(!self->msession_mgr){
		int32_t transport_idx = TSIP_DIALOG_GET_STACK(self)->network.transport_idx_default;
		self->msession_mgr = tmedia_session_mgr_create(action ? action->media.type : tmedia_all,
			TSIP_DIALOG_GET_STACK(self)->network.local_ip[transport_idx], TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type[transport_idx]), tsk_true);
		if(TSIP_DIALOG_GET_STACK(self)->natt.ctx){
			ret = tmedia_session_mgr_set_natt_ctx(self->msession_mgr, TSIP_DIALOG_GET_STACK(self)->natt.ctx, TSIP_DIALOG_GET_STACK(self)->network.aor.ip[transport_idx]);
		}
		
		ret = tmedia_session_mgr_set_ice_ctx(self->msession_mgr, self->ice.ctx_audio, self->ice.ctx_video);
		ret = tsip_dialog_invite_msession_configure(self);
	}

	/* We are the client */
	self->is_client = tsk_true;
	/* Whether it's a client dialog for call transfer */
	self->is_transf = (TSIP_DIALOG_GET_SS(self)->id_parent != TSIP_SSESSION_INVALID_ID);

	/* Get Media type from the action */
	TSIP_DIALOG_GET_SS(self)->media.type = action->media.type;
	/* Appy media params received from the user */
	if(!TSK_LIST_IS_EMPTY(action->media.params)){
		tmedia_session_mgr_set_3(self->msession_mgr, action->media.params);
	}

	/*  RFC 4028 - 7.1. Generating an Initial Session Refresh Request

		A UAC MAY include a Session-Expires header field in an initial
		session refresh request if it wants a session timer applied to the
		session.  The value of this header field indicates the session
		interval desired by the UAC.  If a Min-SE header is included in the
		initial session refresh request, the value of the Session-Expires
		MUST be greater than or equal to the value in Min-SE.

		The UAC MAY include the refresher parameter with value 'uac' if it
		wants to perform the refreshes.  However, it is RECOMMENDED that the
		parameter be omitted so that it can be selected by the negotiation
		mechanisms described below.
	*/
	if(TSIP_DIALOG_GET_SS(self)->media.timers.timeout){
		self->stimers.timer.timeout = TSIP_DIALOG_GET_SS(self)->media.timers.timeout;
		tsk_strupdate(&self->stimers.refresher, TSIP_DIALOG_GET_SS(self)->media.timers.refresher);
		self->stimers.is_refresher = tsk_striequals(self->stimers.refresher, "uac");
		self->supported.timer = tsk_true;
	}
	
	/* QoS
	* One Voice Profile - 5.4.1 SIP Precondition Considerations
	* The UE shall use the Supported header, and not the Require header, to indicate the support of precondition in
	* accordance with Section 5.1.3.1 of 3GPP TS 24.229.
	*/
	self->qos.type = TSIP_DIALOG_GET_SS(self)->media.qos.type;
	self->qos.strength = TSIP_DIALOG_GET_SS(self)->media.qos.strength;
	tmedia_session_mgr_set_qos(self->msession_mgr, self->qos.type, self->qos.strength);
	self->supported.precondition = (self->qos.strength == tmedia_qos_strength_optional);
	self->required.precondition = (self->qos.strength == tmedia_qos_strength_mandatory);

	/* send the request */
	ret = send_INVITE(self, tsk_false);

	/* alert the user */
	TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connecting, "Dialog connecting");

	return ret;
}
示例#5
0
static int tsip_dialog_invite_ice_create_ctx(tsip_dialog_invite_t * self, tmedia_type_t media_type)
{
	int32_t transport_idx;
	if(!self){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}
	transport_idx = TSIP_DIALOG_GET_STACK(self)->network.transport_idx_default;
	if(!self->ice.ctx_audio && (media_type & tmedia_audio)){
		self->ice.ctx_audio = tnet_ice_ctx_create(self->ice.is_jingle, TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type[transport_idx]), 
					self->use_rtcp, tsk_false, tsip_dialog_invite_ice_audio_callback, self);
		if(!self->ice.ctx_audio){
			TSK_DEBUG_ERROR("Failed to create ICE audio context");
			return -2;
		}
		tnet_ice_ctx_set_stun(self->ice.ctx_audio, "stun.l.google.com", 19302, "Doubango", "*****@*****.**", "stun-password"); //FIXME
		tnet_ice_ctx_set_rtcpmux(self->ice.ctx_audio, self->use_rtcpmux);
	}
	if(!self->ice.ctx_video && (media_type & tmedia_video)){
		self->ice.ctx_video = tnet_ice_ctx_create(self->ice.is_jingle, TNET_SOCKET_TYPE_IS_IPV6(TSIP_DIALOG_GET_STACK(self)->network.proxy_cscf_type[transport_idx]), 
					self->use_rtcp, tsk_true, tsip_dialog_invite_ice_video_callback, self);
		if(!self->ice.ctx_video){
			TSK_DEBUG_ERROR("Failed to create ICE video context");
			return -2;
		}
		tnet_ice_ctx_set_stun(self->ice.ctx_video, "stun.l.google.com", 19302, "Doubango", "*****@*****.**", "stun-password"); // FIXME
		tnet_ice_ctx_set_rtcpmux(self->ice.ctx_video, self->use_rtcpmux);
	}

	// "none" comparison is used to exclude the "first call"
	if(self->ice.media_type != tmedia_none && self->ice.media_type != media_type){
		// cancels contexts associated to old medias
		if(self->ice.ctx_audio && !(media_type & tmedia_audio)){
			tnet_ice_ctx_cancel(self->ice.ctx_audio);
		}
		if(self->ice.ctx_video && !(media_type & tmedia_video)){
			tnet_ice_ctx_cancel(self->ice.ctx_video);
		}
		// cancels contexts associated to new medias (e.g. session "remove" then "add")
		// cancel() on newly created contexts don't have any effect
		if(self->ice.ctx_audio && (!(media_type & tmedia_audio) && (self->ice.media_type & tmedia_audio))){
			//tnet_ice_ctx_cancel(self->ice.ctx_audio);
		}
		if(self->ice.ctx_video && (!(media_type & tmedia_video) && (self->ice.media_type & tmedia_video))){
			//tnet_ice_ctx_cancel(self->ice.ctx_video);
		}
	}

	self->ice.media_type = media_type;
	

	// For now disable timers until both parties get candidates
	// (RECV ACK) or RECV (200 OK)
	tsip_dialog_invite_ice_timers_set(self, -1);

	// update session manager with the right ICE contexts
	if(self->msession_mgr){
		tmedia_session_mgr_set_ice_ctx(self->msession_mgr, self->ice.ctx_audio, self->ice.ctx_video);
	}

	return 0;
}