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 + -
显示快捷键?