?? smsc_smpp.c
字號:
/* * smsc_smpp.c - SMPP v3.3 and v3.4 implementation * * Lars Wirzenius */ /* XXX check SMSCConn conformance */ /* XXX UDH reception */ /* XXX check UDH sending fields esm_class and data_coding from GSM specs */ /* XXX charset conversions on incoming messages (didn't work earlier, either) */ /* XXX numbering plans and type of number: check spec */ #include "gwlib/gwlib.h" #include "msg.h" #include "smsc_p.h" #include "smpp_pdu.h" #include "smscconn_p.h" #include "bb_smscconn_cb.h" #include "sms.h" #include "dlr.h" /* * Select these based on whether you want to dump SMPP PDUs as they are * sent and received or not. Not dumping should be the default in at least * stable releases. */ #define DEBUG 1#ifndef DEBUG /* This version doesn't dump. */ static void dump_pdu(const char *msg, Octstr *id, SMPP_PDU *pdu) { } #else /* This version does dump. */ static void dump_pdu(const char *msg, Octstr *id, SMPP_PDU *pdu) { debug("bb.sms.smpp", 0, "SMPP[%s]: %s", octstr_get_cstr(id), msg); smpp_pdu_dump(pdu); } #endif /* * Some defaults. */ #define SMPP_ENQUIRE_LINK_INTERVAL 30.0 #define SMPP_MAX_PENDING_SUBMITS 10 #define SMPP_RECONNECT_DELAY 10.0 #define SMPP_DEFAULT_VERSION 0x34#define SMPP_DEFAULT_PRIORITY 0#define SMPP_THROTTLING_SLEEP_TIME 15/* * Some SMPP error messages we come across */enum { SMPP_ESME_RMSGQFUL = 0x00000014, SMPP_ESME_RTHROTTLED = 0x00000058} SMPP_ERROR_MESSAGES; /*********************************************************************** * Implementation of the actual SMPP protocol: reading and writing * PDUs in the correct order. */ typedef struct { long transmitter; long receiver; List *msgs_to_send; Dict *sent_msgs; List *received_msgs; Counter *message_id_counter; Octstr *host; Octstr *system_type; Octstr *username; Octstr *password; Octstr *address_range; Octstr *our_host; Octstr *my_number; int source_addr_ton; int source_addr_npi; int dest_addr_ton; int dest_addr_npi; int alt_dcs; int transmit_port; int receive_port; int quitting; long enquire_link_interval; long max_pending_submits; long reconnect_delay; int version; int priority; /* set default priority for messages */ time_t throttling_err_time; int smpp_msg_id_type; /* msg id in C string, hex or decimal */ int autodetect_addr; SMSCConn *conn; } SMPP; static SMPP *smpp_create(SMSCConn *conn, Octstr *host, int transmit_port, int receive_port, Octstr *system_type, Octstr *username, Octstr *password, Octstr *address_range, Octstr *our_host, int source_addr_ton, int source_addr_npi, int dest_addr_ton, int dest_addr_npi, int alt_dcs, int enquire_link_interval, int max_pending_submits, int reconnect_delay, int version, int priority, Octstr *my_number, int smpp_msg_id_type, int autodetect_addr) { SMPP *smpp; smpp = gw_malloc(sizeof(*smpp)); smpp->transmitter = -1; smpp->receiver = -1; smpp->msgs_to_send = list_create(); smpp->sent_msgs = dict_create(16, NULL); list_add_producer(smpp->msgs_to_send); smpp->received_msgs = list_create(); smpp->message_id_counter = counter_create(); smpp->host = octstr_duplicate(host); smpp->system_type = octstr_duplicate(system_type); smpp->username = octstr_duplicate(username); smpp->password = octstr_duplicate(password); smpp->address_range = octstr_duplicate(address_range); smpp->source_addr_ton = source_addr_ton; smpp->source_addr_npi = source_addr_npi; smpp->dest_addr_ton = dest_addr_ton; smpp->dest_addr_npi = dest_addr_npi; smpp->alt_dcs = alt_dcs; smpp->our_host = octstr_duplicate(our_host); smpp->my_number = octstr_duplicate(my_number); smpp->transmit_port = transmit_port; smpp->receive_port = receive_port; smpp->enquire_link_interval = enquire_link_interval; smpp->max_pending_submits = max_pending_submits; smpp->reconnect_delay = reconnect_delay; smpp->quitting = 0; smpp->version = version; smpp->priority = priority; smpp->conn = conn; smpp->throttling_err_time = 0; smpp->smpp_msg_id_type = smpp_msg_id_type; smpp->autodetect_addr = autodetect_addr; return smpp; } static void smpp_destroy(SMPP *smpp) { if (smpp != NULL) { list_destroy(smpp->msgs_to_send, msg_destroy_item); dict_destroy(smpp->sent_msgs); list_destroy(smpp->received_msgs, msg_destroy_item); counter_destroy(smpp->message_id_counter); octstr_destroy(smpp->host); octstr_destroy(smpp->username); octstr_destroy(smpp->password); octstr_destroy(smpp->system_type); octstr_destroy(smpp->address_range); octstr_destroy(smpp->our_host); gw_free(smpp); } } /* * Try to read an SMPP PDU from a Connection. Return -1 for error (caller * should close the connection), 0 for no PDU to ready yet, or 1 for PDU * read and unpacked. Return a pointer to the PDU in `*pdu'. Use `*len' * to store the length of the PDU to read (it may be possible to read the * length, but not the rest of the PDU - we need to remember the lenght * for the next call). `*len' should be zero at the first call. */ static int read_pdu(SMPP *smpp, Connection *conn, long *len, SMPP_PDU **pdu) { Octstr *os; if (*len == 0) { *len = smpp_pdu_read_len(conn); if (*len == -1) { error(0, "SMPP[%s]: Server sent garbage, ignored.", octstr_get_cstr(smpp->conn->id)); return -1; } else if (*len == 0) { if (conn_eof(conn) || conn_read_error(conn)) return -1; return 0; } } os = smpp_pdu_read_data(conn, *len); if (os == NULL) { if (conn_eof(conn) || conn_read_error(conn)) return -1; return 0; } *len = 0; *pdu = smpp_pdu_unpack(os); if (*pdu == NULL) { error(0, "SMPP[%s]: PDU unpacking failed.", octstr_get_cstr(smpp->conn->id)); debug("bb.sms.smpp", 0, "SMPP[%s]: Failed PDU follows.", octstr_get_cstr(smpp->conn->id)); octstr_dump(os, 0); octstr_destroy(os); return -1; } octstr_destroy(os); return 1; } static Msg *pdu_to_msg(SMPP_PDU *pdu) { Msg *msg; gw_assert(pdu->type == deliver_sm); msg = msg_create(sms); msg->sms.sender = pdu->u.deliver_sm.source_addr; pdu->u.deliver_sm.source_addr = NULL; msg->sms.receiver = pdu->u.deliver_sm.destination_addr; pdu->u.deliver_sm.destination_addr = NULL; msg->sms.msgdata = pdu->u.deliver_sm.short_message; pdu->u.deliver_sm.short_message = NULL; charset_gsm_to_latin1(msg->sms.msgdata); msg->sms.pid = pdu->u.deliver_sm.protocol_id; dcs_to_fields(&msg, pdu->u.deliver_sm.data_coding); return msg; } static long smpp_status_to_smscconn_failure_reason(long status) { switch(status) { case SMPP_ESME_RMSGQFUL: return SMSCCONN_FAILED_TEMPORARILY; break; case SMPP_ESME_RTHROTTLED: return SMSCCONN_FAILED_TEMPORARILY; break; default: return SMSCCONN_FAILED_REJECTED; }} static SMPP_PDU *msg_to_pdu(SMPP *smpp, Msg *msg) { SMPP_PDU *pdu; Octstr *buffer; Octstr *relation_UTC_time = NULL; struct tm gmtime, localtime, tm; int gwqdiff; pdu = smpp_pdu_create(submit_sm, counter_increase(smpp->message_id_counter)); pdu->u.submit_sm.source_addr = octstr_duplicate(msg->sms.sender); pdu->u.submit_sm.destination_addr = octstr_duplicate(msg->sms.receiver); /* Check for manual override of source ton and npi values */ if(smpp->source_addr_ton > -1 && smpp->source_addr_npi > -1) { pdu->u.submit_sm.source_addr_ton = smpp->source_addr_ton; pdu->u.submit_sm.source_addr_npi = smpp->source_addr_npi; debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced source addr ton = %d, source add npi = %d", octstr_get_cstr(smpp->conn->id), smpp->source_addr_ton, smpp->source_addr_npi); } else { /* setup default values */ pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */ pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */ } if (smpp->autodetect_addr) { /* lets see if its international or alphanumeric sender */ if (octstr_get_char(pdu->u.submit_sm.source_addr,0) == '+') { if (!octstr_check_range(pdu->u.submit_sm.source_addr, 1, 256, gw_isdigit)) { pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; /* alphanum */ pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN; /* short code */ } else { /* numeric sender address with + in front -> international (remove the +) */ octstr_delete(pdu->u.submit_sm.source_addr, 0, 1); pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_INTERNATIONAL; } } else { if (!octstr_check_range(pdu->u.submit_sm.source_addr,0, 256, gw_isdigit)) { pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN; } } } /* Check for manual override of destination ton and npi values */ if (smpp->dest_addr_ton > -1 && smpp->dest_addr_npi > -1) { pdu->u.submit_sm.dest_addr_ton = smpp->dest_addr_ton; pdu->u.submit_sm.dest_addr_npi = smpp->dest_addr_npi; debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced dest addr ton = %d, source add npi = %d", octstr_get_cstr(smpp->conn->id), smpp->dest_addr_ton, smpp->dest_addr_npi); } else { pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */ pdu->u.submit_sm.dest_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */ } /* * if its a international number starting with +, lets remove the * '+' and set number type to international instead */ if (octstr_get_char(pdu->u.submit_sm.destination_addr,0) == '+') {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -