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 + -
显示快捷键?