/*
 * Area.c
 *
 *  Created on: 2025年12月2日
 *      Author: adan
 */
#include "CM_Types.h"
#include "CM_Memory.h"
#include "CM_Socket.h"
#include "CM_UDP.h"
#include "CM_Convert.h"
#include "PFM_Cfg.h"
#include "CM_Sem.h"
#include "CM_MultiThread.h"
#include "CM_MultiThread_Priority.h"
#include "CM_Time.h"
#include "DFM_Time.h"
#include "MSCP_Define.h"
#include "PFM_LOG.h"
#include "DFM_Time.h"
#include "CM_CRC32.h"
#include "Area_Net.h"
#include "MSCP_APP_Interface.h"
#include "CM_MQ.h"
#include "stdarg.h"

static CM_MQ_Struct_T s_AreaLogMsgQ;
 /**
 * @brief UDP接收线程
 * @param arg 指向STRU_CFM_RECV_CTRL的指针
 * @details
 * 创建本线程之前应先配置好STRU_CFM_RECV_CTRL，包括创建阻塞通信的socket
 * 本线程将以阻塞方式接收UDP报文并写入线程接收队列
 */
 CM_THREAD_FUNC_T t_Area_2oo2_UdpRecvThread(IN CM_Thread_Arg_Struct_T* arg)
 {
     /*- 变量初始化 */
 	 STR_Area_Net_Cfg* pCtrl = (STR_Area_Net_Cfg*)arg; /* 线程控制信息 */
     ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
     CM_UINT8* rcvBuf = NULL;
     CM_INT32 len; /* 报文长度 */
     CM_UINT32 srcIP;/* 源IP */
     CM_UINT16 srcPort;/* 源端口 */
     CM_SOCKADDR_T addr;/* 地址转换*/
     CM_UINT32 cpu_mask = 0;
     /*- 本线程锁定在 A53 core 1 */
     cpu_mask = (0x04u);
     set_thread_affinity(cpu_mask);
     MSCP_LOG_MSG("IP:%s:%d UDP recv Start\n", pCtrl->IP_Local, pCtrl->Port);
     /*- 循环接收UDP数据 */
     while (1)
     {
     	/*- UDP阻塞接收 */
 		rcvBuf = CM_MQ_Get_BufAddr(&pCtrl->MsgQ);
 		if(NULL != rcvBuf)
 		{
 			len = CM_UDP_Recv_Msg(pCtrl->Socket, &rcvBuf[0u], (CM_INT32)CM_UNSIGNED_SHORT_EXP(pCtrl->MsgQ.maxMsgSize), &srcIP, &srcPort);
 			/*- 是否收到有效数据 */
 			if (len > 0)
 			{
 				/*- 源IP端口是否合法 */
 				if ((srcIP == inet_addr(pCtrl->IP_Pear)) && (srcPort== pCtrl->Port))
 				{
 					/*- 保存通信数据 */
 					rt = CM_MQ_UpData(&pCtrl->MsgQ,(CM_UINT16)CM_SIGNED_INT_EXP(len));
 					/*- 数据保存是否成功 */
 					if (ENUM_CM_TRUE == rt)
 					{
 						/*成功无操作*/
 					}
 					else
 					{
 						/*- 防御性清空*/
 						MSCP_LOG_MSG("port %d rx overflow(msgLen=%d),t\n", pCtrl->Port, len);
 						rt = CM_MQ_Clear(&pCtrl->MsgQ);
 						CM_RE_ASSERT(ENUM_CM_TRUE == rt, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_1);
 					}
 				}
 				else
 				{
 					/*- 来自非预期IP端口的数据*/
 					addr.sin_addr.s_addr = srcIP;
 					MSCP_LOG_MSG("rx err want port:%d src [%s:%d]:%d \n", pCtrl->Port, inet_ntoa(addr.sin_addr), srcPort, len);
 					CM_RE_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_2);
 				}
 			}
 			else
 			{
 				/*- 接收出错 */
 				MSCP_LOG_MSG("warning ASSERT1103: port %d rx err(len=%d)\n", pCtrl->Port, len);
 				(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(NET_MODE, DARK_FAULT_CODE_FUN_ORDER_8, TSCP_DARK_ASSERT_1));
 			}
 		}
 		else
 		{
 			/*获取队列指针失败，清空队列*/
 			rt = CM_MQ_Clear(&pCtrl->MsgQ);
 			MSCP_LOG_MSG("buf clear\n");
 			CM_RE_ASSERT(ENUM_CM_TRUE == rt, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_4);
 		}
     }
     return NULL;
 }


 CM_THREAD_FUNC_T t_Area_UdpRecvThread(IN STR_Area_IP_Cfg* arg)
 {
     /*- 变量初始化 */
	 STR_Area_IP_Cfg* pCtrl = (STR_Area_IP_Cfg*)arg; /* 线程控制信息 */
     ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
     CM_UINT8* rcvBuf = NULL;
     CM_INT32 len; /* 报文长度 */
     CM_UINT32 srcIP;/* 源IP */
     CM_UINT16 srcPort;/* 源端口 */
     CM_SOCKADDR_T addr;/* 地址转换*/

     CM_UINT32 cpu_mask = 0;
     /*- 本线程锁定在 A53 core 1 */
     cpu_mask = (0x04u);
     set_thread_affinity(cpu_mask);
     MSCP_LOG_MSG("IP:%s:%d UDP recv Start\n", pCtrl->IP_Local, pCtrl->port);
     /*- 循环接收UDP数据 */
     while (1)
     {
     	/*- UDP阻塞接收 */
 		rcvBuf = CM_MQ_Get_BufAddr(&pCtrl->MsgQ);
 		if(NULL != rcvBuf)
 		{
 			len = CM_UDP_Recv_Msg(pCtrl->Socket, &rcvBuf[0u], (CM_INT32)CM_UNSIGNED_SHORT_EXP(pCtrl->MsgQ.maxMsgSize), &srcIP, &srcPort);
 			/*- 是否收到有效数据 */
 			if (len > 0)
 			{
 				/*- 源IP端口是否合法 */
 				if ((srcIP != 0) && (srcPort != 0))
 				{
 					/*- @alias 将收到的报文写入线程接收队列 */
// 					MSCP_LOG_MSG("!!! area recv len = %d \r\n",len);
 					/*- 保存通信数据 */
 					rt = CM_MQ_UpData(&pCtrl->MsgQ,(CM_UINT16)CM_SIGNED_INT_EXP(len));
 					/*- 数据保存是否成功 */
 					if (ENUM_CM_TRUE == rt)
 					{
 						/*成功无操作*/
 					}
 					else
 					{
 						/*- 防御性清空*/
 						rt = CM_MQ_Clear(&pCtrl->MsgQ);
 						CM_RE_ASSERT(ENUM_CM_TRUE == rt, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_1);
 					}

 				}
 				else
 				{
 					/*- 来自非预期IP端口的数据*/
 					addr.sin_addr.s_addr = srcIP;
 					CM_RE_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_2);
 				}
 			}
 			else
 			{
 				/*- 接收出错 */
 				MSCP_LOG_MSG("warning ASSERT1103: port %d rx err(len=%d)\n", pCtrl->port, len);
 				(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(NET_MODE, DARK_FAULT_CODE_FUN_ORDER_8, TSCP_DARK_ASSERT_1));
 			}
 		}
 		else
 		{
 			/*获取队列指针失败，清空队列*/
 			rt = CM_MQ_Clear(&pCtrl->MsgQ);
 			MSCP_LOG_MSG("buf clear\n");
 			CM_RE_ASSERT(ENUM_CM_TRUE == rt, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_11, TSCP_DARK_ASSERT_4);
 		}
     }
     return NULL;
 }

 ENUM_CM_RETURN Area_LogMQ_Init(void)
 {
	 return CM_MQ_Init(&s_AreaLogMsgQ, (CM_UINT16)CFM_INNET_LOG_SIZE, (CM_UINT16)(CFM_INNET_LOG_SIZE));
 }
 /**
 * @brief 平台记录格式化字符串日志
 * @param filename 文件路径
 * @param func 函数名
 * @param line 行号
 * @param fmt 格式化字符串
 */
void Area_LOG_MSG(IN const CM_CHAR *filename, IN CM_INT32 line, IN const CM_CHAR* fmt, ...)
 {
     /*- 变量初始化 */
     va_list argList;
     CM_CHAR msgBuf[1024];
     CM_INT32 headLen = 0;
 	CM_INT32 msgLen = 0;
 	if(NULL == fmt)
 	{
 		/* 无处理 */
 	}
 	else
 	{
 		/*- 记录文件名、函数名、行号 */
 		headLen = snprintf(msgBuf, sizeof(msgBuf), "ps_Area:%s:%d:", filename, line);
 		va_start(argList, (fmt));
 		/*- 记录日志内容 */
 		msgLen += vsnprintf(msgBuf + headLen, sizeof(msgBuf) - (CM_SIZE_T)headLen, fmt, argList);
 		va_end(argList);
 #ifdef WIN32
 		Bootprintf("%s", msgBuf + headLen);
 #endif
 	    /*printf("%s", msgBuf + headLen);*/
 	    /*- 输出日志信息 */
 	    CM_MQ_Write((CM_MQ_Struct_T*)&s_AreaLogMsgQ, (CM_UINT8*)msgBuf, (CM_UINT16)headLen + msgLen);
 	}
 }
 /*日志转换*/
 void Area_LOG_Transition(void)
 {
 	ENUM_CM_RETURN rt = ENUM_CM_FALSE;
 	CM_UINT8 buf[1024] = {0};
 	CM_UINT16 len = 1024;
 	while(1)
 	{
 		len = 1024;
 		rt = CM_MQ_Read(&s_AreaLogMsgQ, buf, (CM_UINT16*)&len);
 		if(ENUM_CM_TRUE == rt)
 		{
 		    /*- 输出日志信息 */
 		    (void)CFM_BaseLog_Send((CM_UINT8*)buf, len);
 		}
 		else
 		{
 			/*无处理*/
 			break;
 		}
 	}
 }
