/**
* @file SFM_Prtcl.c
* @brief Safe Function Module: 安全协议处理
* @details
* 从通信层获取输入数据交给平台层交换、比较
* 从平台层获取输入数据交给协议层解析
* 从协议层获取输入数据交给应用层使用
* 从应用层获取输出数据交给协议层封装
* 从协议层获取输出数据交给平台层比较
* 从平台层获取输出数交给通信层发送
* @author GT-BU
* @date 2021.02.20
* @version V1.0
* @copyright TCT
* @par 修改日志
* <table>
* <tr><th>Date        <th>Version  <th>Author     <th>Description
* <tr><td>2021.02.01  <td>V1.0     <td>GT-BU      <td>创建初始版本
* </table>
*/
#ifndef SFM_PRTCL_H
#define SFM_PRTCL_H
#include "CM_Types.h"
#include "CFM_Net.h"
#include "MSCP_APP_Interface.h"
#ifdef __cplusplus
extern "C"
{
#endif

#define SFM_INNETSAFE_BUFF_SIZE (1024u*640u*2u)    /* 内网安全通信通道UDP缓冲区大小 640k*2，应用许用量为500k */
#define SFM_OUTNETSAFE_BUFF_SIZE (1024u*1024u*10u) /* 外网安全通信通道UDP缓冲区大小 512k*20，应用许用量为500k */
#define SFM_COM485_RECV_SIZE     (1024u*10u*10u) /*接收485串口通道空间*/
#define SFM_INNETSAFE_RM_BUFF_SIZE (1024u*10u)    /* 远程部署内网安全通信通道UDP缓冲区大小 10k */

#if SFM_OUTNETSAFE_BUFF_SIZE > SFM_INNETSAFE_BUFF_SIZE
#define SFM_TMP_CACHE_SIZE SFM_OUTNETSAFE_BUFF_SIZE
#else
#define SFM_TMP_CACHE_SIZE SFM_INNETSAFE_BUFF_SIZE
#endif

    /** 内网通道类型 */
    typedef enum
    {
        ENUM_INNET_ERROR = 0, /**< 保留 */
        ENUM_INNET_GREEN = 1, /**< 绿网 */
        ENUM_INNET_PURPLE = 2 /**< 紫网 */
    }ENUM_INNET_CHN_T;


    /* 外网安全协议初始化(-1) */
    void SFM_PrtclOutInit(void);
    /* 内网安全协议初始化(sfp) */
    void SFM_PrtclInInit(CM_UINT8* p_SfpInnetPara);
    /* 获取协议适配层跟随数据 */
    CM_UINT32 SFM_GetPrtclFollowData(OUT CM_UINT8 *Buf, IN CM_UINT32 BufSize);
    /* 设置协议适配层跟随数据 */
    void SFM_SetPrtclFollowData(IN CM_UINT8 *Buf);

    /*以下周期调用API按调用顺序描述：*/
    /* 缓冲区切换 */
    void SFM_PrtclBufSwitch(void);

    /*
     * 1.从通信层获取原始输入数据并打包成协议帧
     */

     /*从CFM接收通信数据，打包成协议内网帧*/
    CM_INT32 SFM_RxInnetSafe(OUT CM_UINT8 Buf[], IN CM_UINT32 BufSize);
    /*从CFM接收通信数据，打包成协议外网帧*/
    CM_INT32 SFM_RxOutnetSafe(OUT CM_UINT8 buf[], IN CM_UINT32 bufSize);

    /*
     * 2.进行2oo2交换和2x2交换
     */
     /*(在平台层PFM处理)*/

     /*
      * 3.将所有输入数据写入协议层
      */
      /*把协议内网帧格式的数据写入协议层*/
    void SFM_WriteInnetSafeInput(IN const CM_UINT8 buf[], IN CM_UINT32 len, IN ENUM_INNET_CHN_T ch);

    /*把协议外网帧格式的数据写入协议层*/
    void SFM_WriteOutnetSafeInput(IN const CM_UINT8 buf[], IN CM_UINT32 len, IN ENUM_OUTNET_CHN_T ch);

    /*
     * 4.协议层解析收到的数据
     */
     /* 协议适配层接收处理 */
    void SFM_UnPrtclProc(void);

    /*
     * 5.从协议层读取解析后的应用输入数据（交给应用）
     */
    /* 应用收到的外网协议数据 */
    CM_UINT32 Prtcl_OutnetSafe_AppRecv(OUT CM_UINT16 *pSrcName, OUT CM_UINT16 *pSrcLogicID, OUT CM_UINT8 *pLifeTime,
        OUT CM_UINT8 *rxBuf, IN CM_UINT32 rxSize);
    /* 应用收到的内网协议数据 */
    CM_UINT32 Prtcl_InnetSafe_AppRecv(OUT CM_UINT16 *pSrcName, OUT CM_UINT8 *pLifeTime, OUT CM_UINT8 *rxBuf, IN CM_UINT32 rxSize);

     /*
     * 6.执行应用周期逻辑
     */
     /*(在逻辑层处理)*/

    /*
     * 7.将应用输出写入协议层
     */
    /* 应用发送的外网协议数据 */
    CM_UINT8 Prtcl_OutnetSafe_AppSend(IN CM_UINT16 dstName, IN CM_UINT16 dstLogicID, IN const CM_UINT8 *txBuf, IN CM_UINT32 txLen);
    /*应用发送的内网协议数据 */
    CM_UINT8 Prtcl_InnetSafe_AppSend(IN CM_UINT16 dstName, IN const CM_UINT8 *txBuf, IN CM_UINT32 txLen);

    /*
     * 8.协议层封装待发送数据
     */
    /* 协议适配层发送处理 */
    void SFM_EnPrtclProc(void);

    /*
     * 9.从协议层读取封装后的协议输出数据
     */
     /* 读取协议内网输出报文 */
    CM_UINT32 SFM_ReadInnetCodedOutput(OUT CM_UINT8 Buf[], IN CM_UINT32 BufSize);
    /* 读取协议外网输出报文 */
    CM_UINT32 SFM_ReadOutnetCodedOutput(OUT CM_UINT8 Buf[], IN CM_UINT32 BufSize);

    /*
     * 10.进行2oo2比较和2x2校验
     */
     /*(在平台层处理)*/

     /*
      * 11.交给通信层发送
      */
      /* 将内网输出报文交给CFM发送 */
    void SFM_TxInnetSafe(IN CM_UINT8 Buf[], IN CM_UINT32 Len);
    /* 将外网输出报文交给CFM发送 */
    void SFM_TxOutnetSafe(IN CM_UINT8 buf[], IN CM_UINT32 Len);

    /* 断开外网安全链接 */
    CM_UINT8 SFM_OutnetDisconnect(IN CM_UINT16 devID, IN CM_UINT16 logicID);
    /* -1安全协议日志打印 */
    void SFM_LogOutPrtcl(void);

    /* 内网安全协议日志打印 */
    void SFM_LogInPrtcl(void);
    /* 维护模式协议层解析收到的数据(无宕机函数) */
    void SFM_UnPrtclProc_Crash(void);

    /* 维护模式协议层封装待发送数据(无宕机函数) */
    void SFM_EnPrtclProc_Crash(void);

    /* 维护模式下sfp协议数据写入应用队列(无宕机函数) */
    void SFM_PrtclBufToApp_InnetSafeCrash(void);

    /* 维护模式下应用将sfp协议数据写到协议队列(无宕机函数) */
    void SFM_AppToPrtclBuf_InnetSafeCrash(void);

    /* 维护模式下应用将sfp协议数据写到协议队列(无宕机函数) */
    void SFM_AppToPrtclBuf_InnetSafeCrash(void);

    /* 内网远程部署安全数据接收 */
    CM_INT32 SFM_RxInnetRemoteUpdate(OUT CM_UINT8 Buf[], IN CM_UINT32 BufSize);

    /* 从协议适配层读取协议内网输出帧 */
    CM_UINT32 SFM_ReadInnetCodedOutputCrash(OUT CM_UINT8 Buf[], IN CM_UINT32 BufSize);

    /* 发送内网远程部署安全通信数据 */
    void SFM_TxInnetSafeRemoteUpdate(IN CM_UINT8 Buf[], IN CM_UINT32 Len);

    CM_UINT8 Prtcl_InnetSafe_AppRmSend(IN const CM_UINT8* txBuf, IN CM_UINT32 txLen);

    CM_UINT32 Prtcl_InnetSafe_RmRecv(OUT CM_UINT16* pSrcName, OUT CM_UINT8* pLifeTime, OUT CM_UINT8* rxBuf, IN CM_UINT32 rxSize);

    CM_UINT32 Prtcl_InnetSafe_PlatRmRecv(OUT CM_UINT16* pSrcName, OUT CM_UINT8* pLifeTime, OUT CM_UINT8* rxBuf, IN CM_UINT32 rxSize);

    CM_UINT32 SFM_ReadInnetRmCodedOutput(OUT CM_UINT8 Buf[], IN CM_UINT32 BufSize);

    CM_INT32 SFM_RxInnetSafeRm(OUT CM_UINT8 Buf[], IN CM_UINT32 BufSize);

    void SFM_WriteInnetSafeRmInput(IN const CM_UINT8 buf[], IN CM_UINT32 len, IN ENUM_INNET_CHN_T ch);

    CM_UINT8 Prtcl_InnetSafe_RmSend(IN CM_UINT16 dstName, IN const CM_UINT8* txBuf, IN CM_UINT32 txLen);

    void SFM_TxInnetSafeRm(IN CM_UINT8 Buf[], IN CM_UINT32 Len);

    /* 去重-1协议数据 */
    CM_UINT8 SFM_OutProtclTwoRepeat(INOUT CM_UINT8* data1, IN CM_UINT32 data1Len,INOUT CM_UINT8* data2,INOUT CM_UINT32* data2Len);

    /**
    * @brief 获取安全通道链路状态
    * @return 安全通道链路状态
    */
    CM_UINT8 SFM_GetLnkStatus(CM_UINT8 destType,CM_UINT8 destId,CM_UINT16 logId);

    /**
    * @brief 远程内网安全协议日志打印
    */
    void SFM_LogRmInPrtcl(void);
    CM_UINT32 SFM_GetSfpPrtclFollowData(OUT CM_UINT8* Buf, IN CM_UINT32 BufSize);
    void SFM_SetSfpPrtclFollowData(IN CM_UINT32 Len, IN CM_UINT8* Buf);

    /**
    * @brief 设置外网数据的帧序号
    * @param sn 需要设置的序号：0~0xffff
    * @return 无
    */
    void SFM_SetTxSn(CM_UINT32 sn);
    /**
    * @brief 获取外网数据发送序列号
    * @param 无
    * @return 获取到的外网数据序列号
    */
    CM_UINT32 SFM_GetTxSn(void);
#ifdef __cplusplus
}
#endif

#endif
