cmppapi.c

来自「用c/c++实现的一个CMPP API」· C语言 代码 · 共 2,167 行 · 第 1/5 页

C
2,167
字号
}/* *描述:(1) 初始化系统接口的配置参数        (2) 连接MTBS服务器        (3) 创建连接接收线程        (4) 创建连接发送线程        (5) 创建接收缓冲区        (6) 创建发送缓冲区        (7) 创建MO、回执缓冲区 *输入:sIniFile 配置文件名 *输出:无 *返回值:API_OK 成功 *        其它 失败 *//*int ASPAPI nHInitInterface( const char* sIniFile )*//*金华业公司聂咸义修改*/int ASPAPI nHInitInterface( const char* sIniFile, int  nFD ){    int nRet;    CONNFD FD;  // 连接句柄                Trace( "Call nHInitInterface \n" );    if( sIniFile == NULL )    {        vSetErrorDetail("Invalid Input Parameter, ini File is NULL\n" );        return  API_ERR_INVALID;    }            FD = nFD;    if( g_HConnDesc[ FD ].nInitFlag == YES_INIT )    {        Trace( "Already Init H level Interface \n" );        return API_OK;            }        nRet =  nInitByFD( sIniFile, FD );        /*    *高层的回复RESPNOSE为自动    */    g_HConnDesc[ FD ].rCfgPara.bAutoDeliveryResponse = TRUE;                                          return nRet;    }/* *描述:(1)释放API资源        (2)关闭同MTBS的连接  注意:系统退出时必须调用nHExitInterface,释放线程资源 *输入:无 *输出:无 *返回值:API_OK 成功 *        其它 失败 */int ASPAPI nHExitInterface( ){        Trace( "call nHExitinterface\n" );    return nExitInterface( HCONNFD );    }              /* * 描述:SUBMIT,支持群发包(拆分包)接口 *       (1) 发送MT请求 *       (2) 接收MT响应 *       该接口支持群发,和内容超长度的拆分 *       群发的目的地址号码用","号分割, 返回API_OK,表明发送都 *       成功,如果非API_OK, 输出参数sLastTerminateId *        说明最后一个失败的目标号码, 如果返回的是API_ERR_RESP, *        说明是网关返回了一个RESPONSE表明错误, pnResult表明结果 * 输入: *       recSubmit*    prSubmit submit的参数消息结构:            各个域的值含义如下:              <1>  unsigned char *sInMsgId     信息标识, 由SP输入(该字段长度可以等于0,                                                 不等于0表示用于MO和MT匹配)              <2>  unsigned char ucPkTotal     相同的MSGID的信息的总条数,从1开始              <3>  unsigned char ucPkNumber    相同的MSGID的信息序号,从1开始                         ( 这两个参数为支持EMS用, 和拆分包的功能互斥,                          即:如果内容超长包发送,这两个参数无效, 应该填为1 )                            <4>  const char *sFeeTerminalId, 计费号码, 仅限一个号码 字段长度可以等于0,                                               如果长度等于0 对目的终端计费               <5>  const char *sFeeType,      取值见MacFeeType_...常量定义              <6>  int   nFeeCode,             费率(单位:分),                                    如按次计费为每次费用,如包月计费为包月费用,              <7>  const char *sServiceId,    业务类型               <8>  const unsigned char ucTpPid  Gsm协议类型              <9>  const unsigned char ucTpUdhi Gsm协议类型              <10> const char *sSrcId,        源号码                            *       const char *sDstTerminateId  目标地址号码( 以,号分割多个号码) *       const unsigned char ucMsgFmt 信息格式 *       const unsigned int  unMsgLength 内容长度 *       const char *sMsgContent  内容 * 输出:unsigned char *sOutMsgId 信息标识, 由网关产生 *       unsigned char *pchResult 结果, 为O 是正确 *       char* sLastTerminateId      最后处理的目标号码 * 返回值:API_OK 成功 *         其它 失败 */int ASPAPI nHSubmit(                        int nFD, /*niexianyi add*/			           recSubmit*    prSubmit,          			           const char *sDstTerminateId,			           const unsigned char ucDstTerminateType,                       const unsigned char ucMsgFmt,                       const unsigned int  unMsgLength,                       const char *sMsgContent,                       unsigned char *sOutMsgId,                       unsigned char *pchResult,                       char *sLastTerminateId                        ){    int nRet;    recCmppSubmit rCmppSubmit;    recCmppSubmitResp   rCmppSubmitResp;    if(g_nEnableLog != 0)    {	    char pcContents[1024]="" ;	    vPrintBin(prSubmit,sizeof(recSubmit),pcContents);	    Trace("%s",pcContents);    }    memset( &rCmppSubmit, 0, sizeof( recCmppSubmit ) );    memset( &rCmppSubmitResp, 0, sizeof( recCmppSubmitResp ) );    if( prSubmit == NULL ||        strlen( prSubmit->sFeeType ) == 0  || prSubmit->nFeeCode < 0 ||         strlen( prSubmit->sServiceId )== 0 || strlen( prSubmit->sSrcId ) == 0 ||        sDstTerminateId == NULL || ((ucDstTerminateType != 1 ) && strlen( sDstTerminateId ) == 0 )||        pchResult == NULL || sLastTerminateId == NULL ||         sOutMsgId == NULL ||sMsgContent == NULL          )    {        vSetErrorDetail( "Invalid input parameter\n" );        return API_ERR_INVALID;    }        /*    * 从配置中得到的submit值    */    nRet = nInitSubmitValue( nFD, &rCmppSubmit);    if( nRet != API_OK )    {        return nRet;    }    if( prSubmit->ucPkTotal <= 0 )    {        vSetErrorDetail( "Invalid input parameter, ucPkTotal must > 0\n" );        return API_ERR_INVALID;    }    else    {        rCmppSubmit.ucPkTotal = prSubmit->ucPkTotal;    }    if( prSubmit->ucPkNumber <= 0 )    {        vSetErrorDetail( "Invalid input parameter, ucPkNumber must > 0\n" );        return API_ERR_INVALID;    }    else    {        rCmppSubmit.ucPkNumber = prSubmit->ucPkNumber;                    }    /*    * 校验 pk_total 和 pk_total 和 msg_length的合法性    */    if( prSubmit->ucPkTotal > 1 || prSubmit->ucPkNumber > 1 )    {        if (  unMsgLength >= 160 ||              ( ucMsgFmt != MSG_FORMAT_ASCII && unMsgLength > 140 ) )        {            vSetErrorDetail( "Invalid input parameter, ucPkNumber or ucPkTotal "                              " must = 1 when unMsgLength too big [160] or [140]\n" );            return API_ERR_INVALID;        }                  }    if( strlen( prSubmit->sInMsgId ) != 0 )    {    	memcpy(rCmppSubmit.uchMsgId, prSubmit->sInMsgId, MacMsgId);    }        //仅限一个号码 ,可以为NULL     //modify by lijian 2003-12.11 修改伪码的问题    if( prSubmit->ucFeeTerminalType == 1 )    {        memcpy( rCmppSubmit.chFeeTerminateId, prSubmit->sFeeTerminalId, MacFeeTermId );        rCmppSubmit.ucFeeUserType = MacFeeUserType_Third;    }    else    {        		if( strlen( prSubmit->sFeeTerminalId ) != 0 )		{		       memcpy( rCmppSubmit.chFeeTerminateId, prSubmit->sFeeTerminalId, MacFeeTermId );		      rCmppSubmit.ucFeeUserType = MacFeeUserType_Third;		 }		else			rCmppSubmit.ucFeeUserType = MacFeeUserType_Dest;    }    rCmppSubmit.ucFeeTerminalType = prSubmit->ucFeeTerminalType;            //取值见MacFeeType_...常量定义    strncpy( rCmppSubmit.chFeeType,  prSubmit->sFeeType, MacFeeType );        //费率(单位:分),如按次计费为每次费用,如包月计费为包月费用,    snprintf( rCmppSubmit.chFeeCode, MacFeeCode+1,  "%d", prSubmit->nFeeCode );        //业务类型     strncpy( rCmppSubmit.chServiceId, prSubmit->sServiceId, MacServiceId );        //源号码    strncpy( rCmppSubmit.chSrcId, prSubmit->sSrcId, MacSrcId );       // LinkID    strncpy(rCmppSubmit.chLinkId, prSubmit->sLinkId, MacLinkId);    /*    *是否?: 如果ucMsgFmt 为二进制, 则 tp_pid 和 tp_udhi 填为 1     *否则都填为 0     */        rCmppSubmit.ucTpPid = prSubmit->ucTpPid;    rCmppSubmit.ucTpUdhi  = prSubmit->ucTpUdhi;    rCmppSubmit.ucMsgFmt = ucMsgFmt;    nRet = nSubmit( nFD,                     sDstTerminateId,                    ucDstTerminateType,                    unMsgLength,                    sMsgContent,                          &rCmppSubmit,                    &rCmppSubmitResp,                    sLastTerminateId );        memcpy(  sOutMsgId, rCmppSubmitResp.uchMsgId, MacMsgId );    *pchResult = rCmppSubmitResp.unResult ;        return nRet;        }/* * 描述:高层取缓冲中的普通MO,回执    * 输入:int nTimeOut 超时时间(秒) * 输出:int* pnReceiptOrNot   *           类型:1 回执 0 deliver   *       unsigned int* punSequenceId   *       recCmppDeliver*      prCmppDeliver  *       recCmppReceiptBody*  prReceiptBody,  *               (在*pnReceiptOrNot为1时有效) *       int  nTimeOut 超时时间(秒) * 返回值:API_OK 成功 *         API_NOCELL 没有数据包 *         其它 失败  */int ASPAPI nHGetDeliver(                 int nFD, /*niexianyi add*/                  int* pnReceiptOrNot,                  unsigned int* punSequenceId,                 recCmppDeliver* prCmppDeliver,                 recCmppReceiptBody* prReceiptBody,                 int nTimeOut                 ){    return nGetDeliver(                         nFD, /*niexianyi add*/                        pnReceiptOrNot,                         punSequenceId,                        prCmppDeliver,                        prReceiptBody,                        nTimeOut                        );}/*---------------------------------------------------------------------------*//*---------------------------------------------------------------------------*//*底层接口函数*//*---------------------------------------------------------------------------*//* *查找空闲的连接资源 */CONNFD  nSearchFreeConn( ){    int i;        for( i=1; i < MAXCONNNUM; ++i )    {        if( g_HConnDesc[ i ].nInitFlag == NO_INIT )        return i;    }    return -1;}/**创建连接接收线程*创建连接发送线程*创建发送缓冲区*创建MO、回执缓冲区*创建sequence缓冲区*/static  int nInitAConnBufferAndThread( CONNFD conndesc ){    int nRet;    static CONNFD FD;                FD = conndesc;            /*    * 创建发送缓冲区    */    nRet = nLockInitAQueue(  0, sizeof( recCmppPck ), QUEUECELLNUM,  TRUE,                             &(g_HConnDesc[FD].rSendBufFd) );    if( nRet != QUEUE_OK )    {        vSetErrorDetail( "Error when initialize send buffer\n" );        return  API_ERR_OTHER;            }        /*    * 创建MO、回执缓冲区    */    nRet = nLockInitAQueue(  0, sizeof( recCmppPck ), QUEUECELLNUM,  TRUE,                             &(g_HConnDesc[FD].rDeliverBufFd) );    if( nRet != QUEUE_OK )    {        // release resource         nLockRemoveQueue( &(g_HConnDesc[FD].rSendBufFd) );                vSetErrorDetail( "Error when initialize delivery buffer\n" );        return API_ERR_OTHER;            }        /*    *创建sequence缓冲区    */    nRet = nLockInitMemHT( sizeof( int ), sizeof( recSeqCell ),                            SEQUENCENUM/4, SEQUENCENUM,                           &(g_HConnDesc[FD].rSeqBufFd) );    if( nRet != SHMHT_OK )    {        // release resource             nLockRemoveQueue( &(g_HConnDesc[FD].rSendBufFd) );        nLockRemoveQueue( &(g_HConnDesc[FD].rDeliverBufFd) );        vSetErrorDetail( "Error when initialize sequence buffer\n" );        return  API_ERR_OTHER;    }    /*    * 创建连接接收线程    * 创建连接发送线程    */    g_HConnDesc[FD].bThreadExit = FALSE;       nRet = nAPICreatThread( &g_HConnDesc[FD].SendThreadHandle, vSendThread, &FD );    if( nRet != THREAD_OK )    {        vSetErrorDetail( "Error when initialize send thread\n" );        nLockRemoveQueue( &(g_HConnDesc[FD].rSendBufFd) );        nLockRemoveQueue( &(g_HConnDesc[FD].rDeliverBufFd) );                nLockRemoveMemHT(&(g_HConnDesc[FD].rSeqBufFd));        return  API_ERR_OTHER;    }    nRet = nAPICreatThread( &g_HConnDesc[FD].RecvThreadHandle, vRecvThread, &FD );    if( nRet != THREAD_OK )    {        nAPICancelThread(&g_HConnDesc[FD].SendThreadHandle);                nLockRemoveQueue( &(g_HConnDesc[FD].rSendBufFd) );        nLockRemoveQueue( &(g_HConnDesc[FD].rDeliverBufFd) );                nLockRemoveMemHT(&(g_HConnDesc[FD].rSeqBufFd));                vSetErrorDetail( "Error when initialize recv thread\n" );                        return  API_ERR_OTHER;    }        return API_OK;}static  int nInitByFD( const char* sIniFile, CONNFD FD ){    int nRet;    int nInitRet;    recCmppConnect rCmppConnect;    recCmppConnectResp rCmppConnectResp;        memset( &rCmppConnect, 0, sizeof( recCmppConnect ) );    memset( &rCmppConnectResp, 0, sizeof( recCmppConnectResp ) );        g_HConnDesc[ FD ].nInitFlag = YES_INIT;    /*    *读取配置参数    */    nRet = nReadConfig( sIniFile, &g_HConnDesc[FD].rCfgPara );    if( nRet != 0 )    {        vSetErrorDetail("Error when read config file[%s] \n", sIniFile );        nInitRet = API_ERR_INIFILE;        goto ERR_RETURN;    }    /*    *连接MTBS服务器    */    nRet = nTcpConnect_Api( g_HConnDesc[FD].rCfgPara.sHostAddr,                         g_HConnDesc[FD].rCfgPara.nHostPort                         );    if( nRet == TCPLIB_FAIL )    {        vSetErrorDetail("Error when connect Server IP[%s] PORT[%d]\n",                        g_HConnDesc[FD].rCfgPara.sHostAddr,                         g_HConnDesc[FD].rCfgPara.nHostPort                         );        nInitRet = API_ERR_NETWORK;        goto ERR_RETURN;    }    else    {        g_HConnDesc[FD].nConnFd = nRet;        g_HConnDesc[FD].eSocketStatus = ConnectOpen;    }        /*    *创建连接接收线程

⌨️ 快捷键说明

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