/**
* @file CFM_Raw.c
* @brief Communication Function Module: 网络透传通信
* @details
* 内网透传通信的实现
* @author GT-BU
* @date 2021.03.01
* @version V1.0
* @copyright TCT
* @par 修改日志
* <table>
* <tr><th>Date        <th>Version  <th>Author     <th>Description
* <tr><td>2021.03.01  <td>V1.0     <td>GT-BU      <td>创建初始版本
* </table>
*/
#include "CFM_Raw.h"
#include "CM_Convert.h"
#include "CFM_Net.h"
#include "PFM_Log.h"
#include "CM_Mutex.h"
#include "DFM_Time.h"
#include "SFM_2oo2.h"
#include "CM_Memory.h"
#include "PFM_Cfg.h"
#include "PFM_RemoteUpdate.h"
#include "CM_CRC32.h"
/**
* @brief 内网透传数据接收
* @param ch      内网透传通道序号，[1...n]有效
* @param Buf     接收内网透传数据指针
* @param bufSize 接收内网透传数据缓冲区大小
* @return 收到的内网透传数据帧长度
* @details
* 从通信层获取本周期内网透传输入数据
* 按内网透传接收帧打包后交给平台层
*/
static CM_UINT32 s_CFM_RawInfo_len = 0u;
static CM_UINT8  s_CFM_RawInfo[CFM_INNET_RAW_MSG_NUM_MAX * 12u];
static CM_UINT32 s_CFM_RawInfo_peer_len = 0u;
static CM_UINT8  s_CFM_RawInfo_peer[CFM_INNET_RAW_MSG_NUM_MAX * 12u];
/**
* @brief 内网透传接收（通用模式--原艾弗瑞模式）
* @param ch 透传通道号
* @buf 接收数组
* @bufSize 接收数组大小
* @maininfobuf 本机辅助信息数组
* @maininfolen 本机辅助信息数组长度
* @peerinfobuf 邻机辅助信息数组
* @peerinfolen 邻机辅助信息数组长度
* @infobufSize
* @return 接收数据长度
*/
CM_UINT32 CFM_RxInnetRaw_COM(IN CM_INT32 ch, OUT CM_UINT8* buf, IN CM_UINT32 bufSize,
							OUT CM_UINT8* maininfobuf,OUT CM_UINT32* maininfolen,
							OUT CM_UINT8* peerinfobuf,OUT CM_UINT32* peerinfolen,IN CM_UINT32 infobufSize)
{
    /*- 变量初始化 */
    CM_UINT32 len = 0u;
    CM_UINT8 CompareEnable = 0u;
    if(RAW_COM_DISENABLE == g_PFM_Cfg.Local_Cfg.Innet_Raw_Parameter[ch].Port_Type_Enable)
    {
    	/*禁用透传端口*/
    }
    else
    {

		/*- 是否开启2oo2功能 */
		if ((0x55u == g_PFM_Cfg.Local_Cfg.Innet_Raw_Parameter[ch].INNET_2oo2_RAW) &&
			(0x55u == g_PFM_Cfg.Local_Cfg.Innet_Raw_Parameter[ch].TIME_STAMP_ENABLE))
		{
			CFM_InnetRawClear_Mutex_Lock(ch);
			/*- 获取本机的内网透传通道特征信息 */
			s_CFM_RawInfo_len = CFM_InnetRaw_GetInfo(ch, s_CFM_RawInfo, (CM_UINT32)sizeof(s_CFM_RawInfo),&CompareEnable);
			/*- 将特征信息进行2oo2交换 */
			if(0x55u == g_PFM_Cfg.M_2oo2_Enable)
			{
				s_CFM_RawInfo_peer_len = (CM_UINT32)SFM_2oo2_Exchange_Currency(s_CFM_RawInfo, (CM_INT32)s_CFM_RawInfo_len, s_CFM_RawInfo_peer, (CM_UINT32)sizeof(s_CFM_RawInfo_peer), ENUM_2oo2_RAW_INFO);
			}
			else
			{
				/*二取开关未打开*/
			}
			/*MSCP_LOG_MSG("[%d]info:%d,%d\n", ch, s_CFM_RawInfo_len, s_CFM_RawInfo_peer_len);*/
			if(1u == CompareEnable)
			{
				/*- 对双机的特征信息进行比较，提取2oo2比较一致的内网透传接收报文*/
				len = CFM_InnetRaw_Rx(ch, buf, bufSize);
				MSCP_LOG_MSG("[%d]rx %u Info, %u bytes\n", ch, s_CFM_RawInfo_len/12u, len);
			}
			else
			{
				/*不比较数据，直接读取透传数据到缓冲区*/
				len = CFM_InnetRaw_Rx_Camera(ch, buf, bufSize,maininfobuf,maininfolen,peerinfobuf,peerinfolen,infobufSize);
				MSCP_LOG_MSG("[%d]rx %d Info,%u Minfo,%u Pinfo, %u bytes\n", ch, s_CFM_RawInfo_len/10u,*maininfolen,*peerinfolen, len);
			}
			CFM_InnetRawClear_Mutex_UnLock(ch);
		}
		else
		{
			/*- 从内网透传通道读取接收信息 */
			len = CFM_RxInnetRaw(ch, buf, bufSize);
		}

    }
    /*- 返回接收数据长度 */
    return len;
}
/**
* @brief 内网透传接收
* @param ch 内网透传通道号
* @param buf 接收数组
* @param bufSize 接收数组大小
* @return 接收数据长度
*/
CM_UINT32 CFM_RxInnetRaw(IN CM_INT32 ch, OUT CM_UINT8 *buf, IN CM_UINT32 bufSize)
{
    /*- 变量初始化 */
    CM_UINT32 rxLen = 0u;      /* 接收报文长度 */
    CM_UINT32 i = 0u;          /* 循环变量 */
    CM_UINT32 srcIP = 0u;    /* 源IP */
    CM_UINT16 srcPort = 0u;  /* 源端口 */
    CM_UINT16 devID = 0u;    /* 设备ID */
    STRU_PFM_INNET_CFG_T *pCom = NULL; /*通信配置信息*/

    CM_INT32 count = 0;

    /*- 循环接收内网透传数据 */
    do
    {
        /*- 从通信层读取通信数据 */
        rxLen = (CM_UINT32)CFM_InnetRaw_Recv(ch, buf + i + PFM_RAW_HEADER_SIZE, bufSize - (CM_UINT32)i - PFM_RAW_HEADER_SIZE, &srcIP, &srcPort); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
        /*- 是否读到了数据 */
        if (rxLen > 0u)
        {
            /*- 获取源ID */
            pCom = PFM_INI_InnetIP2Addr(srcIP, srcPort);

            if(NULL == pCom)
            {
            	devID = (CM_UINT16)ch;
            }
            else
            {
            	devID = pCom->InnetID;
            }
            
            count++;

            /*
            内网透传帧格式：
            4字节 长度（不含自身）
            2字节 源ID
            n字节 数据
            */
            /*- 填入接收队列 */
            CM_LongToChar((rxLen + PFM_RAW_DEVID_SIZE), buf + i); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
            CM_ShortToChar(devID, buf + i + PFM_RAW_LEN_SIZE);    /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
            /* i += (rxLen + 4); */
            i = i + (rxLen + PFM_RAW_HEADER_SIZE);
        }
        else
		{
			/*- 无处理 */
		}
    } while (rxLen > 0u);
    (void)CFM_DarkLog_Multiple(DARK_LOG_HEX, TSCP_DARK_CFMNET_INNETRAW_RECVLEN, 3U, 
									sizeof(CM_INT32),ch,
									sizeof(CM_INT32),count,
									sizeof(CM_UINT32),i);
    /*- @alias 记录接收信息数量 */
    MSCP_LOG_MSG("[%d]rx %d pkts, %d bytes\n", ch, count, i);

    /*- 返回报文总长度 */
    return i;
}
/**
* @brief 雷达数据的2oo2比较接收
* @param ch 通道号
* @param peer_info 邻机特征信息数组
* @param peer_len 邻机特征信息长度
* @param buf 2oo2通过的接收信息数组
* @param buf_size 接收信息数组大小
* @return 2oo2通过的接收信息长度
* @details
* 核心算法描述如下：
* while(!local.empty() && !peer.empty())
* {
*      info_local = local.front();
*      info_peer = peer.front();
*      if (info_local.ts == info_peer.ts)
*      {
*           if (info_local.crc == info_peer.crc)
*           {
*               app.push(info_local.msg);
*           }
*           local.pop();
*           peer.pop();
*       }
*       else if (info_local.ts < info_peer.ts)
*       {
*           local.pop();
*       }
*       else
*       {
*           peer.pop();
*       }
* }
*/
CM_UINT32 CFM_InnetRaw_Rx(IN CM_INT32 ch, OUT CM_UINT8 buf[], IN CM_UINT32 buf_size)
{
    /*- 变量初始化 */
    CM_UINT32 rtnLen = 0u;/*返回数据长度*/
    CM_UINT32 local_info_len = 0u;/*本机信息长度*/
    CM_UINT32 peer_info_len = 0u;/*临机信息长度*/
    CM_UINT32 local_now_info_len = 0u;/*本机当前信息长度*/
    CM_UINT32 peer_now_info_len = 0u;/*临机当前信息长度*/
    CM_UINT64 ts_local = 0u; /* 本机时间戳 */
    CM_UINT64 ts_peer = 0u;  /* 邻机时间戳 */
    CM_UINT32 crc_local = 0u;/* 本机CRC */
    CM_UINT32 crc_peer = 0u; /* 邻机CRC */
    CM_UINT8 temp_buf[16] = {0u};/* 临时信息缓冲 */
    CM_UINT32 temp_len = 0u; /*临时信息长度*/
    CM_UINT32 msg_len = 0u; /*本地信息长度*/
    CM_UINT32 src_ip = 0u;   /* 源IP */
    CM_UINT16 src_port = 0u; /* 源端口 */

    CM_UINT16 dev_id = 0u;   /* 源设备ID */
    STRU_PFM_INNET_CFG_T* pCom = NULL; /* 临时变量 */

    CM_INT32 drop_local = 0;  /* 丢弃的本机包数 */
    CM_INT32 drop_peer = 0;   /* 丢弃的邻机包数 */
    CM_INT32 drop_both = 0;   /* 丢弃的双机包数（CRC不一致）*/
    CM_INT32 count = 0;       /* 总包数 */
    CM_UINT64 stick = 0u;     /* 开始时刻 */
    CM_UINT64 etick = 0u;     /* 结束时刻 */
	
    /*- 读取消息数量 */
    local_info_len = s_CFM_RawInfo_len / 12u;
    peer_info_len = s_CFM_RawInfo_peer_len / 12u;
    stick= CM_64FromChar(s_CFM_RawInfo);
    if(0x55u == g_PFM_Cfg.M_2oo2_Enable)
    {
    	/*2取使能*/
		while(((local_info_len -  local_now_info_len) > 0u) && ((peer_info_len - peer_now_info_len) > 0u))
		{
			/*- 获取本机队列和邻机队列队首的特征信息 */
			ts_local = CM_64FromChar(&s_CFM_RawInfo[(local_now_info_len*12u)]);
			crc_local = CM_LongFromChar(&s_CFM_RawInfo[(local_now_info_len*12u) + 8u]);

			ts_peer = CM_64FromChar(&s_CFM_RawInfo_peer[(peer_now_info_len*12u)]);
			crc_peer = CM_LongFromChar(&s_CFM_RawInfo_peer[(peer_now_info_len * 12u) + 8u]);
			/*- 两队队首报文的时间戳是否相同 */
			if (ts_local == ts_peer)
			{
				/*- 两队队首报文的crc是否相同 */
				if (crc_local == crc_peer)
				{
					temp_len = 6u;
					msg_len = buf_size - (CM_UINT32)rtnLen;
					(void)CFM_InnetRaw_Rx_MsgInfoQueue(ch,&temp_buf[0],temp_len,&buf[rtnLen + PFM_RAW_HEADER_SIZE],&msg_len);
					src_ip = CM_LongFromChar(temp_buf);
					src_port = CM_ShortFromChar(temp_buf + 4);
					/*- 查找源设备ID */
					pCom = PFM_INI_InnetIP2Addr(src_ip, src_port);

					if(NULL == pCom)
					{
						dev_id = (CM_UINT16)ch;
					}
					else
					{
						dev_id = pCom->InnetID;
					}
					/*- 队首加入应用接收队列 */
					CM_RE_ASSERT(msg_len <= 65531u, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_1);
					CM_LongToChar((CM_UINT32)(msg_len+PFM_RAW_DEVID_SIZE),&buf[rtnLen]);
					CM_ShortToChar(dev_id, &buf[rtnLen + PFM_RAW_LEN_SIZE]);
					rtnLen = rtnLen + (msg_len + PFM_RAW_HEADER_SIZE);
					count++;
				}
				else
				{
					/*crc比较失败-丢弃此条数据*/
					drop_local++;
					CFM_Clear_InnetRaw_Rx_Msg(ch);
				}
				local_now_info_len++;
				peer_now_info_len++;
			}
			/*- 本机队列队首的时间戳是否更小 */
			else if (ts_local < ts_peer)
			{
				/*- 本机队列队首出队 */
				CFM_Clear_InnetRaw_Rx_Msg(ch);
				local_now_info_len++;
				drop_both++;
			}
			else /* if ts_local > ts_peer */
			{
				/*- 邻机队列队首出队 */
				peer_now_info_len++;
				drop_peer++;
			}
		}
    }
    else
    {
    	/*2取未使能*/
    	while(((local_info_len -  local_now_info_len) > 0u))
    	{
    		ts_local = CM_64FromChar(&s_CFM_RawInfo[(local_now_info_len*12)]);
    		temp_len = 6u;
			msg_len = (CM_UINT32)buf_size - (CM_UINT32)rtnLen;
			(void)CFM_InnetRaw_Rx_MsgInfoQueue(ch,&temp_buf[0],temp_len,&buf[rtnLen + PFM_RAW_HEADER_SIZE],&msg_len);
			src_ip = CM_LongFromChar(temp_buf);
			src_port = CM_ShortFromChar(temp_buf + 4);
			/*- 查找源设备ID */
			pCom = PFM_INI_InnetIP2Addr(src_ip, src_port);

			if(NULL == pCom)
			{
				dev_id = (CM_UINT16)ch;
			}
			else
			{
				dev_id = pCom->InnetID;
			}
			/*- 队首加入应用接收队列 */
			CM_RE_ASSERT(msg_len <= 65531u, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_2);
			CM_LongToChar((CM_UINT32)(msg_len+PFM_RAW_DEVID_SIZE),&buf[rtnLen]);
			CM_ShortToChar(dev_id, &buf[rtnLen + PFM_RAW_LEN_SIZE]);
			rtnLen = rtnLen + (msg_len + PFM_RAW_HEADER_SIZE);
			count++;
			local_now_info_len++;
    	}
    }
    /*- @alias 记录收到的报文数量 */
    if ((ch == 2) || (ch == 7) || (ch == 1))
    {
        etick = ts_local;
        MSCP_LOG_MSG("rx[%d]:%d pkts, %d bytes(%llx...%llx)\n", ch,count,rtnLen,stick,etick);
    }
    else
    {
        /* 不处理 */
    }

    /*- @alias 记录双机CRC不一致的报文数量 */
    if (drop_local > 0)
    {
        MSCP_LOG_MSG("[%d]drop local %d pkts\n",ch, drop_local);
    }
    else
    {
        /* 不处理 */
    }

    /*- @alias 记录丢弃的邻机报文数量 */
    if (drop_peer > 0)
    {
        MSCP_LOG_MSG("[%d]drop peer %d pkts\n",ch, drop_peer);
    }
    else
    {
        /* 不处理 */
    }

    /*- @alias 记录丢弃的本机报文数量 */
    if (drop_both > 0)
    {
        MSCP_LOG_MSG("[%d]drop both %d pkts\n",ch, drop_both);
    }
    else
    {
        /* 不处理 */
    }
    /*判断缓冲区空间是否足够*/
    CM_RE_ASSERT(buf_size >= (CM_UINT32)rtnLen, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_3);
    /*- 返回2oo2通过的接收报文长度 */
    return rtnLen;
}
/**
* @brief 相机数据的2oo2比较接收
* @param ch 通道号 取值范围:0~0xffff
* @param buf 接收数组 取值范围:非空
* @param buf_size 接收数组大小 取值范围:0~0xffffffff
* @param maininfobuf 本机辅助信息数组 取值范围:非空
* @param maininfolen 本机辅助信息数组长度 取值范围:非空
* @param peerinfobuf 邻机辅助信息数组 取值范围:非空
* @param peerinfolen 邻机辅助信息数组长度 取值范围:非空
* @param infobufSize 辅助信息通道缓冲区大小 取值范围:0~0xffffffff
* @return 接收数据大小  取值范围:0~0xffffffff
* @details 
*/
CM_UINT32 CFM_InnetRaw_Rx_Camera(IN CM_INT32 ch, OUT CM_UINT8 buf[], IN CM_UINT32 buf_size,
								OUT CM_UINT8 maininfobuf[],OUT CM_UINT32* maininfolen,
								OUT CM_UINT8 peerinfobuf[],OUT CM_UINT32* peerinfolen,IN CM_UINT32 infobufSize)
{
	/*- 变量初始化 */
	ENUM_CM_RETURN rt = ENUM_CM_FALSE;
	CM_UINT8 RawFrontCache[256u] = { 0u }; /**< 临时缓冲区 */
	CM_UINT16 i = 0u;
	CM_UINT16 j = 0u;
	CM_UINT16 timeoffset = 0u;
	CM_UINT32 tmpmsgLen = 0u;
	CM_UINT32 retmsgLen = 0u;
	CM_UINT32 msgBeginLen = 0u;/*记录每帧起始下标*/
	CM_UINT32 msgLen = 0u;
	CM_UINT32 msgFrontLen = 0u;
	CM_UINT32 myinfolen = 0u;/*辅助信息长度*/
	CM_UINT32 otherinfolen = 0u;/*辅助信息长度*/
	CM_UINT8  Complete_Flag = 0u;/*找到完整帧标志*/
	CM_UINT16 Complete_Size = 0u;/*完整帧数量*/
	CM_UINT16 InfoArea = 0u;/*时间戳辅助信息的位置*/
	CM_UINT32 srcIP = 0u;    /* 源IP */
	CM_UINT16 srcPort = 0u;  /* 源端口 */
	CM_UINT16 devID = 0u;    /* 设备ID */
	CM_UINT8 DataType = 0u;    /* 数据类型 */
	CM_UINT8 DataShift = 0u;    /* 数据类型 */
	STRU_PFM_INNET_CFG_T *pCom = NULL; /*通信配置信息*/
	/*- 循环解析特征信息数据包 */
	CM_ASSERT(buf != NULL, RAW_MODE,DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_3);
	for(i = 0u;i<(s_CFM_RawInfo_len/10u);++i)
	{
		/*- 获取数据类型 */
		DataType = s_CFM_RawInfo[i*10u];
		/*- 如果是起始帧*/
		if(0x01u == DataType)
		{
			/*记录找到时间戳*/
			if(1u == Complete_Flag)
			{
				/*丢弃多余时间戳*/

				CFM_Clear_InnetRaw_Rx_Msg(ch);
				/*丢弃不完整图像数据*/
				for(j = 0u;j < Complete_Size;++j)
				{
					CFM_Clear_InnetRaw_Rx_Msg(ch);
				}
			}
			else
			{
				/*nothing to do*/
			}
			/*- 如果获取偏移量大于0*/
			if(0u < s_CFM_RawInfo[i*10u+1u])
			{
				/*- 偏移为真实偏移量*/
				DataShift = s_CFM_RawInfo[i*10u+1u]+6u;
			}
			else
			{
				/*- 偏移为默认兼容旧版本偏移量*/
				DataShift = 14u;
			}
			/*- 更新找到起始帧标志*/
			Complete_Flag = 1u;
			/*- 完整帧包数清零*/
			Complete_Size = 0u;
			/*- 更新时间戳偏移量*/
			timeoffset = i;
		}
		else
		{
			/*- 如果不是起始帧*/
			if(1u == Complete_Flag)
			{
				/*- 如果是结束帧*/
				if(0x02u == DataType)
				{
					/*此阶段日志过多会丢包*/
					/*- 起始帧标志清零*/
					Complete_Flag = 0u;
					/*- 取出起始帧数据*/
					CFM_Clear_InnetRaw_Rx_Msg(ch);
					/*- 记录起始帧时间戳*/
					(void)CM_Memcpy(&maininfobuf[myinfolen],(infobufSize-myinfolen),&s_CFM_RawInfo[timeoffset*10+2],8u);
					myinfolen += 8u;
					CM_RE_ASSERT(infobufSize >= myinfolen, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
					/*
					内网透传帧格式：
					4字节 长度（不含自身）
					2字节 源ID
					n字节 数据
					*/
					/*- 拷贝图像数据第一包*/
					msgBeginLen = tmpmsgLen;/*记录起始下标，用来添加长度*/
					tmpmsgLen += PFM_RAW_HEADER_SIZE;/*4字节长度+2字节设备类型ID*/
					msgLen = buf_size - tmpmsgLen;
					msgFrontLen = DataShift;
					rt = CFM_InnetRaw_Rx_MsgInfoQueue(ch,RawFrontCache,msgFrontLen,&buf[tmpmsgLen],&msgLen);
					/*- 如果拷贝图像数据第一包成功*/
					if(ENUM_CM_TRUE == rt)
					{
						srcIP = CM_LongFromChar(RawFrontCache);        /* parasoft-suppress BD-PB-CHECKRET "后续在查询对应内网ID时进行非法值防护" */
						srcPort = CM_ShortFromChar(RawFrontCache + 4); /* parasoft-suppress BD-PB-CHECKRET "后续在查询对应内网ID时进行非法值防护" */
						/*- 获取设备类型ID*/
						pCom = PFM_INI_InnetIP2Addr(srcIP, srcPort);
						/*- 如果设备类型ID为空*/
						if(NULL == pCom)
						{
							/*- 更新设备类型ID为通道号*/
							devID = (CM_UINT16)ch;
						}
						else
						{
							/*- 更新设备类型ID为内网设备ID*/
							devID = pCom->InnetID;
						}
						/*- 填写设备类型ID*/
						CM_ShortToChar(devID, &buf[msgBeginLen + PFM_RAW_LEN_SIZE]);
						tmpmsgLen += msgLen;
						/*- 连续拷贝剩余图像数据*/
						for(j = 1u;j < Complete_Size;++j)
						{
							msgLen = buf_size - tmpmsgLen;
							msgFrontLen = DataShift;
							rt = CFM_InnetRaw_Rx_MsgInfoQueue(ch,RawFrontCache,msgFrontLen,&buf[tmpmsgLen],&msgLen);
							/*- 如果拷贝剩余图像错误*/
							if(ENUM_CM_FALSE == rt)
							{
								/*- 结束拷贝*/
								break;
							}
							tmpmsgLen += msgLen;
						}
						/*- 如果拷贝剩余图像正确*/
						if(ENUM_CM_TRUE == rt)
						{
							/*- 拷贝完成添加长度*/
							CM_LongToChar((tmpmsgLen - msgBeginLen - PFM_RAW_LEN_SIZE), &buf[msgBeginLen]);
							/*- 拷贝完成更新长度*/
							retmsgLen = tmpmsgLen;
							/*- 读出帧尾-丢弃*/
							CFM_Clear_InnetRaw_Rx_Msg(ch);
							/*- 完整帧数量清零*/
							Complete_Size = 0u;
						}
						else
						{
							/*- 空间不足结束处理*/
							break;
						}
					}
					else
					{
						/*- 空间不足结束处理*/
						break;
					}
				}
				else
				{
					/*- 更新完整帧包数量*/
					Complete_Size++;
				}
			}
			else
			{
				/*未找到时间戳也不是时间戳，删除此条消息*/
				CFM_Clear_InnetRaw_Rx_Msg(ch);
			}
		}
	}
	/*- 起始帧标志清零*/
	Complete_Flag = 0u;
	/*- 完整帧数量清零*/
	Complete_Size = 0u;
	/*- 循环解析邻机特征信息数据包 */
	for(i = 0u;i<(s_CFM_RawInfo_peer_len/10u);i++)
	{
		/*- 获取数据类型 */
		DataType = s_CFM_RawInfo_peer[i*10u];
		/*- 如果是起始帧*/
		if(0x01u == DataType)
		{
			/*记录找到时间戳*/
			InfoArea = i;
			/*- 完整帧包数清零*/
			Complete_Size = 0u;
			/*- 更新找到起始帧标志*/
			Complete_Flag = 1u;
		}
		else
		{
			/*- 如果不是起始帧*/
			if(1u == Complete_Flag)
			{
				/*- 如果是结束帧*/
				if(0x02u == DataType)
				{
					/*- 起始帧标志清零*/
					Complete_Flag = 0u;
					/*- 记录起始帧时间戳*/
					(void)CM_Memcpy(&peerinfobuf[otherinfolen],(infobufSize-otherinfolen),&s_CFM_RawInfo_peer[10*InfoArea+2],8u);
					otherinfolen += 8u;
				}
				else
				{
					/*- 更新完整帧包数量*/
					Complete_Size++;
				}
				CM_RE_ASSERT(infobufSize >= otherinfolen, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_2);
			}
			else
			{
				/*无操作*/
			}
		}
	}
	/*- 输出本机时间戳特征信息长度*/
	*maininfolen = myinfolen;
	/*- 输出邻机时间戳特征信息长度*/
	*peerinfolen = otherinfolen;
	/*- 输出有效数据长度*/
	return retmsgLen;
}
/**
* @brief 发送内网透传报文
* @param ch    内网透传通道序号，[1...n]有效
* @param txBuf 发送的应用报文数组
* @param txLen 发送的应用报文长度
* @return 函数执行结果
* - 1 成功
* - 0 失败(输入非法)
*/
CM_UINT8 CFM_TxInnetRaw(IN CM_INT32 ch, IN const CM_UINT8 *Buf, IN CM_UINT32 Len)
{
    /*- 变量初始化 */
    CM_UINT8 rt = 1u;
    CM_UINT32 i = 0u;
    CM_UINT16 msgLen = 0u;
    CM_UINT16 dstID = 0u;
    ENUM_CM_RETURN ret = ENUM_CM_FALSE;
    STRU_PFM_INNET_CFG_T *pCom = NULL;

    /*- 循环发送所有内网透传数据 */
    while ((i + 4u) < Len)
    {
        /*
        内网透传协议头：
        2字节 长度（不含自身）
        2字节 目的ID
        n字节 数据
        */
        /*- 解析内网发送协议头 */
        msgLen = CM_ShortFromChar(Buf + i);    /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
        dstID = CM_ShortFromChar(Buf + i + 2u); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */

        CM_RE_ASSERT(msgLen > 2u, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_1);
        CM_RE_ASSERT((i + msgLen + 2u) <= Len, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_2);

        /*- 查询目的IP、端口 */
        pCom = PFM_INI_InnetID2Addr(dstID);
        /*- 查询目的IP、端口是否成功 */
        if (NULL != pCom)
        {
        	if(RAW_COM_DISENABLE == g_PFM_Cfg.Local_Cfg.Innet_Raw_Parameter[ch].Port_Type_Enable)
			{
				/*禁用透传端口*/
			}
			else if (RAW_COM_TCP == g_PFM_Cfg.Local_Cfg.Innet_Raw_Parameter[ch].Port_Type_Enable)
			{
				CM_RE_ASSERT(pCom->InnetID == g_PFM_Cfg.Local_Cfg.Innet_Raw_Parameter[ch].Server_DevId, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_3);
				ret = CFM_InnetRaw_Tcp_Send(pCom->InnetID, Buf + i + 4u, (CM_INT32)CM_UNSIGNED_SHORT_EXP(msgLen - 2u)); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
				/*- @alias 记录发送异常信息 */
	            if (ENUM_CM_TRUE != ret)
	            {
	                MSCP_LOG_MSG("innet raw tcp send to %04x fail\n", dstID);
	                rt = 0u;
	            }
	            else
				{
					/*- 无处理 */
				}
			}
			else
			{
	            /*- @alias 调用通信层发送 */
	            if (1u == g_PFM_Cfg.CPU_ID)
	            {
	                ret = CFM_InnetRaw_Send(ch, Buf + i + 4u, (CM_INT32)CM_UNSIGNED_SHORT_EXP(msgLen - 2u), pCom->IP_G,pCom->Port_Raw_G); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
	            }
	            else
	            {
	                ret = CFM_InnetRaw_Send(ch, Buf + i + 4u, (CM_INT32)CM_UNSIGNED_SHORT_EXP(msgLen - 2u), pCom->IP_P, pCom->Port_Raw_P); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
	            }
	            MSCP_LOG_MSG("CFM_InnetRaw_Send:ch:%d,dstID:0x%x,len:%d\n", ch,dstID,msgLen - 2u);
	            /*- @alias 记录发送异常信息 */
	            if (ENUM_CM_TRUE != ret)
	            {
	                MSCP_LOG_MSG("innet raw send to %04x fail\n", dstID);
	                rt = 0u;
	            }
	            else
				{
					/*- 无处理 */
				}				
			}
        }
        else
        {
            /*- 报错 */
            MSCP_LOG_MSG("innet raw send err:wrong dstID = %04x\n",dstID);
            CM_RE_ASSERT(0, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_4);
            rt = 0u;
        }
        /*- 跳转到下一条待发送报文 */
        i = i + (CM_UINT32)CM_UNSIGNED_SHORT_EXP(msgLen + 2u);
    }
    /*- 返回执行结果 */
    return rt;
}

/**
* @brief 外网透传接收
* @param buf 接收数组
* @param bufSize 接收数组大小
* @return 接收数据长度
*/
CM_UINT32 CFM_RxOutnetRaw(OUT CM_UINT8 buf[], IN CM_UINT32 bufSize)
{
    /*- 变量初始化 */
    CM_UINT16 rxLen = 0u;      /* 接收报文长度 */
    CM_UINT32 i = 0u;          /* 循环变量 */
    ENUM_OUTNET_CHN_T Chn = ENUM_OUTNET_ERROR;
    /*- 循环接收内网透传数据 */
    do
    {
        /*- 从通信层读取通信数据 */
        rxLen = CFM_OutnetRaw_Recv(&buf[i+4u], CM_UNSIGNED_INT_EXP(bufSize - i - 4u),&Chn); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
        /*- 是否读到了数据 */
        if (rxLen > 0u)
        {      
       		CM_LongToChar((CM_UINT32)rxLen, &buf[i]); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
            i = i + (CM_UINT32)CM_UNSIGNED_SHORT_EXP(rxLen + 4u);
        }
        else
		{
			/*- 无处理 */
		}
    } while (rxLen > 0u);

    /*- 返回报文总长度 */
    return i;
}

/**
* @brief 发送外网透传报文
* @param txBuf 发送的应用报文数组
* @param txLen 发送的应用报文长度
* @return 函数执行结果
* - 1 成功
* - 0 失败(输入非法)
*/
CM_UINT8 CFM_TxOutnetRaw(IN CM_UINT8 Buf[], IN CM_UINT32 Len)
{
    /*- 变量初始化 */
    CM_UINT8 rt = 1u;
    CM_UINT16 i = 0u;
    CM_UINT16 msgLen = 0u;
    CM_UINT32 tx_sn = 0u;
    CM_UINT32 Crc = 0u;

	if ((0u < Len) && (0x55u == g_PFM_Cfg.M_OutnetRaw_Enable))
	{
		while((CM_UINT16)(i + 19u) < Len)
		{
			/*CC外网输出帧
			2字节 长度
			1字节 协议版本
			4字节 周期号
			4字节帧序号
			2字节 目的设备id
			2字节 目的逻辑id
			2字节 协议类型
			n字节 数据
			4字节CRC
			*/
	        /*- 解析透传发送头 */
	        msgLen = CM_ShortFromChar(&Buf[i]);    /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
	        /*- 填写帧序号*/
	        tx_sn = SFM_GetTxSn();
	        CM_LongToChar(tx_sn, &Buf[i + 7u]);
	        if(msgLen > 2u)
	        {
	        	Crc = CM_Crc32(&Buf[i], msgLen - 2u);
	        }
	        else
	        {
	        	MSCP_LOG_MSG("Crc len error!!!\n");
	        }
	        CM_LongToChar(Crc, &Buf[i + msgLen - 2u]);
	        CM_RE_ASSERT(msgLen > (CM_UINT16)(19u), RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_4, TSCP_DARK_ASSERT_1);
	        CM_RE_ASSERT((i + msgLen + 2u) <= Len, RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_4, TSCP_DARK_ASSERT_2);
			/*- 向红网CC发送CC外网帧 */
			(void)CFM_OutnetRaw_Send(&Buf[i], (CM_INT32)(msgLen + 2u), ENUM_OUTNET_RED);
			/*- 向蓝网CC发送CC外网帧 */
			(void)CFM_OutnetRaw_Send(&Buf[i], (CM_INT32)(msgLen + 2u), ENUM_OUTNET_BLUE);

			/*- 跳转到下一条待发送报文 */
        	i = i + (msgLen + 2u);
		}
	}
	else
	{
		rt = 0u;
	}

	return rt;
}
/**
* @brief 外网心跳接收
* @param buf 接收数组 取值范围：非空
* @param bufSize 接收数组大小 取值范围：0~0xFFFFFFFF
* @return 接收数据长度 取值范围：0~0xFFFFFFFF
*/
CM_UINT32 CFM_RxOutnetHeart(OUT CM_UINT8 buf[], IN CM_UINT32 bufSize)
{
    /*- 变量初始化 */
    CM_UINT16 rxLen = 0u;      /*- 接收报文长度 */
    CM_UINT32 i = 0u;          /*- 循环变量 */
    ENUM_OUTNET_CHN_T Chn = ENUM_OUTNET_ERROR;
	CM_UINT8 send_2oo2_buf[16] = {0u};
	CM_UINT8 rcv_2oo2_buf[16] = {0u};
	CM_INT32 rcv_len = 0;
	CM_UINT32 cycle = DFM_GetBirthCount();
    CM_UINT8 ccState[2] = {0,0};
    CM_UINT8 sebState[2] = {0,0};
    /*- 如果入参指针不为空  */
	if(NULL != buf)
	{
	    /*- 循环接收内网透传数据 */
	    do
	    {
	        /*- 从通信层读取通信数据 */
	        rxLen = CFM_OutnetHeart_Recv(&buf[i+4u], CM_UNSIGNED_INT_EXP(bufSize - i - 4u),&Chn); /*- parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
	        /*- 是否读到了数据 */
	        if (rxLen > 0u)
	        {
	       		CM_LongToChar((CM_UINT32)rxLen, &buf[i]); /*- parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
	            i = i + (CM_UINT32)CM_UNSIGNED_SHORT_EXP(rxLen + 4u);
				/*- 记录通信状态*/
				switch (Chn)
				{
				case ENUM_OUTNET_RED:
					g_Hardware_boot_com_state.CCU_A_Count = cycle;
					break;
				case ENUM_OUTNET_BLUE:
					g_Hardware_boot_com_state.CCU_B_Count = cycle;
					break;
				case ENUM_OUTNET_EXTEND_RED:
					g_Hardware_boot_com_state.SEB_A_Count = cycle;
					break;
				case ENUM_OUTNET_EXTEND_BLUE:
					g_Hardware_boot_com_state.SEB_B_Count = cycle;
					break;
				default:
					break;
				}
	        }
	        else
			{
				/*- 无处理 */
			}
	    } while (rxLen > 0u);

		g_Hardware_boot_com_state.SYS_Count = cycle;
	    /*- @alias 二取同步双cpu通信结果 */
		if(0x55u == g_PFM_Cfg.M_2oo2_Enable)
		{
			CM_LongToChar(g_Hardware_boot_com_state.CCU_A_Count,&send_2oo2_buf[0u]);
			CM_LongToChar(g_Hardware_boot_com_state.CCU_B_Count,&send_2oo2_buf[4u]);
			CM_LongToChar(g_Hardware_boot_com_state.SEB_A_Count,&send_2oo2_buf[8u]);
			CM_LongToChar(g_Hardware_boot_com_state.SEB_B_Count,&send_2oo2_buf[12u]);
			rcv_len = SFM_2oo2_Exchange_Currency(send_2oo2_buf,16,rcv_2oo2_buf,16,ENUM_2oo2_RAW_INFO);
			if(16 == rcv_len)
			{
				(g_Hardware_boot_com_state.CCU_A_Count >= CM_LongFromChar(&rcv_2oo2_buf[0])) ? (g_Hardware_boot_com_state.CCU_A_Count) : (g_Hardware_boot_com_state.CCU_A_Count = CM_LongFromChar(&rcv_2oo2_buf[0]));
				(g_Hardware_boot_com_state.CCU_B_Count >= CM_LongFromChar(&rcv_2oo2_buf[4])) ? (g_Hardware_boot_com_state.CCU_B_Count) : (g_Hardware_boot_com_state.CCU_B_Count = CM_LongFromChar(&rcv_2oo2_buf[4]));
				(g_Hardware_boot_com_state.SEB_A_Count >= CM_LongFromChar(&rcv_2oo2_buf[8])) ? (g_Hardware_boot_com_state.SEB_A_Count) : (g_Hardware_boot_com_state.SEB_A_Count = CM_LongFromChar(&rcv_2oo2_buf[8]));
				(g_Hardware_boot_com_state.SEB_B_Count >= CM_LongFromChar(&rcv_2oo2_buf[12])) ? (g_Hardware_boot_com_state.SEB_B_Count) : (g_Hardware_boot_com_state.SEB_B_Count = CM_LongFromChar(&rcv_2oo2_buf[12]));
			}
			else
			{
				/*- 无处理 */
			}
		}
		else
		{
			/*- 无处理 */
		}
		MSCP_LOG_MSG("CCU_A_Count = %d,CCU_B_Count = %d,SEB_A_Count = %d,SEB_B_Count = %d\n",g_Hardware_boot_com_state.CCU_A_Count,g_Hardware_boot_com_state.CCU_B_Count,g_Hardware_boot_com_state.SEB_A_Count,g_Hardware_boot_com_state.SEB_B_Count);
	}
	else
	{
		/*- 空指针无处理*/
	}

	/*- @alias 向aim汇报通信情况 */
	(1u == PFM_CCUSEB_Comstate(0))? (ccState[1] = 0xaau) : (ccState[1] = 0x55u);
	(1u == PFM_CCUSEB_Comstate(1))? (ccState[0] = 0xaau) : (ccState[0] = 0x55u);
	(1u == PFM_CCUSEB_Comstate(2))? (sebState[1] = 0xaau) : (sebState[1] = 0x55u);
	(1u == PFM_CCUSEB_Comstate(3))? (sebState[0] = 0xaau) : (sebState[0] = 0x55u);
	MSCP_LOG_MSG("rCC = %d, bCC = %d, rSEB = %d, bSEB = %d\n", ccState[1], ccState[0], sebState[1], sebState[0]);

    /*- 填写暗文日志 */
    (void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_CCSTATE, 2U, &ccState);
    (void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_SEBSTATE, 2U, &sebState);

    /*- 返回报文总长度 */
    return i;
}
/**
* @brief 发送外网心跳报文
* @param txBuf 发送的应用报文数组
* @param txLen 发送的应用报文长度
* @return 函数执行结果
* - 1 成功
* - 0 失败(输入非法)
*/
CM_UINT8 CFM_TxOutnetHeart(IN const CM_UINT8 Buf[], IN CM_UINT32 Len)
{
    /*- 变量初始化 */
    CM_UINT8 rt = 0u;

	if ((0u < Len) && (NULL != Buf))
	{
		/*- 向所有外设发送心跳请求 ，是否区分CPU*/
		(void)CFM_OutnetHeart_Send(Buf,Len,ENUM_OUTNET_RED);
		(void)CFM_OutnetHeart_Send(Buf,Len,ENUM_OUTNET_BLUE);
		if(NULL != p_Status_Communication_Func)
		{
			(void)CFM_OutnetHeart_Send(Buf,Len,ENUM_OUTNET_EXTEND_RED);
			(void)CFM_OutnetHeart_Send(Buf,Len,ENUM_OUTNET_EXTEND_BLUE);
		}
		rt = 1u;
	}
	else
	{
		/*- 无处理*/
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_WARNING, 4U, DARK_FAULT_CODE_MERGE(RAW_MODE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_1));
	}

	return rt;
}

