// 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;
}
Example #2
0
// 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;
}
/* ======================== 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;
}
Example #4
0
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;
}