// Smgp.h: interface for the CSmgp class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SMGP_H__7DF8EA3F_89A5_4FC9_8D87_131385D01734__INCLUDED_)
#define AFX_SMGP_H__7DF8EA3F_89A5_4FC9_8D87_131385D01734__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

//#define SMGP_3_0          //cmpp属于3.0

/*
#include "Winsock2.h"
#pragma comment(lib, "Ws2_32.lib")
*/
#pragma pack( push )
#pragma pack( 1 )

typedef struct _Smgp_Data_Recv
{
	ULONG       lDataLen;  //应收字节数
	ULONG       lRecvLen;  //已收字节数
	BOOL        bRecvFrame; //是否正在收Frame;
	BYTE      * pRecvFrame; //收到的Frame
}Smgp_Data_Recv;

typedef struct _Smgp_Head
{
	ULONG       Total_Length;
	ULONG       Command_Id;
	ULONG       Sequence_Id;
}Smgp_Head;

typedef struct _Smgp_Login
{
	char       ClientID[8];
	UCHAR      AuthenticatorClient[16];
	UCHAR      LoginMode;
	ULONG      TimeStamp;
	UCHAR      ClientVersion;
}Smgp_Login;
typedef struct _Smgp_Login_Resp
{
	ULONG      Status;
	UCHAR      AuthenticatorSource[16];
	UCHAR      ServerVersion;
}Smgp_Login_Resp;


typedef struct _Smgp_Submit
{
	UCHAR    MsgType;
	UCHAR    NeedReport;
	UCHAR    Priority;
	UCHAR    ServiceID[10];
	UCHAR    FeeType[2];
	UCHAR    FeeCode[6];
	UCHAR    FixedFee[6];
	UCHAR    MsgFormat;
	UCHAR    ValidTime[17];
	UCHAR    AtTime[17];
	UCHAR    SrcTermID[21];
	UCHAR    ChargeTermID[21];
	UCHAR    DestTermIDCount;
	UCHAR    DestTermID[21];
	UCHAR    MsgLength;
}Smgp_Submit;

typedef struct _Smgp_Submit_Ex
{
	UCHAR    Reserve[8];
	short    TP_Pid_Tag;
	short    TP_Pid_Length;
	UCHAR    TP_Pid;
	short    TP_udhi_Tag;
	short    TP_udhi_Length;
	UCHAR    TP_udhi;
	short    PkNumber_Tag;
	short    PkNumber_Length;
	UCHAR    PkNumber;
	short    PkTotal_Tag;
	short    PkTotal_Length;
	UCHAR    PkTotal;
	//short    TP_LinkID_Tag;
	//short    TP_LinkID_Length;
	//UCHAR    LinkID[20];

}Smgp_Submit_Ex;

typedef struct _Smgp_Submit_Resp
{
	UCHAR    MsgID[10];
	ULONG    Status;
}Smgp_Submit_Resp;
typedef struct _Smgp_Send_List
{
	ULONG       lSendID;         //数据库中记录的SendID
	ULONG       lSeq;            //发送cmpp里的序号
	ULONG       lSmgpSeq;        //使用cmpp转接的源序号
	ULONG       lSendTime;       //最后一次发送时间
    ULONG       lReSendCount;    //重复发送了多少次
	UCHAR       Msg[512];        //信息内容
	Smgp_Submit Submit;
	Smgp_Submit_Ex SubmitEx;
}Smgp_Send_List;
//发送返回状态
typedef struct _Smgp_Send_Resp
{
	ULONG       lSendID;         //数据库中记录的SendID
	ULONG       lResult;         //返回状态
    ULONG       lReSendCount;    //重复发送了多少次
	UCHAR       lMsgID[10];          //发送成功时有此返回
}Smgp_Send_Resp;

typedef struct _Smgp_Deliver
{
	UCHAR       MsgID[10];          //发送成功时有此返回
	UCHAR       IsReport;           //是否为状态报告
	UCHAR       MsgFormat;           //消息格式
	UCHAR       RecvTime[14];        //短消息接收时间
	UCHAR       SrcTermID[21];       //短消息发送号码
	UCHAR       DestTermID[21];       //短消息接收号码
	UCHAR       MsgLength;            //短消息长度
}Smgp_Deliver;
typedef struct _Smgp_Status
{
	UCHAR       S_MsgID[3];          //发送成功时有此返回
	UCHAR       MsgID[10];          //发送成功时有此返回
	UCHAR       S_Sub[5];
	UCHAR       Sub[3];
	UCHAR       S_Dlvrd[7];
	UCHAR       Dlvrd[3];
	UCHAR       S_Submit_date[13];
	UCHAR       Submit_date[10];
	UCHAR       S_done_date[11];
	UCHAR       done_date[10];
	UCHAR       S_Stat[6];
	UCHAR       Stat[7];
	UCHAR       S_Err[5];
	UCHAR       Err[3];
	UCHAR       S_Txt[6];
	UCHAR       Txt[20];
}Smgp_Status;
typedef struct _Smgp_Deliver_Resp
{
	UCHAR       MsgID[10];          //发送成功时有此返回
	ULONG       Status;
}Smgp_Deliver_Resp;

typedef struct _Smgp_Deliver_List
{
	ULONG        lSendID;
	Smgp_Deliver deliver;
	Smgp_Status  status;
	UCHAR        szMsg[512];
}Smgp_Deliver_List;

#define MAX_SMGPEXCHANGE  50
typedef struct _SmgpExchange
{
	char      szNum[32];  //端口号
	SOCKET    sock;       //Socket接口
	long      lIndex;     //序号
	ULONG     lID;        //回复序号
	long      lSendCount; //发送计数
	long      lSendRetCount; //发送返回计数
}SmgpExchange;


typedef struct _SmgpExchangeResp
{
	long  lType;     //0 Submit rest  , 1 deliver
	long  lSendID;   //发送ID , lType==0时有效
	char  szNum[32]; //目标号码, lType==1时有效
	long  lExNum;    //adc特殊转发时用到
	long  lLen;
	ULONG lCmd;
	ULONG lSeq;
	BYTE  Data[512];
}SmgpExchangeResp;


#pragma pack( pop )

typedef void (*SGM_PRECVPROC)(Smgp_Data_Recv * pDataRecv);

#define      SMGP_PORT       3058   //cmpp端口号
#define      SMGP_EXCHANGE_PORT 3059
#define      SMGP_EXCHANGE_PORT2 3057  //adc下,采用此端口

#define      SMGP_LOGIN		         0x00000001  //请求连接
#define      SMGP_LOGIN_RESP	     0x80000001  //请求连接应答
#define      SMGP_SUBMIT             0x00000002  //提交短信
#define      SMGP_SUBMIT_RESP        0x80000002  //提交短信应答
#define      SMGP_DELIVER            0x00000003  //短信下发
#define      SMGP_DELIVER_RESP       0x80000003  //下发短信应答
#define      SMGP_ACTIVE_TEST        0x00000004  //链路检测
#define      SMGP_ACTIVE_TEST_RESP   0x80000004  //下发短信应答
#define      SMGP_FORWARD            0x00000005  //消息前转
#define      SMGP_FORWARD_RESP       0x80000005  //消息前转应答
#define      SMGP_EXIT  			 0x00000006  //激活测试
#define      SMGP_EXIT_RESP          0x80000006  //激活测试应答


#define      SMGP_LOGINTYPE_SEND        0  //登录类型,发送
#define      SMGP_LOGINTYPE_RECV        1  //登录类型,接收
#define      SMGP_LOGINTYPE_SENDRECV    2  //登录类型,收、发

#ifdef SMGP_3_0
#define      SMGP_SMS_MAX_LIST          256         //最大的队列数
#else
#define      SMGP_SMS_MAX_LIST          256         //最大的队列数
#endif
#define      SMGP_SMS_MAX_RESP          2048        //最大的队列数
#define      SMGP_SMS_MAX_DELIVER       2048        //最大的队列数
#define      SMGP_SMS_MAX_STATUS        2048        //最大的队列数
#define      SMGP_SMS_MAX_SMGPEXCHANGERESP          2048        //最大的队列数

#define      SMGP_ACTIVE_TESTTIME  30000      //多长时间进行链路检测
#define      SMGP_ACTIVE_TIMEOUT   20000      //链路检测超时时间
#define      SMGP_ACTIVE_COUNTOUT  3          //链路检测超过次数
#define      SMGP_SENDSMS_TIMEOUT  30000      //发送短信超时时间
#define      SMGP_SENDSMS_RECOUNT  1          //发送短信重试次数

//typedef CTypedPtrList<CPtrList, Smgp_Send_List*>  CSendList;
//typedef CTypedPtrList<CPtrList, Smgp_Send_Resp*>  CSendResp;
//typedef CTypedPtrList<CPtrList, Smgp_Deliver_List*>  CDeliverList;
class CSmgp  
{
public:
	SOCKET       m_hSocket;
	char         m_szIP[64];
	long         m_lPort;
	long         m_lLoginType;
	BOOL         m_bQuitThread;
	DWORD        m_dwEndSendTime;
	DWORD        m_dwEndRecvTime;
	DWORD        m_dwTestCount;
	BOOL         m_bRecvFrame;
	BOOL         m_bConnect;
	long         m_bLoginSmgp;
	//CSendList    m_SendList;
	//CSendResp    m_SendResp;
	//CDeliverList m_DeliverList;

	ULONG          m_lSendID;
	Smgp_Send_List *    m_pSendList;
	Smgp_Send_Resp *    m_pRespList;
	Smgp_Deliver_List*  m_pDeliverList;
	Smgp_Deliver_List*  m_pStatusList;
	SmgpExchangeResp * m_pSmgpExchangeResp;

	CmppExchange * m_pSmgpExchange;
	long           m_lSmgpExchange;

	long           m_lSendList;
	long           m_lRespList;
	long           m_lDeliverList;
	long           m_lStatusList;
	long           m_lSmgpExchangeRespList;

	char         m_szSmgpIP[32];
	char         m_szSmgpUser[32];
	char         m_szSmgpPasswd[32];
	char         m_szSmgpCorpID[32];

	BOOL         m_bInitSmgp;

	CRITICAL_SECTION m_CriSendSms;
	CRITICAL_SECTION m_CriRespList;
	CRITICAL_SECTION m_CriDeliverList;
	CRITICAL_SECTION m_CriStatusList;
	CRITICAL_SECTION m_CriSmgpExchangeResp;

	BOOL        m_bAdc;


	ULONG        m_lID;
	SGM_PRECVPROC     m_pRecvProc;
	//用于控制发送速度
	DWORD        m_dwEndSocketSendTime; //最后短信发出间隔
	long         m_lSendInterval; //发送间隔时间
	long         m_lSendIntervalCount;  //发送间隔数量
	long         m_lSendIntervalIndex;  //发送间隔统计

	HANDLE       m_hThread;
	HANDLE       m_hThread_Send;

	CRITICAL_SECTION m_CriErrMsg;
	CString          m_strErrMsg;

public:
	BOOL Sms_Add(Smgp_Send_List sms);
	BOOL Sms_Get(Smgp_Send_List*& pSms);
	BOOL isConnectGateWay();
	void SetErrMsg(CString str);
	CString GetErrMsg();

	long GetReportSms();
	static TCHAR * PrintMsgID( TCHAR * pMsgID , UCHAR lMsgID[]);
	long GetWFSms();
	void SetSendSpeed(long lSpeed);
	void SetSmgpExchangeNum(CmppExchange * pSmgpExchange , long lSmgpExchange);
	BOOL SmgpExchangeResp_Add(SmgpExchangeResp resp);
	BOOL GetSmgpExchangeResp(SmgpExchangeResp &resp);
	long Smgp_GetReport(TCHAR * No ,TCHAR * Stat , TCHAR * Done_time,TCHAR * MsgID );
	long Smgp_Get(TCHAR *SendNo,TCHAR * RecvNo, BYTE *Msg, TCHAR *Msg_Fmt, TCHAR *Msg_Length,long & lLongMsgRand ,long & lLongMsgAll, long & lLongMsgIndex);
	BOOL Status_Add(Smgp_Deliver_List Deliver);
	BOOL GetStatus(Smgp_Deliver_List &deliver);
	int CharHex(char ch);
	void AsciiToHex(const char *pszOrgRandom , TCHAR *pszDesRandom , long lLen);
	void ExchangeUniCode( char * pData );
	void HexToAscii(const char *pszOrgRandom , char *pszDesRandom );
	long AsciiToUCS2(const char * pAscii , WCHAR * pUCS2);
	long UCS2ToAscii( const WCHAR * pUCS2 , char * pAscii);
	BOOL isChinese(const TCHAR *pSrc, long lSrcLen);
	unsigned char GetMobilePhoneTON(const char *pSrc, char *pOrg);
	long Smgp_SendSms(const char * SendNo , const char * RecvNo,long Msg_Fmt,long udhi,long Msg_Length,BOOL bHandFree,const BYTE * Msg ,const char * Service_Id,long Fee_UserType,const char * FeeType, const char * FeeCode ,long Registered_Delivery,const char *ValId_Time,const char *At_Time,long lSendID,char * MsgID, BOOL bNo86);
	BOOL Deliver_Add(Smgp_Deliver_List Deliver);
	BOOL SendResp_Add(Smgp_Send_Resp resp);
	void UCS2ToAscii2( char * pUCS2 , char * pAscii , long lSrcLen );
	BOOL Smgp_Exit();
	BOOL GetDeliver(Smgp_Deliver_List &deliver);
	long Process_Deliver(Smgp_Head head,BYTE *pData, long lLen);
	long Process_Active(Smgp_Head head,BYTE *pData, long lLen);
	BOOL GetSendResp( Smgp_Send_Resp & resp );
	long Process_Submit(Smgp_Head head,BYTE *pData, long lLen);
	BOOL Socket_SendSms(Smgp_Send_List * pSend );
	long Back_Send();
	BOOL InitSmgp2();
	BOOL SendSms(Smgp_Send_List sms );
	long Process_Connect(Smgp_Head head, BYTE * pData , long lLen );
	static long SendFrame(SOCKET sock,ULONG &lID,DWORD &dwEndSendTime,ULONG lCommandID,UCHAR * pData , long lDataLen,ULONG & lSeq );
	long Smgp_Init( const char * pIP,long lPort,const char * pUser,const char * pPasswd,const char * pCorpID,long lLoginType );
	BOOL RecvFrame(Smgp_Data_Recv &Drecv);
	static BOOL ReadFrame(SOCKET s, Smgp_Data_Recv *pRecv);
	void SetRecvProc(SGM_PRECVPROC proc);
	static DWORD WINAPI SocketRecv( LPVOID lParam );
	static DWORD WINAPI SocketSend(LPVOID lParam);
	static long Send(SOCKET sock,BYTE *pData, long lLen);
	void Close();
	static BOOL isSocketClose(SOCKET s);
	void Stop();
	BOOL isConnect();
	BOOL Connect2();
	BOOL Connect( const char * pAddr , long lPort , BOOL bReConnect = true );
	CSmgp();
	virtual ~CSmgp();

};

#endif // !defined(AFX_SMGP_H__7DF8EA3F_89A5_4FC9_8D87_131385D01734__INCLUDED_)