⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smsbox.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ====================================================================  * 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.   */ /* * smsbox.c - main program of the smsbox */#include <errno.h>#include <unistd.h>#include <signal.h>#include <string.h>#include "gwlib/gwlib.h"#include "gwlib/regex.h"#include "msg.h"#include "sms.h"#include "dlr.h"#include "bb.h"#include "shared.h"#include "heartbeat.h"#include "html.h"#include "urltrans.h"#include "ota_prov_attr.h"#include "ota_prov.h"#include "ota_compiler.h"#include "xml_shared.h"#ifdef HAVE_SECURITY_PAM_APPL_H#include <security/pam_appl.h>#endif#define SENDSMS_DEFAULT_CHARS "0123456789 +-"#define O_DESTROY(a) { if(a) octstr_destroy(a); a = NULL; }/* Defaults for the HTTP request queueing inside http_queue_thread */#define HTTP_MAX_RETRIES    0#define HTTP_RETRY_DELAY    10 /* in sec. *//* have we received restart cmd from bearerbox? */volatile sig_atomic_t restart = 0;static Cfg *cfg;static long bb_port;static int bb_ssl = 0;static long sendsms_port = 0;static Octstr *sendsms_interface = NULL;static Octstr *smsbox_id = NULL;static Octstr *sendsms_url = NULL;static Octstr *sendota_url = NULL;static Octstr *xmlrpc_url = NULL;static Octstr *bb_host;static Octstr *accepted_chars = NULL;static int only_try_http = 0;static URLTranslationList *translations = NULL;static long sms_max_length = MAX_SMS_OCTETS;static char *sendsms_number_chars;static Octstr *global_sender = NULL;static Octstr *reply_couldnotfetch = NULL;static Octstr *reply_couldnotrepresent = NULL;static Octstr *reply_requestfailed = NULL;static Octstr *reply_emptymessage = NULL;static int mo_recode = 0;static Numhash *white_list;static Numhash *black_list;static regex_t *white_list_regex = NULL;static regex_t *black_list_regex = NULL;static unsigned long max_http_retries = HTTP_MAX_RETRIES;static unsigned long http_queue_delay = HTTP_RETRY_DELAY;static Octstr *ppg_service_name = NULL;static List *smsbox_requests = NULL;      /* the inbound request queue */static List *smsbox_http_requests = NULL; /* the outbound HTTP request queue */int charset_processing (Octstr *charset, Octstr *text, int coding);static long get_tag(Octstr *body, Octstr *tag, Octstr **value, long pos, int nostrip);/*********************************************************************** * Communication with the bearerbox. *//* * Identify ourself to bearerbox for smsbox-specific routing inside bearerbox. * Do this even while no smsbox-id is given to unlock the sender thread in * bearerbox. */static void identify_to_bearerbox(void){    Msg *msg;    msg = msg_create(admin);    msg->admin.command = cmd_identify;    msg->admin.boxc_id = octstr_duplicate(smsbox_id);    write_to_bearerbox(msg);}/* * Read an Msg from the bearerbox and send it to the proper receiver * via a List. At the moment all messages are sent to the smsbox_requests * List. */static void read_messages_from_bearerbox(void){    time_t start, t;    int secs;    int total = 0;    Msg *msg;    start = t = time(NULL);    while (program_status != shutting_down) {    /* block infinite for reading messages */	msg = read_from_bearerbox(INFINITE_TIME);	if (msg == NULL)	    break;	if (msg_type(msg) == admin) {	    if (msg->admin.command == cmd_shutdown) {		info(0, "Bearerbox told us to die");		program_status = shutting_down;	    } else if (msg->admin.command == cmd_restart) {		info(0, "Bearerbox told us to restart");		restart = 1;		program_status = shutting_down;	    }	    /*	     * XXXX here should be suspend/resume, add RSN	     */	    msg_destroy(msg);	} else if (msg_type(msg) == sms) {	    if (total == 0)		start = time(NULL);	    total++;	    list_produce(smsbox_requests, msg);	} else if (msg_type(msg) == ack) {	    /*	     * do nothing for now. Later we will handle this	     * gracefully...	     */	    msg_destroy(msg);	} else {	    warning(0, "Received other message than sms/admin, ignoring!");	    msg_destroy(msg);	}    }    secs = difftime(time(NULL), start);    info(0, "Received (and handled?) %d requests in %d seconds "    	 "(%.2f per second)", total, secs, (float)total / secs);}/*********************************************************************** * Send Msg to bearerbox for delivery to phone, possibly split it first. *//* * Counter for catenated SMS messages. The counter that can be put into * the catenated SMS message's UDH headers is actually the lowest 8 bits. */static Counter *catenated_sms_counter; /* * Send a message to the bearerbox for delivery to a phone. Use * configuration from `trans' to format the message before sending. * Return >= 0 for success & count of splitted sms messages,  * -1 for failure.  Does not destroy the msg. */static int send_message(URLTranslation *trans, Msg *msg){    int max_msgs;    Octstr *header, *footer, *suffix, *split_chars;    int catenate;    unsigned long msg_sequence, msg_count;    List *list;    Msg *part;    gw_assert(msg != NULL);    gw_assert(msg_type(msg) == sms);    if (trans != NULL)	max_msgs = urltrans_max_messages(trans);    else	max_msgs = 1;    if (max_msgs == 0) {	info(0, "No reply sent, denied.");	return 0;    }    /*     * Encode our smsbox-id to the msg structure.     * This will allow bearerbox to return specific answers to the     * same smsbox, mainly for DLRs and SMS proxy modes.     */    if (smsbox_id != NULL) {        msg->sms.boxc_id = octstr_duplicate(smsbox_id);    }    /*     * Empty message? Two alternatives have to be handled:     *  a) it's a HTTP sms-service reply: either ignore it or     *     substitute the "empty" warning defined     *  b) it's a sendsms HTTP interface call: leave the message empty     *     if at least a UDH is given.     *     * XXX this still does not cover the case when the sendsms interface is     * used with *no* text and udh. What should we do then?!     */    if (octstr_len(msg->sms.msgdata) == 0 && octstr_len(msg->sms.udhdata) == 0) {        if (trans != NULL && urltrans_omit_empty(trans))            return 0;        else            msg->sms.msgdata = octstr_duplicate(reply_emptymessage);    }    if (trans == NULL) {	header = NULL;	footer = NULL;	suffix = NULL;	split_chars = NULL;	catenate = 0;    } else {    	header = urltrans_header(trans);	footer = urltrans_footer(trans);	suffix = urltrans_split_suffix(trans);	split_chars = urltrans_split_chars(trans);	catenate = urltrans_concatenation(trans);    }    if (catenate)    	msg_sequence = counter_increase(catenated_sms_counter) & 0xFF;    else    	msg_sequence = 0;    list = sms_split(msg, header, footer, suffix, split_chars, catenate,    	    	     msg_sequence, max_msgs, sms_max_length);    msg_count = list_len(list);        debug("sms", 0, "message length %ld, sending %ld messages",          octstr_len(msg->sms.msgdata), msg_count);        /*     * In order to get catenated msgs work properly, we     * have moved catenation to bearerbox.     * So here we just need to put splitted msgs into one again and send     * to bearerbox that will care about catenation.     */    if (catenate) {        Msg *new_msg = msg_duplicate(msg);        octstr_delete(new_msg->sms.msgdata, 0, octstr_len(new_msg->sms.msgdata));        while((part = list_extract_first(list)) != NULL) {            octstr_append(new_msg->sms.msgdata, part->sms.msgdata);            msg_destroy(part);        }        write_to_bearerbox(new_msg);    } else {        /* msgs are the independed parts so sent those as is */        while ((part = list_extract_first(list)) != NULL)            write_to_bearerbox(part);    }        list_destroy(list, NULL);    return msg_count;}/*********************************************************************** * Stuff to remember which receiver belongs to which HTTP query. * This also includes HTTP request data to queue a failed HTTP request * into the smsbox_http_request queue which is then handled by the * http_queue_thread thread on a re-scheduled time basis. */static HTTPCaller *caller;static Counter *num_outstanding_requests;     struct receiver {    Msg *msg;    URLTranslation *trans;    int method;  /* the HTTP method to use */    Octstr *url; /* the after pattern URL */    List *http_headers;     Octstr *body; /* body content of the request */    unsigned long retries; /* number of performed retries */};/* * Again no urltranslation when we got an answer to wap push - it can only be dlr. */static void *remember_receiver(Msg *msg, URLTranslation *trans, int method,                               Octstr *url, List *headers, Octstr *body,                               unsigned int retries){    struct receiver *receiver;    counter_increase(num_outstanding_requests);    receiver = gw_malloc(sizeof(*receiver));    receiver->msg = msg_create(sms);    receiver->msg->sms.sender = octstr_duplicate(msg->sms.sender);    receiver->msg->sms.receiver = octstr_duplicate(msg->sms.receiver);    /* ppg_service_name should always be not NULL here */    if (trans != NULL && (msg->sms.service == NULL || ppg_service_name == NULL ||        octstr_compare(msg->sms.service, ppg_service_name) != 0)) {        receiver->msg->sms.service = octstr_duplicate(urltrans_name(trans));    } else {        receiver->msg->sms.service = octstr_duplicate(msg->sms.service);    }    receiver->msg->sms.smsc_id = octstr_duplicate(msg->sms.smsc_id);    /* to remember if it's a DLR http get */    receiver->msg->sms.sms_type = msg->sms.sms_type;    receiver->trans = trans;    /* remember the HTTP request if we need to queue this */    receiver->method = method;    receiver->url = octstr_duplicate(url);    receiver->http_headers = http_header_duplicate(headers);    receiver->body = octstr_duplicate(body);    receiver->retries = retries;    return receiver;}static void get_receiver(void *id, Msg **msg, URLTranslation **trans, int *method,                         Octstr **url, List **headers, Octstr **body,                         unsigned long *retries){    struct receiver *receiver;    receiver = id;    *msg = receiver->msg;    *trans = receiver->trans;    *method = receiver->method;    *url = receiver->url;    *headers = receiver->http_headers;    *body = receiver->body;    *retries = receiver->retries;    gw_free(receiver);    counter_decrease(num_outstanding_requests);}static long outstanding_requests(void)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -