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

📄 smsc_cgw.c

📁 主要包括sms网关和wap网关实现说明和源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ====================================================================  * The Kannel Software License, Version 1.0  *  * Copyright (c) 2001-2005 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_cgw.c - Implements an interface to the Sonera ContentGateway software * * Anders Lindh, FlyerOne Ltd <alindh@flyerone.com> * * * Changelog: * * 22/02/2002: Preliminary support for the Euro character (req. ProviderServer 2.5.2) * 25/01/2002: Caught a potentially nasty bug * 16/01/2002: Some code cleanup * 10/01/2002: Fixed a bug in trn handling * 16/11/2001: Some minor fixes (Thanks to Tuomas Luttinen) * 12/11/2001: Delivery reports, better acking and numerous other small fixes * 05/11/2001: Initial release. Based heavily on smsc_emi2 and smsc_at2.  * * * TO-DO: Do some real life testing *        Squash bugs * * Usage: add the following to kannel.conf: * * group = smsc * smsc = cgw * host = x.x.x.x      <- CGW server host * port = xxxx 	       <- CGW server otp port (if omitted, defaults to 21772) * receive-port = xxxx <- our port for incoming messages * appname = xxxx      <- Name of a "Send only" service. Defaults to "send". *	           	  All outgoing messages are routed through this service. * * Configure ContentGateway software to use the above port as text-port * (in provider.cnf). This is documented in their "Guide for Service * development 2.5", page 80. * * Add a new "Receive only" service (with the Remote Control tool), and set * the "Application for Incoming Message" to "text://kannelhost:receive-port". * * * Note: * * Do NOT define the service as a "Query/Reply" service, as it expects response * messages to have a matching session-id tag. Kannel does not store the * relation between a query and a reply, so the response message will not have * the session-id tag. Even though the messages are delivered successfully, * billing of premium priced services will fail. * * */#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"#define CGW_DEFPORT 	21772#define	CGW_EOL     	0x0A#define CGW_TRN_MAX 	500	/* Size of our internal message buffer. */#define CGWOP_MAXARGS	10     	/* max. number of name:value pairs in cgwop *//* Valid CGW operations */#define CGW_OP_NOP	0     	/* this doesn't really exist.. */#define CGW_OP_MSG	1#define CGW_OP_OK	2#define CGW_OP_ERR	3#define CGW_OP_DELIVERY	4#define CGW_OP_HELLO	5#define CGW_OP_STATUS	6struct cgwop{    int op;    			/* one of above */    int num_fields;    int trn;                    /* transaction number, used to ACK messages */    Octstr **name;    		/* for storing name/value pairs */    Octstr **value;};static char *cgw_ops[6] = {"nop", "msg", "ok", "err", "delivery", "hello"};typedef struct privdata{    List *outgoing_queue;    long receiver_thread;    long sender_thread;    int	shutdown;    	       	/* Internal signal to shut down */    int	listening_socket;     	/* File descriptor */    int	send_socket;    int	port;    	        /* SMSC port */    int	rport;    		/* port for receiving messages*/    int	our_port;    	  	/* Optional local port number in which to                	        	 * bind our end of send connection */    Octstr *host;    Octstr *allow_ip, *deny_ip;    Octstr *appname;    	/* Application name as defined in Sonera Remote manager */    Msg	*sendmsg[CGW_TRN_MAX];    time_t sendtime[CGW_TRN_MAX];    int	dlr[CGW_TRN_MAX];    	/* dlr = DLR_SMSC_SUCCESS || DLR_SMSC_FAIL */    int	unacked;    		/* Sent messages not acked */    int	waitack;        	/* Seconds to wait to ack */    int	nexttrn;    long check_time;     	/* last checked ack/nack status */}PrivData;static int cgw_add_msg_cb(SMSCConn *conn, Msg *sms);static int cgw_shutdown_cb(SMSCConn *conn, int finish_sending);static void cgw_start_cb(SMSCConn *conn);static long cgw_queued_cb(SMSCConn *conn);static void cgw_sender(void *arg);static Connection *cgw_open_send_connection(SMSCConn *conn);static int cgw_send_loop(SMSCConn *conn, Connection *server);void cgw_check_acks(PrivData *privdata);int cgw_wait_command(PrivData *privdata, SMSCConn *conn, Connection *server, int timeout);static int cgw_open_listening_socket(SMSCConn *conn, PrivData *privdata);static void cgw_listener(void *arg);static void cgw_receiver(SMSCConn *conn, Connection *server);static int cgw_handle_op(SMSCConn *conn, Connection *server, struct cgwop *cgwop);struct cgwop *cgw_read_op(PrivData *privdata, SMSCConn *conn, Connection *server, time_t timeout);/****************************************************************************** * Functions for handling cgwop -structures */static void cgwop_add(struct cgwop *cgwop, Octstr *name, Octstr *value){    if (cgwop->num_fields < CGWOP_MAXARGS)    {        cgwop->name[cgwop->num_fields] = octstr_duplicate(name);        cgwop->value[cgwop->num_fields] = octstr_duplicate(value);        cgwop->num_fields++;    } else    {        info(0, "cgw: CGWOP_MAXARGS exceeded.");    }}static struct cgwop *cgwop_create(int op, int trn){    struct cgwop *ret;    Octstr *trnstr;    ret = gw_malloc(sizeof(struct cgwop));    ret->op = op;    ret->num_fields = 0;    ret->trn = trn;    ret->name = gw_malloc(CGWOP_MAXARGS * sizeof(Octstr *));    ret->value = gw_malloc(CGWOP_MAXARGS * sizeof(Octstr *));    if (trn != -1)    {        trnstr = octstr_create("");        octstr_append_decimal(trnstr, trn);        cgwop_add(ret, octstr_imm("client-id"), trnstr);        octstr_destroy(trnstr);    }    return ret;}static void cgwop_destroy(struct cgwop *cgwop){    int len;    len = cgwop->num_fields;    while (--len >= 0)    {        octstr_destroy(cgwop->name[len]);      /* octstr_destroy(NULL) is ok */        octstr_destroy(cgwop->value[len]);    }    gw_free(cgwop->name);    gw_free(cgwop->value);    gw_free(cgwop);}static Octstr *cgwop_get(struct cgwop *cgwop, Octstr *name){    int len = cgwop->num_fields;    while (--len >= 0)        if (octstr_compare(name, cgwop->name[len]) == 0)            return cgwop->value[len];    return NULL;}static Octstr *cgwop_tostr(struct cgwop *cgwop){    int len = cgwop->num_fields;    Octstr *str;    if (cgw_ops[cgwop->op] == NULL) return NULL;     /* invalid operation */    str = octstr_create("");    octstr_append(str, octstr_imm("op:"));    octstr_append(str, octstr_imm(cgw_ops[cgwop->op]));    octstr_append_char(str, CGW_EOL);    while (--len >= 0)    {        octstr_append(str, cgwop->name[len]);        octstr_append_char(str, ':');        octstr_append(str, cgwop->value[len]);        octstr_append_char(str, CGW_EOL);    }    octstr_append(str, octstr_imm("end:"));    octstr_append(str, octstr_imm(cgw_ops[cgwop->op]));    octstr_append_char(str, CGW_EOL);    return str;}static int cgwop_send(Connection *conn, struct cgwop *cgwop){    Octstr *dta = cgwop_tostr(cgwop);    if (dta == NULL) return -1;     /* couldn't convert to string */    if (conn_write(conn, dta) == -1)    {        octstr_destroy(dta);        return -1;    }    octstr_destroy(dta);    return 1;}/****************************************************************************** * cgw_encode_msg - Encode a msg according to specifications */static Octstr *cgw_encode_msg(Octstr* str){    int i;    char esc = 27;    char e = 'e';    /* Euro char (0x80) -> ESC + e. We do this conversion as long as the message        length is under 160 chars (the checking could probably be done better) */    while ((i = octstr_search_char(str, 0x80, 0)) != -1) {            octstr_delete(str, i, 1);     /* delete Euro char */	if (octstr_len(str) < 160) {	    octstr_insert_data(str, i, &esc, 1);  /* replace with ESC + e */	    octstr_insert_data(str, i+1, &e, 1);  	} else {	    octstr_insert_data(str, i, &e, 1);  /* no room for ESC + e, just replace with an e */        }    }    /* Escape backslash characters */    while ((i = octstr_search_char(str, '\\', 0)) != -1) {        octstr_insert(str, octstr_imm("\\"), i);    }    /* Remove Line Feed characters */    while ((i = octstr_search_char(str, CGW_EOL, 0)) != -1) {        octstr_delete(str, i, 1);     /* delete EOL char */        octstr_insert(str, octstr_imm("\\n"), i);    }    /* Remove Carriage return characters */    while ((i = octstr_search_char(str, 13, 0)) != -1) {        octstr_delete(str, i, 1);     /* delete EOL char */        octstr_insert(str, octstr_imm("\\r"), i);    }    return str;}/****************************************************************************** * cgw_decode_msg - Decode an incoming msg */static Octstr *cgw_decode_msg(Octstr* str){    int i;    /* make \n -> linefeed */    while ((i = octstr_search(str, octstr_imm("\\n"), 0)) != -1) {        octstr_delete(str, i, 2);     /* delete "\n" str */        octstr_insert(str, octstr_imm("\n"), i);    }    /* make \r -> carriage return */    while ((i = octstr_search(str, octstr_imm("\\r"), 0)) != -1) {        octstr_delete(str, i, 2);     /* delete EOL char */        octstr_insert(str, octstr_imm("\r"), i);    }    /* remove double backslashes */    while ((i = octstr_search(str, octstr_imm("\\\\"), 0)) != -1) {        octstr_delete(str, i, 1);    }    return str;}/****************************************************************************** * msg_to_cgwop - Create a send cgwop from a message */static struct cgwop *msg_to_cgwop(PrivData *privdata, Msg *msg, int trn){    struct cgwop *cgwop;    Octstr *sender, *udh, *dta;    cgwop = cgwop_create(CGW_OP_MSG, trn);    if (cgwop == NULL) return NULL;    if (!octstr_check_range(msg->sms.sender, 0, octstr_len(msg->sms.sender), gw_isdigit))    {        /* If alphanumeric, simply prefix sender with '$' char */        sender = octstr_create("$");        octstr_append(sender, msg->sms.sender);    } else sender = octstr_duplicate(msg->sms.sender);    cgwop_add(cgwop, octstr_imm("app"), privdata->appname);    cgwop_add(cgwop, octstr_imm("from"), sender);    cgwop_add(cgwop, octstr_imm("to"), msg->sms.receiver);    /* If delivery reports are asked, ask for them by adding a nrq:anything field */    if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))        cgwop_add(cgwop, octstr_imm("nrq"), octstr_imm("true"));    octstr_destroy(sender);    if (octstr_len(msg->sms.udhdata))    {        udh = octstr_duplicate(msg->sms.udhdata);        octstr_binary_to_hex(udh, 1);        cgwop_add(cgwop, octstr_imm("udh"), udh);        octstr_destroy(udh);

⌨️ 快捷键说明

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