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