/****************************************************************/
/*	M2UA Implementation Program									*/
/*	Version 10.0.3												*/
/*	Designed By Ying Min										*/
/*	Last Update: 2006-2-14										*/
/****************************************************************/

#include "./include/m2ua_pub.h"
#include "./include/m2ua.h"
#include "./include/m2ua_const.h"
#include "./include/m2ua_def.h"
#include "./include/m2ua_struct.h"
#include "./include/m2ua_msg.h"
#include "./include/m2ua_fsm.h"
#include "./include/m2ua_debug.h"

int m2ua_get_local_ip(void)
{
	struct hostent *host;
	
	if (gethostname(hostname, 50) == -1)
	{
		printf("M2UA gethostname fail!\n");
		exit(3);
	}
	
	if ((host = gethostbyname(hostname)) == NULL)
	{
		printf("M2UA gethostbyname fail!\n");
		exit(4);
	}
	else
	{
		sprintf(hostip, "%d.%d.%d.%d", 
				(BYTE)host->h_addr_list[0][0],
				(BYTE)host->h_addr_list[0][1],
				(BYTE)host->h_addr_list[0][2],
				(BYTE)host->h_addr_list[0][3]);
		host_ip 		= inet_addr(hostip);	// Network byte order host_ip, like 0xE60012AC
		printf("hostip: %s (0x%lX)\n", hostip, host_ip);
	}
	
	return 0;
}

/*
int m2ua_get_mtp3_para(void)
{
	DWORD	oid[20] = {1,3,6,1,4,1,1373,1,3,2,2,2,2,9,1};	// SG Attributes
	BYTE	msg[64], vartype;
	int		i;
	
	printf("M2UA start to get MTP3 link_para!\n");
	
	for (i = 0; i < M2UA_MAX_SG_NUM; i++)
	{
		oid[15] = i;
		if (get_response(16, oid, msg, &vartype) < 0)
		{
			printf("M2UA get MTP3 sg_para failed, please set it from MTP3!\n");
			return -1;
		}
		else
			set_m2ua_sg(i, msg);
	}
	
	oid[14] = 5;	// Link Attributes
	for (i = 0; i < M2UA_MAX_LK_NUM; i++)
	{
		oid[15] = i;
		if (get_response(16, oid, msg, &vartype) < 0)
		{
			printf("M2UA get MTP3 link_para failed, please set it from MTP3!\n");
			return -1;
		}
		else
			set_m2ua_link(i, msg);
	}
	
	return 0;
}
*/


void m2ua_init(BYTE system_id)
{
	int				id, fd;
	//static DWORD	init_times = 0;
	
	printf("M2UA Init Start!\n");
	
	plat_id = system_id%2;
	
	m2ua_get_local_ip();
	
	for (id = 0; id < M2UA_MAX_SG_FSM_NUM; id++)
	{
		m2ua_sg_init(id);
		m2ua_sg_mon_fg[id] = 0;
	}
	m2ua_sg_mon_count = 0;
	
#ifndef _LKSCTP
	if ((fd = m2ua_sctp_t_open(M2UA_LISTEN_SG_NUM_0)) <= 0)
	{
		printf("M2UA_LISTEN_SG_NUM_0 sctp_t open failure!\n");
		exit(2);
	}
#else
	if ((fd = m2ua_sctp_open_lksctp(M2UA_LISTEN_SG_NUM_0)) <= 0)
	{
        printf("M2UA_LISTEN_SG_NUM_0 lksctp open failure!\n");
		exit(2);
  }
#endif
	else
	{
		m2ua_sg_info[M2UA_LISTEN_SG_NUM_0].fd 		= fd;
		m2ua_sg_info[M2UA_LISTEN_SG_NUM_0].enable 	= 1;
		printf("M2UA_LISTEN_SG_NUM_0 listening fd open succeed!\n");
	}
#ifndef _LKSCTP
	if ((fd = m2ua_sctp_t_open(M2UA_LISTEN_SG_NUM_1)) <= 0)
	{
		printf("M2UA_LISTEN_SG_NUM_1 sctp_t open failure!\n");
		exit(2);
	}
#else
	if ((fd = m2ua_sctp_open_lksctp(M2UA_LISTEN_SG_NUM_1)) <= 0)
	{
        printf("M2UA_LISTEN_SG_NUM_1 lksctp open failure!\n");
		exit(2);
  }
#endif
	else
	{
		m2ua_sg_info[M2UA_LISTEN_SG_NUM_1].fd 		= fd;
		m2ua_sg_info[M2UA_LISTEN_SG_NUM_1].enable 	= 1;
		printf("M2UA_LISTEN_SG_NUM_1 listening fd open succeed!\n");
	}	
//add by yizane
#ifndef _LKSCTP
	if ((fd = m2ua_sctp_t_open(IUA_LISTEN_SG_NUM_0)) <= 0)
	{
		printf("IUA_LISTEN_SG_NUM_0 sctp_t open failure!\n");
		exit(2);
	}
#else
	if ((fd = m2ua_sctp_open_lksctp(IUA_LISTEN_SG_NUM_0)) <= 0)
	{
        printf("IUA_LISTEN_SG_NUM_0 lksctp open failure!\n");
		exit(2);
  }
#endif
	else
	{
		m2ua_sg_info[IUA_LISTEN_SG_NUM_0].fd 		= fd;
		m2ua_sg_info[IUA_LISTEN_SG_NUM_0].enable 	= 1;
		printf("IUA_LISTEN_SG_NUM_0 listening fd open succeed!\n");
	}
#ifndef _LKSCTP
	if ((fd = m2ua_sctp_t_open(IUA_LISTEN_SG_NUM_1)) <= 0)
	{
		printf("IUA_LISTEN_SG_NUM_1 sctp_t open failure!\n");
		exit(2);
	}
#else
	if ((fd = m2ua_sctp_open_lksctp(IUA_LISTEN_SG_NUM_1)) <= 0)
	{
        printf("IUA_LISTEN_SG_NUM_1 lksctp open failure!\n");
		exit(2);
  }
#endif
	else
	{
		m2ua_sg_info[IUA_LISTEN_SG_NUM_1].fd 		= fd;
		m2ua_sg_info[IUA_LISTEN_SG_NUM_1].enable 	= 1;
		printf("IUA_LISTEN_SG_NUM_1 listening fd open succeed!\n");
	}	
//add by yizane	

	
	
	for (id = 0; id < M2UA_MAX_LK_NUM; id++)
	{
		m2ua_lk_init(id);
		m2ua_lk_mon_fg[id] = 0;
	}
	m2ua_lk_mon_count = 0;
	
	for (id = 0; id < M2UA_MAX_M3MSG_NUM; id++)
		x256[id] = 256 * id;
	
	bzero(&m2ua_csta, sizeof(m2ua_csta_t));
	bzero(err, 256);
	
	m2ua_mtp3_sd_h = 0;
	m2ua_mtp3_sd_t = 0;

	iua_q931_sd_h = 0;
	iua_q931_sd_t = 0;
	
	m2ua_sctp_cmd_len = 0;
	m2ua_sctp_dat_len = 0;
	
	m2ua_sctp_addr.port 		= htons(2904);
	m2ua_sctp_server_addr.port 	= htons(2904);
	inet_aton(hostip, &m2ua_sctp_addr.addr);
	
    strcpy(m2ua_asciin_buf, "\0");
    strcpy(m2ua_asciout_buf, "\0");
    moniter_fg = MONITOR_NONE;
    m2ua_debug_set();
    
    init_flag = 0;
    m2ua_command = M2UA_CMD_IDLE;
    //if (init_times++);
    	//m2ua_get_mtp3_para();
    
	printf("M2UA Init Complete!\n");
}

void m2ua_t10ms()
{
	static 	int cnt_10ms = 0;
	static 	int ls_hb_flag = 0;
	static 	int ls_hb_lk = 0;
	WORD	nsg;
	WORD	i, fd;
	
	if (ls_hb_flag)
	{
		if (ls_hb_lk < M2UA_MAX_LK_NUM)
		{
			if (m2ua_para.lk_para[ls_hb_lk].enable == 1)
			{
				nsg = m2ua_para.lk_para[ls_hb_lk].lk_sg;
				if ((m2ua_para.sg_para[nsg].xUA_ack>>1) == M2UA_APP)
					m2ua_sd_mtp3_primi(ls_hb_lk, m2ua_lk_info[ls_hb_lk].lk_st);
				else if ((m2ua_para.sg_para[nsg].xUA_ack>>1) == IUA_APP)
					iua_sd_q931_primi(ls_hb_lk, m2ua_lk_info[ls_hb_lk].lk_st);			
			}			
			ls_hb_lk++;
		}
		else
		{
			ls_hb_flag 	= 0;
			ls_hb_lk 	= 0;
		}
	}
	
	if (!(++cnt_10ms % 10))
	{	// 100 ms
		m2ua_mon();
		
		if (!(cnt_10ms % 100))
		{	// 1 seconds
			if (m2ua_command != M2UA_CMD_IDLE)
			{
				sprintf(m2ua_ascitemp_buf, "M2UA Restart! m2ua_command=%d\n\r", m2ua_command);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_asciout_proc("\n\r");
				
				m2ua_command = M2UA_CMD_IDLE;
		
				for (i = 0; i < M2UA_MAX_SG_FSM_NUM; i++)
				{
					if ((fd = m2ua_sg_info[i].fd) > 0)
					{
						if ((m2ua_sg_info[i].sctp_state > 2) ||
							((m2ua_sg_info[i].sctp_state == 2) &&
							(m2ua_sg_info[i].sctp_state_1 > 0)))
						{
#ifndef _LKSCTP
							if (i >= M2UA_MAX_SG_NUM)
								m2ua_sctp_discon_req(fd, i, m2ua_sg_info[i].seq);
							else
								m2ua_sctp_discon_req(fd, i, 0);
#else
							m2ua_sctp_discon_req_lksctp(fd, i, 0);
#endif
						}
#ifndef _LKSCTP
						m2ua_sctp_close(m2ua_sg_info[i].fd, i);
#endif
					}
				}
		
				m2ua_init(plat_id);
			}	
			else if (cnt_10ms >= 1500)
			{	// 15 seconds
				cnt_10ms = 0;
				ls_hb_flag = 1;
			}
		}
	}
}

// Called every 10 ms
void m2ua_timer(void)
{
	WORD 		sg, sg_dual, i;
	static BYTE	sg_start = 0;
	static BYTE lk_scan = 0;
	
	for (sg = sg_start; sg < sg_start + 128; sg++)
	{
		sg_dual = sg;
		if (m2ua_sg_info[sg_dual].m2ua_state == 3)
		{
			for (i = 0; i < 32; i++)
			{
				if (m2ua_sg_fsm(sg_dual) < 0)
					break;
			}
		}
		else
			m2ua_sg_fsm(sg_dual);
			
		sg_dual = sg + M2UA_MAX_SG_NUM/2;
			
		if (m2ua_sg_info[sg_dual].m2ua_state == 3)
		{
			for (i = 0; i < 32; i++)
			{
				if (m2ua_sg_fsm(sg_dual) < 0)
					break;
			}
		}
		else
			m2ua_sg_fsm(sg_dual);						
	}
	sg_start += 128;
	
	if (sg_start == 0)
	{
		m2ua_sg_fsm(M2UA_LISTEN_SG_NUM_0);
		m2ua_sg_fsm(M2UA_LISTEN_SG_NUM_1);		
		m2ua_sg_fsm(IUA_LISTEN_SG_NUM_0);		
		m2ua_sg_fsm(IUA_LISTEN_SG_NUM_1);		
	}
	
	if (m2ua_lk_info[lk_scan].lk_timer > 0)
		m2ua_lk_info[lk_scan].lk_timer--;
	lk_scan ++;

	m2ua_t10ms();
}

int m2ua_restart()
{
	if (m2ua_command != M2UA_CMD_IDLE)
		return 0;
	else if (init_flag == 2)
	{
		m2ua_command = M2UA_CMD_STATUS_INIT;
		return 0;
	}
	
	return 1;
}
