📄 smsc_smasi.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * 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 protocol. * 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_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 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->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);}/* * Re-escape SMASI ASCII representation of binary data with the * original binary data octet string. * XXX this may be done by the internal parser routines too. */static void decode_binary_data(Octstr *data) { long pos = 0; while (pos < octstr_len(data)) { int check = octstr_get_char(data, pos); if (check == ':') { Octstr *byte; int msb = octstr_get_char(data, pos + 1); int lsb = octstr_get_char(data, pos + 2); if (msb != -1 && lsb != -1) { byte = octstr_create(""); octstr_append_char(byte, msb); octstr_append_char(byte, lsb); if (octstr_hex_to_binary(byte) != -1) { /* Do inplace unescaping. */ octstr_delete(data, pos, 3); octstr_insert(data, byte, pos); } else { error(0, "Malformed binary encoded data."); } octstr_destroy(byte); } } pos++; } }/************************************************************************//* MESSAGE PROCESSING *//************************************************************************/static Octstr *get_ton_npi_value(int override, int message) { if (override != -1) { debug("bb.sms.smasi", 0, "SMASI: Manually forced ton or npi to `%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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -