?? smsc_smpp.c
字號:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2005 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. */ /* * smsc_smpp.c - SMPP v3.3 and v3.4 implementation * * Lars Wirzenius * Stipe Tolj <stolj@wapme.de> * Alexander Malysh <amalysh at kannel.org> *//* 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"#define SMPP_DEFAULT_CHARSET "windows-1252"/* * 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#define dump_pdu(msg, id, pdu) do{}while(0)#else/** This version does dump. */#define dump_pdu(msg, id, pdu) \ do { \ debug("bb.sms.smpp", 0, "SMPP[%s]: %s", \ octstr_get_cstr(id), msg); \ smpp_pdu_dump(pdu); \ } while(0)#endif/* * Some defaults. */#define SMPP_ENQUIRE_LINK_INTERVAL 30.0#define SMPP_MAX_PENDING_SUBMITS 10#define SMPP_DEFAULT_VERSION 0x34#define SMPP_DEFAULT_PRIORITY 0#define SMPP_THROTTLING_SLEEP_TIME 15#define SMPP_DEFAULT_CONNECTION_TIMEOUT 10 * SMPP_ENQUIRE_LINK_INTERVAL#define SMPP_DEFAULT_WAITACK 60#define SMPP_DEFAULT_SHUTDOWN_TIMEOUT 30/* * Some defines */#define SMPP_WAITACK_RECONNECT 0x00#define SMPP_WAITACK_REQUEUE 0x01#define SMPP_WAITACK_NEVER_EXPIRE 0x02/*********************************************************************** * 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 *my_number; Octstr *service_type; int source_addr_ton; int source_addr_npi; int dest_addr_ton; int dest_addr_npi; long bind_addr_ton; long bind_addr_npi; int transmit_port; int receive_port; int quitting; long enquire_link_interval; long max_pending_submits; int version; int priority; /* set default priority for messages */ int validityperiod; time_t throttling_err_time; int smpp_msg_id_type; /* msg id in C string, hex or decimal */ int autodetect_addr; Octstr *alt_charset; Octstr *alt_addr_charset; long connection_timeout; long wait_ack; int wait_ack_action; SMSCConn *conn; } SMPP; struct smpp_msg { time_t sent_time; Msg *msg;};/* * create smpp_msg struct */static struct smpp_msg* smpp_msg_create(Msg *msg){ struct smpp_msg *result = gw_malloc(sizeof(struct smpp_msg)); gw_assert(result != NULL); result->sent_time = time(NULL); result->msg = msg; return result;}/* * destroy smpp_msg struct. If destroy_msg flag is set, then message will be freed as well */static void smpp_msg_destroy(struct smpp_msg *msg, int destroy_msg){ /* sanity check */ if (msg == NULL) return; if (destroy_msg && msg->msg != NULL) msg_destroy(msg->msg); gw_free(msg);} static SMPP *smpp_create(SMSCConn *conn, Octstr *host, int transmit_port, int receive_port, Octstr *system_type, Octstr *username, Octstr *password, Octstr *address_range, int source_addr_ton, int source_addr_npi, int dest_addr_ton, int dest_addr_npi, int enquire_link_interval, int max_pending_submits, int version, int priority, int validity, Octstr *my_number, int smpp_msg_id_type, int autodetect_addr, Octstr *alt_charset, Octstr *alt_addr_charset, Octstr *service_type, long connection_timeout, long wait_ack, int wait_ack_action) { SMPP *smpp; smpp = gw_malloc(sizeof(*smpp)); smpp->transmitter = -1; smpp->receiver = -1; smpp->msgs_to_send = gwlist_create(); smpp->sent_msgs = dict_create(max_pending_submits, NULL); gwlist_add_producer(smpp->msgs_to_send); smpp->received_msgs = gwlist_create(); smpp->message_id_counter = counter_create(); counter_increase(smpp->message_id_counter); 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->my_number = octstr_duplicate(my_number); smpp->service_type = octstr_duplicate(service_type); 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->quitting = 0; smpp->version = version; smpp->priority = priority; smpp->validityperiod = validity; smpp->conn = conn; smpp->throttling_err_time = 0; smpp->smpp_msg_id_type = smpp_msg_id_type; smpp->autodetect_addr = autodetect_addr; smpp->alt_charset = octstr_duplicate(alt_charset); smpp->alt_addr_charset = octstr_duplicate(alt_addr_charset); smpp->connection_timeout = connection_timeout; smpp->wait_ack = wait_ack; smpp->wait_ack_action = wait_ack_action; smpp->bind_addr_ton = 0; smpp->bind_addr_npi = 0; return smpp; } static void smpp_destroy(SMPP *smpp) { if (smpp != NULL) { gwlist_destroy(smpp->msgs_to_send, msg_destroy_item); dict_destroy(smpp->sent_msgs); gwlist_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->service_type); octstr_destroy(smpp->address_range); octstr_destroy(smpp->my_number); octstr_destroy(smpp->alt_charset); octstr_destroy(smpp->alt_addr_charset); 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_error(conn)) return -1; return 0; } } os = smpp_pdu_read_data(conn, *len); if (os == NULL) { if (conn_eof(conn) || conn_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 long convert_addr_from_pdu(Octstr *id, Octstr *addr, long ton, long npi, Octstr *alt_addr_charset){
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -