static int tsip_dialog_message_event_callback(const tsip_dialog_message_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
{
	int ret = -1;

	switch(type)
	{
	case tsip_dialog_i_msg:
		{
			if(msg){
				if(TSIP_MESSAGE_IS_RESPONSE(msg)){
					const tsip_action_t* action = tsip_dialog_keep_action(TSIP_DIALOG(self), msg) ? TSIP_DIALOG(self)->curr_action : tsk_null;
					if(TSIP_RESPONSE_IS_1XX(msg)){
						ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_1xx, msg, action);
					}
					else if(TSIP_RESPONSE_IS_2XX(msg)){
						ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_2xx, msg, action);
					}
					else if(TSIP_RESPONSE_CODE(msg) == 401 || TSIP_RESPONSE_CODE(msg) == 407 || TSIP_RESPONSE_CODE(msg) == 421 || TSIP_RESPONSE_CODE(msg) == 494){
						ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_401_407_421_494, msg, action);
					}
					else if(TSIP_RESPONSE_IS_3456(msg)){
						ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_300_to_699, msg, action);
					}
					else{ /* Should never happen */
						ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_error, msg, action);
					}
				}
				else if (TSIP_REQUEST_IS_MESSAGE(msg)){ /* have been checked by dialog layer...but */
					// REQUEST ==> Incoming MESSAGE
					ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_receiveMESSAGE, msg, tsk_null);
				}
			}
			break;
		}

	case tsip_dialog_canceled:
		{
			ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_cancel, msg, tsk_null);
			break;
		}

	case tsip_dialog_terminated:
	case tsip_dialog_timedout:
	case tsip_dialog_error:
	case tsip_dialog_transport_error:
		{
			ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_transporterror, msg, tsk_null);
			break;
		}
	}

	return ret;
}
/* Outgoing -> (i2xx INVITE) -> Connected
*/
int c0000_Outgoing_2_Connected_X_i2xxINVITE(va_list *app)
{
	int ret;

	tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
	const tsip_response_t *r2xxINVITE = va_arg(*app, const tsip_response_t *);
	/* const tsip_action_t* action = */ va_arg(*app, const tsip_action_t *);

	/* Update the dialog state */
	if((ret = tsip_dialog_update(TSIP_DIALOG(self), r2xxINVITE))){
		return ret;
	}
	
	/* Process remote offer */
	if((ret = tsip_dialog_invite_process_ro(self, r2xxINVITE))){
		send_BYE(self);
		return ret;
	}
	else{
		/* send ACK */
		ret = send_ACK(self, r2xxINVITE);
	}
	
	/* Determine whether the remote party support UPDATE */
	self->support_update = tsip_message_allowed(r2xxINVITE, "UPDATE");

	/* Session Timers */
	if(self->stimers.timer.timeout){
		tsip_dialog_invite_stimers_handle(self, r2xxINVITE);
	}

	// starts ICE timers now that both parties received the "candidates"
	if(tsip_dialog_invite_ice_is_enabled(self)){
		tsip_dialog_invite_ice_timers_set(self, (self->required.ice ? -1 : TSIP_DIALOG_INVITE_ICE_CONNCHECK_TIMEOUT));
	}
	
	/* Alert the user (session) */
	ret = TSIP_DIALOG_INVITE_SIGNAL(self, tsip_ao_request, 
			TSIP_RESPONSE_CODE(r2xxINVITE), TSIP_RESPONSE_PHRASE(r2xxINVITE), r2xxINVITE);
		/* Alert the user (dialog) */
	ret = TSIP_DIALOG_SIGNAL(self, tsip_event_code_dialog_connected, "Dialog connected");
	
	if(self->is_transf){
		ret = tsip_dialog_invite_notify_parent(self, r2xxINVITE);
		self->is_transf = tsk_false;//final response -> no longer need to notify the parent
	}

	/* MSRP File Transfer */
	/*if(TSIP_DIALOG(self)->curr_action && ((TSIP_DIALOG(self)->curr_action->media.type & tmedia_msrp) == tmedia_msrp)){
		// FIXME
		tmedia_session_mgr_send_file(self->msession_mgr, "C:\\avatar.png", 
			TMEDIA_SESSION_SET_NULL());
	}*/
	
	return ret;
}
/**
 * Callback function called by the transport layer to alert the transaction for incoming messages
 *			or errors (e.g. transport error).
 *
 * @param [in,out]	self	A pointer to the NIC transaction. 
 * @param	type		The event type. 
 * @param [in,out]	msg	The incoming message.
 *
 * @return	Zero if succeed and no-zero error code otherwise. 
**/
int tsip_transac_nict_event_callback(const tsip_transac_nict_t *self, tsip_transac_event_type_t type, const tsip_message_t *msg)
{	
	int ret = 0;

	switch(type)
	{
	case tsip_transac_incoming_msg:
		{
			if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)){
				if(TSIP_RESPONSE_IS_1XX(msg)){
					ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_1xx, msg);
				}
				else if(TSIP_RESPONSE_IS_23456(msg)){
					ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_200_to_699, msg);
				}
				else{
					TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg));
				}
			}
			break;
		}

	case tsip_transac_canceled:
	case tsip_transac_terminated:
	case tsip_transac_timedout:
		break;

	case tsip_transac_error:
		{
			ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg);
			break;
		}

	case tsip_transac_transport_error:
		{
			ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg);
			break;
		}
            
        default: break;
	}

	return ret;
}
	/*tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);*/
	/*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/

	return 0;
}

/* Trying -> (2xx) -> Terminated
*/
int tsip_dialog_subscribe_Trying_2_Terminated_X_2xx(va_list *app)
{
	tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
	const tsip_response_t *response = va_arg(*app, const tsip_response_t *);

	/* Alert the user. */
	TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, self->unsubscribing ? tsip_ao_unsubscribe : tsip_ao_subscribe, 
		TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response), response);

	return 0;
}

/* Trying -> (2xx) -> Connected
*/
int tsip_dialog_subscribe_Trying_2_Connected_X_2xx(va_list *app)
{
	int ret;
	tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
	const tsip_response_t *response = va_arg(*app, const tsip_response_t *);

	tsk_bool_t first_time_to_connect = (TSIP_DIALOG(self)->state == tsip_initial);

	/* Update the dialog state. */