?? smsc_smasi.c
字號:
/* * Implementation of a SM/ASI SMSC module. * * Stipe Tolj <tolj@wapme-systems.de> * * This module connects to a CriticalPath InVoke SMS Center which * uses the SM/ASI protocoll. * The module is heavily based on the SMPP module design. * * TODO: * 1. alt_dcs is not used. Instead, msg->sms.mclass is used as the SMASI * Class. * 2. Numbers are not handled correctly, I guess. SMASI allows only(?) * international numbers without leading double zero. How to ensure * this? * 3. Handling of npi and ton correct? * 4. SubmitMulti PDUs not supported. * 5. Replace PDUs not supported. * 6. Status PDUs not supported. * 7. Cancel PDUs not supported. * 8. UserRes PDUs not supported. * 9. Smsc PDUs not supported. * 10. EnquireLink PDUs not supported. */#include "gwlib/gwlib.h"#include "msg.h"#include "smsc_p.h"#include "smasi_pdu.h"#include "smscconn_p.h"#include "bb_smscconn_cb.h"#include "sms.h"#include "dlr.h"#define DEBUG 1#ifndef DEBUGstatic void dump_pdu(const char *msg, Octstr *id, SMASI_PDU *pdu) { }#elsestatic void dump_pdu(const char *msg, Octstr *id, SMASI_PDU *pdu) { debug("bb.sms.smasi", 0, "SMASI[%s]: %s", octstr_get_cstr(id), msg); smasi_pdu_dump(pdu);}#endif/************************************************************************//* DEFAULT SETTINGS *//************************************************************************/#define SMASI_DEFAULT_PORT 21500#define SMASI_RECONNECT_DELAY 10.0#define SMASI_DEFAULT_PRIORITY 0#define MAX_PENDING_SUBMITS 10#define SMASI_THROTTLING_SLEEP_TIME 15#define SMASI_ENQUIRE_LINK_INTERVAL 30.0 /************************************************************************//* OVERRIDE SETTINGS *//************************************************************************//* Set these to -1 if no override desired. Values carried in message will * be used then. Or the defaults - if message has no values. * * Otherwise these values will be forced! */#define SMASI_OVERRIDE_SOURCE_TON 1#define SMASI_OVERRIDE_SOURCE_NPI -1#define SMASI_OVERRIDE_DEST_TON -1#define SMASI_OVERRIDE_DEST_NPI -1/************************************************************************//* SMASI STRUCTURE AND RELATED FUNCTIONS *//************************************************************************/typedef struct { SMSCConn * conn; /* connection to the bearerbox */ int thread_handle; /* handle for the SMASI thread */ List *msgs_to_send; Dict *sent_msgs; /* hash table for send, but yet not confirmed */ List *received_msgs; /* list of received, but yet not processed */ Counter *message_id_counter; /* sequence number */ Octstr *host; /* host or IP of the SMASI server */ long port; /* port to connect to */ Octstr *username; Octstr * password; Octstr * my_number; long source_addr_ton; long source_addr_npi; long dest_addr_ton; long dest_addr_npi; long reconnect_delay; long priority; time_t throttling_err_time; int quitting; long enquire_link_interval; int logged_off;} SMASI;static SMASI *smasi_create(SMSCConn *conn) { SMASI *smasi = gw_malloc(sizeof(SMASI)); smasi->conn = conn; smasi->thread_handle = -1; smasi->msgs_to_send = list_create(); smasi->sent_msgs = dict_create(16, NULL); smasi->received_msgs = list_create(); smasi->message_id_counter = counter_create(); smasi->host = NULL; smasi->username = NULL; smasi->password = NULL; smasi->source_addr_ton = -1; smasi->source_addr_npi = -1; smasi->dest_addr_ton = -1; smasi->dest_addr_npi = -1; smasi->my_number = NULL; smasi->port = 21500; smasi->reconnect_delay = 10; smasi->quitting = 0; smasi->logged_off = 0; smasi->priority = 0; smasi->throttling_err_time = 0; smasi->enquire_link_interval = 30; list_add_producer(smasi->msgs_to_send); return smasi;} static void smasi_destroy(SMASI *smasi) { if (smasi == NULL) return; list_destroy(smasi->msgs_to_send, msg_destroy_item); dict_destroy(smasi->sent_msgs); list_destroy(smasi->received_msgs, msg_destroy_item); counter_destroy(smasi->message_id_counter); octstr_destroy(smasi->host); octstr_destroy(smasi->username); octstr_destroy(smasi->password); gw_free(smasi);} /************************************************************************//* DATA ENCODING *//************************************************************************//* These values will be initialized on module startup. They contain the * ASCII representation of the chars that need to be escaped in the message * body before transmission. Example: "," (comma) will be represented by * the octet string ":2c". */static Octstr *colon = NULL;static Octstr *assign = NULL;static Octstr *comma = NULL;static Octstr *cr = NULL;static Octstr *lf = NULL;/* * Escapes outgoing message body data by replacing occurrences of "special" * chars inside the octet string. */static void escape_data(Octstr *data) { long pos = 0; /* This one uses a different approach than the encode and decode * functions. Because it is assumed, that only a fraction of the * contained chars have to be escaped. */ while (pos < octstr_len(data)) { Octstr * escaped = NULL; int check = octstr_get_char(data, pos); if (check == ':') escaped = colon; else if (check == '=') escaped = assign; else if (check == ',') escaped = comma; else if (check == '\n') escaped = cr; else if (check == '\r') escaped = lf; if (escaped != NULL) { /* If the current char has to be escaped, delete the char from * the source string, replace it with the escape sequence, and * advance position until after the inserted sequence. */ octstr_delete(data, pos, 1); octstr_insert(data, escaped, pos); pos += octstr_len(escaped); } else { /* If not escaped, simply skip the current char. */ pos++; } } } /* * Unescapes incoming message body data by replacing occurrences of escaped * chars with their original character representation. */static void unescape_data(Octstr *data) { long pos = 0; /* Again, an inplace transformation is used. Because, again, it is * assumed that only a fraction of chars has to be unescaped. */ while (pos < octstr_len(data)) { int check = octstr_get_char(data, pos); if (check == ':') { char byte = 0; int msb = octstr_get_char(data, pos + 1); int lsb = octstr_get_char(data, pos + 2); if (msb == '0') msb = 0; else if (msb >= '1' && msb <= '9') msb -= '1' + 1; else msb -= 'a' + 10; if (lsb == '0') lsb = 0; else if (lsb >= '1' && lsb <= '9') lsb -= '1' + 1; else lsb -= 'a' + 10; byte = msb << 4 | lsb; /* Do inplace unescaping. */ octstr_delete(data, pos, 3); octstr_insert_data(data, pos, &byte, 1); } pos++; } }/* * Will replace a binary data octet string (inplace) with a SMASI conform * ASCII representation of the data. */static void encode_binary_data(Octstr *data) { Octstr *result = octstr_create(""); long pos = 0; while (pos < octstr_len(data)) { int encode = octstr_get_char(data, pos); int msb = (encode & 0xf0) >> 4; int lsb = (encode & 0x0f) >> 0; if (msb == 0) msb = '0'; else if (msb < 10) msb = '1' + msb - 1; else msb = 'a' + msb - 10; if (lsb == 0) lsb = '0'; else if (lsb < 10) lsb = '1' + lsb - 1; else lsb = 'a' + lsb - 10; octstr_append_char(result, ':'); octstr_append_char(result, msb); octstr_append_char(result, lsb); pos++; } /* Replace binary data octet string with ASCII representation. */ octstr_delete(data, 0, octstr_len(data)); octstr_append(data, result); octstr_destroy(result);}/* * Replaces a SMASI conform ASCII representation of binary data with the * original binary data octet string. Will abort data decoding if the ASCII * representation is invalid. */static void decode_binary_data(Octstr *data) { long pos = 0; Octstr * result = octstr_create(""); for (pos = 0; pos < octstr_len(data); pos += 3) { int check = octstr_get_char(data, pos); if (check != ':') { warning(0, "Malformed binary encoded data."); return; } else { int byte = 0; int msb = octstr_get_char(data, pos + 1); int lsb = octstr_get_char(data, pos + 2); if (msb == '0') msb = 0; else if (msb >= '1' && msb <= '9') msb = msb - 48; else msb = msb - 'a' + 10; if (lsb == '0') lsb = 0; else if (lsb >= '1' && lsb <= '9') lsb = lsb - 48; else lsb = lsb - 'a' + 10; byte = msb << 4 | lsb; octstr_append_char(result, byte); } } /* Replace ASCII representation with binary data octet string. */ octstr_delete(data, 0, octstr_len(data)); octstr_append(data, result); octstr_destroy(result);}/************************************************************************//* MESSAGE PROCESSING *//************************************************************************/static Octstr *get_ton_npi_value(int override, int message) { if(override != -1) { debug("bb.sms.smasi", 0, "SMASI: Manually forced source addr ton = %d", override); return(octstr_format("%ld", override)); } else { return(octstr_format("%ld", message)); }}/* * Gets the value to be used as source_addr_ton. Will use override values * if configured. Will use values from message otherwise. Or fall back to * defaults if nothing given. */static Octstr *get_source_addr_ton(SMASI *smasi, Msg *msg) { return get_ton_npi_value(smasi->source_addr_ton, GSM_ADDR_TON_INTERNATIONAL);}/* * Gets the value to be used as source_addr_npi. Will use override values * if configured. Will use values from message otherwise. Or fall back to * defaults if nothing given. */static Octstr *get_source_addr_npi(SMASI *smasi, Msg *msg) { return get_ton_npi_value(smasi->source_addr_npi, GSM_ADDR_NPI_E164);}/* * Gets the value to be used as dest_addr_ton. Will use override values * if configured. Will use values from message otherwise. Or fall back to * defaults if nothing given.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -