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

📄 smsc_http.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ====================================================================  * 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_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 <stolj@wapme.de> * 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"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;    long open_sends;    Octstr *username;   /* if needed */    Octstr *password;   /* as said */    int no_sender;      /* ditto */    int no_coding;      /* this, too */    int no_sep;         /* not to mention this */    Octstr *proxy;      /* proxy a constant string */    /* 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);    octstr_destroy(conndata->allow_ip);    octstr_destroy(conndata->send_url);    octstr_destroy(conndata->username);    octstr_destroy(conndata->password);    octstr_destroy(conndata->proxy);    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;            }            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 */enum { HEX_NOT_UPPERCASE = 0 };static void kannel_send_sms(SMSCConn *conn, Msg *sms){    ConnData *conndata = conn->data;    Octstr *url;    List *headers;    if (!conndata->no_sep) {        url = octstr_format("%S?"			    "username=%E&password=%E&to=%E&text=%E",			     conndata->send_url,			     conndata->username, conndata->password,			     sms->sms.receiver, sms->sms.msgdata);    } else {        octstr_binary_to_hex(sms->sms.msgdata, HEX_NOT_UPPERCASE);        url = octstr_format("%S?"			    "username=%E&password=%E&to=%E&text=%S",			     conndata->send_url,			     conndata->username, conndata->password,			     sms->sms.receiver,                              sms->sms.msgdata);     }       if (octstr_len(sms->sms.udhdata)) {        if (!conndata->no_sep) {	    octstr_format_append(url, "&udh=%E", sms->sms.udhdata);        } else {	    octstr_binary_to_hex(sms->sms.udhdata, HEX_NOT_UPPERCASE);            octstr_format_append(url, "&udh=%S", sms->sms.udhdata);	}    }    if (!conndata->no_sender)        octstr_format_append(url, "&from=%E", sms->sms.sender);    if (sms->sms.mclass != MC_UNDEF)	octstr_format_append(url, "&mclass=%d", sms->sms.mclass);    if (!conndata->no_coding && sms->sms.coding != DC_UNDEF)	octstr_format_append(url, "&coding=%d", sms->sms.coding);    if (sms->sms.mwi != MWI_UNDEF)	octstr_format_append(url, "&mwi=%d", sms->sms.mwi);    if (sms->sms.account) /* prepend account with local username */	octstr_format_append(url, "&account=%E:%E", sms->sms.service, sms->sms.account);    if (sms->sms.binfo) /* prepend billing info */	octstr_format_append(url, "&binfo=%S", sms->sms.binfo);    if (sms->sms.smsc_id) /* proxy the smsc-id to the next instance */	octstr_format_append(url, "&smsc=%S", sms->sms.smsc_id);    if (sms->sms.dlr_url) {        octstr_format_append(url, "&dlr-url=%E", sms->sms.dlr_url);    }    if (sms->sms.dlr_mask != DLR_UNDEFINED && sms->sms.dlr_mask != DLR_NOTHING)        octstr_format_append(url, "&dlr-mask=%d", sms->sms.dlr_mask);    headers = list_create();    debug("smsc.http.kannel", 0, "HTTP[%s]: Start request",          octstr_get_cstr(conn->id));    http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,                        NULL, 0, sms, NULL);    octstr_destroy(url);    http_destroy_headers(headers);}static void kannel_parse_reply(SMSCConn *conn, Msg *msg, int status,			       List *headers, Octstr *body){    /* Test on three cases:     * 1. an smsbox reply of an remote kannel instance     * 2. an smsc_http response (if used for MT to MO looping)     * 3. an smsbox reply of partly successful sendings */    if ((status == HTTP_OK || status == HTTP_ACCEPTED)        && (octstr_case_compare(body, octstr_imm("Sent.")) == 0 ||            octstr_case_compare(body, octstr_imm("Ok.")) == 0 ||            octstr_ncompare(body, octstr_imm("Result: OK"),10) == 0)) {        bb_smscconn_sent(conn, msg, NULL);    } else {        bb_smscconn_send_failed(conn, msg,

⌨️ 快捷键说明

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