/* ======================== 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; }
int subscribe_handle_event(const tsip_event_t *_event) { const tsip_subscribe_event_t* sub_event = TSIP_SUBSCRIBE_EVENT(_event); const session_t* session; tsip_ssession_id_t sid; /* Find associated session */ sid = tsip_ssession_get_id(_event->ss); if(!(session = session_get_by_sid(ctx->sessions, sid))) { TSK_DEBUG_WARN("Failed to match session event."); return -1; } switch(sub_event->type) { case tsip_ao_subscribe: { /* Answer to outgoing SUBSCRIBE */ if(_event->sipmessage) { if(TSIP_MESSAGE_IS_RESPONSE(_event->sipmessage)) { TSK_DEBUG_INFO("Event: Answer to outgoing SUBSCRIBE. Code=%d and phrase=%s", _event->sipmessage->line.response.status_code, _event->sipmessage->line.response.reason_phrase); } else { // request } } break; } case tsip_ao_unsubscribe: { /* Answer to outgoing unSUBSCRIBE */ if(_event->sipmessage) { if(TSIP_MESSAGE_IS_RESPONSE(_event->sipmessage)) { TSK_DEBUG_INFO("Event: Answer to outgoing unSUBSCRIBE. Code=%d and phrase=%s", _event->sipmessage->line.response.status_code, _event->sipmessage->line.response.reason_phrase); } else { // request } } break; } case tsip_i_notify: { /* Incoming NOTIFY */ TSK_DEBUG_INFO("Event: Incoming NOTIFY."); if(TSIP_MESSAGE_HAS_CONTENT(_event->sipmessage)) { const tsk_buffer_t* content = TSIP_MESSAGE_CONTENT(_event->sipmessage); TSK_DEBUG_INFO("NOTIFY Content-Type: %s", TSIP_MESSAGE_CONTENT_TYPE(_event->sipmessage)); TSK_DEBUG_INFO("NOTIFY Content: %s", content->data); } break; } /* Server events (For whose dev. Server Side IMS Services) */ case tsip_i_subscribe: /* Incoming SUBSCRIBE */ case tsip_i_unsubscribe: { /* Incoming unSUBSCRIBE */ TSK_DEBUG_WARN("Event not support by Client Framework."); break; } default: { /* Any other event */ TSK_DEBUG_WARN("%d not a valid SIP Subscription event.", sub_event->type); break; } } return 0; }