⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spsms.c

📁 使用标准C开发的同时支持CMPP3.0 和 CMPP2.0 的SP短信网关程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	time_t nTime;
	char sTmp[16];
	char sAuth[128];

	memset(sTmp, 0x00, sizeof(sTmp));
	memset(sAuth, 0x00, sizeof(sAuth));
	memset(&rPacket, 0x00, sizeof(TCmppPacket));

	
	rPacket.rMsgHead.nTotalLen = htonl(nPacketLen);
	rPacket.rMsgHead.nCommandId = htonl(CMPP_CONNECT);
	strcpy(rPacket.rMsgBody.rConnectReq.sSpId, sSpId);

	time(&nTime);
	memcpy(&rTm,localtime(&nTime), sizeof(rTm));
	sprintf(sTmp, "%02d%02d%02d%02d%02d", rTm.tm_mon+1, rTm.tm_mday, rTm.tm_hour, rTm.tm_min, rTm.tm_sec);	

	p = sAuth;
	strcpy(p, sSpId), p += strlen(sSpId);
	p += 9;
	strcpy(p, sSpPwd), p += strlen(sSpPwd);
	strncpy(p, sTmp, 10), p += 10;

	
	GetMD5((unsigned char *)sAuth, p-sAuth,  \
		(unsigned char *)rPacket.rMsgBody.rConnectReq.sAuthenticatorSource);
	
#ifndef CMPP_VERSION_20
	rPacket.rMsgBody.rConnectReq.nVersion = 0x30;
#else
	rPacket.rMsgBody.rConnectReq.nVersion = 0x20;
#endif

	rPacket.rMsgBody.rConnectReq.nTimeStamp = htonl(atol(sTmp));
	nRet = SendPacketToMISC(&rPacket, nPacketLen,0);

	return nRet;
}

/**
 *@brief 终止与ISMG的连接请求
 *
 * 
 *@param 
 *@return
*/
void CMPP_SendTerminateReq()
{
	TCmppHead rCmppHead;

	memset(&rCmppHead, 0x00, sizeof(TCmppHead));
	rCmppHead.nTotalLen = htonl(sizeof(TCmppHead));
	rCmppHead.nCommandId = htonl(CMPP_TERMINATE);

	SendPacketToMISC(&rCmppHead, sizeof(TCmppHead),0);
}

/**
 *@brief 终止与ISMG连接响应 
 *
 * 
 *@param nSeqId [in] ISMG发送回来的序列号
 *@return
*/
void CMPP_SendTerminateRep(unsigned int nSeqId)
{
	TCmppHead rCmppHead;

	memset(&rCmppHead, 0x00, sizeof(TCmppHead));
	rCmppHead.nTotalLen = htonl(sizeof(TCmppHead));
	rCmppHead.nSeqId = htonl(nSeqId);
	rCmppHead.nCommandId = htonl(CMPP_TERMINATE_RESP);

	SendPacketToMISC(&rCmppHead, sizeof(TCmppHead),0);
}

/**
 *@brief 链路检测请求
 *
 * 
 *@param 
 *@return
*/
void CMPP_SendActiveTestReq()
{
	TCmppHead rCmppHead;

	memset(&rCmppHead, 0x00, sizeof(TCmppHead));
	rCmppHead.nTotalLen = htonl(sizeof(TCmppHead));
	rCmppHead.nCommandId = htonl(CMPP_ACTIVE_TEST);

	SendPacketToMISC(&rCmppHead, sizeof(TCmppHead),0);
	SmgTrace(2, "SendActiveTest to MISC.\n");
}

/**
 *@brief 链路检测响应
 *
 * 
 *@param nSeqId [in] ISMG发送回来的序列号
 *@return
*/
void CMPP_SendActiveTestRep(unsigned int nSeqId)
{
	TCmppHead rCmppHead;

	memset(&rCmppHead, 0x00, sizeof(TCmppHead));
	rCmppHead.nTotalLen = htonl(sizeof(TCmppHead));
	rCmppHead.nCommandId = htonl(CMPP_ACTIVE_TEST_RESP);

	SendPacketToMISC(&rCmppHead, sizeof(TCmppHead),0);
}

/**
 *@brief SP对ISMG向SP递交的短信的响应
 *MO短信类型,由手机终端或者其他终端发起,经ISMG或者MISC最终上行到SP
 *然后SP对该MO类型短信进行响应
 * 
 *
 *@param sMsgId [in] 信息标识字段
 *@param nSeqId [in] ISMG发送回来的序列号
 *@return
*/
void CMPP_SendDeliverRep(char *sMsgId, unsigned int nSeqId)
{
	TCmppPacket rPacket;

	int nPacketLen = sizeof(TCmppHead) + sizeof(TCmppDeliverRep);

	memset(&rPacket, 0x00, sizeof(TCmppPacket));

	rPacket.rMsgHead.nTotalLen = htonl(nPacketLen);
	rPacket.rMsgHead.nCommandId = htonl(CMPP_DELIVER_RESP);

#ifndef CMPP_VERSION_20
	rPacket.rMsgBody.rDeliverRep.nResult = htonl(0);
	memcpy(rPacket.rMsgBody.rDeliverRep.sMsgId, sMsgId, MAX_MSG_ID_LEN);
	SendPacketToMISC(&rPacket, nPacketLen,0);
#else
	rPacket.rMsgBody.rDeliverRep.nResult = 0;
	memcpy(rPacket.rMsgBody.rDeliverRep.sMsgId, sMsgId, MAX_MSG_ID_LEN);
	SendPacketToMISC(&rPacket, nPacketLen,0); // cmpp2.0的deliverrep的包结果为1字节
#endif
}

/**
 *@brief SP向ISMG查询发送短信状态
 *
 * 
 *@param sServiceId [in] 业务代码,只有当nQueryType=1时有用
 *@param sTime [in] YYYYMMDD精确到日
 *@param nQueryType [in] =0时,总数查询;=1时,按业务查询
 *@return
*/
void CMPP_SendQureyReq(char* sServiceId, char* sTime, unsigned char nQueryType)
{
	TCmppPacket rPacket;

	int nPacketLen = sizeof(TCmppHead) + sizeof(TCmppQueryReq);

	memset(&rPacket, 0x00, sizeof(TCmppPacket));

	rPacket.rMsgHead.nTotalLen = htonl(nPacketLen);
	rPacket.rMsgHead.nCommandId = htonl(CMPP_QUERY);

	if(sServiceId != NULL)
		strcpy(rPacket.rMsgBody.rQueryReq.sQueryCode, sServiceId);
	rPacket.rMsgBody.rQueryReq.nQueryType =  nQueryType;
	strcpy(rPacket.rMsgBody.rQueryReq.sTime, sTime);

	SendPacketToMISC(&rPacket, nPacketLen,0);
}

/**
 *@brief SP向ISMG发起删除短信
 *
 * 
 *@param sMsgId [in] 要删除的信息标识符
 *@return
*/
void CMPP_SendCancelReq(char *sMsgId)
{
	TCmppPacket rPacket;

	int nPacketLen = sizeof(TCmppHead) + sizeof(TCmppCancelReq);

	memset(&rPacket, 0x00, sizeof(TCmppPacket));

	rPacket.rMsgHead.nTotalLen = htonl(nPacketLen);
	rPacket.rMsgHead.nCommandId = htonl(CMPP_CANCEL);

	memcpy(rPacket.rMsgBody.rCancelReq.sMsgId, sMsgId, MAX_MSG_ID_LEN);

	SendPacketToMISC(&rPacket, nPacketLen,0);
}

/**
 *@brief SP向ISMG提交短信
 *
 * 
 *@param pnSeqId [in] 
 *@param sMsgId [in] 信息标识,由SP接入的短信网关本身产生,本处填空。
 *@param nPkTotal [in] 相同Msg_Id的信息总条数,从1开始
 *@param nPkNumber [in] 相同Msg_Id的信息序号,从1开始
 *@param nRegister [in] 是否要求返回状态确认报告。
						0:不需要 1:需要
 *@param nMsgLevel [in] 信息级别
 *@param sServiceId [in] 业务标识,是数字、字母和符号的组合
 *@param nFeeUserType [in]	 计费用户类型字段
							 0:对目的终端MSISDN计费;
							 1:对源终端MSISDN计费;
							 2:对SP计费;
							 3:表示本字段无效,对谁计费参见Fee_terminal_Id字段
 *@param sFeeTerminalId [in] 被计费用户的号码(如本字节填空,则表示本字段无效,对谁计费参见Fee_UserType字段,本字段与Fee_UserType字段互斥)
 *@param nFeeTerminalType [in] 被计费用户的号码类型,0:真实号码;1:伪码
 *@param nTPPid [in] GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.9
 *@param nTPUdhi [in] GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐
 *@param nMsgFmt [in]	 信息格式
						 0:ASCII串
						 3:短信写卡操作
						 4:二进制信息
						 8:UCS2编码
						 15:含GB汉字 
 *@param sSpId [in] 信息内容来源(SP_Id)
 *@param nFeeType [in]   资费类别
						 01:对"计费用户号码"免费
						 02:对"计费用户号码"按条计信息费
						 03:对"计费用户号码"按包月收取信息费
						 04:对"计费用户号码"的信息费封顶
						 05:对"计费用户号码"的收费是由SP实现
 *@param sFeeCode [in] 资费代码(以分为单位)
 *@param sSrcTerminalId [in] 源号码
							 SP的服务代码或前缀为服务代码的长号码, 
							 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,
							 该号码最终在用户手机上显示为短消息的主叫号码
 *@param nDstAddrNumber [in] 
 *@param sDstTerminalId [in] 接收短信的MSISDN号码
 *@param nDstTerminalType [in] 接收短信的用户的号码类型,0:真实号码;1:伪码
 *@param nMsgLen [in] 信息长度(Msg_Fmt值为0时:<160个字节;其它<=140个字节)
 *@param sMsgContent [in] 信息内容
 *@param sLinkId [in] 点播业务使用的LinkID,非点播类业务的MT流程不使用该字段
 *@param md5 [in] 校验码
 *@return
*/
int  CMPP_SendSubmitReq(unsigned int*	pnSeqId,
						char*			sMsgId,
						unsigned char	nPkTotal,
						unsigned char	nPkNumber,
						unsigned char	nRegister,
						unsigned char	nMsgLevel,
						char*			sServiceId,
						unsigned char	nFeeUserType,
						char*			sFeeTerminalId,
						unsigned char	nFeeTerminalType,
						unsigned char	nTPPid,
						unsigned char	nTPUdhi,
						unsigned char	nMsgFmt,
						char*			sSpId,
						unsigned char	nFeeType,
						char*			sFeeCode,
						char*			sSrcTerminalId,
						unsigned char	nDstAddrNumber,
						char *			sDstTerminalId,
						unsigned char	nDstTerminalType,
						unsigned char	nMsgLen,
						char *			sMsgContent,
						char *			sLinkId,
						char *			md5)
{
	int nTmpValue=0;
	char sItem[2048];
	char *p;
	int nRet = 0;
	
	memset(sItem, 0x00, 2048);
	p = sItem;

	p += 4;

	nTmpValue = htonl(CMPP_SUBMIT);
	memcpy(p, &nTmpValue, 4), p += 4;
//	*pnSeqId = g_nSeqId;  ???
//	nTmpValue = htonl(g_nSeqId++);???

//	*pnSeqId = SendMsgLink.SeqId;
	nTmpValue = htonl(SendMsgLink.SeqId++);
	memcpy(p, &nTmpValue, 4), p += 4;

	if(sMsgId == NULL)
		p += MAX_MSG_ID_LEN;
	else
		memcpy(p, sMsgId, MAX_MSG_ID_LEN), p += MAX_MSG_ID_LEN;
	*p++ = nPkTotal;
	*p++ = nPkNumber;
	*p++ = nRegister;
	*p++ = nMsgLevel;
	if( sServiceId != NULL)
		strcpy(p, sServiceId), p += MAX_SERVICE_ID_LEN;
	else
		p += MAX_SERVICE_ID_LEN;
	*p++ = nFeeUserType;
	
#ifndef CMPP_VERSION_20
	if(sFeeTerminalId != NULL)
		strcpy(p, sFeeTerminalId), p += MAX_FEE_TERMINALID_LEN;
	else
		p += MAX_FEE_TERMINALID_LEN;
	*p++ = nFeeTerminalType;
#else
	if(sFeeTerminalId != NULL)
		strcpy(p, sFeeTerminalId), p += MAX_SRC_TERMINALID_LEN;
	else
		p += MAX_SRC_TERMINALID_LEN;
#endif
	
	*p++ = nTPPid;
	*p++ = nTPUdhi;
	*p++ = nMsgFmt;
	if(sSpId != NULL)
		memcpy(p, sSpId, MAX_SP_ID_LEN), p += MAX_SP_ID_LEN;
	else
		return -2;
	sprintf(p, "0%d", nFeeType), p += MAX_FEE_TYPE_LEN;
	if(sFeeCode != NULL)
		strcpy(p, sFeeCode), p += MAX_FEE_CODE_LEN;
	else
		p += MAX_FEE_CODE_LEN;
	p += MAX_VALID_TIME_LEN; //char sValidTime[MAX_VALID_TIME_LEN];
	p += MAX_VALID_TIME_LEN; //char sAtTime[MAX_VALID_TIME_LEN];
	if(sSrcTerminalId != NULL)
		strcpy(p, sSrcTerminalId), p += MAX_SRC_TERMINALID_LEN;
	else
		return -3;
	*p++ = nDstAddrNumber;
#ifndef CMPP_VERSION_20
	if(sDstTerminalId != NULL)
		strcpy(p, sDstTerminalId), p += MAX_DST_TERMINALID_LEN;
	else
		return -4;
	*p++ = nDstTerminalType;
#else
	if(sDstTerminalId != NULL)
		strcpy(p, sDstTerminalId), p += MAX_SRC_TERMINALID_LEN;
	else
		return -4;
#endif
	
	*p++ = nMsgLen;
	if(sMsgContent != NULL)
		memcpy(p, sMsgContent, nMsgLen);
	p += nMsgLen;

#ifndef CMPP_VERSION_20
	if(sLinkId != NULL)
		memcpy(p, sLinkId, MAX_LINK_ID_LEN), p += MAX_LINK_ID_LEN;
	else
		p += MAX_LINK_ID_LEN;
#else
		p += 8;
#endif
	
	nTmpValue = htonl(p - sItem);
	memcpy(sItem, &nTmpValue, 4);

	nRet = SendPacketToMISC(sItem, p-sItem,md5);

	return nRet;
}

#define ToChar(c)       (c)>=10?((c)-10+'a'):((c)+'0')


int CMPP_PraseMsgId(char *sMsgId, int nMsgIdLen, char *sStrMsgId)
{
    int i=0, nLen=0;
    unsigned char *p, *q;
    if( nMsgIdLen == 0  || sMsgId == NULL || sStrMsgId == NULL)
		return -1;
    p = (unsigned char *)sMsgId;
    q = (unsigned char *)sStrMsgId;
    while( i++ < nMsgIdLen )
    {
        *(q++) = ToChar(((unsigned char)(*p)>>4)&0x0f);
        *(q++) = ToChar((unsigned char)(*p)&0x0f);
        p++;
        nLen += 2;
    }
    *q = 0x00;
    return nLen;
}

void CMPP_PraseReport(char *sReport, TCmppReportMsg *pCmppReportMsg)
{
	char *p;
	char sStat[8] = {0x00};
	int nTempValue = 0;
	
	if(sReport == NULL || pCmppReportMsg == NULL)
		return;

	p = sReport;

	CMPP_PraseMsgId(p, MAX_MSG_ID_LEN, pCmppReportMsg->sMsgId);
	p += MAX_MSG_ID_LEN;
	strncpy(sStat, p, 7), p += 7;
	if(strcmp(sStat, "DELIVRD") == 0)
		pCmppReportMsg->nState = 0;
	else if(strcmp(sStat, "ACCEPTD") == 0)
		pCmppReportMsg->nState = 1;
	else
		pCmppReportMsg->nState = 2;
	strncpy(pCmppReportMsg->sSubmitTime, p, 10), p += 10;
	strncpy(pCmppReportMsg->sDoneTime, p, 10), p += 10;
	strncpy(pCmppReportMsg->sDstTerminalId, p, 32), p += 32;
	memcpy(&nTempValue, p, 4);
	pCmppReportMsg->nSeqId = ntohl(nTempValue); ////???
}

/**
 *@brief 接收ISMG发送给SP的信息,并调用相应的处理函数
 *
 * 
 *@param ptr [in] ISMG发送给SP的消息包
 *@return
*/
void RecvSMCFromISMG(RecvIsmg_Prim_Type * ptr)
{
	char *sBuf;
	unsigned short nLen;
	TCmppPacket rPacket;
	char *p;
	unsigned int nTmpValue = 0;
	char *sMsgId[64] = {0x00};
	IsmgSendQ_Prim_Type * IsmgMsg;
	int nRet;

	/*
	//test
	char ch;
	int i = 0;
	*/

	int nAllLen = 0, len = 0;
	char strSendToDB[32] = {0};
//	TIMER_T	 *	IsmgMsgTv;
	
	SmcSetTimer(&SysTestTv);
	sBuf = (char *)ptr;
	sBuf += 4;
	nLen = ptr->len;
	memset(&rPacket, 0x00, sizeof(TCmppPacket));
	CMPP_UnpackMsgHead(&rPacket.rMsgHead, sBuf);

	p = sBuf+sizeof(TCmppHead);

	if (rPacket.rMsgHead.nSeqId != SendMsgLink.P_R	|| \
		rPacket.rMsgHead.nSeqId < SendMsgLink.LWE_R	|| \
		rPacket.rMsgHead.nSeqId > (SendMsgLink.LWE_R+ISMGMESWIDOW))
	{
		PutIdleBlock(&ptr);
		return;
	}

	SendMsgLink.LWE_S = rPacket.rMsgHead.nSeqId;
	SendMsgLink.P_R = ((rPacket.rMsgHead.nSeqId+1)%ISMGMESWIDOW);
	PutIsmgTimer(rPacket.rMsgHead.nSeqId);

	//! 扫描SP向ISMG发送消息的队列,直到队列为空为止
	while((IsmgMsg = ScanIsmgQq()) != NULL)
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -