bb_smscconn.c

来自「mms client」· C语言 代码 · 共 776 行 · 第 1/2 页

C
776
字号
/* * 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 "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_wdp;extern List *incoming_sms;extern List *outgoing_sms;extern Counter *incoming_sms_counter;extern Counter *outgoing_sms_counter;extern List *sms8bitreassembly;extern List *flow_threads;extern List *suspended;extern List *isolated;extern Dict *smsbox_routes;extern SMSCConn *modemConn;/* our own thingies */static volatile sig_atomic_t smsc_running;static List *smsc_list;static List *smsc_groups;static Octstr *unified_prefix;static Numhash *black_list;static Numhash *white_list;static long maximum_queue_length;static long router_thread = -1;void route_incoming_sms(Msg *sms);static void log_sms(SMSCConn *conn, Msg *sms, char *message) {    Octstr *text, *udh;    text = sms->sms.msgdata ? octstr_duplicate(sms->sms.msgdata) : octstr_create("");    udh = sms->sms.udhdata ? octstr_duplicate(sms->sms.udhdata) : octstr_create("");    if ((sms->sms.coding == DC_8BIT || sms->sms.coding == DC_UCS2))        octstr_binary_to_hex(text, 1);    octstr_binary_to_hex(udh, 1);    alog("%s [SMSC:%s] [SVC:%s] [ACT:%s] [from:%s] [to:%s] [flags:%d:%d:%d:%d:%d] [msg:%d:%s]"         " [udh:%d:%s]",         message,         conn ? (smscconn_id(conn) ? octstr_get_cstr(smscconn_id(conn)) : "")         : "",         sms->sms.service ? octstr_get_cstr(sms->sms.service) : "",         sms->sms.account ? octstr_get_cstr(sms->sms.account) : "",         sms->sms.sender ? octstr_get_cstr(sms->sms.sender) : "",         sms->sms.receiver ? octstr_get_cstr(sms->sms.receiver) : "",         sms->sms.mclass, sms->sms.coding, sms->sms.mwi, sms->sms.compress,         sms->sms.dlr_mask,         octstr_len(sms->sms.msgdata), octstr_get_cstr(text),         octstr_len(sms->sms.udhdata), octstr_get_cstr(udh)        );    octstr_destroy(udh);    octstr_destroy(text);}/*--------------------------------------------------------------------------- * 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);}void bb_smscconn_sent(SMSCConn *conn, Msg *sms) {    Msg *mack;    counter_increase(outgoing_sms_counter);    if (conn) counter_increase(conn->sent);    /* write ACK to store file */    mack = msg_create(ack);    mack->ack.nack = 0;    mack->ack.time = sms->sms.time;    mack->ack.id = sms->sms.id;    (void) store_save(mack);    msg_destroy(mack);    /* XXX relay confirmancy message should be generated here */    log_sms(conn, sms, "Sent SMS");    msg_destroy(sms);}void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason) {    Msg *mnack;    switch (reason) {                case SMSCCONN_FAILED_SHUTDOWN:        case SMSCCONN_FAILED_TEMPORARILY:            list_produce(outgoing_sms, sms);            break;        default:            /* write NACK to store file */            mnack = msg_create(ack);            mnack->ack.nack = 1;            mnack->ack.time = sms->sms.time;            mnack->ack.id = sms->sms.id;            (void) store_save(mnack);            msg_destroy(mnack);            if (conn) counter_increase(conn->failed);            if (reason == SMSCCONN_FAILED_DISCARDED)                log_sms(conn, sms, "DISCARDED SMS");            else                log_sms(conn, sms, "FAILED Send SMS");            msg_destroy(sms);    } }    int bb_smscconn_receive(SMSCConn *conn, Msg *sms) {    char *uf;    /* do some queue control */    if (maximum_queue_length != -1 && bb_status == BB_FULL &&         list_len(incoming_sms) <= maximum_queue_length) {        bb_status = BB_RUNNING;        warning(0, "started to accept messages again");    }    if (maximum_queue_length != -1 &&         list_len(incoming_sms) > maximum_queue_length) {        if (bb_status != BB_FULL)            bb_status = BB_FULL;        warning(0, "incoming messages queue too long, dropping a message");        log_sms(conn, sms, "DROPPED Received SMS");        gwthread_sleep(0.1); /* letting the queue go down */        return -1;    }    /* else if (list_len(incoming_sms) > 100)     *	gwthread_sleep(0.5);     */    /*     * First normalize in smsc level and then on global level.     * In outbound direction it's vise versa, hence first global then smsc.     */    uf = 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));        log_sms(conn, sms, "REJECTED - not white-listed SMS");        msg_destroy(sms);        return -1;    }    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));        log_sms(conn, sms, "REJECTED - black-listed SMS");        msg_destroy(sms);        return -1;    }    /* MJ - ASL comment out the following 2 lines as            it now needs to cater for push messages as well */    /*    if (sms->sms.sms_type != report)        sms->sms.sms_type = mo;    */    /* write to store (if enabled) */    if (store_save(sms) == -1)        return -1;    if (sms->sms.sms_type != report)        log_sms(conn, sms, "Receive SMS");    else        log_sms(conn, sms, "DLR SMS");    /*     * 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.     */    route_incoming_sms(sms);    /* list_produce(incoming_sms, sms); */    counter_increase(incoming_sms_counter);    counter_increase(conn->received);    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);        } 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;    smsc_list = list_create();    smsc_groups = list_create();    grp = cfg_get_single_group(cfg, octstr_imm("core"));    unified_prefix = cfg_get(grp, octstr_imm("unified-prefix"));    if (cfg_get_integer(&maximum_queue_length, grp,                         octstr_imm("maximum-queue-length")) == -1)        maximum_queue_length = -1;    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);    }    os = cfg_get(grp, octstr_imm("black-list"));    if (os != NULL) {        black_list = numhash_create(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)            panic(0, "Cannot start with SMSC connection failing");                list_append(smsc_list, conn);    }    */    list_add_producer(smsc_list);    for (i = 0; i < list_len(smsc_groups) &&         (grp = list_get(smsc_groups, i)) != NULL; i++) {        conn = smscconn_create(grp, 1);         if (conn == NULL)            panic(0, "Cannot start with SMSC connection failing");        else             modemConn = conn;        list_append(smsc_list, conn);    }    list_remove_producer(smsc_list);    if ((router_thread = gwthread_create(sms_router, NULL)) == -1)        panic(0, "Failed to start a new thread for SMS routing");    list_add_producer(incoming_sms);    list_add_producer(incoming_wdp);    list_add_producer(sms8bitreassembly);    smsc_running = 1;    return 0;}static int smsc2_find(Octstr *id) {    SMSCConn *conn = NULL;    int i;

⌨️ 快捷键说明

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