📄 cmpp_client.cpp
字号:
#include "StdAfx.h"
#include "cmpp_client.h"
#include "global.h"
#include "cmpp.h"
#include "proxyserver.h"
#include ".\cmpp_client.h"
#define EACH_SMS_LEN 120
vector<FeeNode> CCMPP_Client::m_FeeList;
bool CCMPP_Client::m_bCanUsed = false;
char CCMPP_Client::m_SrcID[80];
char CCMPP_Client::m_DefaultMsgSrc[80];
CLogFile CCMPP_Client::m_LogFile;
char CCMPP_Client::m_LogFileName[256]={"log\\CMPPClient.log"};
DWORD CCMPP_Client::m_LastUserID=0;
int CCMPP_Client::m_SocketCount=0;
CCMPP_Client::CCMPP_Client(void)
{
}
CCMPP_Client::~CCMPP_Client(void)
{
}
void CCMPP_Client::CMPP_MSG_Dowith(char* pData, DWORD nLen, DWORD UserID)
{
CMPP_ActiveTestResp * pActiveResp;
//CMPP_CancelResp *pCancelResp;
CMPP_ConnectResp *pConnectResp;
CMPP_DeliverResp *pDeliverResp;
CMPP_Deliver *pDeliver;
CMPP_QueryResp *pQueryResp;
CMPP_SubmitResp * pSubmitResp;
CMPP_Terminate * pTerminate;
CMPP_TerminateResp * pTerminateResp;
CMPP_Head Head;
char buffer[32768];
if(nLen > 4096)
{
TRACE("too long%ld\r\n", nLen);
return ;
}
//加入数据到缓冲区
m_CMPPSocket.AppendData(UserID, (BYTE*)pData, nLen);
for(;;)
{
TRACE("ok-1\r\n");
int bytes = m_CMPPSocket.GetData(UserID, (BYTE*)&Head, sizeof(CMPP_Head));
if(bytes == sizeof(CMPP_Head))
{
if( ntohl(Head.TotalLength) > 2048 || ntohl(Head.TotalLength) == 0)
{
m_CMPPSocket.Clear(UserID);
break;
}
int RcvBytes = m_CMPPSocket.GetDataAndRemove(UserID, (BYTE*)buffer, ntohl(Head.TotalLength));
TRACE("响应消息ID=0x%08X,length=%ld,bytes=%ld\r\n", ntohl(Head.CommandID), ntohl(Head.TotalLength),RcvBytes);
if(RcvBytes == ntohl(Head.TotalLength))
{
switch(ntohl(Head.CommandID))
{
case CMPP_Msg::ACTIVE_TEST:
break;
case CMPP_Msg::ACTIVE_TEST_RESP:
TRACE("测试连接响应消息\r\n");
pActiveResp = (CMPP_ActiveTestResp*)buffer;
break;
case CMPP_Msg::CANCEL_RESP:
TRACE("取消短信响应消息\r\n");
// pCancelResp = (CMPP_ConnectResp*)buffer;
break;
case CMPP_Msg::CONNECT_RESP:
TRACE("连接登陆响应消息\r\n");
pConnectResp = (CMPP_ConnectResp*)buffer;
if(pConnectResp->Status == 0)
{
m_ListMsg.InsertStringToQueue(0, "登陆短信网关成功。连接编号:%ld,版本:%0X", UserID, pConnectResp->Version);
m_bCanUsed = true;
}
else
{
m_ListMsg.InsertStringToQueue(1, "登陆短信网关失败,连接编号:%ld, 状态:%d,版本:%0X", UserID, pConnectResp->Status, pConnectResp->Version);
}
break;
case CMPP_Msg::DELIVER_RESP:
TRACE("接收短信响应消息\r\n");
pDeliverResp = (CMPP_DeliverResp*)buffer;
break;
case CMPP_Msg::DELIVER:
TRACE("接收短信消息\r\n");
pDeliver = (CMPP_Deliver*)buffer;
//m_ListMsg.InsertStringToQueue(0, "接收到Deliver消息,TotalLength=%ld, MsgLength=%d", htonl(pDeliver->TotalLength), pDeliver->Msg_Length);
m_ListMsg.InsertStringToQueue( 0, "接收到Deliver消息,TotalLength=%ld, MsgLength=%d,SocketID:%d", htonl(pDeliver->TotalLength), pDeliver->Msg_Length, UserID);
DeliverMsg( pDeliver, UserID );
break;
case CMPP_Msg::QUERY_RESP:
TRACE("查询响应消息\r\n");
pQueryResp = (CMPP_QueryResp*)buffer;
break;
case CMPP_Msg::SUBMIT_RESP:
TRACE("提交短信响应消息\r\n");
pSubmitResp = (CMPP_SubmitResp*)buffer;
if(pSubmitResp->Result == 0)
{
m_ListMsg.InsertStringToQueue( 0, "短消息发送成功");
//SetMsgID(ntohl(pSubmitResp->SequenceID), pSubmitResp->Msg_Id );
}
else
{
m_ListMsg.InsertStringToQueue(1, "短消息发送失败。错误值:%d", pSubmitResp->Result);
}
break;
case CMPP_Msg::TERMINATE:
TRACE("终止消息\r\n");
pTerminate = (CMPP_Terminate*)buffer;
m_bCanUsed = false;
SendTerminateResp(UserID);
break;
case CMPP_Msg::TERMINATE_RESP:
TRACE("终端响应消息\r\n");
pTerminateResp = (CMPP_TerminateResp*)buffer;
// m_CMPPSocket.Close(UserID);
break;
default:
break;
}
}
else
break;
}
else
break;
}
}
void CCMPP_Client::DowithConnect(char * strIP, short Port, DWORD UserID)
{
m_ListMsg.InsertStringToQueue(0, "与CMPP服务器建立连接。IP=%s, Port=%d,,并发送登陆包,等待回应。", m_CMPPSocket.GetIP(UserID), m_CMPPSocket.GetPort(UserID));
m_bCanUsed = false;
//
m_LogFile.WriteLog(m_LogFileName, "与短信网关建立连接,并发送登陆包,等待回应。");
//建立连接,发送登陆包
SendLogon(UserID);
}
void CCMPP_Client::DowithDisconnect(char * strIP, short Port, DWORD UserID)
{
m_ListMsg.InsertStringToQueue(1, "与短消息网关的连接断开。");
m_bCanUsed = false;
m_SocketTimer.AddOnceTimer(60, UserID, 0, 0);
this->m_CMPPSocket.Clear(UserID);
}
void CCMPP_Client::SendActive(DWORD UserID)
{
CMPP_ActiveTest Active;
DWORD ret = m_CMPPSocket.Send((BYTE*)&Active, sizeof(CMPP_ActiveTest), UserID);
/*char temp[80];
AfxMessageBox(itoa(ret, temp, 10));
Sleep(100);*/
}
void CCMPP_Client::SendActiveResp(DWORD UserID)
{
CMPP_ActiveTestResp Active;
m_CMPPSocket.Send((BYTE*)&Active, sizeof(CMPP_ActiveTestResp), UserID);
}
bool CCMPP_Client::Connect(DWORD UserID)
{
char IP[512];
m_bCanUsed = false;
char keyname[80];
sprintf(keyname, "Port%d", UserID);
int Port = GetPrivateProfileInt("CMPP", keyname, 0, CGlobal::IniFile);
sprintf(keyname, "IP%d", UserID);
GetPrivateProfileString("CMPP", keyname, "", IP, 256, CGlobal::IniFile);
if(m_CMPPSocket.Connect(IP, Port, UserID) == 0)
{
Sleep(10);
m_SocketTimer.RemoveTimer(UserID);
return true;
}
else
{
m_ListMsg.InsertStringToQueue(1, "不能与CMPP服务器建立连接,请检查网络及相关参数。IP=%s, Port=%d", m_CMPPSocket.GetIP(UserID), m_CMPPSocket.GetPort(UserID));
m_SocketTimer.AddOnceTimer(60, UserID, 0, 0);
int t=0;
TRACE("\r已经设置了自动重新连接!时间是%d\r",t=60);
return false;
}
}
void CCMPP_Client::SendLogon(DWORD UserID)
{
BYTE Authenticator[256];
char pwd[80], sp[80];
GetPrivateProfileString("CMPP", "Authenticator", "", pwd, 64, IniFile);
GetPrivateProfileString("CMPP", "user", "", sp, 64, IniFile);
strcpy(m_DefaultMsgSrc, sp);
GetPrivateProfileString("CMPP", "sp", "", m_SrcID, 64, IniFile);
char temp[256];
ZeroMemory(temp, 256);
/*SYSTEMTIME t;
GetLocalTime(&t);*/
//生成登陆消息
CMPP_Connect logon;
// sprintf(temp, "%s000000000%s%02d%02d%02d%02d%02d", sp, pwd, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
char time[80];
sprintf(time, "%010d", ntohl(logon.Timestamp));
sprintf(temp, "%s000000000%s%s", sp, pwd, time );
memset((BYTE*)&temp[strlen(sp)], 0, 9);
int len = CMD5Checksum::GetMD5( Authenticator, (BYTE*)temp, (int)strlen(sp) + 9 + (int)strlen(pwd) + (int)strlen(time));
memcpy(logon.SourceAddr, sp, strlen(sp));
memcpy(logon.Authenticator, Authenticator, len);
if(m_CMPPSocket.Send((BYTE*)&logon, sizeof(CMPP_Connect), UserID) > 0)
{
m_ListMsg.InsertStringToQueue(0, "发送登陆鉴权消息成功。");
}
else
m_ListMsg.InsertStringToQueue(1, "发送登陆鉴权消息失败。");
}
void CCMPP_Client::SendTerminate(DWORD UserID)
{
CMPP_Terminate Terminate;
m_CMPPSocket.Send((BYTE*)&Terminate, sizeof(CMPP_Terminate), UserID);
}
void CCMPP_Client::SendTerminateResp(DWORD UserID)
{
CMPP_TerminateResp TerminateResp;
m_CMPPSocket.Send((BYTE*)&TerminateResp, sizeof(CMPP_TerminateResp), UserID);
}
void CCMPP_Client::DeliverMsg(CMPP_Deliver* pDeliver, DWORD UserID)
{
char Sender[80];
char Receiver[80];
ZeroMemory(Sender, 80);
ZeroMemory(Receiver, 80);
CMPP_DeliverResp DeliverResp;
memcpy(DeliverResp.Msg_Id, pDeliver->Msg_Id, 8);
try
{
//消息头检验
if( htonl(pDeliver->TotalLength) == (CMPP_DELIVER_HEAD_LENGTH + pDeliver->Msg_Length + 8)
&& pDeliver->Msg_Length <128 )
{
DeliverResp.Result = 0;
DeliverReport Report;
if(pDeliver->Registered_Delivery == 0)//SMS
{
m_ListMsg.InsertStringToQueue(0, "收到短信,开始处理。");
//TRACE("接收到短信\r\n");
char Context[1024];
ZeroMemory(Context, 256);
memcpy(Sender, pDeliver->Srcterminal_id, __min(20, strlen(pDeliver->Srcterminal_id)));
memcpy(Receiver, pDeliver->Destnation_id, __min(20, strlen(pDeliver->Destnation_id)));
m_ListMsg.InsertStringToQueue(0, "收到短信,开始处理。len=%d", pDeliver->Msg_Length);
int len = __min(255, pDeliver->Msg_Length);
if(len != 0)
{
if( pDeliver->Msg_Fmt == 8 )
{
CMPP_Head::UCS2_To_ASCII( (LPCWSTR)pDeliver->Msg_Content, pDeliver->Msg_Length, Context);
//Context[pDeliver->Msg_Length/2] = 0;
}
else
memcpy( Context, pDeliver->Msg_Content, len );
}
TRACE("接收到短信---3\r\n");
m_ListMsg.InsertStringToQueue(0, "收到短信:%s, 发送方号码:%s, 接收方号码:%s", Context, Sender, Receiver);
//发送给短信处理程序
//if(pDeliver->Msg_Length > 0)
TRACE("接收到短信---4\r\n");
//记录日志
//
CProxyServer::FireRcvSM(pDeliver->Srcterminal_id, pDeliver->Destnation_id, Context, pDeliver->Msg_Length);
TRACE("接收到短信---5\r\n");
}
else if(pDeliver->Registered_Delivery == 1)//REPORT
{
if( pDeliver->Msg_Length == sizeof(DeliverReport) )
{
TRACE("接收到报告\r\n");
memcpy(&Report, pDeliver->Msg_Content, __min(pDeliver->Msg_Length, sizeof(DeliverReport)));
char stat[80];
ZeroMemory(stat, 80);
memcpy(stat, Report.Stat, 7);
memcpy(Receiver, Report.Dest_terminal_Id, __min(20, strlen(Report.Dest_terminal_Id)));
m_ListMsg.InsertStringToQueue(0, "收到状态报告:%s, 接收方号码:%s", stat, Receiver);
FeeResult( Report );
}
else
{
DeliverResp.Result = 1;
m_ListMsg.InsertStringToQueue(1, "收到的状态报告包有错误。");
}
}
}
else
{
DeliverResp.Result = 4;
m_ListMsg.InsertStringToQueue(1, "接收短信消息长度错误");
}
}
catch(...)
{
DeliverResp.Result = 9;
m_ListMsg.InsertStringToQueue(1, "接收短信消息的异常错误。");
}
TRACE("Deliver Response MSG \r\n");
memcpy(DeliverResp.Msg_Id, pDeliver->Msg_Id, 8);
m_CMPPSocket.Send((BYTE*)&DeliverResp, sizeof(CMPP_DeliverResp), UserID);
}
/*
char FeeUserType--一般等于0
计费用户类型字段
0:对目的终端MSISDN计费;
1:对源终端MSISDN计费;
2:对SP计费;
3:表示本字段无效,对谁计费参见Fee_terminal_Id字段。
char* FeeTerminal---被计计费的用户号码
char MsgFmt--端消息的编码格式
0:ASCII串
3:短信写卡操作
4:二进制信息
8:UCS2编码
15:含GB汉字
char* MsgSrc -信息内容来源(SP_Id)
char * FeeType--资费类别
01:对“计费用户号码”免费
02:对“计费用户号码”按条计信息费
03:对“计费用户号码”按包月收取信息费
04:对“计费用户号码”的信息费封顶
05:对“计费用户号码”的收费是由SP实现
如果MsgSrc为空则填写m_DefaultMsgSrc的值m_DefaultMsgSrc从设置文件的[CMPP]的sp读取
char* FeeCode--付费金额
char* SrcId--源号码
SP的服务代码或前缀为服务代码的长号码, 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,
该号码最终在用户手机上显示为短消息的主叫号码
char* DestTerminal ==接收方号码
char Registered_Delivery=是否需要报告
0:不需要
1:需要
2:产生SMC话单(该类型短信仅供网关计费使用,不发送给目的终端)
int MsgLength==消息的长度
char* MsgContext==消息的内容
*/
int CCMPP_Client::Submit(/*char * ServiceID, */
char FeeUserType, char* FeeTerminal, char MsgFmt, char* MsgSrc,
char * FeeType, char* FeeCode, char* SrcId, char* DestTerminal,
char Registered_Delivery, int MsgLength, char* MsgContext)
{
BYTE buffer[1024];//定义要发送的字符序列
CMPP_Submit Submit;//实例化短信提交类
DWORD UserID =GetSendID();//得到系统内部的soketid
if(UserID>=0xFFFF)//如果用户不存在
{
return -3;//退出
}
strcpy(Submit.Service_id,m_SrcID);//给类中的变量赋值,该变量表示业务类型
strcpy(Submit.Fee_terminal_id,FeeTerminal);//给类中的变量赋值,该变量表示被计费的用户号码
if(strlen(MsgSrc))//如果信息来源长度不是零
{
strcpy(Submit.Msg_src,m_DefaultMsgSrc);//信息来源表示的是sp的id,该id是给移动的短信平台来识别sp的识别码
}
else
{
strcpy(Submit.Msg_src,MsgSrc);
}
memcpy(Submit.FeeType,FeeType,2);//FeeType表示资费类型
strncpy(Submit.FeeCode,FeeCode,__min(6,strlen(FeeCode)));//FeeCode表示资费代码
if(strlen(SrcId)!=0)
{
strcpy(Submit.Src_terminal_id,SrcId);//Src_terminal_id是sp的号码,给用户识别的代码,在这里指短信的发送方
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -