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

📄 test_cimd2.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ====================================================================  * 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.   */ /* test_cimd2.c - fake cimd2 smsc * * This program pretends to be an CIMD 2 SMS center, accessible via IP. * It is used to test the Kannel smsc_cimd2 code. *  * Richard Braakman *//* Note: The CIMD2 parsing code was written as a prototype, and currently * its main use is to exercise the *real* CIMD2 code in gw/smsc_cimd2.c. * Please don't use this code for anything real. * Richard Braakman *//* * TODO: If log level is high and activity level is low, there will be * "SND" log entries for packets that are not sent, which is confusing * and should be fixed. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <ctype.h>#include <stdarg.h>#include <limits.h>#include <unistd.h>#include <time.h>#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include "gwlib/gwlib.h"enum { TIMESTAMP_MAXLEN = 13 };unsigned char *progname;/* Set up a fake account for Kannel to use */unsigned char *username = "foo";unsigned char *password = "bar";int port = 6789;/* This can be useful to get past protocol-ID checks when testing spew. */unsigned char *intro = "";enum ACT {	ACT_listen = 0,	ACT_reply = 1,	ACT_deliver = 2,	ACT_flood = 3};enum SPEW {	SPEW_nothing = 0,	SPEW_binary = 1,	SPEW_characters = 2,	SPEW_packets = 3};enum LOG {	LOG_nothing = 0,	LOG_data = 1,	LOG_packets = 2,	LOG_sms = 3};enum CHK {	CHK_nothing = 0,	CHK_packets = 1,	CHK_sums = 2,	CHK_protocol = 3,	CHK_sms = 4};int activity = ACT_listen;int spew = SPEW_nothing;int logging = LOG_nothing;int checking = CHK_nothing;int max_deliveries = -1;int deliveries = 0;time_t start_time = 0;int sockfd = -1;Octstr *inbuffer;Octstr *outbuffer;/* Maximum reasonable outbuffer size.  It can go above this, but we don't * deliberately add data when it's already more than this. */enum { OUTBUFFER_LIMIT = 65536 };/* Test dependencies on neatly-sized read and write chunks, by using * a deliberately evil buffer size.  1021 is the largest prime smaller * than 1024. */enum { EVIL_BUFSIZE = 1021 };enum CHARS {	STX = 2,	ETX = 3,	TAB = 9,	LF = 10,	CR = 13};static void usage(FILE *out) {	fprintf(out, "Usage: %s [options...]\n""  --help          Print this message\n""  --user USER     Allow clients to log in with username USER (default %s)\n""  --password PASS Allow clients to log in with password PASS (default %s)\n""  --intro INTRO   Send INTRO string before anything else (default nothing)\n""  --port PORT     TCP port to listen on (default %d)\n""  --activity ACT  Activity level of test server (default %d)\n""      ACT = 0     send nothing, just listen\n""      ACT = 1     send valid replies, do not initiate any transactions\n""      ACT = 2     attempt to deliver a random SMS every few seconds (NI)\n""      ACT = 3     deliver many random SMSes, measure throughput (NI)\n""  --spew SPEW     Flood client, overrides --activity (default %d)\n""      SPEW = 0    don't spew, use --activity instead\n""      SPEW = 1    spew random binary gunk at client\n""      SPEW = 2    spew random data of the right character set at client (NI)\n""      SPEW = 3    spew valid packets with random contents at client (NI)\n""  --logging LOG   Log level of test server (default %d)\n""      LOG = 0     log nothing\n""      LOG = 1     log all data\n""      LOG = 2     log summaries of valid packets\n""      LOG = 3     log successfully sent and received SMSes (NI)\n""  --checking CHK  Check level of test server (default %d)\n""      CHK = 0     check nothing\n""      CHK = 1     signal invalid packets (NI)\n""      CHK = 2     signal checksum errors (NI)\n""      CHK = 3     signal protocol errors (NI)\n""      CHK = 4     signal invalid SMS contents (NI)\n""  --max MAX       With high activity values, stop after MAX deliveries\n"" NI means Not Implemented\n"	, progname, username, password, port,	activity, spew, logging, checking);}static void pretty_print(unsigned char *data, size_t length) {	size_t i;	int c;	for (i = 0; i < length; i++) {		c = data[i];		switch(c) {		default:			if (isprint(c))				putchar(c);			else				printf("<%d>", c);			break;		case TAB: fputs("<TAB>", stdout); break;		case LF: fputs("<LF>\n", stdout); break;		case CR: fputs("<CR>", stdout); break;		case STX: fputs("<STX>", stdout); break;		case ETX: fputs("<ETX>\n", stdout); break;		}	}	fflush(stdout);}static void read_data(Octstr *in, int fd) {	unsigned char buf[EVIL_BUFSIZE];	int ret;	ret = read(fd, buf, sizeof(buf));	if (ret > 0) {		octstr_append_data(in, buf, ret);		if (logging == LOG_data)			pretty_print(buf, ret);	} else if (ret == 0) {		fprintf(stderr, "Client closed socket\n");		exit(0);	} else {		if (errno == EINTR || errno == EAGAIN)			return;		error(errno, "read_data");		exit(1);	}}static void write_data(Octstr *out, int fd) {	unsigned char buf[EVIL_BUFSIZE];	int len;	ssize_t ret;		len = sizeof(buf);	if (len > octstr_len(out))		len = octstr_len(out);	if (len == 0)		return;	octstr_get_many_chars(buf, out, 0, len);	ret = write(fd, buf, len);	if (ret > 0) {		if (logging == LOG_data)			pretty_print(buf, ret);		octstr_delete(out, 0, ret);	} else if (ret == 0) {		warning(0, "empty write");	} else {		if (errno == EINTR || errno == EAGAIN)			return;		error(errno, "write_data");		exit(1);	}}static void gen_message(Octstr *out);/* Return the minimum interval (in microseconds) after which we will * want to be called again.  This value is only used if we _don't_ * generate data this time through. */static long gen_data(Octstr *out) {	unsigned char buf[EVIL_BUFSIZE];	size_t i;	long interval = -1;	static int last_sms;  /* Used by ACT_deliver */	time_t now;	if (max_deliveries < 0 || deliveries < max_deliveries) {		switch (activity) {		case ACT_deliver:			now = time(NULL);			if (last_sms == 0)				last_sms = now;			while (last_sms < now) {				if (random() % 7 == 1) {					gen_message(out);					last_sms = now;				} else					last_sms++;			}			interval = 1000000;			break;		case ACT_flood:			gen_message(out);			break;		}	}	switch (spew) {	case SPEW_binary:		for (i = 0; i < sizeof(buf); i++) {			buf[i] = random() % 256;		}		octstr_append_data(out, buf, sizeof(buf));		break;	}	return interval;}/******************************* CIMD 2 specific code ************************/int awaiting_response = 0;/* buf must be at least TIMESTAMP_MAXLEN bytes long. */static void make_timestamp(unsigned char *buf, time_t fortime) {	/* Is there a thread-safe version of gmtime? */	struct tm tm = gw_gmtime(fortime);	sprintf(buf, "%02d%02d%02d%02d%02d%02d",		tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,		tm.tm_hour, tm.tm_min, tm.tm_sec);}	static void send_packet(Octstr *out, int opcode, int sequence, ...) {	va_list ap;	int parm;	unsigned char *value;	int checksum;	int old_len, new_len;	if (activity == ACT_listen)		return;	old_len = octstr_len(out);	octstr_format_append(out, "%c%02d:%03d%c", STX, opcode, sequence, TAB);	va_start(ap, sequence);	for (parm = va_arg(ap, int); parm != 0; parm = va_arg(ap, int)) {		value = va_arg(ap, unsigned char *);		octstr_format_append(out, "%03d:%s\11", parm, value);	}	va_end(ap);	/* Calculate checksum */	checksum = 0;	for (new_len = octstr_len(out); old_len < new_len; old_len++) {		checksum = (checksum + octstr_get_char(out, old_len)) & 0xff;	}	octstr_format_append(out, "%02X%c", checksum, ETX);}static void send_error(Octstr *out, int opcode, int sequence,			unsigned char *errorcode, unsigned char *errortext) {	if (logging == LOG_packets)		printf("SND: ERROR, %s\n", errortext);	send_packet(out, opcode, sequence, 900, errorcode, 901, errortext, 0);}static int eat_char(Octstr *packet, int ch) {	if (octstr_get_char(packet, 0) == ch) {		octstr_delete(packet, 0, 1);		return 0;	}	return -1;}static Octstr *eat_string_parm(Octstr *packet, int parm, int maxlen) {	long start, datastart;	long tab;	Octstr *result;	Octstr *parmheader;    	parmheader = octstr_format("%c%03d:", TAB, parm);	start = octstr_search(packet, parmheader, 0);	if (start < 0) {		octstr_destroy(parmheader);		return NULL;	}	datastart = start + octstr_len(parmheader);	tab = octstr_search_char(packet, TAB, datastart + 1);	if (tab < 0) {		tab = octstr_len(packet);	}	result = octstr_copy(packet, datastart, tab - datastart);	octstr_delete(packet, start, tab - start);	octstr_destroy(parmheader);	return result;}static long eat_number(Octstr *ostr) {	long result;	long pos;	pos = octstr_parse_long(&result, ostr, 0, 10);	if (pos < 0)		return INT_MIN;	octstr_delete(ostr, 0, pos);	return result;}static long eat_int_parm(Octstr *packet, int parm, int maxlen) {	Octstr *value;	long result;	value = eat_string_parm(packet, parm, maxlen);	if (!value)		return INT_MIN;	result = eat_number(value);	if (octstr_len(value) > 0)		result = INT_MIN;	octstr_destroy(value);	return result;}static void eat_checksum(Octstr *packet) {	int len;	int ch1, ch2, ch3;	len = octstr_len(packet);	if (len < 3)		return;	ch1 = octstr_get_char(packet, len - 3);	ch2 = octstr_get_char(packet, len - 2);	ch3 = octstr_get_char(packet, len - 1);		if (isxdigit(ch3) && isxdigit(ch2) && ch1 == TAB)		octstr_delete(packet, len - 3, 3);}static void handle_login(Octstr *packet, Octstr *out, int sequence) {	Octstr *user = eat_string_parm(packet, 10, 32);	Octstr *pass = eat_string_parm(packet, 11, 32);	if (user == NULL)		user = octstr_create("");	if (pass == NULL)		pass = octstr_create("");	if (logging == LOG_packets)		printf("RCV: Login user '%s', password '%s'\n",			octstr_get_cstr(user), octstr_get_cstr(pass));	if (octstr_str_compare(user, username) == 0 &&	    octstr_str_compare(pass, password) == 0) {		if (logging == LOG_packets)			printf("SND: Login OK\n");		send_packet(out, 51, sequence, 0);	} else {		send_error(out, 51, sequence, "100", "invalid login");	}	octstr_destroy(user);	octstr_destroy(pass);}static void handle_logout(Octstr *packet, Octstr *out, int sequence) {	if (logging == LOG_packets)		printf("RCV: Logout\n");	if (logging == LOG_packets)		printf("SND: Logout OK\n");	send_packet(out, 52, sequence, 0);}static void handle_submit(Octstr *packet, Octstr *out, int sequence) {	Octstr *dest_addr = eat_string_parm(packet, 21, 20);	Octstr *orig_addr = eat_string_parm(packet, 23, 20);	long DCS = eat_int_parm(packet, 30, 3);	Octstr *UDH = eat_string_parm(packet, 32, 280);	Octstr *text = eat_string_parm(packet, 33, 480);	Octstr *textb = eat_string_parm(packet, 34, 280);	long valid_rel = eat_int_parm(packet, 50, 3);	Octstr *valid_abs = eat_string_parm(packet, 51, 12);	long proto_id = eat_int_parm(packet, 52, 3);	long delivery_rel = eat_int_parm(packet, 53, 3);	Octstr *delivery_abs = eat_string_parm(packet, 54, 12);	long reply_path = eat_int_parm(packet, 55, 1);	long SRR = eat_int_parm(packet, 56, 2);	long cancel = eat_int_parm(packet, 58, 1);	long tariff_class = eat_int_parm(packet, 64, 2);	long service_desc = eat_int_parm(packet, 65, 1);	long priority = eat_int_parm(packet, 67, 1);	List *other_dests = list_create();	Octstr *tmp;	while ((tmp = eat_string_parm(packet, 21, 20)))		list_append(other_dests, tmp);	if (logging == LOG_packets) {		int i;		printf("RCV: Submit to %s", octstr_get_cstr(dest_addr));		for (i = 0; i < list_len(other_dests); i++) {			printf(", %s",				octstr_get_cstr(list_get(other_dests, i)));		}		printf("\n");		if (orig_addr)			printf("    From: %s\n", octstr_get_cstr(orig_addr));		if (DCS > INT_MIN)			printf("    Data coding: %ld\n", DCS);		if (UDH)			printf("    User data header: %s\n",				octstr_get_cstr(UDH));		if (text)			printf("    Text: %s\n", octstr_get_cstr(text));		if (textb)			printf("    Text (binary): %s\n",				octstr_get_cstr(textb));		if (valid_rel > INT_MIN)			printf("    Validity period: %ld (relative)\n",				valid_rel);		if (valid_abs)			printf("    Validity period: %s (absolute)\n",				octstr_get_cstr(valid_abs));		if (proto_id > INT_MIN)			printf("    Protocol ID: %ld\n", proto_id);		if (delivery_rel > INT_MIN)			printf("    First delivery: %ld (relative)\n",				delivery_rel);		if (delivery_abs)			printf("    First delivery: %s (absolute)\n",				octstr_get_cstr(delivery_abs));		if (reply_path == 0)			printf("    Reply path disabled\n");		else if (reply_path == 1)			printf("    Reply path enabled\n");		else if (reply_path > INT_MAX)			printf("    Reply path: %ld\n", reply_path);		if (SRR > INT_MAX)			printf("    Status report flags: %ld\n", SRR);		if (cancel == 0)			printf("    Cancel disabled\n");		else if (cancel == 1)

⌨️ 快捷键说明

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