📄 smsc_http.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2007 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_http.c - interface to various HTTP based content/SMS gateways * * HTTP based "SMSC Connection" is meant for gateway connections, * and has following features: * * o Kannel listens to certain (HTTP server) port for MO SMS messages. * The exact format of these HTTP calls are defined by type of HTTP based * connection. Kannel replies to these messages as ACK, but does not * support immediate reply. Thus, if Kannel is linked to another Kannel, * only 'max-messages = 0' services are practically supported - any * replies must be done with SMS PUSH (sendsms) * * o For MT messages, Kannel does HTTP GET or POST to given address, in format * defined by type of HTTP based protocol * * The 'type' of requests and replies are defined by 'system-type' variable. * The only type of HTTP requests currently supported are basic Kannel. * If new support is added, smsc_http_create is modified accordingly and new * functions added. * * * KANNEL->KANNEL linking: (UDH not supported in MO messages) * ***** * FOR CLIENT/END-POINT KANNEL: * * group = smsc * smsc = http * system-type = kannel * port = NNN * smsc-username = XXX * smsc-password = YYY * send-url = "server.host:PORT" * ***** * FOR SERVER/RELAY KANNEL: * * group = smsbox * sendsms-port = PORT * ... * * group = sms-service * keyword = ... * url = "client.host:NNN/sms?user=XXX&pass=YYY&from=%p&to=%P&text=%a" * max-messages = 0 * * group = send-sms * username = XXX * password = YYY * * Kalle Marjola for Project Kannel 2001 * Stipe Tolj <st@tolj.org> * Alexander Malysh <amalysh at kannel.org> * Tobias Weber <weber@wapme.de> */#include <sys/types.h>#include <sys/socket.h>#include <unistd.h>#include <errno.h>#include <time.h>#include <limits.h>#include "gwlib/gwlib.h"#include "smscconn.h"#include "smscconn_p.h"#include "bb_smscconn_cb.h"#include "msg.h"#include "sms.h"#include "dlr.h"#include "urltrans.h"typedef struct conndata { HTTPCaller *http_ref; long receive_thread; long send_cb_thread; int shutdown; int port; /* port for receiving SMS'es */ Octstr *allow_ip; Octstr *send_url; Octstr *dlr_url; /* our own DLR MO URL */ long open_sends; Octstr *username; /* if needed */ Octstr *password; /* as said */ Octstr *system_id; /* api id for clickatell */ int no_sender; /* ditto */ int no_coding; /* this, too */ int no_sep; /* not to mention this */ Octstr *proxy; /* proxy a constant string */ /* The following are compiled regex for the 'generic' type for handling * success, permanent failure and temporary failure. For types that use * simple HTTP body parsing, these may be used also for other types, * ie. for our own Kannel reply parsing. */ regex_t *success_regex; regex_t *permfail_regex; regex_t *tempfail_regex; /* callback functions set by HTTP-SMSC type */ void (*send_sms) (SMSCConn *conn, Msg *msg); void (*parse_reply) (SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body); void (*receive_sms) (SMSCConn *conn, HTTPClient *client, List *headers, Octstr *body, List *cgivars);} ConnData;static void conndata_destroy(ConnData *conndata){ if (conndata == NULL) return; if (conndata->http_ref) http_caller_destroy(conndata->http_ref); if (conndata->success_regex) gw_regex_destroy(conndata->success_regex); if (conndata->permfail_regex) gw_regex_destroy(conndata->permfail_regex); if (conndata->tempfail_regex) gw_regex_destroy(conndata->tempfail_regex); octstr_destroy(conndata->allow_ip); octstr_destroy(conndata->send_url); octstr_destroy(conndata->dlr_url); octstr_destroy(conndata->username); octstr_destroy(conndata->password); octstr_destroy(conndata->proxy); octstr_destroy(conndata->system_id); gw_free(conndata);}/* * Thread to listen to HTTP requests from SMSC entity */static void httpsmsc_receiver(void *arg){ SMSCConn *conn = arg; ConnData *conndata = conn->data; HTTPClient *client; Octstr *ip, *url, *body; List *headers, *cgivars; ip = url = body = NULL; headers = cgivars = NULL; /* Make sure we log into our own log-file if defined */ log_thread_to(conn->log_idx); while (conndata->shutdown == 0) { /* XXX if conn->is_stopped, do not receive new messages.. */ client = http_accept_request(conndata->port, &ip, &url, &headers, &body, &cgivars); if (client == NULL) break; debug("smsc.http", 0, "HTTP[%s]: Got request `%s'", octstr_get_cstr(conn->id), octstr_get_cstr(url)); if (connect_denied(conndata->allow_ip, ip)) { info(0, "HTTP[%s]: Connection `%s' tried from denied " "host %s, ignored", octstr_get_cstr(conn->id), octstr_get_cstr(url), octstr_get_cstr(ip)); http_close_client(client); } else conndata->receive_sms(conn, client, headers, body, cgivars); debug("smsc.http", 0, "HTTP[%s]: Destroying client information", octstr_get_cstr(conn->id)); octstr_destroy(url); octstr_destroy(ip); octstr_destroy(body); http_destroy_headers(headers); http_destroy_cgiargs(cgivars); } debug("smsc.http", 0, "HTTP[%s]: httpsmsc_receiver dying", octstr_get_cstr(conn->id)); conndata->shutdown = 1; http_close_port(conndata->port); /* unblock http_receive_result() if there are no open sends */ if (conndata->open_sends == 0) http_caller_signal_shutdown(conndata->http_ref);}/* * Thread to handle finished sendings */static void httpsmsc_send_cb(void *arg){ SMSCConn *conn = arg; ConnData *conndata = conn->data; Msg *msg; int status; List *headers; Octstr *final_url, *body; /* Make sure we log into our own log-file if defined */ log_thread_to(conn->log_idx); while (conndata->shutdown == 0 || conndata->open_sends) { msg = http_receive_result(conndata->http_ref, &status, &final_url, &headers, &body); if (msg == NULL) break; /* they told us to die, by unlocking */ /* Handle various states here. */ /* request failed and we are not in shutdown mode */ if (status == -1 && conndata->shutdown == 0) { error(0, "HTTP[%s]: Couldn't connect to SMS center " "(retrying in %ld seconds).", octstr_get_cstr(conn->id), conn->reconnect_delay); conn->status = SMSCCONN_RECONNECTING; gwthread_sleep(conn->reconnect_delay); debug("smsc.http.kannel", 0, "HTTP[%s]: Re-sending request", octstr_get_cstr(conn->id)); conndata->send_sms(conn, msg); continue; } /* request failed and we *are* in shutdown mode, drop the message */ else if (status == -1 && conndata->shutdown == 1) { } /* request succeeded */ else { /* we received a response, so this link is considered online again */ if (status && conn->status != SMSCCONN_ACTIVE) { conn->status = SMSCCONN_ACTIVE; time(&conn->connect_time); } conndata->parse_reply(conn, msg, status, headers, body); } conndata->open_sends--; http_destroy_headers(headers); octstr_destroy(final_url); octstr_destroy(body); } debug("smsc.http", 0, "HTTP[%s]: httpsmsc_send_cb dying", octstr_get_cstr(conn->id)); conndata->shutdown = 1; if (conndata->open_sends) { warning(0, "HTTP[%s]: Shutdown while <%ld> requests are pending.", octstr_get_cstr(conn->id), conndata->open_sends); } gwthread_join(conndata->receive_thread); conn->data = NULL; conndata_destroy(conndata); conn->status = SMSCCONN_DEAD; bb_smscconn_killed();}/*---------------------------------------------------------------- * SMSC-type specific functions * * 3 functions are needed for each: * * 1) send SMS * 2) parse send SMS result * 3) receive SMS (and send reply) * * These functions do not return anything and do not destroy * arguments. They must handle everything that happens therein * and must call appropriate bb_smscconn functions *//*---------------------------------------------------------------- * Kannel * * This type allows concatenation of Kannel instances, ie: * * <smsc>--<bearerbox2><smsbox2>--HTTP--<smsc_http><bearerbox1><smsbox1> * * Where MT messages are injected via the sendsms HTTP interface at smsbox1, * forwarded to bearerbo1 and routed via the SMSC HTTP type kannel to * sendsms HTTP interface of smsbox2 and further on. * * This allows chaining of Kannel instances for MO and MT traffic. * * DLR handling: * For DLR handling we have the usual effect that the "last" smsbox instance
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -