1168 lines
30 KiB
C
1168 lines
30 KiB
C
/*
|
|
** CDMA 2000 project, SMPP module
|
|
**
|
|
** File name: smpp_func.c
|
|
** Written by Li Long at 2004-11-25
|
|
** CVS $Id: smpp_func.c,v0.1 2004/11/25 17:03:14 lilong Exp $
|
|
**
|
|
*/
|
|
|
|
#include "./include/smpp.h"
|
|
#include "./include/smpp_def.h"
|
|
|
|
extern int register_ssn(BYTE ssn, BYTE usertype);
|
|
|
|
/* by simon at 23/9/26 */
|
|
SocketsMsg SockMsg;
|
|
|
|
int smpp_init_new(u8 sys_id)
|
|
{
|
|
smpp_system_no = sys_id & 0x01;
|
|
#ifdef SMPP_DEBUG
|
|
smpp_debugInit();
|
|
#endif //end ifdef SMPP_DEBUG
|
|
smpp_mibInit();
|
|
smpp_loadParam();
|
|
smpp_writeParam();
|
|
|
|
heartbeat_init(0xffff);
|
|
|
|
smpp_initTCPClient();
|
|
smpp_initTCPServer();
|
|
smpp_stateInit();
|
|
smpp_msgInit();
|
|
|
|
// if (FALSE == register_ssn(SMPP_PPS_SSN, SMPP_PPS_USERTYPE))
|
|
if (FALSE == register_ssn(SMPP_PPS_SSN, SMPP_SMSC_USERTYPE))
|
|
printf("SMPP register PPS SSN %d fail!\n", SMPP_PPS_SSN);
|
|
if (FALSE == register_ssn(SMPP_SMSC_SSN, SMPP_SMSC_USERTYPE))
|
|
printf("SMPP register SMSC SSN %d fail!\n", SMPP_SMSC_SSN);
|
|
printf("SMPP init........ Complete.\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void smpp_reset()
|
|
{
|
|
int i;
|
|
for (i=0; i<MAX_SMPP_LINK; i++) {
|
|
if (smpp_param[i].link_type == SMPP_TCP)
|
|
smpp_closeTCPConnection(i);
|
|
}
|
|
close(Mysock.DaemonSock);
|
|
smpp_init_new(smpp_system_no);
|
|
|
|
for (i=0; i<MAX_SMPP_LINK; i++) {
|
|
if (callBackFunc[i].link_proc != NULL)
|
|
callBackFunc[i].link_proc(i, FALSE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
return: bit7: 0-not fill, 1-fill
|
|
bit6-0: link number (<=128)
|
|
server_type: 0-SMPP_CLIENT; 1-SMPP_SERVER
|
|
session_type: 0-BIND_TX; 1-BIND_RX; 2-BIND_TRX
|
|
service_number_ptr: poiter to remote service number.
|
|
message_mode: 0-STORE_AND_FORWARD; 1-DATAGRAM; 2-TRANSACTION
|
|
*/
|
|
BYTE smpp_registerLink(BYTE server_type, BYTE session_type, char* service_number_ptr, BYTE message_mode)
|
|
{
|
|
char debugBuf[1024];
|
|
int i, len_get, len_in_para;
|
|
|
|
for (i=0; i<MAX_SMPP_LINK; i++) {
|
|
if ((smpp_param[i].link_enable & 0x01) == 0) continue;
|
|
if (smpp_param[i].session_type != session_type) continue;
|
|
if (smpp_param[i].server_type != server_type) continue;
|
|
if(smpp_param[i].local_ip>0x00 && smpp_param[i].local_ip != GetLocalIP()) continue;
|
|
|
|
len_get = strlen(service_number_ptr);
|
|
if (len_get > 8) {
|
|
service_number_ptr[8] = 0;
|
|
len_get = 8;
|
|
}
|
|
len_in_para = strlen(smpp_param[i].service_number);
|
|
if (len_in_para < len_get) {
|
|
if (strncmp(service_number_ptr, smpp_param[i].service_number, len_in_para) == 0) {
|
|
smpp_param[i].message_mode = message_mode;
|
|
return (BYTE)((i&0x7F)|0x80);
|
|
}
|
|
}
|
|
else {
|
|
if (strcmp(service_number_ptr, smpp_param[i].service_number) == 0) {
|
|
smpp_param[i].message_mode = message_mode;
|
|
return (BYTE)((i&0x7F)|0x80);
|
|
}
|
|
}
|
|
}
|
|
|
|
sprintf(debugBuf,"smpp_registerLink(server_type:%d,session_type:%d,service_number:%s,message_mode:%d) fail\r\n\r\n",server_type,session_type,service_number_ptr,message_mode);
|
|
smpp_send_error(debugBuf);
|
|
return 0;
|
|
}
|
|
|
|
void smpp_attach_link(BYTE linkNo, smpp_callBack_dataProc onDataRecv,
|
|
smpp_callBack_linkProc onLinkStateChange)
|
|
{
|
|
BYTE temp_status;
|
|
|
|
if(linkNo>=MAX_SMPP_LINK) return;
|
|
|
|
// removed by simon, 2023/11/04
|
|
// added by simon at 2024/06/12
|
|
smeg_debug_log("[smpp]link %d attached.\n", linkNo);
|
|
if(smpp_state[linkNo] == ESTABLISHED ||
|
|
smpp_state[linkNo] == SUSPEND)
|
|
{
|
|
if(callBackFunc[linkNo].link_proc!= NULL)
|
|
callBackFunc[linkNo].link_proc(linkNo,TRUE);
|
|
return;
|
|
}
|
|
else if(smpp_state[linkNo] == WAITING)
|
|
{
|
|
if(callBackFunc[linkNo].link_proc!= NULL)
|
|
callBackFunc[linkNo].link_proc(linkNo,FALSE);
|
|
return;
|
|
}
|
|
|
|
linkAttachFlag[linkNo] = TRUE;
|
|
smpp_state[linkNo] = IDLE;
|
|
temp_status = IDLE;
|
|
temp_status = temp_status<<((linkNo%4)*2);
|
|
smpp_hearbeat_status[linkNo/4] |= temp_status;
|
|
callBackFunc[linkNo].data_proc = onDataRecv;
|
|
callBackFunc[linkNo].link_proc = onLinkStateChange;
|
|
exterEvent[linkNo][exter_head[linkNo]] = Setup;
|
|
exter_head[linkNo] = (exter_head[linkNo]+1)&0x7;
|
|
|
|
if(SMPP_TCP == smpp_param[linkNo].link_type)
|
|
{
|
|
switch (smpp_param[linkNo].session_type) {
|
|
case BIND_TX:
|
|
case BIND_TRX:
|
|
if (smpp_param[linkNo].server_type == SMPP_CLIENT)
|
|
smpp_TCPClientFlag[linkNo] = 1;
|
|
break;
|
|
case BIND_RX:
|
|
if (smpp_param[linkNo].server_type == SMPP_SERVER)
|
|
smpp_TCPClientFlag[linkNo] = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
WORD smpp_send(BYTE linkNo, SMPP_MSG* pMsg, WORD dataLen)
|
|
{
|
|
PDU_SUBMIT_SM *pSubmitSM;
|
|
PDU_SUBMIT_MULTI *pSubmitMulti;
|
|
PDU_DELIVER_SM *pDeliverSM;
|
|
PDU_DATA_SM *pDataSM;
|
|
PDU_QUERY_SM *pQuerySM;
|
|
PDU_CANCEL_SM *pCancelSM;
|
|
PDU_REPLACE_SM *pReplaceSM;
|
|
DWORD seqNum;
|
|
|
|
smeg_debug_log("\33[32mlink %d call smpp_send, message_type=%d\33[0m\n", linkNo, pMsg->message_type);
|
|
switch (pMsg->message_type)
|
|
{
|
|
case 0x0B: /* SUBMIT SM */
|
|
pSubmitSM = &pMsg->pdu.submit_sm;
|
|
pSubmitSM->head.command_id = htonl(SUBMIT_SM);
|
|
pSubmitSM->head.command_status = 0x0;
|
|
//seqNum = smpp_getSequenceNumber(linkNo);
|
|
//pSubmitSM->head.sequence_number = htonl(seqNum);
|
|
pSubmitSM->head.sequence_number = htonl(pSubmitSM->head.sequence_number);
|
|
|
|
smpp_encode_msg(linkNo, pMsg, SubmitSM);
|
|
break;
|
|
case 0x0C: /* SUBMIT SM RESP */
|
|
pMsg->pdu.submit_sm_resp.head.command_id = htonl(SUBMIT_SM_RESP);
|
|
seqNum = ntohl(pMsg->pdu.submit_sm_resp.head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, SubmitSMResp);
|
|
break;
|
|
case 0x0D: /* SUBMIT MULTI */
|
|
pSubmitMulti = &pMsg->pdu.submit_multi;
|
|
pMsg->pdu.submit_multi.head.command_id = htonl(SUBMIT_MULTI);
|
|
pMsg->pdu.submit_multi.head.command_status = 0x0;
|
|
//seqNum = smpp_getSequenceNumber(linkNo);
|
|
//pMsg->pdu.submit_multi.head.sequence_number = htonl(seqNum);
|
|
pSubmitMulti->head.sequence_number = htonl(pSubmitMulti->head.sequence_number);
|
|
|
|
smpp_encode_msg(linkNo, pMsg, SubmitMulti);
|
|
break;
|
|
case 0x0E: /* SUBMIT MULTI RESP */
|
|
pMsg->pdu.submit_multi_resp.head.command_id = htonl(SUBMIT_MULTI_RESP);
|
|
seqNum = ntohl(pMsg->pdu.submit_multi_resp.head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, SubmitMultiResp);
|
|
break;
|
|
case 0x0F: /* DELIVER SM */
|
|
pDeliverSM = &pMsg->pdu.deliver_sm;
|
|
pDeliverSM->head.command_id = htonl(DELIVER_SM);
|
|
pDeliverSM->head.command_status = 0x0;
|
|
//seqNum = smpp_getSequenceNumber(linkNo);
|
|
//pDeliverSM->head.sequence_number = htonl(seqNum);
|
|
pDeliverSM->head.sequence_number = htonl(pDeliverSM->head.sequence_number);
|
|
|
|
pDeliverSM->schedule_delivery_time = 0;
|
|
pDeliverSM->validity_period = 0;
|
|
pDeliverSM->replace_if_present_flag = 0;
|
|
pDeliverSM->sm_default_msg_id = 0;
|
|
|
|
smpp_encode_msg(linkNo, pMsg, DeliverSM);
|
|
break;
|
|
case 0x10: /* DELIVER SM RESP */
|
|
pMsg->pdu.deliver_sm.head.command_id = htonl(DELIVER_SM_RESP);
|
|
seqNum = ntohl(pMsg->pdu.deliver_sm.head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, DeliverSMResp);
|
|
break;
|
|
case 0x11: /* DATA SM */
|
|
pDataSM = &pMsg->pdu.data_sm;
|
|
pDataSM->head.command_id = htonl(DATA_SM);
|
|
pDataSM->head.command_status = 0x0;
|
|
//seqNum = smpp_getSequenceNumber(linkNo);
|
|
//pDataSM->head.sequence_number = htonl(seqNum);
|
|
pDataSM->head.sequence_number = htonl(pDataSM->head.sequence_number);
|
|
|
|
smpp_encode_msg(linkNo, pMsg, DataSM);
|
|
break;
|
|
case 0x12: /* DATA SM RESP */
|
|
pMsg->pdu.data_sm_resp.head.command_id = htonl(DATA_SM_RESP);
|
|
seqNum = ntohl(pMsg->pdu.data_sm_resp.head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, DataSMResp);
|
|
break;
|
|
case 0x13: /* QUERY SM */
|
|
pQuerySM = &pMsg->pdu.query_sm;
|
|
pMsg->pdu.query_sm.head.command_id = htonl(QUERY_SM);
|
|
pMsg->pdu.query_sm.head.command_status = 0x0;
|
|
//seqNum = smpp_getSequenceNumber(linkNo);
|
|
//pMsg->pdu.query_sm.head.sequence_number = htonl(seqNum);
|
|
pQuerySM->head.sequence_number = htonl(pQuerySM->head.sequence_number);
|
|
|
|
smpp_encode_msg(linkNo, pMsg, QuerySM);
|
|
break;
|
|
case 0x14: /* QUERY SM RESP */
|
|
pMsg->pdu.query_sm_resp.head.command_id = htonl(QUERY_SM_RESP);
|
|
seqNum = ntohl(pMsg->pdu.query_sm_resp.head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, QuerySMResp);
|
|
break;
|
|
case 0x15: /* CANCEL SM */
|
|
pCancelSM = &pMsg->pdu.cancel_sm;
|
|
pMsg->pdu.cancel_sm.head.command_id = htonl(CANCEL_SM);
|
|
pMsg->pdu.cancel_sm.head.command_status = 0x0;
|
|
//seqNum = smpp_getSequenceNumber(linkNo);
|
|
//pMsg->pdu.cancel_sm.head.sequence_number = htonl(seqNum);
|
|
pCancelSM->head.sequence_number = htonl(pCancelSM->head.sequence_number);
|
|
|
|
smpp_encode_msg(linkNo, pMsg, CancelSM);
|
|
break;
|
|
case 0x16: /* CANCEL SM RESP */
|
|
pMsg->pdu.cancel_sm_resp.head.command_id = htonl(CANCEL_SM_RESP);
|
|
seqNum = ntohl(pMsg->pdu.cancel_sm_resp.head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, CancelSMResp);
|
|
break;
|
|
case 0x17: /* REPLACE SM */
|
|
pReplaceSM = &pMsg->pdu.replace_sm;
|
|
pMsg->pdu.replace_sm.head.command_id = htonl(REPLACE_SM);
|
|
pMsg->pdu.replace_sm.head.command_status = 0x0;
|
|
//seqNum = smpp_getSequenceNumber(linkNo);
|
|
//pMsg->pdu.replace_sm.head.sequence_number = htonl(seqNum);
|
|
pReplaceSM->head.sequence_number = htonl(pReplaceSM->head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, ReplaceSM);
|
|
break;
|
|
case 0x18: /* REPLACE SM RESP */
|
|
pMsg->pdu.replace_sm_resp.head.command_id = htonl(REPLACE_SM_RESP);
|
|
seqNum = ntohl(pMsg->pdu.replace_sm_resp.head.sequence_number);
|
|
smpp_encode_msg(linkNo, pMsg, ReplaceSMResp);
|
|
break;
|
|
default:
|
|
smeg_debug_log("[ERROR]link %d no such message type!(=%02x)\n", linkNo, pMsg->message_type);
|
|
return 0;
|
|
}
|
|
|
|
return seqNum;
|
|
}
|
|
|
|
void smpp_close(BYTE linkNo)
|
|
{
|
|
exterEvent[linkNo][exter_head[linkNo]] = Close;
|
|
exter_head[linkNo] = (exter_head[linkNo]+1)&0x7;
|
|
}
|
|
|
|
void smpp_PrimitiveSend(int linkNo, int event_id)
|
|
{
|
|
switch (event_id)
|
|
{
|
|
case BindTransmitter:
|
|
smpp_sendBind(linkNo, BindTransmitter);
|
|
break;
|
|
case BindTransmitterResp:
|
|
smpp_sendBindResp(linkNo, BindTransmitterResp, 0);
|
|
break;
|
|
case BindReceiver:
|
|
smpp_sendBind(linkNo, BindReceiver);
|
|
break;
|
|
case BindReceiverResp:
|
|
smpp_sendBindResp(linkNo, BindReceiverResp, 0);
|
|
break;
|
|
case BindTransceiver:
|
|
smpp_sendBind(linkNo, BindTransceiver);
|
|
break;
|
|
case BindTransceiverResp:
|
|
smpp_sendBindResp(linkNo, BindTransceiverResp, 0);
|
|
break;
|
|
case Unbind:
|
|
smpp_sendUnbind(linkNo);
|
|
break;
|
|
case UnbindResp:
|
|
smpp_sendUnbindResp(linkNo);
|
|
break;
|
|
case EnquireLink:
|
|
smpp_sendEnquireLink(linkNo);
|
|
break;
|
|
case EnquireLinkResp:
|
|
smpp_sendEnquireLinkResp(linkNo);
|
|
break;
|
|
case Outbind:
|
|
smpp_sendOutbind(linkNo);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void smpp_initTCPClintByLink(unsigned int linkNo)
|
|
{
|
|
int on=1, flag=1;
|
|
struct sockaddr_in local_addr;
|
|
|
|
if(linkNo>=MAX_SMPP_LINK) return;
|
|
|
|
if (((smpp_param[linkNo].link_enable & 0x01) == 0) || (smpp_param[linkNo].link_type == SMPP_UDP))
|
|
{
|
|
return;
|
|
}
|
|
if ((Mysock.client_sock[linkNo] = socket(AF_INET, SOCK_STREAM, 0))<0)
|
|
{
|
|
return;
|
|
}
|
|
if (setsockopt(Mysock.client_sock[linkNo], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
|
|
{
|
|
close(Mysock.client_sock[linkNo]);
|
|
return;
|
|
}
|
|
if (setsockopt(Mysock.client_sock[linkNo], SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1)
|
|
{
|
|
close(Mysock.client_sock[linkNo]);
|
|
return;
|
|
}
|
|
if (fcntl(Mysock.client_sock[linkNo], F_SETFL, O_NONBLOCK) == -1)
|
|
{
|
|
close(Mysock.client_sock[linkNo]);
|
|
return;
|
|
}
|
|
/* Set this sockets as a Non-blocking sockets. */
|
|
if (ioctl(Mysock.client_sock[linkNo], FIONBIO, &flag) == -1)
|
|
{
|
|
close(Mysock.client_sock[linkNo]);
|
|
return;
|
|
}
|
|
|
|
bzero(&local_addr, sizeof(local_addr));
|
|
local_addr.sin_family = AF_INET;
|
|
local_addr.sin_addr.s_addr = GetLocalIP();//htonl(INADDR_ANY);
|
|
local_addr.sin_port = 0;
|
|
memset(local_addr.sin_zero, 0, sizeof(local_addr.sin_zero));
|
|
if (bind(Mysock.client_sock[linkNo], (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0)
|
|
{
|
|
perror("init TCP Client By Link: bind error");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void smpp_initTCPClient()
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<MAX_SMPP_LINK; i++)
|
|
{
|
|
smpp_initTCPClintByLink(i);
|
|
}
|
|
}
|
|
|
|
void smpp_tcp_connect(int link)
|
|
{
|
|
struct sockaddr_in server;
|
|
int on = 1, flag = 1;
|
|
|
|
server.sin_family = AF_INET;
|
|
server.sin_port = htons(SMPP_PORT);
|
|
server.sin_addr.s_addr = smpp_param[link].remote_ip;
|
|
/* Connect to the server. */
|
|
if (connect(Mysock.client_sock[link], (struct sockaddr *)&server, sizeof(server))<0)
|
|
{
|
|
if( EINPROGRESS !=errno && EALREADY != errno)//ch:Bad file descriptor
|
|
{
|
|
close(Mysock.client_sock[link]);
|
|
Mysock.client_sock[link]=0;
|
|
smpp_initTCPClintByLink(link);
|
|
/*
|
|
if ((Mysock.client_sock[link] = socket(AF_INET, SOCK_STREAM, 0))<0)
|
|
return;
|
|
if (setsockopt(Mysock.client_sock[link], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
|
|
{
|
|
close(Mysock.client_sock[link]);
|
|
return;
|
|
}
|
|
if (setsockopt(Mysock.client_sock[link], SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1)
|
|
{
|
|
close(Mysock.client_sock[link]);
|
|
return;
|
|
}
|
|
if (fcntl(Mysock.client_sock[link], F_SETFL, O_NONBLOCK) == -1)
|
|
{
|
|
close(Mysock.client_sock[link]);
|
|
return;
|
|
}
|
|
if (ioctl(Mysock.client_sock[link], FIONBIO, &flag) == -1)
|
|
{
|
|
close(Mysock.client_sock[link]);
|
|
return;
|
|
}
|
|
*/
|
|
}
|
|
//perror("connect");
|
|
return;
|
|
}
|
|
/*
|
|
FD_SET(clientSockFd, &Mysock.readfds);
|
|
FD_SET(clientSockFd, &Mysock.writefds);
|
|
FD_SET(clientSockFd, &Mysock.exceptfds);
|
|
*/
|
|
Mysock.Sockets[link] = Mysock.client_sock[link];
|
|
Mysock.client_sock[link] =-1;
|
|
|
|
smeg_debug_log("[init TCP client]link %d socket number = %d\n", link, Mysock.Sockets[link]);
|
|
}
|
|
|
|
extern DWORD GetLocalIP();
|
|
|
|
void smpp_initTCPServer()
|
|
{
|
|
int serverSockFd;
|
|
int on=1;
|
|
struct sockaddr_in local_addr;
|
|
|
|
serverSockFd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (serverSockFd < 0)
|
|
{
|
|
perror("server socket error!");
|
|
exit(1);
|
|
}
|
|
//if ((serverSockFd = socket(AF_INET, SOCK_STREAM, 0))<0) { return (-1); }
|
|
if (setsockopt(serverSockFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
|
|
{
|
|
close(serverSockFd);
|
|
return;
|
|
}
|
|
if (setsockopt(serverSockFd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1)
|
|
{
|
|
close(serverSockFd);
|
|
return;
|
|
}
|
|
if (fcntl(serverSockFd, F_SETFL, O_NONBLOCK) == -1)
|
|
{
|
|
close(serverSockFd);
|
|
return;
|
|
}
|
|
bzero(&local_addr, sizeof(local_addr));
|
|
local_addr.sin_family = AF_INET;
|
|
// local_addr.sin_addr.s_addr = inet_addr(smpp_getLocalIP());
|
|
local_addr.sin_addr.s_addr = GetLocalIP();//htonl(INADDR_ANY);
|
|
local_addr.sin_port = htons(SMPP_PORT);
|
|
memset(local_addr.sin_zero, 0, sizeof(local_addr.sin_zero));
|
|
// printf("Init TCP server: ip = %s, port = %d\n",
|
|
// inet_ntoa(local_addr.sin_addr),
|
|
// ntohs(local_addr.sin_port));
|
|
if (bind(serverSockFd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0)
|
|
{
|
|
perror("bind error");
|
|
exit(1);
|
|
}
|
|
if (listen(serverSockFd, MAX_SMPP_LINK*2) < 0)
|
|
{
|
|
perror("listen error");
|
|
exit(1);
|
|
}
|
|
|
|
/*set this socket as a non-blocking socket.
|
|
if (ioctl(serverSockFd, FIONBIO, &flag) == -1)
|
|
{
|
|
perror("ioctl error");
|
|
close(serverSockFd);
|
|
}
|
|
*/
|
|
Mysock.DaemonSock = serverSockFd;
|
|
FD_SET(serverSockFd, &Mysock.readfds);
|
|
FD_SET(serverSockFd, &Mysock.exceptfds);
|
|
|
|
smeg_debug_log("init TCP server complete. socket number = %d.\n",serverSockFd);
|
|
}
|
|
|
|
WORD smpp_getServerPort()
|
|
{
|
|
static WORD offset = 0;
|
|
|
|
offset = offset % 1000;
|
|
return (offset + offset++);
|
|
}
|
|
|
|
DWORD smpp_getSequenceNumber(int linkNo)
|
|
{
|
|
DWORD sequence_number;
|
|
|
|
sequence_number = smpp_link[linkNo].seq_num;
|
|
sequence_number++;
|
|
smpp_link[linkNo].seq_num = sequence_number;
|
|
#ifdef SMPP_PRINT_SCREEN
|
|
// printf("link %d sequence number = %d.\n", linkNo, sequence_number);
|
|
#endif //end ifdef SMPP_PRINT_SCREEN
|
|
return sequence_number;
|
|
}
|
|
|
|
char *smpp_getLocalIP()
|
|
{
|
|
char hostname[128];
|
|
|
|
char *host_ip;
|
|
struct hostent *host;
|
|
if (gethostname(hostname,128) == 0)
|
|
{
|
|
if ((host = gethostbyname(hostname)) != NULL)
|
|
{
|
|
((struct in_addr *)(*host->h_addr_list))->s_addr = GetLocalIP();
|
|
host_ip = inet_ntoa(*(struct in_addr *)(*host->h_addr_list));
|
|
}
|
|
else
|
|
{
|
|
perror("[smpp] gethostbyname");
|
|
exit(2);
|
|
}
|
|
}
|
|
|
|
return host_ip;
|
|
}
|
|
|
|
int smpp_closeTCPConnection(int linkNo)
|
|
{
|
|
int retcode;
|
|
|
|
if ( (linkNo>=MAX_SMPP_LINK) || (linkNo<0) || (Mysock.Sockets[linkNo]<=0) )
|
|
return (0);
|
|
retcode = close(Mysock.Sockets[linkNo]);
|
|
|
|
FD_CLR(Mysock.Sockets[linkNo], &Mysock.readfds);
|
|
FD_CLR(Mysock.Sockets[linkNo], &Mysock.writefds);
|
|
FD_CLR(Mysock.Sockets[linkNo], &Mysock.exceptfds);
|
|
Mysock.Sockets[linkNo] = 0;
|
|
|
|
#ifdef SMPP_PRINT_SCREEN
|
|
// printf("link %d close TCP connection.\n", linkNo);
|
|
#endif
|
|
return (retcode);
|
|
}
|
|
|
|
int QuerySocketsMsg()
|
|
{
|
|
fd_set rfds,wfds,efds;
|
|
int retcode,i;
|
|
struct timeval TimeOut;
|
|
|
|
rfds = Mysock.readfds;
|
|
wfds = Mysock.writefds;
|
|
efds = Mysock.exceptfds;
|
|
TimeOut.tv_sec = 0;
|
|
TimeOut.tv_usec = 0;
|
|
bzero((char *)&SockMsg, sizeof(SockMsg));
|
|
if ((retcode = select(MAX_SMPP_LINK, &rfds, &wfds, &efds, &TimeOut)) == 0)
|
|
{
|
|
return (0);
|
|
}
|
|
if (FD_ISSET(Mysock.DaemonSock, &rfds))
|
|
{
|
|
SockMsg.AcceptNum = 1;
|
|
}
|
|
for (i=0; i<MAX_SMPP_LINK; i++)
|
|
{
|
|
if ((Mysock.Sockets[i]>0) && (FD_ISSET(Mysock.Sockets[i],&rfds)))
|
|
{
|
|
SockMsg.ReadQueue[SockMsg.ReadNum++] = i;
|
|
}
|
|
}
|
|
for (i=0; i<MAX_SMPP_LINK; i++)
|
|
{
|
|
if ((Mysock.Sockets[i]>0) && (FD_ISSET(Mysock.Sockets[i],&wfds)))
|
|
{
|
|
SockMsg.WriteQueue[SockMsg.WriteNum++] = i;
|
|
}
|
|
}
|
|
if (FD_ISSET(Mysock.DaemonSock, &efds))
|
|
{
|
|
SockMsg.AcceptNum = -1;
|
|
}
|
|
for (i=0; i<MAX_SMPP_LINK; i++)
|
|
{
|
|
if ((Mysock.Sockets[i]>0) && (FD_ISSET(Mysock.Sockets[i],&efds)))
|
|
{
|
|
SockMsg.WriteQueue[SockMsg.ExceptNum++] = i;
|
|
}
|
|
}
|
|
|
|
return (retcode);
|
|
}
|
|
|
|
int smpp_check_sysid_route(char* sysid_rv, BYTE sysidlen_rv, BYTE server_type, BYTE session_type)
|
|
{
|
|
int i;
|
|
char debugBuf[256];
|
|
|
|
for (i=0; i<MAX_SMPP_LINK; i++) {
|
|
if (linkAttachFlag[i] == FALSE) continue;
|
|
if ((smpp_param[i].link_enable & 0x01) == 0) continue;
|
|
if (smpp_param[i].server_type == server_type) continue;
|
|
if (smpp_param[i].session_type != session_type) continue;
|
|
|
|
#ifdef SMPP_DEBUG
|
|
if ((smppDebug.debug_switch == 1) || (smppDebug.link_switch[i] == 1)) {
|
|
sprintf(debugBuf,
|
|
"link: %d, link type: %d\n \
|
|
[RECEIVE] system id: %s, sysidlen: %d\n \
|
|
[PARAM] system id: %s\n",
|
|
i, smpp_param[i].link_type, sysid_rv, sysidlen_rv, smpp_param[i].sys_id);
|
|
smpp_send_ascout(debugBuf);
|
|
}
|
|
#endif
|
|
if (memcmp(sysid_rv, smpp_param[i].sys_id, sysidlen_rv) == 0)
|
|
return i;
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
void smpp_setSccpAddr(int linkNo, SCCP_ADDR *pSrcAddr, SCCP_ADDR *pDstAddr)
|
|
{
|
|
/* set SCCP source addr. */
|
|
pSrcAddr->RI = 0;
|
|
pSrcAddr->GTI = 4;
|
|
pSrcAddr->TT = 0;
|
|
pSrcAddr->NP = 1; /* MSISDN */
|
|
pSrcAddr->NAI = 4;
|
|
pDstAddr->SSN = smpp_param[linkNo].localSSN;
|
|
pSrcAddr->len = smpp_ascii2GTAI(pSrcAddr->GTAI, smpp_param[linkNo].localGTT);
|
|
|
|
/* set SCCP destination address. */
|
|
pDstAddr->RI = 0;
|
|
pDstAddr->GTI = 4;
|
|
pDstAddr->TT = 0;
|
|
pDstAddr->NP = 1; /* MSISDN */
|
|
pDstAddr->NAI = 4;
|
|
pDstAddr->SSN = smpp_param[linkNo].remoteSSN;
|
|
pDstAddr->len = smpp_ascii2GTAI(pDstAddr->GTAI, smpp_param[linkNo].remoteGTT);
|
|
}
|
|
|
|
BYTE smpp_ascii2GTAI(BYTE *pGTAI, char *pGTT)
|
|
{
|
|
BYTE len, bcd;
|
|
int i;
|
|
char debugBuf[1024];
|
|
|
|
len = strlen(pGTT);
|
|
if (len < 1) return 0;
|
|
if (len==16) len = 15;//last BYTE is ssn
|
|
for (i=0; i<len; i++)
|
|
{
|
|
bcd = pGTT[i]-'0';
|
|
if (i%2 == 0)
|
|
pGTAI[i/2] = 0|bcd;
|
|
else
|
|
pGTAI[i/2] = pGTAI[i/2]|(bcd<<4);
|
|
}
|
|
if (len%2 == 1)
|
|
pGTAI[(len-1)/2] |= 0xf0;
|
|
|
|
#ifdef SMPP_DEBUG
|
|
if (smppDebug.debug_switch == 1) {
|
|
sprintf(debugBuf, "GTAI: ");
|
|
for (i=0; i<(len+1)/2; i++)
|
|
{
|
|
sprintf(debugBuf+6+i*2, "%02X", pGTAI[i]);
|
|
}
|
|
debugBuf[6+i*2] = 0x0a;
|
|
debugBuf[7+i*2] = 0;
|
|
smpp_send_ascout(debugBuf);
|
|
}
|
|
#endif
|
|
/*
|
|
#ifdef SMPP_PRINT_SCREEN
|
|
printf("GTAI[]: ");
|
|
for (i=0; i<(len+1)/2; i++)
|
|
{
|
|
printf("0x%02x ", pGTAI[i]);
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
*/
|
|
return len;
|
|
}
|
|
|
|
void smpp_GTAI2ascii(char *pGTT, BYTE *pGTAI, BYTE len)
|
|
{
|
|
BYTE i;
|
|
|
|
for (i=0; i<(len+1)/2; i++)
|
|
{
|
|
pGTT[i*2] = (pGTAI[i]&0xf) + '0';
|
|
if ((pGTAI[i]>>4) == 0xf)
|
|
{
|
|
pGTT[i*2+1] = '\0';
|
|
}
|
|
else
|
|
{
|
|
pGTT[i*2+1] = ((pGTAI[i]>>4)&0xf) + '0';
|
|
}
|
|
}
|
|
pGTT[len] = '\0';
|
|
}
|
|
|
|
void smpp_addTLV(BYTE *smpp_msg, WORD optionTag, BYTE *pMsg, WORD len)
|
|
{
|
|
WORD ns_optionTag;
|
|
WORD ns_len;
|
|
|
|
ns_optionTag = htons(optionTag);
|
|
switch (optionTag)
|
|
{
|
|
/* value 0 byte */
|
|
case ALERT_ON_MESSAGE_DELIVERY:
|
|
memcpy(smpp_msg, &ns_optionTag, 2);
|
|
len = 0;
|
|
memcpy(smpp_msg+2, &len, 2);
|
|
break;
|
|
/* value 1 byte for integer. */
|
|
case DEST_ADDR_SUBUNIT:
|
|
case SOURCE_ADDR_SUBUNIT:
|
|
case DEST_NETWORK_TYPE:
|
|
case SOURCE_NETWORK_TYPE:
|
|
case DEST_BEARER_TYPE:
|
|
case SOURCE_BEARER_TYPE:
|
|
case PRIVACY_INDICATOR:
|
|
case PAYLOAD_TYPE:
|
|
case LANGUAGE_INDICATOR:
|
|
case USER_RESPONSE_CODE:
|
|
case MS_MSG_WAIT_FACILITIES:
|
|
case SAR_TOTAL_SEGMENTS:
|
|
case SAR_SEGMENT_SEQNUM:
|
|
case SC_INTERFACE_VERSION:
|
|
case DISPLAY_TIME:
|
|
case MS_VALIDITY:
|
|
case DPF_RESULT:
|
|
case SET_DPF:
|
|
case MS_AVAILABILITY_STATUS:
|
|
case DELIVERY_FAILURE_REASON:
|
|
case MORE_MESSAGES_TO_SEND:
|
|
case MESSAGE_STATE:
|
|
case CALLBACK_NUM_PRES_IND:
|
|
case NUMBER_OF_MESSAGES:
|
|
case ITS_REPLY_TYPE:
|
|
case USSD_SERVICE_OP:
|
|
memcpy(smpp_msg, &ns_optionTag, 2);
|
|
len = 1;
|
|
ns_len = htons(len);
|
|
memcpy(smpp_msg+2, &ns_len, 2);
|
|
*(smpp_msg+4) = *pMsg;
|
|
break;
|
|
/* value 2 bytes for integer */
|
|
case DEST_TELEMATICS_ID:
|
|
case SOURCE_TELEMATICS_ID:
|
|
case USER_MESSAGE_REFERENCE:
|
|
case SOURCE_PORT:
|
|
case DESTINATION_PORT:
|
|
case SAR_MSG_REF_NUM:
|
|
case SMS_SIGNAL:
|
|
case ITS_SESSION_INFO:
|
|
memcpy(smpp_msg, &ns_optionTag, 2);
|
|
len = 2;
|
|
ns_len = htons(len);
|
|
memcpy(smpp_msg+2, &ns_len, 2);
|
|
memcpy(smpp_msg+4, pMsg, 2);
|
|
break;
|
|
/* value 3 bytes for octet string */
|
|
case NETWORK_ERROR_CODE:
|
|
memcpy(smpp_msg, &ns_optionTag, 2);
|
|
len = 3;
|
|
ns_len = htons(len);
|
|
memcpy(smpp_msg+2, &ns_len, 2);
|
|
memcpy(smpp_msg+4, pMsg, 3);
|
|
break;
|
|
/* value 4 bytes for integer */
|
|
case QOS_TIME_TO_LIVE:
|
|
memcpy(smpp_msg, &ns_optionTag, 2);
|
|
len = 4;
|
|
ns_len = htons(len);
|
|
memcpy(smpp_msg+2, &ns_len, 2);
|
|
memcpy(smpp_msg+4, pMsg, 4);
|
|
break;
|
|
/* variable length */
|
|
case ADDITIONAL_STATUS_INFO_TEXT:
|
|
case RECEIPTED_MESSAGE_ID:
|
|
case SOURCE_SUBADDRESS:
|
|
case DEST_SUBADDRESS:
|
|
case MESSAGE_PAYLOAD:
|
|
case CALLBACK_NUM:
|
|
case CALLBACK_NUM_ATAG:
|
|
memcpy(smpp_msg, &ns_optionTag, 2);
|
|
ns_len = htons(len);
|
|
memcpy(smpp_msg+2, &ns_len, 2);
|
|
memcpy(smpp_msg+4, pMsg, len+1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void smpp_display_hex_msg(BYTE* disp_ptr, int len)
|
|
{
|
|
int i;
|
|
char debugBuf[4096];
|
|
|
|
for (i=0; i<len; i++)
|
|
{
|
|
sprintf(debugBuf+i*3, "%02X ", disp_ptr[i]);
|
|
}
|
|
debugBuf[len*3] = 0x0a; //line feed
|
|
debugBuf[len*3+1] = 0;
|
|
smpp_send_ascout(debugBuf);
|
|
}
|
|
|
|
void smpp_command_id_to_string(char *comm_str, DWORD command_id)
|
|
{
|
|
switch (command_id)
|
|
{
|
|
case BIND_TRANSMITTER:
|
|
strcpy(comm_str, "BIND_TRANSMITTER");
|
|
break;
|
|
case BIND_TRANSMITTER_RESP:
|
|
strcpy(comm_str, "BIND_TRANSMITTER_RESP");
|
|
break;
|
|
case BIND_RECEIVER:
|
|
strcpy(comm_str, "BIND_RECEIVER");
|
|
break;
|
|
case BIND_RECEIVER_RESP:
|
|
strcpy(comm_str, "BIND_RECEIVER_RESP");
|
|
break;
|
|
case BIND_TRANSCEIVER:
|
|
strcpy(comm_str, "BIND_TRANSCEIVER");
|
|
break;
|
|
case BIND_TRANSCEIVER_RESP:
|
|
strcpy(comm_str, "BIND_TRANSCEIVER_RESP");
|
|
break;
|
|
case ENQUIRE_LINK:
|
|
strcpy(comm_str, "ENQUIRE_LINK");
|
|
break;
|
|
case ENQUIRE_LINK_RESP:
|
|
strcpy(comm_str, "ENQUIRE_LINK_RESP");
|
|
break;
|
|
case SUBMIT_SM:
|
|
strcpy(comm_str, "SUBMIT_SM");
|
|
break;
|
|
case SUBMIT_SM_RESP:
|
|
strcpy(comm_str, "SUBMIT_SM_RESP");
|
|
break;
|
|
case SUBMIT_MULTI:
|
|
strcpy(comm_str, "SUBMIT_MULTI");
|
|
break;
|
|
case SUBMIT_MULTI_RESP:
|
|
strcpy(comm_str, "SUBMIT_MULTI_RESP");
|
|
break;
|
|
case DELIVER_SM:
|
|
strcpy(comm_str, "DELIVER_SM");
|
|
break;
|
|
case DELIVER_SM_RESP:
|
|
strcpy(comm_str, "DELIVER_SM_RESP");
|
|
break;
|
|
case DATA_SM:
|
|
strcpy(comm_str, "DATA_SM");
|
|
break;
|
|
case DATA_SM_RESP:
|
|
strcpy(comm_str, "DATA_SM_RESP");
|
|
break;
|
|
case UNBIND:
|
|
strcpy(comm_str, "UNBIND");
|
|
break;
|
|
case UNBIND_RESP:
|
|
strcpy(comm_str, "UNBIND_RESP");
|
|
break;
|
|
case GENERIC_NAK:
|
|
strcpy(comm_str, "GENERIC_NAK");
|
|
break;
|
|
case OUTBIND:
|
|
strcpy(comm_str, "OUTBIND");
|
|
break;
|
|
default:
|
|
strcpy(comm_str, "\x1b[31mUnknown Command Id\x1b[0m");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void smpp_command_status_to_string(char* status_str, DWORD command_status)
|
|
{
|
|
switch (command_status)
|
|
{
|
|
case ESME_ROK:
|
|
strcpy(status_str, "No Error");
|
|
break;
|
|
case ESME_RINVMSGLEN:
|
|
strcpy(status_str, "Message Length is invalid");
|
|
break;
|
|
case ESME_RINVCMDLEN:
|
|
strcpy(status_str, "Command Length is invalid");
|
|
break;
|
|
case ESME_RINVCMDID:
|
|
strcpy(status_str, "Invalid Command ID");
|
|
break;
|
|
case ESME_RINVBNDSTS:
|
|
strcpy(status_str, "Incorrect BIND status for given command");
|
|
break;
|
|
case ESME_RALYBND:
|
|
strcpy(status_str, "ESME Already in Bound State");
|
|
break;
|
|
case ESME_RINVPRTFLG:
|
|
strcpy(status_str, "Invalid Priority Flag");
|
|
break;
|
|
case ESME_RINVREGDLVFLG:
|
|
strcpy(status_str, "Invalid Registered Delivery Flag");
|
|
break;
|
|
case ESME_RSYSERR:
|
|
strcpy(status_str, "System Error");
|
|
break;
|
|
case ESME_RINVSRCADR:
|
|
strcpy(status_str, "Invalid Source Address");
|
|
break;
|
|
case ESME_RINVDSTADR:
|
|
strcpy(status_str, "Invalid Dest Addr");
|
|
break;
|
|
case ESME_RINVMSGID:
|
|
strcpy(status_str, "Message ID is invalid");
|
|
break;
|
|
case ESME_RBINDFAIL:
|
|
strcpy(status_str, "Bind Failed");
|
|
break;
|
|
case ESME_RINVPASWD:
|
|
strcpy(status_str, "Invalid Password");
|
|
break;
|
|
case ESME_RINVSYSID:
|
|
strcpy(status_str, "Invalid System ID");
|
|
break;
|
|
case ESME_RCANCELFAIL:
|
|
strcpy(status_str, "Cancel SM Failed");
|
|
break;
|
|
case ESME_RREPLACEFAIL:
|
|
strcpy(status_str, "Replace SM Failed");
|
|
break;
|
|
case ESME_RMSGQFUL:
|
|
strcpy(status_str, "Message Queue Full");
|
|
break;
|
|
case ESME_RINVSERTYP:
|
|
strcpy(status_str, "Invalid Service Type");
|
|
break;
|
|
case ESME_RINVNUMDESTS:
|
|
strcpy(status_str, "Invalid Number of Destinations");
|
|
break;
|
|
case ESME_RINVDLNAME:
|
|
strcpy(status_str, "Invalid Distribution List Name");
|
|
break;
|
|
case ESME_RINVDESTFLAG:
|
|
strcpy(status_str, "Destination flag is invalid");
|
|
break;
|
|
case ESME_RINVSUBREP:
|
|
strcpy(status_str, "Invalid 'submit with replace' reques( i.e. submit_sm with replace_if_present_flag set");
|
|
break;
|
|
case ESME_RINVESMCLASS:
|
|
strcpy(status_str, "Invalid esm_class filed data");
|
|
break;
|
|
case ESME_RCNTSUBDL:
|
|
strcpy(status_str, "Cannot Submit to Distribution List");
|
|
break;
|
|
case ESME_RSUBMITFAIL:
|
|
strcpy(status_str, "submit_sm or submit_multi failed");
|
|
break;
|
|
case ESME_RINVSRCTON:
|
|
strcpy(status_str, "Invalid Source address TON");
|
|
break;
|
|
case ESME_RINVSRCNPI:
|
|
strcpy(status_str, "Invalid Source address NPI");
|
|
break;
|
|
case ESME_RINVDSTTON:
|
|
strcpy(status_str, "Invalid Destination address TON");
|
|
break;
|
|
case ESME_RINVDSTNPI:
|
|
strcpy(status_str, "Invalid Destination address NPI");
|
|
break;
|
|
case ESME_RINVSYSTYP:
|
|
strcpy(status_str, "Invalid system_tpye field");
|
|
break;
|
|
case ESME_RINVREPFLAG:
|
|
strcpy(status_str, "Invalid replace_if_present flag");
|
|
break;
|
|
case ESME_RINVNUMMSGS:
|
|
strcpy(status_str, "Invalid number of messages");
|
|
break;
|
|
case ESME_RTHROTTLED:
|
|
strcpy(status_str, "Throttling error(ESME has exceeded allowed message limits)");
|
|
break;
|
|
case ESME_RINVSCHED:
|
|
strcpy(status_str, "Invalid Scheduled Delivery Time");
|
|
break;
|
|
case ESME_RINVEXPIRY:
|
|
strcpy(status_str, "Invalid message validity period(Expiry time)");
|
|
break;
|
|
case ESME_RINVDFTMSGID:
|
|
strcpy(status_str, "Predefined Message Invalid or Not Found");
|
|
break;
|
|
case ESME_RX_T_APPN:
|
|
strcpy(status_str, "ESME Receiver Temporary App Error Code");
|
|
break;
|
|
case ESME_RX_P_APPN:
|
|
strcpy(status_str, "ESME Receiver Permanent App Error Code");
|
|
break;
|
|
case ESME_RX_R_APPN:
|
|
strcpy(status_str, "ESME Receiver Reject Message Error Code");
|
|
break;
|
|
case ESME_RQUERYFAIL:
|
|
strcpy(status_str, "query_sm request failed");
|
|
break;
|
|
case ESME_RINVOPTPARSTREAM:
|
|
strcpy(status_str, "Error in the optional part of the PDU Body");
|
|
break;
|
|
case ESME_ROPTPARNOTALLWD:
|
|
strcpy(status_str, "Optional Parameter Length");
|
|
break;
|
|
case ESME_RINVPARSLEN:
|
|
strcpy(status_str, "Invalid Parameter Length");
|
|
break;
|
|
case ESME_RMISSINGOPTPARAM:
|
|
strcpy(status_str, "Expected Optional Parameter missing");
|
|
break;
|
|
case ESME_RINVOPTPARAMVAL:
|
|
strcpy(status_str, "Invalid Optional Parameter Value");
|
|
break;
|
|
case ESME_RDELIVERYFAILURE:
|
|
strcpy(status_str, "Delivery Failure (used for data_sm_resp)");
|
|
break;
|
|
case ESME_RUNKNOWNERR:
|
|
strcpy(status_str, "Unknown Error");
|
|
break;
|
|
default:
|
|
strcpy(status_str, "Reserved");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void smpp_ton_to_string(char* ton_str, BYTE ton)
|
|
{
|
|
switch (ton)
|
|
{
|
|
case TON_UNKNOWN:
|
|
strcpy(ton_str, "Unknown");
|
|
break;
|
|
case TON_INTERNATIONAL:
|
|
strcpy(ton_str, "International");
|
|
break;
|
|
case TON_NATIONAL:
|
|
strcpy(ton_str, "National");
|
|
break;
|
|
case TON_NETWORK_SPECIFIC:
|
|
strcpy(ton_str, "Network Specific");
|
|
break;
|
|
case TON_SUBSCRIBER_NUMBER:
|
|
strcpy(ton_str, "Subscriber Number");
|
|
break;
|
|
case TON_ALPHANUMERIC:
|
|
strcpy(ton_str, "Alphanumeric");
|
|
break;
|
|
case TON_ABBREVIATE:
|
|
strcpy(ton_str, "Abbreviated");
|
|
break;
|
|
default:
|
|
strcpy(ton_str, "Reserved");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void smpp_npi_to_string(char* npi_str, BYTE npi)
|
|
{
|
|
switch (npi)
|
|
{
|
|
case NPI_UNKNOWN:
|
|
strcpy(npi_str, "Unknown");
|
|
break;
|
|
case NPI_ISDN:
|
|
strcpy(npi_str, "ISDN(E163/E164)");
|
|
break;
|
|
case NPI_DATA:
|
|
strcpy(npi_str, "Data(X.121)");
|
|
break;
|
|
case NPI_TELEX:
|
|
strcpy(npi_str, "Telex(F.69)");
|
|
break;
|
|
case NPI_LAND_MOBILE:
|
|
strcpy(npi_str, "Land Mobile(E.212)");
|
|
break;
|
|
case NPI_NATIONAL:
|
|
strcpy(npi_str, "National");
|
|
break;
|
|
case NPI_PRIVATE:
|
|
strcpy(npi_str, "Private");
|
|
break;
|
|
case NPI_ERMES:
|
|
strcpy(npi_str, "ERMES");
|
|
break;
|
|
case NPI_INTERNET:
|
|
strcpy(npi_str, "Internet(IP)");
|
|
break;
|
|
default:
|
|
strcpy(npi_str, "Reserved");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* msg_ptr start with optional parameters. len=optional parameter total length */
|
|
int smpp_decode_optional_parameter(SMPP_OPTIONAL_PARAMETER* opt_ptr, BYTE* msg_ptr, int t_len)
|
|
{
|
|
int param_counter = 0, pointer = 0;
|
|
WORD tag = 0, len = 0;
|
|
char debugBuf[1024];
|
|
|
|
while (pointer < t_len)
|
|
{
|
|
tag = msg_ptr[pointer++];
|
|
tag = (tag<<8) + msg_ptr[pointer++];
|
|
opt_ptr[param_counter].tag = tag;
|
|
|
|
len = msg_ptr[pointer++];
|
|
len = (len<<8) + msg_ptr[pointer++];
|
|
opt_ptr[param_counter].len = len;
|
|
|
|
memcpy(&opt_ptr[param_counter].value, msg_ptr+pointer, len);
|
|
pointer = pointer + len;
|
|
|
|
#ifdef SMPP_DEBUG
|
|
sprintf(debugBuf, "optional parameter %d: tag = 0x%04X, len = %d, value[0] = 0x%02X",
|
|
param_counter, tag, len, *(msg_ptr+pointer));
|
|
//smpp_send_ascout(debugBuf);
|
|
//printf("%s\n", debugBuf);
|
|
#endif
|
|
|
|
param_counter++;
|
|
}
|
|
|
|
return param_counter;
|
|
}
|