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

📄 drive_smpp.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 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.   */ /* * drive_smpp.c - SMPP server for testing purposes * * Lars Wirzenius */#include <errno.h>#include <signal.h>#include <sys/types.h>#include <sys/socket.h>#include "gwlib/gwlib.h"#include "gw/smsc/smpp_pdu.h"#include "gw/msg.h"static int quitting = 0;static Octstr *smsc_system_id;static Octstr *smsc_source_addr;static Counter *message_id_counter;static Octstr *bearerbox_host;static int port_for_smsbox;static Counter *num_to_esme;static long max_to_esme;static Counter *num_from_bearerbox;static Counter *num_to_bearerbox;static Counter *num_from_esme;static time_t start_time = (time_t) -1;static time_t first_to_esme = (time_t) -1;static time_t last_to_esme = (time_t) -1;static time_t last_from_esme = (time_t) -1;static time_t first_from_bb = (time_t) -1;static time_t last_to_bb = (time_t) -1;static long enquire_interval = 1; /* Measured in messages, not time. */static void quit(void){    quitting = 1;    gwthread_wakeup_all();}typedef struct {    Connection *conn;    int transmitter;    int receiver;} ESME;static ESME *esme_create(Connection *conn){    ESME *esme;        esme = gw_malloc(sizeof(*esme));    esme->conn = conn;    esme->transmitter = 0;    esme->receiver = 0;    return esme;}static void esme_destroy(ESME *esme){    if (esme != NULL) {	conn_destroy(esme->conn);	gw_free(esme);    }}static SMPP_PDU *handle_bind_transmitter(ESME *esme, SMPP_PDU *pdu){    SMPP_PDU *resp;        esme->transmitter = 1;    resp = smpp_pdu_create(bind_transmitter_resp,    	    	    	    pdu->u.bind_transmitter.sequence_number);#if 0 /* XXX system_id is not implemented in the PDU at the moment */    resp->u.bind_transmitter_resp.system_id =     	octstr_duplicate(smsc_system_id);#endif    return resp;}static SMPP_PDU *handle_bind_receiver(ESME *esme, SMPP_PDU *pdu){    SMPP_PDU *resp;        esme->receiver = 1;    resp = smpp_pdu_create(bind_receiver_resp,    	    	    	    pdu->u.bind_receiver.sequence_number);#if 0 /* XXX system_id is not implemented in the PDU at the moment */    resp->u.bind_receiver_resp.system_id = octstr_duplicate(smsc_system_id);#endif    return resp;}static SMPP_PDU *handle_submit_sm(ESME *esme, SMPP_PDU *pdu){    SMPP_PDU *resp;    unsigned long id;        debug("test.smpp", 0, "submit_sm: short_message = <%s>",    	  octstr_get_cstr(pdu->u.submit_sm.short_message));    id = counter_increase(num_from_esme) + 1;    if (id == max_to_esme)    	info(0, "ESME has submitted all messages to SMSC.");    time(&last_from_esme);    resp = smpp_pdu_create(submit_sm_resp, pdu->u.submit_sm.sequence_number);#if 0 /* XXX message_id is not implemented in the PDU at the moment */    resp->u.submit_sm_resp.message_id =     	octstr_format("%ld", counter_increase(message_id_counter));#endif    return resp;}static SMPP_PDU *handle_deliver_sm_resp(ESME *esme, SMPP_PDU *pdu){    return NULL;}static SMPP_PDU *handle_unbind(ESME *esme, SMPP_PDU *pdu){    SMPP_PDU *resp;        resp = smpp_pdu_create(unbind_resp, pdu->u.unbind.sequence_number);    return resp;}static SMPP_PDU *handle_enquire_link(ESME *esme, SMPP_PDU *pdu){    return smpp_pdu_create(enquire_link_resp,     	    	    	   pdu->u.enquire_link.sequence_number);}static SMPP_PDU *handle_enquire_link_resp(ESME *esme, SMPP_PDU *pdu){    return NULL;}static struct {    unsigned long type;    SMPP_PDU *(*handler)(ESME *, SMPP_PDU *);} handlers[] = {    #define HANDLER(name) { name, handle_ ## name },    HANDLER(bind_transmitter)    HANDLER(bind_receiver)    HANDLER(submit_sm)    HANDLER(deliver_sm_resp)    HANDLER(unbind)    HANDLER(enquire_link)    HANDLER(enquire_link_resp)    #undef HANDLER};static int num_handlers = sizeof(handlers) / sizeof(handlers[0]);static void handle_pdu(ESME *esme, SMPP_PDU *pdu){    SMPP_PDU *resp;    Octstr *os;    int i;    debug("test.smpp", 0, "Handling SMPP PDU of type %s", pdu->type_name);    for (i = 0; i < num_handlers; ++i) {    	if (handlers[i].type == pdu->type) {	    resp = handlers[i].handler(esme, pdu);	    if (resp != NULL) {	    	os = smpp_pdu_pack(resp);		conn_write(esme->conn, os);		octstr_destroy(os);		smpp_pdu_destroy(resp);	    }	    return;	}    }    error(0, "Unhandled SMPP PDU.");    smpp_pdu_dump(pdu);}static void send_smpp_thread(void *arg){    ESME *esme;    Octstr *os;    SMPP_PDU *pdu;    unsigned long id;    esme = arg;        id = 0;    while (!quitting && counter_value(num_to_esme) < max_to_esme) {	id = counter_increase(num_to_esme) + 1;    	while (!quitting && counter_value(num_from_esme) + 500 < id)	    gwthread_sleep(1.0);	if (quitting)	    break;	pdu = smpp_pdu_create(deliver_sm,			       counter_increase(message_id_counter));	pdu->u.deliver_sm.source_addr = octstr_create("456");	pdu->u.deliver_sm.destination_addr = octstr_create("123");	pdu->u.deliver_sm.short_message = octstr_format("%ld", id);	os = smpp_pdu_pack(pdu);	conn_write(esme->conn, os);	octstr_destroy(os);	smpp_pdu_destroy(pdu);	if (first_to_esme == (time_t) -1)	    time(&first_to_esme);	debug("test.smpp", 0, 	      "Delivered SMS %ld of %ld to bearerbox via SMPP.",	      id, max_to_esme);    	if ((id % enquire_interval) == 0) {	    pdu = smpp_pdu_create(enquire_link, 	    	    	    	  counter_increase(message_id_counter));	    os = smpp_pdu_pack(pdu);	    conn_write(esme->conn, os);	    octstr_destroy(os);	    smpp_pdu_destroy(pdu);	    debug("test.smpp", 0, "Sent enquire_link to bearerbox.");	}    }    time(&last_to_esme);    if (id == max_to_esme)	info(0, "All messages sent to ESME.");    debug("test.smpp", 0, "%s terminates.", __func__);}static void receive_smpp_thread(void *arg){    ESME *esme;    Octstr *os;    long len;    long sender_id;    SMPP_PDU *pdu;    esme = arg;        sender_id = -1;    len = 0;    while (!quitting && conn_wait(esme->conn, -1.0) != -1) {    	for (;;) {	    if (len == 0) {		len = smpp_pdu_read_len(esme->conn);		if (len == -1) {		    error(0, "Client sent garbage, closing connection.");		    goto error;		} else if (len == 0) {		    if (conn_eof(esme->conn) || conn_error(esme->conn))		    	goto error;		    break;		}	    }        	    gw_assert(len > 0);	    os = smpp_pdu_read_data(esme->conn, len);	    if (os != NULL) {    	    	len = 0;		pdu = smpp_pdu_unpack(os);		if (pdu == NULL) {		    error(0, "PDU unpacking failed!");		    octstr_dump(os, 0);		} else {		    handle_pdu(esme, pdu);		    smpp_pdu_destroy(pdu);		}		octstr_destroy(os);	    } else if (conn_eof(esme->conn) || conn_error(esme->conn))	    	goto error;	    else		break;	}    	if (!quitting && esme->receiver && sender_id == -1)	    sender_id = gwthread_create(send_smpp_thread, esme);    }error:    if (sender_id != -1) {	quit();	gwthread_join(sender_id);    }    esme_destroy(esme);    quit();    debug("test.smpp", 0, "%s terminates.", __func__);}static void smsbox_thread(void *arg){    Connection *conn;    Msg *msg;    Octstr *os;    Octstr *reply_msg;    unsigned long count;        msg = msg_create(sms);    msg->sms.sender = octstr_create("123");    msg->sms.receiver = octstr_create("456");    msg->sms.msgdata = octstr_create("hello world");    reply_msg = msg_pack(msg);    msg_destroy(msg);    gwthread_sleep(1.0);    conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL);    if (conn == NULL) {	gwthread_sleep(2.0);	conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL);    	if (conn == NULL)	    panic(0, "Couldn't connect to bearerbox as smsbox");    }    while (!quitting && conn_wait(conn, -1.0) != -1) {    	for (;;) {	    os = conn_read_withlen(conn);	    if (os == NULL) {		if (conn_eof(conn) || conn_error(conn))		    goto error;		break;	    }	    	    msg = msg_unpack(os);	    if (msg == NULL || msg->type == wdp_datagram)		error(0, "Bearerbox sent garbage to smsbox");	    if (msg->type == sms) {		if (first_from_bb == (time_t) -1)		    time(&first_from_bb);		count = counter_increase(num_from_bearerbox) + 1;		debug("test.smpp", 0, 		      "Bearerbox sent sms #%ld <%s> to smsbox, sending reply.",		      count, octstr_get_cstr(msg->sms.msgdata));		if (count == max_to_esme)		    info(0, "Bearerbox has sent all messages to smsbox.");		conn_write_withlen(conn, reply_msg);		counter_increase(num_to_bearerbox);	    }	    msg_destroy(msg);	    octstr_destroy(os);	    time(&last_to_bb);	}    }    error:    conn_destroy(conn);    octstr_destroy(reply_msg);    debug("test.smpp", 0, "%s terminates.", __func__);}static void accept_thread(void *arg){    int fd;    int new_fd;    int port;    socklen_t addrlen;    struct sockaddr addr;    long smsbox_thread_id;        port = *(int *) arg;    fd = make_server_socket(port, NULL);    if (fd == -1)    	panic(0, "Couldn't create SMPP listen port.");        smsbox_thread_id = -1;    for (;;) {	if (gwthread_pollfd(fd, POLLIN, -1.0) != POLLIN)	    break;	addrlen = sizeof(addr);	new_fd = accept(fd, &addr, &addrlen);    	if (start_time == (time_t) -1)	    time(&start_time);	gwthread_create(receive_smpp_thread, 			esme_create(conn_wrap_fd(new_fd, 0)));	if (smsbox_thread_id == -1)	    smsbox_thread_id = gwthread_create(smsbox_thread, NULL);    }        debug("test.smpp", 0, "%s terminates.", __func__);}static void handler(int signal){    panic(0, "Caught signal %d.", signal);}static void help(void){    info(0, "drive_smpp [-h] [-v level]燵-p port]");}int main(int argc, char **argv){    struct sigaction act;    int http_port;    int port;    int opt;    double run_time;    char *log_file;    gwlib_init();    act.sa_handler = handler;    sigemptyset(&act.sa_mask);    act.sa_flags = 0;    sigaction(SIGTERM, &act, NULL);    sigaction(SIGINT, &act, NULL);    port = 2345;    http_port = 8080;    smsc_system_id = octstr_create("kannel_smpp");    smsc_source_addr = octstr_create("123456");    message_id_counter = counter_create();    bearerbox_host = octstr_create("localhost");    port_for_smsbox = 13001;    max_to_esme = 1;    num_to_esme = counter_create();    num_from_esme = counter_create();    num_to_bearerbox = counter_create();    num_from_bearerbox = counter_create();    log_file = NULL;    while ((opt = getopt(argc, argv, "hv:p:P:m:l:")) != EOF) {	switch (opt) {	case 'v':	    log_set_output_level(atoi(optarg));	    break;	case 'h':	    help();	    exit(0);	case 'm':	    max_to_esme = atoi(optarg);	    break;	case 'p':	    port = atoi(optarg);	    break;	case 'P':	    http_port = atoi(optarg);	    break;    	case 'l':	    log_file = optarg;	    break;	case '?':	default:	    error(0, "Invalid option %c", opt);	    help();	    panic(0, "Stopping.");	}    }    if (log_file != NULL)    	log_open(log_file, GW_DEBUG, GW_NON_EXCL);    info(0, "Starting drive_smpp test.");    gwthread_create(accept_thread, &port);    gwthread_join_all();    debug("test.smpp", 0, "Program exiting normally.");    run_time = difftime(last_from_esme, first_to_esme);    info(0, "Number of messages sent to ESME: %ld",    	 counter_value(num_to_esme));    info(0, "Number of messages sent to smsbox: %ld",    	 counter_value(num_from_bearerbox));    info(0, "Number of messages sent to bearerbox: %ld",    	 counter_value(num_to_bearerbox));    info(0, "Number of messages sent to SMSC: %ld",    	 counter_value(num_from_esme));    info(0, "Time: %.0f secs", run_time);    info(0, "Time until all sent to ESME: %.0f secs",     	 difftime(last_to_esme, start_time));    info(0, "Time from first from bb to last to bb: %.0f secs",     	 difftime(last_to_bb, first_from_bb));    info(0, "Time until all sent to SMSC: %.0f secs",     	 difftime(last_from_esme, start_time));    info(0, "SMPP messages SMSC to ESME: %.1f msgs/sec",    	 counter_value(num_to_esme) / run_time);    info(0, "SMPP messages ESME to SMSC: %.1f msgs/sec",    	 counter_value(num_from_esme) / run_time);    octstr_destroy(smsc_system_id);    octstr_destroy(smsc_source_addr);    octstr_destroy(bearerbox_host);    counter_destroy(num_to_esme);    counter_destroy(num_from_esme);    counter_destroy(num_to_bearerbox);    counter_destroy(num_from_bearerbox);    counter_destroy(message_id_counter);    gwlib_shutdown();    return 0;}

⌨️ 快捷键说明

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