/* ** 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; i0x00 && 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; ih_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; i0) && (FD_ISSET(Mysock.Sockets[i],&rfds))) { SockMsg.ReadQueue[SockMsg.ReadNum++] = i; } } for (i=0; i0) && (FD_ISSET(Mysock.Sockets[i],&wfds))) { SockMsg.WriteQueue[SockMsg.WriteNum++] = i; } } if (FD_ISSET(Mysock.DaemonSock, &efds)) { SockMsg.AcceptNum = -1; } for (i=0; i0) && (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; iRI = 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>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