📄 smsbox.c
字号:
/* ==================================================================== * 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 + -