cmppapi.c
来自「用c/c++实现的一个CMPP API」· C语言 代码 · 共 2,167 行 · 第 1/5 页
C
2,167 行
/*************************************************************************** Copyright : 2002, ASPIRE TECHNOLOGIES (SHENZHEN) LTD. Program ID : apifunc.c Description : cmppapi 的函数实现文件 Version : cmppapi 1.5 Modification Log: DATE AUTHOR DESCRIPTION -------------------------------------------------------------------------- 2002-11-27 wenyz Create 2003-04-03 wenyz 修改MO包误认为状态报告 2003-12-11 lijian 修改伪码相关信息***************************************************************************/#include "datatype.h" // 内部数据结构定义#include "cfgs.h" // 配置文件函数定义#include "apilockht.h" // sequence 匹配函数定义#include "queuelock.h" // queue 函数定义#include "seterrno.h" // 错误信息函数定义#include "event.h" // 事件函数定义#include "cmpppack.h" // 编解码函数定义#include "tcplib.h" // socket 函数定义#include "log.h" // 调试跟踪函数定义#include "md5.h" // 加密函数MD5定义#include "cmppthread.h" // 线程函数定义#define MAC_TIMEOUT 10 // 超时时间(秒)extern int g_nEnableLog = -1; /* 是否打开日志 */typedef struct _seqCell{ recCmppPck rCmppPck; recEvent* prEvent; // 事件的指针,用于接收线程唤醒用户线程序}recSeqCell;#define MAXCONNNUM 40#define HCONNFD 0 // 高层连接句柄#define QUEUECELLNUM 1024 //队列的最大数据包个数#define SEQUENCENUM 2048 //SEQUENCE匹配的CACHE包个数#define MAXSEQUENCE 99999999 //最大SEQUENCEstatic recConnDesc g_HConnDesc[ MAXCONNNUM ]; // 连接句柄 #define MAX_DST_TERMIN 99 // 群发最大终端数const char cDivTag = ','; // 群发目标号码串分隔符const int g_nMsgLenAscii = 159; // ASCII码单包最大长度const int g_nMsgLenOther = 140; // 非ASCII码单包最大长度/**内部使用函数*//* * 描述:设置绝对时间格式字符串 * 输入:const char* psInputStr 输入时间字符串 int nTimeFmt 绝对时间 * 输出:char* psTimeFmt 符合smpp格式的时间字符串 * 返回值:int API_OK 成功 其它 失败 */static int nSetAbsoluteTimeFmt(char* psTimeFmt, const char* psInputStr);/* * 描述:设置相对时间格式字符串 * 输入:const char* psInputStr 输入时间字符串 int nTimeFmt 绝对时间 * 输出:char* psTimeFmt 符合smpp格式的时间字符串 * 返回值:int API_OK 成功 其它 失败 */static int nSetRelativeTimeFmt(char* psTimeFmt, const char* psInputStr);static int nReadConfig(const char* sIniFile, recCfgPara* rCfgPara);static int nLogin( CONNFD connDesc, recCmppConnect *prCmppConnect, recCmppConnectResp *prCmppConnectResp, EBool bSocket ); static int nValidConnFD( CONNFD nFd );static void vFreeConnFD( recConnDesc* prConnDesc );static int nInitAConnBufferAndThread( CONNFD conndesc );static int nCheckSocketAndLogin( CONNFD FD );static int nAddSequence( CONNFD FD );static int nSendCmppAndGetResp( CONNFD connDesc, recCmppPck* prCmppPck, recCmppPck* prRespCmppPck, EBool bSocket, int nTimeOut );static int nCmppSendSocket( int nSocket, recCmppPck* prCmppPck );static int nSendActive( CONNFD connDesc, EBool bSocket ); static int nGetConnectDataByCfg( recCfgPara* prCfg, recCmppConnect* prCmppConnect );static int nMSgRecv( int nSock, char* pBuf, int nTimeout );static int nInitByFD( const char* sIniFile, CONNFD FD ); int ASPAPI nSendDeliverResponse(CONNFD connDesc, unsigned int unSequenceId, recCmppDeliverResp* prCmppDeliverResp );static int nValidConnFD( CONNFD nFd ){ if( nFd < 0 || nFd >=MAXCONNNUM ) { vSetErrorDetail( "Error: Invalid connection description[%d]\n", nFd ); return API_ERR_INVALID; } if( g_HConnDesc[ nFd ].nInitFlag != YES_INIT ) { vSetErrorDetail( "Error: Connection description is not initialized \n" ); return API_ERR_INVALID; } return API_OK;}/** 将内存数据复位原来的值*/static void vFreeConnFD( recConnDesc* prConnDesc ){ if( prConnDesc == NULL ) return ; nTcpClose_Api( prConnDesc->nConnFd ); prConnDesc->eSocketStatus = ConnectClose; prConnDesc->eLoginStatus = NoLogined ; prConnDesc->nConnFd = -1; prConnDesc->nInitFlag = NO_INIT; prConnDesc->nSequence = 0; }/*---------------------------------------------------------------------------*//*高层接口函数*//* * 描述:设置绝对时间格式字符串 * 输入:const char* psInputStr 输入时间字符串 int nTimeFmt 绝对时间 * 输出:char* psTimeFmt 符合smpp格式的时间字符串 * 返回值:int API_OK 成功 其它 失败 */int nSetAbsoluteTimeFmt(char* psTimeFmt, const char* psInputStr){ char* psHead; char sTmp[128]; int nTmp; if( (psTimeFmt == NULL) || (psInputStr == NULL) ) { return -1; } if( strlen(psInputStr) < 13 ) { return -1; } psHead = (char*)psInputStr; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断年的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 99) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断月的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 1) || (nTmp > 12) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断日的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 1) || (nTmp > 31) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断小时的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 23) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断分钟的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 59) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断秒的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 59) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 1); /* 判断1/10 秒的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 10) ) { return -1; } memcpy(psTimeFmt, psInputStr, 13); strcat(psTimeFmt, "32+"); return API_OK;}/* * 描述:设置相对时间格式字符串 * 输入:const char* psInputStr 输入时间字符串 int nTimeFmt 绝对时间 * 输出:char* psTimeFmt 符合smpp格式的时间字符串 * 返回值:int API_OK 成功 其它 失败 */int nSetRelativeTimeFmt(char* psTimeFmt, const char* psInputStr){ char* psHead; char sTmp[128]; int nTmp; if( (psTimeFmt == NULL) || (psInputStr == NULL) ) { return -1; } if( strlen(psInputStr) < 12 ) { return -1; } psHead = (char*)psInputStr; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断年的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 99) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断月的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 12) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断日的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 31) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断小时的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 23) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断分钟的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 59) ) { return -1; } psHead = psHead + 2; memset(sTmp, 0, sizeof(sTmp)); strncpy(sTmp, psHead, 2); /* 判断秒的时间格式是否合法 */ nTmp = atoi(sTmp); if( (nTmp < 0) || (nTmp > 59) ) { return -1; } memcpy(psTimeFmt, psInputStr, 12); strcat(psTimeFmt, "000R"); return API_OK;}static unsigned int nGetTimeStamp(){ time_t nowtime; struct tm *newtime; char stimestr[11]; unsigned int nTimeStamp; memset( stimestr, 0, sizeof(stimestr)); time( &nowtime ); newtime = localtime( &nowtime ); sprintf( stimestr,"%02d%02d%02d%02d%02d", newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec ); nTimeStamp = atoi(stimestr); return nTimeStamp;}/**通过配置得到connect的包内容*/#define VERSION 2static int nGetConnectDataByCfg( recCfgPara* prCfg, recCmppConnect* prCmppConnect ){ unsigned char sAuthenticator[ MacAuthSource ]; unsigned char sMD5Buffer[ 128 ]; // 存放MD5的中间数据 unsigned char* pBuffer; unsigned int nTimeStamp ; int nLen; if( prCfg == NULL || prCmppConnect == NULL ) return API_ERR_INVALID; memset( sAuthenticator, 0, sizeof( sAuthenticator ) ); memset( sMD5Buffer, 0, sizeof( sMD5Buffer ) ); //sp_id SP的企业ID memcpy( prCmppConnect->chSourceAddr, prCfg->sSpID, MacSourceAddress ); /* *用于鉴别源地址。其值通过单向MD5 hash计算得出, *表示如下:AuthenticatorSource =MD5 *(Source_Addr+9 字节的0 +shared secret+timestamp) * Shared secret 由中国移动与源地址实体事先商定, * timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。 */ //得到认证码 pBuffer = sMD5Buffer; nLen = strlen(prCfg->sSpID) < 6 ? strlen(prCfg->sSpID) : 6; memcpy( pBuffer, prCfg->sSpID, nLen); pBuffer += nLen; pBuffer += 9; nLen = strlen(prCfg->sSpPasswod) < 32 ? strlen(prCfg->sSpPasswod) : 32; memcpy( pBuffer, prCfg->sSpPasswod, nLen ); pBuffer +=nLen; nTimeStamp = nGetTimeStamp(); sprintf( pBuffer,"%010u", nTimeStamp ); pBuffer +=10; nLen = pBuffer - sMD5Buffer; vMD5Crypt( sMD5Buffer, nLen, sAuthenticator); // copy认证码 memcpy( prCmppConnect->chAuthSource, sAuthenticator, MacAuthSource ); // 版本号 prCmppConnect->ucVersion = prCfg->nVersion; // 时间戳 prCmppConnect->unTimestamp = nTimeStamp;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?