/* ======================== conds ======================== */ static tsk_bool_t _fsm_cond_get_local_candidates(tsip_dialog_invite_t* self, tsip_message_t* message) { if(self->supported.ice){ tsk_bool_t use_ice = tsk_false; // "action->media.type" will be defined for locally initiated media update tmedia_type_t new_media = TSIP_DIALOG(self)->curr_action ? TSIP_DIALOG(self)->curr_action->media.type : tmedia_none; if(message && TSIP_MESSAGE_HAS_CONTENT(message) && tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){ // If this code is called this means that we are the "answerer" // only gets the candidates if ICE is enabled and the remote peer supports ICE tsdp_message_t* sdp_ro; const tsdp_header_M_t* M; int index; if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){ TSK_DEBUG_ERROR("Failed to parse remote sdp message"); return tsk_false; } index = 0; while((M = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp_ro, tsdp_htype_M, index++))){ if(!tsdp_header_M_findA(M, "candidate")){ use_ice = tsk_false; // do not use ICE if at least on media is ICE-less (e.g. MSRP) break; } use_ice = tsk_true; // only use ICE if there is a least one media line } new_media = tmedia_type_from_sdp(sdp_ro); TSK_OBJECT_SAFE_FREE(sdp_ro); } else if(!message){ // we are the "offerer" -> use ICE only for audio or video medias (ignore ice for MSRP) use_ice = (new_media & tmedia_audio) || (new_media & tmedia_video); } if(use_ice){ if(!self->ice.ctx_audio && !self->ice.ctx_video){ // First time return tsk_true; } else{ if(self->ice.media_type != new_media){ return tsk_true; } return !tsip_dialog_invite_ice_got_local_candidates(self); } } } return tsk_false; }
// Current -> (iINVITE) -> Current static int x0500_Current_2_Current_X_iINVITE(va_list *app) { int ret; tsip_dialog_invite_t *self; const tsip_action_t* action; const tsip_message_t *message; self = va_arg(*app, tsip_dialog_invite_t *); message = va_arg(*app, const tsip_message_t *); action = va_arg(*app, const tsip_action_t *); self->is_client = tsk_false; ret = tsip_dialog_invite_ice_save_action(self, _fsm_action_iINVITE, action, message); // Cancel without notifying ("silent mode") and perform the operation right now ("sync mode") tsip_dialog_invite_ice_cancel_silent_and_sync_ctx(self); // set remote candidates if(TSIP_MESSAGE_HAS_CONTENT(message)){ if(tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){ tsdp_message_t* sdp_ro; if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){ TSK_DEBUG_ERROR("Failed to parse remote sdp message"); return -2; } // create ICE context if((ret = tsip_dialog_invite_ice_create_ctx(self, tmedia_type_from_sdp(sdp_ro)))){ TSK_DEBUG_ERROR("tsip_dialog_invite_ice_create_ctx() failed"); return ret; } ret = tsip_dialog_invite_ice_process_ro(self, sdp_ro, tsk_true); TSK_OBJECT_SAFE_FREE(sdp_ro); } else{ TSK_DEBUG_ERROR("[%s] content-type is not supportted", TSIP_MESSAGE_CONTENT_TYPE(message)); return -3; } } // For now disable ICE timers until we send the 2xx and receive the ACK ret = tsip_dialog_invite_ice_timers_set(self, -1); // Start ICE ret = tsip_dialog_invite_ice_start_ctx(self); return ret; }
// Started -> (iINVITE) -> Started static int x0500_Current_2_Current_X_iINVITE(va_list *app) { int ret; tsip_dialog_invite_t *self; const tsip_action_t* action; const tsip_message_t *message; self = va_arg(*app, tsip_dialog_invite_t *); message = va_arg(*app, const tsip_message_t *); action = va_arg(*app, const tsip_action_t *); self->is_client = tsk_false; ret = tsip_dialog_invite_ice_save_action(self, _fsm_action_iINVITE, action, message); // set remote candidates if(TSIP_MESSAGE_HAS_CONTENT(message)){ if(tsk_striequals("application/sdp", TSIP_MESSAGE_CONTENT_TYPE(message))){ tsdp_message_t* sdp_ro; if(!(sdp_ro = tsdp_message_parse(TSIP_MESSAGE_CONTENT_DATA(message), TSIP_MESSAGE_CONTENT_DATA_LENGTH(message)))){ TSK_DEBUG_ERROR("Failed to parse remote sdp message"); return -2; } // create ICE context if((ret = tsip_dialog_invite_ice_create_ctx(self, tmedia_type_from_sdp(sdp_ro)))){ TSK_DEBUG_ERROR("tsip_dialog_invite_ice_create_ctx() failed"); return ret; } ret = tsip_dialog_invite_ice_process_ro(self, sdp_ro, tsk_true); TSK_OBJECT_SAFE_FREE(sdp_ro); } else{ TSK_DEBUG_ERROR("[%s] content-type is not supportted", TSIP_MESSAGE_CONTENT_TYPE(message)); return -3; } } // Start ICE ret = tsip_dialog_invite_ice_start_ctx(self); return ret; }