/******************************************************************************
版权所有：	
文件名称：	net_debug.c
文件版本：	01.01
创建作者:	   sunxi
创建日期：	2012-11-07
功能说明：	网络调试接口
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include "head.h"
#ifdef LINUX_KERNEL_APP
#include <linux/delay.h> 
#include <linux/syscalls.h>
#include <linux/signal.h>
#else
#include <pthread.h>
#include <sys/prctl.h>
#endif
/*------------------------------- 宏定义 --------------------------------------
*/


/*------------------------------ 类型结构 -------------------------------------
*/


/*------------------------------ 全局变量 -------------------------------------
*/
#ifdef LINUX_KERNEL_APP
static struct task_struct * g_ts_debug_send;
static struct task_struct * g_ts_debug_recv;
#else
static pthread_t g_ts_debug_recv = 0;
#endif

SOCKET g_debug_client = RT_SOCKET_ERR;

unsigned char g_net_debug_buf[NET_RECV_MAX];  // 以太网接收缓冲区

int g_print_to_net;
int g_print_time;

int g_print_comm_raw;
int g_print_101;
int g_print_104;
int g_print_lnk;
int g_print_hmi;
int g_print_can;
int g_print_can_monitor;
int g_print_sys;
int g_print_dd;
int g_print_goose;

u32 g_print_port= -1; // 允许打印的串口通道，用位表示

int g_test_on;

extern struct semaphore 	g_print_sem;

#ifdef LINUX_KERNEL_APP
extern struct semaphore 	g_print_sem;

static pid_t g_net_debug_thread_send_pid ;
static pid_t g_net_debug_thread_recv_pid ;
static int g_net_debug_send_exit_flag = 0;
#endif

static  volatile int g_net_debug_sock_flag = NET_SOCKET_INIT;//关闭SOCKET标志
static int g_net_debug_recv_exit_flag = 0;
DEBUG_COMM g_tDebug; //定义下载串口结构
/*------------------------------ 函数声明 -------------------------------------
*/
void _net_debug_recv_reset(void);
void _net_debug_print_reset(void);
#ifdef LINUX_KERNEL_APP
int _net_debug_thread_send(void * unused);
#endif
int _net_debug_thread_recv(void * unused);


/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/

//设置socket关闭标志并等待socket关闭完成
void net_debug_set_sock_closing(int no)
{
	struct sockaddr_in local_addr;
	unsigned int len = sizeof(local_addr);
	RUN_PARA *pRunPara=&tRunPara;
	unsigned int ip=0;
	int bflag = 0;

	//如果有客户端连接
	if(g_debug_client != RT_SOCKET_ERR)
	{
		//获取客户端连接的IP
		rt_getsockname(g_debug_client, (struct sockaddr *)&local_addr,  &len);
		

		#if 1
		if(pRunPara->tNetPara[no].old_index==0)
		{
			//获取网卡IP
			rt_if_ip_get(pRunPara->tNetPara[no].old_ethid, (unsigned char *)&ip);//sunxi: 20220825 335x
		}
		else
		{
			//获取虚拟网卡上的IP地址
			rt_if_ip_get2(pRunPara->tNetPara[no].old_ethid, pRunPara->tNetPara[no].old_index, (unsigned char *)&ip);//sunxi: 20220825 335x
		}

		//如果是该网卡的IP并且该网卡要修改IP或MASK,则需要通知关闭socket
		if((htonl (ip)==local_addr.sin_addr.s_addr) && pRunPara->tNetPara[no].bInit)//sunxi: 20220825 335x
		{
			bflag = 1;
		
		}		
		#endif

			
		//该网卡的IP和MASK没有修改,则不需要通知关闭socket
		if(!bflag)
		{
			return;
		}

		g_net_debug_sock_flag = NET_SOCKET_CLOSING; //置关闭标志
		
		//等待关闭完成
		while(g_net_debug_sock_flag != NET_SOCKET_CLOSED)
		{
			msleep(20);
		}	
	}
}

//设置socket重新创建标志
void net_debug_set_sock_initflag(void)
{
	if(g_net_debug_sock_flag == NET_SOCKET_CLOSED)
	{
		g_net_debug_sock_flag = NET_SOCKET_REINIT;	
	}
}

//
#ifdef LINUX_KERNEL_APP
int net_debug_s_init(void)
{
	struct sched_param sp;
	pid_t pid;
	
#if 1
		// 如果已经初始化，退出
		if(g_ts_debug_send)
		{
			return 0;
		}
		
		
		// 运行应用调试线程
		//g_ts_debug_send = kthread_run(_net_debug_thread_send,NULL,"net_debug_send");
		pid = kernel_thread(_net_debug_thread_send, NULL,CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
		g_ts_debug_send = find_task_by_vpid(pid);	
		if(IS_ERR(g_ts_debug_send))
		{
			printk("ts=%p\r\n",g_ts_debug_send);
			g_ts_debug_send = NULL;
			return -1;
		}
		g_net_debug_thread_send_pid = pid;
		memset(&sp,0,sizeof(sp));
		sp.sched_priority = 8;
		sched_setscheduler(g_ts_debug_send,SCHED_FIFO,&sp);
		// 设置进程名字
		set_task_comm(g_ts_debug_send, "net_debug_send");

#endif

	return 0;

}
#else
int net_debug_s_init(void)
{
	return 0;
}
#endif

#ifdef LINUX_KERNEL_APP
int net_debug_s_exit(void)
{
	int status;

	if(g_ts_debug_send != NULL)
	{
		up(&g_print_sem);
		g_net_debug_send_exit_flag = 1;
		
		sys_wait4(g_net_debug_thread_send_pid, (int __user *)&status, 0, NULL);
		
		g_ts_debug_send = NULL;
			
	}
	return 0;
}
#else
int net_debug_s_exit(void)
{
	return 0;
}
#endif

//   TODO: 需要确认是否需要重新初始化
int net_debug_init(void)
{
	int ret;
	pthread_attr_t attr;

	//attr.__schedpolicy = SCHED_FIFO;
	//attr.__schedparam.sched_priority =8;

	// 设置调度策略和优先级
	pthread_attr_init(&attr);
	pthread_attr_setschedpolicy(&attr, SCHED_FIFO);  //调度
	struct sched_param s_parm;
	//s_parm.sched_priority = sched_get_priority_max(SCHED_FIFO);
	s_parm.sched_priority = 8;
	pthread_attr_setschedparam(&attr, &s_parm); 	//优先级

	ret = pthread_create(&g_ts_debug_recv, &attr, (void *)_net_debug_thread_recv, NULL);
	if(!ret)
	{
		rt_printf("ret = %d, err = %s\r\n", ret, strerror(ret));
		//g_ts_rcd = 0;
		return ret;
	}

	return 0;
}

#ifdef LINUX_KERNEL_APP
int net_debug_exit(void)
{
	int status;
	#if 0
	if(g_ts_debug_send != NULL)
	{
		up(&g_print_sem);
		g_net_debug_send_exit_flag = 1;
		
		sys_wait4(g_net_debug_thread_send_pid, (int __user *)&status, 0, NULL);
		
		g_ts_debug_send = NULL;
			
	}
	#endif
	if(g_ts_debug_recv != NULL)
	{
		g_net_debug_recv_exit_flag = 1;
		
		sys_wait4(g_net_debug_thread_recv_pid, (int __user *)&status, 0, NULL); 
		
		g_ts_debug_recv = NULL;
			
	}
	
	return 0;
}
#else
int net_debug_exit(void)
{
	if(g_ts_debug_recv)
	{
		g_net_debug_recv_exit_flag = 1;
		
		// sys_wait4(g_net_debug_thread_recv_pid, (int __user *)&status, 0, NULL);
		pthread_join(g_ts_debug_recv, NULL);
		
		g_ts_debug_recv = 0;
			
	}
	
	return 0;

}

#endif 

// 此函数必须在线程中调用，不能在中断中调用。
int net_debug_send(unsigned char *buf,int len)
{
	if(g_debug_client == RT_SOCKET_ERR)
	{
		return 0;
	}

	return	rt_send(g_debug_client,buf,len,0);
}

#ifdef METERING_ENERGY
const char main_Debug[]=
"\r\n*********装置调试菜单*******\r\n \
0：通讯原始数据监视[通道可选]\r\n \
1：101报文监视[通道可选]\r\n \
2：104报文监视[通道可选]\r\n \
3：CAN报文监视\r\n \
4：系统信息监视\r\n \
5：报文时标开启\r\n \
6：关闭所有监视\r\n \
7：面板报文监视\r\n \
8：CAN总线监视\r\n \
A：载入默认公钥\r\n \
B：加密测试\r\n \
C：SOE测试\r\n \
D：重启系统\r\n \
E：打印点表\r\n \
F: 级联报文监视[通道可选]\r\n \
G:goose报文监视\r\n \
H:文件召唤测试\r\n \
I:程序升级测试\r\n \
J:打印终端固有参数\r\n \
K:新生成soe.xml文件\r\n \
L:新生成co.xml文件\r\n \
M:清零电压合格率\r\n \
N:清零脉冲计数值\r\n \
P:61850信息打印\r\n \
Q:生成菜单显示文件\r\n \
R:生成icd文件\r\n \
S:计量板校准\r\n \
T:计量电能清零\r\n \
U:CAN子板ID打印\r\n \
其它：关闭所有监视信息\r\n \
\r\n>:";
#else
const char main_Debug[]=
"\r\n*********装置调试菜单*******\r\n \
0：通讯原始数据监视[通道可选]\r\n \
1：101报文监视[通道可选]\r\n \
2：104报文监视[通道可选]\r\n \
3：CAN报文监视\r\n \
4：系统信息监视\r\n \
5：报文时标开启\r\n \
6：关闭所有监视\r\n \
7：面板报文监视\r\n \
8：CAN总线监视\r\n \
A：载入默认公钥\r\n \
B：加密测试\r\n \
C：SOE测试\r\n \
D：重启系统\r\n \
E：打印点表\r\n \
F: 级联报文监视[通道可选]\r\n \
G:goose报文监视\r\n \
H:文件召唤测试\r\n \
I:程序升级测试\r\n \
J:打印终端固有参数\r\n \
K:新生成soe.xml文件\r\n \
L:新生成co.xml文件\r\n \
M:清零电压合格率\r\n \
N:清零脉冲计数值\r\n \
P:61850信息打印\r\n \
Q:生成菜单显示文件\r\n \
R:生成icd文件\r\n \
r:查看实时线程状态\r\n \
s:复位实时线程状态\r\n \
S:ADC采样状态\r\n \
其它：关闭所有监视信息\r\n \
\r\n>:";
#endif

BYTE arrApn[48];
extern int	g_soe_test;

int _net_debug_get_chn(void)
{
	int chn;

	if(g_tDebug.cRecvCnt >= 3)
	{
		chn = g_tDebug.arrRecvBuf[2] - '0';
		if(chn >=0 && chn < COMM_CHANNEL_NUM)
		{
			g_print_port = 1<<chn;
			return chn;
		}
	}

	return -1;
}

extern int dt_cmd_rt(void);
extern int dt_cmd_adc(void);
extern int dt_cmd_rt_reset(void);
void net_debug_app(void)
{
	u8 ch;
	int chn;
	int ret=-1;
#ifdef CAN_SLAVE_BOARD
	static bool sb_metering=false;
#endif
	
	if(!g_tDebug.bData)
	return;
	
	g_tDebug.bData=false;

	//超级终端处理
	ch=g_tDebug.arrRecvBuf[g_tDebug.cRecvCnt-1];	
	if(ch!=0x0d)  // 回车键
	{
		_net_debug_recv_reset();
		return;
	}

	// 前7个和维护工具配合使用，不可改变
	switch(g_tDebug.arrRecvBuf[0])
	{			
		case '0':            
			g_print_comm_raw = 1;
			g_print_to_net = 1;
			chn = _net_debug_get_chn();
			rt_printf("\r\n打开串口原始数据监视[chn=%d]:\r\n",chn);
 		break;
		
		case '1':            
			g_print_101 = 1;
			g_print_to_net = 1;
			chn = _net_debug_get_chn();
			rt_printf("\r\n打开101报文监视[chn=%d]:\r\n",chn);
		break;
		
		case '2':            
			g_print_104 = 1;
			g_print_to_net = 1;
			chn = _net_debug_get_chn();
			rt_printf("\r\n打开104报文监视[chn=%d]:\r\n",chn);
		break;
		
		case '3':         
			g_print_can = 1;
			g_print_to_net = 1;
			rt_printf("\r\n打开CAN报文监视:\r\n");
		break;
		case '4':            
			g_print_sys = 1;
			g_print_to_net = 1;
			rt_printf("\r\n打开系统监视:\r\n");
		break;
		
		case '5':  
			g_print_time = 1;
			rt_printf("\r\n报文时标开启:\r\n");
		break;
		
		case '6':  
			g_print_to_net = 1;
			g_print_port = -1;
			rt_printf("\r\n所有报文监视关闭:\r\n");
			_net_debug_print_reset();
		break;
		
		case '7':  
			g_print_hmi = 1;
			g_print_to_net = 1;
			rt_printf("\r\n打开面板报文监视:\r\n");

		break;
		
		case '8':            
			g_print_can_monitor= 1;
			g_print_to_net = 1;

		break;
		
		case 'A':         
		case 'a':         
			g_print_to_net = 1;
		#ifdef ENCRYPT_SM2
			InitSM2Key();					
			rt_printf("\r\n公钥保存成功\r\n");
		#else
			rt_printf("\r\n不支持SM2加密\r\n");
		#endif			
		break;	
		case 'B':         
		case 'b':   
			g_print_sys = 1;
			g_print_to_net = 1;
		#ifdef ENCRYPT_SM2
			encrypt_test();
		#else
			rt_printf("\r\n不支持SM2加密\r\n");
		#endif			
		break;
		case 'C':         
		case 'c':   
			g_print_to_net = 1;
			g_soe_test = 1;
		break;
		case 'D':         
		case 'd':   
			g_print_to_net = 1;
			rt_printf("\r\n系统重新启动\r\n");	
			Delayms(dTCounter,T_1s);
			watchdog_reset_cpu(4);
		break;
		case 'E':         
		case 'e':   
			g_print_to_net = 1;
			tbl_printf_cvs();			
		break;
		case 'f':
		case 'F':
			g_print_lnk = 1;
			g_print_to_net = 1;
			chn = _net_debug_get_chn();
			rt_printf("\r\n打开级联报文监视[chn=%d]:\r\n",chn);
		break;
	
	
		case 'J':         
		case 'j': 
			{
				extern void iec_printfihertset(void);
				g_print_to_net = 1;
				rt_printf("\r\n-----配电终端固有参数-----------\r\n");	
				iec_printfixedset();
				g_print_dd = 1;
			}

		break;	

		case 'h':         
		case 'H':   
			{
				g_print_to_net = 1;
				g_print_lnk = 1;
				lnk_read_test_file();			
			}
			break;
		case 'i':         
		case 'I':   
			{
				g_print_to_net = 1;
				g_print_lnk = 1;
				lnk_write_test_file();			
			}

		case 'G':            
		case 'g':            
			g_print_goose= 1;
			g_print_to_net = 1;
			g_print_port = -1;
			//_net_debug_get_chn();
			rt_printf("\r\n打开goose报文监视:\r\n");
		break;
		case 'k':
		case 'K':
			g_print_to_net = 1;
		
			ret = del_history_file(HS_FILE_SOE);

			if(!ret)
			{
				ret = create_event_rcd_file(HS_FILE_SOE);
			}

			if(!ret)
			{
				rt_printf("新生成soe.msg文件成功\r\n");	
			}
			else
			{
				rt_printf("新生成soe.msg文件失败\r\n");	
			}
			break;

			
		case 'l':
		case 'L':
			g_print_to_net = 1;

			ret = del_history_file(HS_FILE_CO);

			if(!ret)
			{
				ret = create_event_rcd_file(HS_FILE_CO);
			}

			if(!ret)
			{
				rt_printf("新生成co.msg文件成功\r\n");	
			}
			else
			{
				rt_printf("新生成co.msg文件失败\r\n");	
			}
			break;

			

		case 'M':         
		case 'm':         
			g_print_to_net = 1;
			SaveUqua(true);			
			rt_printf("\r\n电压合格率清零\r\n");	
		break;	
		case 'N':         
		case 'n':         
			g_print_to_net = 1;
			{
				int sw;
				for(sw=0;sw<SWITCH_NUM_MAX;sw++)
				{
					g_sw[sw].ac_in[SW_AC_IN_IMP1]=0;
					g_sw[sw].ac_in[SW_AC_IN_IMP2]=0;
				}
			}
			rt_printf("\r\n脉冲计数率清零\r\n");	
		break;	

		case 'P':         
		case 'p':         
		{
			void app_goose_inf_print(void);
			g_print_to_net = 1;
		#ifdef __IEC61850_GOOSE_FUNC__
			app_goose_inf_print();
		#endif
		}
		break;	

		case 'Q':         
		case 'q':         
		{
			void mmd_create_menufile(void);
			g_print_to_net = 1;
			mmd_create_menufile();
			rt_printf("\r\n/app/data/lcd_menu.csv 菜单定义文件已生成\r\n");	
		}		
		break;	
    
		case 'r':         
		{
			g_print_to_net = 1;
			dt_cmd_rt();
		}
		break;

		case 'S':         
		{
			g_print_to_net = 1;
			dt_cmd_adc();
		}
		break;

		case 's':         
		{
			g_print_to_net = 1;
			dt_cmd_rt_reset();
		}
		break;
#ifdef CAN_SLAVE_BOARD

		case 'R':         
		case 'r':         
		{
			g_print_to_net = 1;
			can_id_printf();
		}
		break;

		case 'S':         
		case 's':         
		{
			sb_metering = true;
			g_print_to_net = 1;
			can_metering_calib(g_tDebug.arrRecvBuf);
		}
		break;
		case 'T':         
		case 't':         
		{
			g_print_to_net = 1;
			can_app_energy_clear(0, get_can_slot(0));
		}
		break;
		case 'U':         
		case 'u':         
		{
			g_print_to_net = 1;
			can_id_printf();
		}
		break;
	#endif
	
		default:
		#ifdef CAN_SLAVE_BOARD
			ret = 0;
			g_print_to_net = 1;

			if(sb_metering)
			{
				ret = can_metering_calib(g_tDebug.arrRecvBuf);
			}

			if(!ret)
		#endif
			{
				_net_debug_print_reset();
				
				net_debug_send((unsigned char *)main_Debug,sizeof(main_Debug));
				
				g_print_sys=false;
			}
		break;
	}
	
	_net_debug_recv_reset();
}

 
void print_mem_net(char *addr,unsigned char *pd,int lenth)
{

	BYTE i,j;
	char buf[128],tempstr[8];

	if(addr!=NULL)
	{
		sprintf(buf,"%s",addr);
		rt_printf(buf);	
	}
	strcpy(buf,"");

	for(i=0,j=0;i<lenth;i++)
	{
		sprintf(tempstr,"%02X ",*pd++);
		strcat(buf,tempstr);
		j++;
		if(j>18)
		{
			rt_printf(buf);
			strcpy(buf,"\r\n    ");
			j=0;
		}
	}
	if(j>0)
	{	
		rt_printf(buf);
	}
		rt_printf("\r\n");
	

}




/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/
 void _net_debug_recv_reset(void)
{
	g_tDebug.cTypeCounter=0;
	g_tDebug.cRecvCnt=0;
}


void _net_debug_print_reset(void)
{
	g_print_to_net = 0;
	g_print_time = 0;

	g_print_101 = 0;
	g_print_104 = 0;
	g_print_lnk = 0;
	g_print_hmi = 0;
	g_print_can = 0;
	g_print_can_monitor= 0;
	g_print_sys = 0;
	g_print_dd = 0;
	g_print_comm_raw = 0;
	g_print_port = -1;
	g_test_on = 0;
	g_print_goose=0;
}

void _net_debug_recv(BYTE cRcvData) 
{
	if(g_tDebug.bData)
	{
		return;
	}

	//xshell 发送的保活状态消息
	if(cRcvData == 0xff || cRcvData == 0xf1)
	{
		return;
	}
	
	//rt_printf("cRcvData=%02x\r\n",cRcvData);
	
	g_tDebug.arrRecvBuf[g_tDebug.cRecvCnt++]=cRcvData;
	if(cRcvData == 0x0d)
	{
		g_tDebug.bData=true;
	}
	if(g_tDebug.cRecvCnt >= UART_FRAME_LEN)
	{
		_net_debug_recv_reset();
		return;
	}
	return;

}  

#ifdef LINUX_KERNEL_APP
int _net_debug_thread_send(void * unused)
{

	
	while(1)
	{
		msleep(100);

		// 检查是否退出
		if(g_net_debug_send_exit_flag)
		{
			g_net_debug_send_exit_flag = 0;
			return 0;
		}
		//noted by sunxi: 20220701 统一冷火和335x，有信号量，才往下执行
		if(down_interruptible(&g_print_sem)<0)
		{
			continue;
		}

		rt_printf_fifo_get(1);
	}

	return 0;
}
#endif

/*
noted by sunxi：20220825  335x 修复 6000端口超时或断开后，不能重连的问题

*/
int _net_debug_thread_recv(void * unused)
{
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	struct linger  ling;
#ifndef LINUX_KERNEL_APP
	struct timeval timeout;
#endif

	SOCKET sk_server,tmp_sock; 
	
	int sin_size;
	int i,len,ret;
	unsigned char *ip;
#ifdef LINUX_KERNEL_APP	
	unsigned int recv_timeout;
	unsigned int link_timeout = dTCounter;
#else
	int recv_timeout;
	int link_timeout = 0;
#endif
	unsigned int ip_server;

//	while(1) //noted by sunxi：20220825  335x 修复 6000端口超时或断开后，不能重连的问题
//	{
NET_BEGIN:

	// 1、建立socket并侦听
	// 服务器端开始建立socket描述符
#ifdef LINUX_KERNEL_APP	
	sk_server = rt_socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0);
#else
	sk_server = rt_socket(AF_INET, SOCK_STREAM, 0);
#endif
	if (sk_server == RT_SOCKET_ERR)
	{
		RT_PRINTF_POSITION();
		g_ts_debug_recv = NULL;
		return -1;
	}

	// 服务器端填充sockaddr结构
	memset (&server_addr, 0, sizeof (struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	if(get_mt_port_proc()==NET_MT_PORT_PROC_2)
	{
		if(rt_if_ip_get2(0,  3, (unsigned char *)&ip_server)==0)
		{
			server_addr.sin_addr.s_addr = htonl (ip_server);	
		}
		else
		{
			server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
		}
	}
	else
	{
		server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
	}		

	server_addr.sin_port = htons (NET_DEBUG_PORT);

	// 捆绑sockfd描述符
	ret = rt_bind (sk_server, (struct sockaddr *)(&server_addr), sizeof (struct sockaddr));
	if (ret < 0)
	{
		RT_PRINTF_POSITION();
		rt_socket_close (sk_server);
		g_ts_debug_recv = NULL;
		
		return -2;
	}

	// 监听sockfd描述符
	ret = rt_listen (sk_server, 1);
	if (ret < 0)
	{
		RT_PRINTF_POSITION();
		rt_socket_close (sk_server);
		g_ts_debug_recv = NULL;
		
		return -3;
	}
#ifndef LINUX_KERNEL_APP
	// 设置接收超时
	timeout.tv_sec  = 0;
	timeout.tv_usec = 500000;
	rt_setsockopt(sk_server,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout ,sizeof(struct timeval));
#endif	

	// 设置关闭延时
	ling.l_onoff = 1;
	ling.l_linger = 0;
	rt_setsockopt(sk_server,SOL_SOCKET,SO_LINGER,(char *)&ling ,sizeof(struct linger));
	
	prctl(PR_SET_NAME, "_net_debug_recv");
	while(1) //noted by sunxi：20220825  335x 修复 6000端口超时或断开后，不能重连的问题
	{		
		g_debug_client = RT_SOCKET_ACCEPT_RST;
		// 2、接受外部链接
		#ifdef RT_SOCKET_FD
		while(g_debug_client < 0)
		#else
		while(g_debug_client == RT_SOCKET_ACCEPT_RST)
		#endif	
		{
			msleep(100);
			
			// 服务器阻塞，直到客户程序建立连接
			sin_size = sizeof (struct sockaddr_in);
			g_debug_client = rt_accept (sk_server, (struct sockaddr*)(&client_addr), &sin_size);

			// 检查是否退出
			//if(kthread_should_stop())
			if(g_net_debug_recv_exit_flag)
			{
				// 关闭客户端
				if(g_debug_client != RT_SOCKET_ERR)
				{
					tmp_sock = g_debug_client;
					g_debug_client = RT_SOCKET_ERR;
					rt_socket_close (tmp_sock);
				}
				// 关闭服务器
				rt_socket_close (sk_server);
				g_net_debug_recv_exit_flag= 0;	
				return 0;
			}
			//IP已经修改要关闭SOCKET
			if(g_net_debug_sock_flag == NET_SOCKET_CLOSING)
			{
				// 关闭客户端
				if(g_debug_client != RT_SOCKET_ERR)
				{
					tmp_sock = g_debug_client;
					g_debug_client = RT_SOCKET_ERR;
					rt_socket_close (tmp_sock);
				}

				// 关闭服务器
				rt_socket_close (sk_server);
				//置已经关闭标志
				g_net_debug_sock_flag = NET_SOCKET_CLOSED;
				//等待IP修改完成
				while(g_net_debug_sock_flag != NET_SOCKET_REINIT)
				{
					msleep(100);	
				}
				//置为初始化
				g_net_debug_sock_flag = NET_SOCKET_INIT;
				goto NET_BEGIN;
			}			

		}

		
		// 3、关闭侦听socket，避免多个外部连接
		//rt_shutdown(sk_server, SHUT_RDWR);
		//rt_socket_close(sk_server); //noted by sunxi：20220825  335x 修复 6000端口超时或断开后，不能重连的问题
		
		ip = (unsigned char *)&client_addr.sin_addr.s_addr;
		rt_printf("debug client connect(ip=%d.%d.%d.%d)!\r\n",ip[0],ip[1],ip[2],ip[3]);
		{
			char buf[64];
			char log_info[128];
			sprintf(buf,"6000端口连接(%d#网络:IP=%d.%d.%d.%d)!\r\n", set_get_network_id_from_socket(g_debug_client)+1, ip[0],ip[1],ip[2],ip[3]);
			log_str_time(LOG_OPERATE,buf,0,1);
			sprintf(log_info,"6000 port connection(%d#net:IP=%d.%d.%d.%d)",set_get_network_id_from_socket(g_debug_client)+1, ip[0],ip[1],ip[2],ip[3]);
			load_hs_log_rcd(TYPE_CHNL_LINK,true,NULL,log_info,1);
		}

		
		// 4、客户端已连接，处理客户端命令
#ifdef LINUX_KERNEL_APP		
		recv_timeout=dTCounter;
#else
		recv_timeout=0;
#endif
		while(1)
		{
#ifdef LINUX_KERNEL_APP		
			msleep(2);//noted by sunxi: 20221212 设为非阻塞型
			len = rt_recv (g_debug_client, g_net_debug_buf, NET_RECV_MAX, MSG_DONTWAIT);
#else			
			len = rt_recv (g_debug_client, g_net_debug_buf, NET_RECV_MAX, 0);
#endif

			// 检查是否退出
			if(g_net_debug_recv_exit_flag)
			{
				// 关闭客户端
				tmp_sock = g_debug_client;
				g_debug_client = RT_SOCKET_ERR;
				rt_socket_close (tmp_sock);

				// 关闭服务器
				rt_socket_close (sk_server); //noted by sunxi：20220825  335x 修复 6000端口超时或断开后，不能重连的问题
				g_net_debug_recv_exit_flag = 0;
				return 0;
			}
			//IP已经修改要关闭SOCKET
			if(g_net_debug_sock_flag == NET_SOCKET_CLOSING)
			{
				// 关闭客户端
				tmp_sock = g_debug_client;
				g_debug_client = RT_SOCKET_ERR;
				rt_socket_close (tmp_sock);
				// 关闭服务器
				rt_socket_close (sk_server); //noted by sunxi：20220825  335x 修复 6000端口超时或断开后，不能重连的问题
				//置已经关闭标志
				g_net_debug_sock_flag = NET_SOCKET_CLOSED;
				//等待IP修改完成
				while(g_net_debug_sock_flag != NET_SOCKET_REINIT)
				{
					msleep(100);	
				}
				//置为初始化
				g_net_debug_sock_flag = NET_SOCKET_INIT;
				goto NET_BEGIN;	
			}	

#ifdef LINUX_KERNEL_APP
			if(len == -EAGAIN)
#else
			if((len == -EAGAIN)||(len==-1))//使用linux的recvfrom没有接收到数据时返回-1 		jack.liu 20200916
#endif				
			{
				if(rt_get_net_linkstatus(rt_get_netcard_id_from_socket(g_debug_client))==1)
				{
#ifdef LINUX_KERNEL_APP					
					if((dTCounter - link_timeout)>RT_LINK_TIMEOUT*T_1s) //500ms超时
#else
					link_timeout++;
					if(link_timeout>RT_LINK_TIMEOUT*2) //500ms超时
#endif					
					{
						rt_printf("%s: link down\n",__FUNCTION__);
#ifdef LINUX_KERNEL_APP						
						link_timeout  = dTCounter;
#else
						link_timeout  = 0;
#endif
						break;	
					}
				}
				else
				{
#ifdef LINUX_KERNEL_APP				
					link_timeout  = dTCounter;
#else
					link_timeout  = 0;
#endif
				}
				
				// 超时
#ifdef LINUX_KERNEL_APP				
				if((dTCounter -  recv_timeout)>120*T_1s)  // 超时2分钟，端口未收到数据，关闭端口
#else
				recv_timeout++;
				if(recv_timeout>240)  // 超时2分钟，端口未收到数据，关闭端口
#endif				
				{
					rt_printf ("net_debug_thread:timeout\r\n");
				
					break;
				}				
				continue;
			}
#ifdef LINUX_KERNEL_APP
			else if (len <= 0)
#else
			else if ((len == 0)||(len<-1)) //使用linux的recvfrom没有接收到数据时返回-1 		jack.liu 20200916
#endif				
			{
				//调用recv时，如果返回0，则表示对端关闭；返回负数，表示出错
				rt_printf ("net_debug_thread:peer close(ret=%d).\r\n",len);
				msleep(100);
				break;
			}
			
			// 接收数据
#ifdef LINUX_KERNEL_APP			
			recv_timeout = dTCounter;
			link_timeout  = dTCounter;
#else
			recv_timeout = 0;
			link_timeout  = 0;
#endif			
			for(i=0;i<len;i++)
			{
				_net_debug_recv(g_net_debug_buf[i]);
			}
			g_tDebug.bNet=true;
		}

		// 复位调试打印信息
		_net_debug_print_reset();

		// 关闭客户端socket
		tmp_sock = g_debug_client;
		g_debug_client = RT_SOCKET_ERR;
		{
			char buf[64];
			sprintf(buf,"6000端口关闭(%d#网络:IP=%d.%d.%d.%d)!\r\n", set_get_network_id_from_socket(tmp_sock)+1,ip[0],ip[1],ip[2],ip[3]);
			log_str_time(LOG_OPERATE,buf,0,0);
			load_hs_log_rcd(TYPE_CHNL_LINK,true,NULL,"6000 port disconnection",0);
		}
		rt_socket_close (tmp_sock);
	}

	// 理论上，程序不会运行到这儿
	return 0;
}

/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/


/*------------------------------ 文件结束 -------------------------------------
*/
