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

📄 bb_smscconn.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ====================================================================  * 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.   */ /* * SMSC Connection interface for Bearerbox. * * Includes callback functions called by SMSCConn implementations * * Handles all startup/shutdown adminstrative work in bearerbox, plus * routing, writing actual access logs, handling failed messages etc. * * Kalle Marjola 2000 for project Kannel */#include <errno.h>#include <stdlib.h>#include <stdio.h>#include <time.h>#include <string.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>#include "gwlib/gwlib.h"#include "msg.h"#include "sms.h"#include "bearerbox.h"#include "numhash.h"#include "smscconn.h"#include "dlr.h"#include "bb_smscconn_cb.h"    /* callback functions for connections */#include "smscconn_p.h"        /* to access counters *//* passed from bearerbox core */extern volatile sig_atomic_t bb_status;extern List *incoming_sms;extern List *outgoing_sms;extern Counter *incoming_sms_counter;extern Counter *outgoing_sms_counter;extern List *flow_threads;extern List *suspended;extern List *isolated;/* our own thingies */static volatile sig_atomic_t smsc_running;static List *smsc_list;static RWLock smsc_list_lock;static List *smsc_groups;static Octstr *unified_prefix;static Numhash *black_list;static Numhash *white_list;static regex_t *white_list_regex;static regex_t *black_list_regex;static long router_thread = -1;/* * 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. */Counter *split_msg_counter;/* * forward declaration */static long route_incoming_to_smsc(SMSCConn *conn, Msg *msg);/*--------------------------------------------------------------------------- * CALLBACK FUNCTIONS * * called by SMSCConn implementations when appropriate */void bb_smscconn_ready(SMSCConn *conn){    list_add_producer(flow_threads);    list_add_producer(incoming_sms);}void bb_smscconn_connected(SMSCConn *conn){    if (router_thread >= 0)	gwthread_wakeup(router_thread);}void bb_smscconn_killed(void){    /* NOTE: after status has been set to SMSCCONN_DEAD, bearerbox     *   is free to release/delete 'conn'     */    list_remove_producer(incoming_sms);    list_remove_producer(flow_threads);}static void handle_split(SMSCConn *conn, Msg *msg, long reason){    struct split_parts *split = msg->sms.split_parts;        /* if temporarely failed, try again immediately */    if (reason == SMSCCONN_FAILED_TEMPORARILY && smscconn_send(conn, msg) == 0)        return;        /*     * if the reason is not a success and status is still success     * then set status of a split to the reason.     * Note: reason 'malformed','discarded' or 'rejected' has higher priority!     */    switch(reason) {    case SMSCCONN_FAILED_DISCARDED:    case SMSCCONN_FAILED_REJECTED:    case SMSCCONN_FAILED_MALFORMED:        debug("bb.sms.splits", 0, "Set split msg status to %ld", reason);        split->status = reason;        break;    case SMSCCONN_SUCCESS:        break; /* nothing todo */    default:        if (split->status == SMSCCONN_SUCCESS) {            debug("bb.sms.splits", 0, "Set split msg status to %ld", reason);            split->status = reason;        }        break;    }    /*     * now destroy this message, because we don't need it anymore.     * we will split it again in smscconn_send(...).     */    msg_destroy(msg);            if (counter_decrease(split->parts_left) <= 1) {        /* all splited parts were processed */        counter_destroy(split->parts_left);        msg = split->orig;        msg->sms.split_parts = NULL;        if (split->status == SMSCCONN_SUCCESS)            bb_smscconn_sent(conn, msg, NULL);        else {            debug("bb.sms.splits", 0, "Parts of concatenated message failed.");            bb_smscconn_send_failed(conn, msg, split->status, NULL);        }        gw_free(split);    }}void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply){    if (sms->sms.split_parts != NULL) {        handle_split(conn, sms, SMSCCONN_SUCCESS);        return;    }        counter_increase(outgoing_sms_counter);    if (conn) counter_increase(conn->sent);    /* write ACK to store file */    store_save_ack(sms, ack_success);    bb_alog_sms(conn, sms, "Sent SMS");    /* generate relay confirmancy message */    if (DLR_IS_SMSC_SUCCESS(sms->sms.dlr_mask)) {        Msg *dlrmsg;	if (reply == NULL)	    reply = octstr_create("");	octstr_insert_data(reply, 0, "ACK/", 4);        dlrmsg = create_dlr_from_msg((conn->id?conn->id:conn->name), sms,	                reply, DLR_SMSC_SUCCESS);        if (dlrmsg != NULL) {            bb_smscconn_receive(conn, dlrmsg);        }    }    msg_destroy(sms);    octstr_destroy(reply);}void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply){    if (sms->sms.split_parts != NULL) {        handle_split(conn, sms, reason);        return;    }        switch (reason) {    case SMSCCONN_FAILED_SHUTDOWN:    case SMSCCONN_FAILED_TEMPORARILY:	list_produce(outgoing_sms, sms);	break;    default:	/* write NACK to store file */        store_save_ack(sms, ack_failed);	if (conn) counter_increase(conn->failed);	if (reason == SMSCCONN_FAILED_DISCARDED)	    bb_alog_sms(conn, sms, "DISCARDED SMS");	else	    bb_alog_sms(conn, sms, "FAILED Send SMS");        /* generate relay confirmancy message */        if (DLR_IS_SMSC_FAIL(sms->sms.dlr_mask) ||	    DLR_IS_FAIL(sms->sms.dlr_mask)) {            Msg *dlrmsg;	    if (reply == NULL)	        reply = octstr_create("");	    octstr_insert_data(reply, 0, "NACK/", 5);            dlrmsg = create_dlr_from_msg((conn ? (conn->id?conn->id:conn->name) : NULL), sms,	                                 reply, DLR_SMSC_FAIL);            if (dlrmsg != NULL) {                bb_smscconn_receive(conn, dlrmsg);            }        }	msg_destroy(sms);    }    octstr_destroy(reply);}long bb_smscconn_receive(SMSCConn *conn, Msg *sms){    char *uf;    int rc;    Msg *copy;   /*    * First normalize in smsc level and then on global level.    * In outbound direction it's vise versa, hence first global then smsc.    */    uf = (conn && conn->unified_prefix) ? octstr_get_cstr(conn->unified_prefix) : NULL;    normalize_number(uf, &(sms->sms.sender));    uf = unified_prefix ? octstr_get_cstr(unified_prefix) : NULL;    normalize_number(uf, &(sms->sms.sender));    if (white_list &&	numhash_find_number(white_list, sms->sms.sender) < 1) {	info(0, "Number <%s> is not in white-list, message discarded",	     octstr_get_cstr(sms->sms.sender));	bb_alog_sms(conn, sms, "REJECTED - not white-listed SMS");	msg_destroy(sms);        return SMSCCONN_FAILED_REJECTED;    }    if (white_list_regex && (gw_regex_matches(white_list_regex, sms->sms.sender) == NO_MATCH)) {        info(0, "Number <%s> is not in white-list, message discarded",             octstr_get_cstr(sms->sms.sender));        bb_alog_sms(conn, sms, "REJECTED - not white-regex-listed SMS");        msg_destroy(sms);        return SMSCCONN_FAILED_REJECTED;    }        if (black_list &&	numhash_find_number(black_list, sms->sms.sender) == 1) {	info(0, "Number <%s> is in black-list, message discarded",	     octstr_get_cstr(sms->sms.sender));	bb_alog_sms(conn, sms, "REJECTED - black-listed SMS");	msg_destroy(sms);	return SMSCCONN_FAILED_REJECTED;    }    if (black_list_regex && (gw_regex_matches(black_list_regex, sms->sms.sender) == NO_MATCH)) {        info(0, "Number <%s> is not in black-list, message discarded",             octstr_get_cstr(sms->sms.sender));        bb_alog_sms(conn, sms, "REJECTED - black-regex-listed SMS");        msg_destroy(sms);        return SMSCCONN_FAILED_REJECTED;    }    if (sms->sms.sms_type != report_mo)	sms->sms.sms_type = mo;    /* write to store (if enabled) */    if (store_save(sms) == -1)	return SMSCCONN_FAILED_TEMPORARILY;    copy = msg_duplicate(sms);    /*     * Try to reroute internally to an smsc-id without leaving     * actually bearerbox scope.     * Scope: internal routing (to smsc-ids)     */    if ((rc = route_incoming_to_smsc(conn, copy)) == -1) {        /*         * Now try to route the message to a specific smsbox         * connection based on the existing msg->sms.boxc_id or         * the registered receiver numbers for specific smsbox'es.         * Scope: external routing (to smsbox connections)         */        if (route_incoming_to_boxc(copy) == -1) {            warning(0, "incoming messages queue too long, dropping a message.");            if (sms->sms.sms_type == report_mo)                bb_alog_sms(conn, sms, "DROPPED Received DLR");            else                bb_alog_sms(conn, sms, "DROPPED Received SMS");            /* put nack into store-file */            store_save_ack(sms, ack_failed);            msg_destroy(copy);            msg_destroy(sms);            gwthread_sleep(0.1); /* letting the queue go down */            return SMSCCONN_FAILED_QFULL;        }    }    if (sms->sms.sms_type != report_mo)	bb_alog_sms(conn, sms, "Receive SMS");    else	bb_alog_sms(conn, sms, "DLR SMS");    counter_increase(incoming_sms_counter);    if (conn != NULL) counter_increase(conn->received);    msg_destroy(sms);    return 0;}/*--------------------------------------------------------------------- * Other functions *//* function to route outgoing SMS'es from delay-list * use some nice magics to route them to proper SMSC */static void sms_router(void *arg){    Msg *msg, *newmsg, *startmsg;    int ret;        list_add_producer(flow_threads);    gwthread_wakeup(MAIN_THREAD_ID);    newmsg = startmsg = NULL;    ret = 0;        while(bb_status != BB_DEAD) {	if (newmsg == startmsg) {	    if (ret != 1) {		debug("bb.sms", 0, "sms_router: time to sleep"); 		gwthread_sleep(600.0);	/* hopefully someone wakes us up */		debug("bb.sms", 0, "sms_router: list_len = %ld",		      list_len(outgoing_sms));	    }	    startmsg = list_consume(outgoing_sms);	    newmsg = NULL;	    msg = startmsg;	} else {	    newmsg = list_consume(outgoing_sms);	    msg = newmsg;	}	/* debug("bb.sms", 0, "sms_router: handling message (%p vs %p)",	 *         newmsg, startmsg); */		if (msg == NULL)            break;	ret = smsc2_rout(msg);	if (ret == -1) {            warning(0, "No SMSCes to receive message, discarding it!");	    bb_smscconn_send_failed(NULL, msg, SMSCCONN_FAILED_DISCARDED,	                            octstr_create("DISCARDED"));        } else if (ret == 1) {	    newmsg = startmsg = NULL;	}    }    /* router has died, make sure that rest die, too */    smsc_running = 0;    list_remove_producer(flow_threads);}/*------------------------------------------------------------- * public functions * */int smsc2_start(Cfg *cfg){    CfgGroup *grp;    SMSCConn *conn;    Octstr *os;    int i;    if (smsc_running) return -1;    /* create split sms counter */    split_msg_counter = counter_create();        smsc_list = list_create();    gw_rwlock_init_static(&smsc_list_lock);    grp = cfg_get_single_group(cfg, octstr_imm("core"));    unified_prefix = cfg_get(grp, octstr_imm("unified-prefix"));    white_list = black_list = NULL;    os = cfg_get(grp, octstr_imm("white-list"));    if (os != NULL) {        white_list = numhash_create(octstr_get_cstr(os));	octstr_destroy(os);    }    if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) {        if ((white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));        octstr_destroy(os);    }        os = cfg_get(grp, octstr_imm("black-list"));    if (os != NULL) {        black_list = numhash_create(octstr_get_cstr(os));	octstr_destroy(os);    }    if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) {        if ((black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));        octstr_destroy(os);    }    smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));    /*    while(groups && (grp = list_extract_first(groups)) != NULL) {        conn = smscconn_create(grp, 1);         if (conn == NULL)

⌨️ 快捷键说明

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