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; }
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; }