test_cimd2.c
资源名称:gateway-1.2.1 [点击查看]
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:25k
源码类别:
手机WAP编程
开发平台:
WINDOWS
- /* 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 messagen"
- " --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 listenn"
- " ACT = 1 send valid replies, do not initiate any transactionsn"
- " 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 insteadn"
- " SPEW = 1 spew random binary gunk at clientn"
- " 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 nothingn"
- " LOG = 1 log all datan"
- " LOG = 2 log summaries of valid packetsn"
- " LOG = 3 log successfully sent and received SMSes (NI)n"
- " --checking CHK Check level of test server (default %d)n"
- " CHK = 0 check nothingn"
- " 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 deliveriesn"
- " NI means Not Implementedn"
- , 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 socketn");
- 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:%s11", 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, %sn", 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 OKn");
- 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: Logoutn");
- if (logging == LOG_packets)
- printf("SND: Logout OKn");
- 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: %sn", octstr_get_cstr(orig_addr));
- if (DCS > INT_MIN)
- printf(" Data coding: %ldn", DCS);
- if (UDH)
- printf(" User data header: %sn",
- octstr_get_cstr(UDH));
- if (text)
- printf(" Text: %sn", octstr_get_cstr(text));
- if (textb)
- printf(" Text (binary): %sn",
- 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: %ldn", 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 disabledn");
- else if (reply_path == 1)
- printf(" Reply path enabledn");
- else if (reply_path > INT_MAX)
- printf(" Reply path: %ldn", reply_path);
- if (SRR > INT_MAX)
- printf(" Status report flags: %ldn", SRR);
- if (cancel == 0)
- printf(" Cancel disabledn");
- else if (cancel == 1)
- printf(" Cancel enabledn");
- else if (cancel > INT_MAX)
- printf(" Cancel enabled: %ldn", cancel);
- if (tariff_class > INT_MAX)
- printf(" Tariff class: %ldn", tariff_class);
- if (service_desc > INT_MAX)
- printf(" Service description: %ldn", service_desc);
- if (priority > INT_MAX)
- printf(" Priority: %ldn", priority);
- }
- if (!dest_addr) {
- send_error(out, 53, sequence, "300", "no destination");
- } else if (list_len(other_dests) > 0) {
- send_error(out, 53, sequence, "301", "too many destinations");
- /* TODO: Report many other possible errors here */
- } else {
- unsigned char buf[TIMESTAMP_MAXLEN];
- make_timestamp(buf, time(NULL));
- if (logging == LOG_packets)
- printf("SND: Submit OKn");
- send_packet(out, 53, sequence,
- 21, octstr_get_cstr(dest_addr),
- 60, buf,
- 0);
- }
- octstr_destroy(dest_addr);
- octstr_destroy(orig_addr);
- octstr_destroy(UDH);
- octstr_destroy(text);
- octstr_destroy(textb);
- octstr_destroy(valid_abs);
- octstr_destroy(delivery_abs);
- list_destroy(other_dests, octstr_destroy_item);
- }
- static void handle_enquire(Octstr *packet, Octstr *out, int sequence) {
- Octstr *dest_addr = eat_string_parm(packet, 21, 20);
- Octstr *timestamp = eat_string_parm(packet, 60, 12);
- if (logging == LOG_packets)
- printf("RCV: Enquire status, dest='%s', time='%s'n",
- dest_addr ? octstr_get_cstr(dest_addr) : "",
- timestamp ? octstr_get_cstr(timestamp) : "");
- if (!dest_addr) {
- send_error(out, 54, sequence, "400", "no destination");
- } else if (!timestamp) {
- send_error(out, 54, sequence, "401", "no timestamp");
- } else {
- if (logging == LOG_packets)
- printf("SND: Respond: status unknownn");
- send_packet(out, 54, sequence,
- 21, octstr_get_cstr(dest_addr),
- 60, octstr_get_cstr(timestamp),
- 61, "0",
- 0);
- }
- octstr_destroy(dest_addr);
- octstr_destroy(timestamp);
- }
- static void handle_delivery_request(Octstr *packet, Octstr *out, int sequence) {
- long mode = eat_int_parm(packet, 68, 1);
- if (logging == LOG_packets) {
- switch (mode) {
- case 0: printf("RCV: Delivery request, messages waiting?n");
- break;
- case 1: printf("RCV: Delivery request, one messagen");
- break;
- case 2: printf("RCV: Delivery request, all messagesn");
- break;
- case INT_MIN:
- printf("RCV: Delivery request, no moden");
- break;
- default:
- printf("RCV: Delivery request, mode %ldn", mode);
- }
- }
- if (mode == INT_MIN)
- mode = 1;
- switch (mode) {
- case 0:
- if (logging == LOG_packets)
- printf("SND: Respond: 0 messagesn");
- send_packet(out, 55, sequence,
- 66, "0",
- 0);
- break;
- case 1:
- send_error(out, 55, sequence, "500", "no messages available");
- break;
- case 2:
- send_error(out, 55, sequence, "500", "no messages available");
- break;
- default:
- send_error(out, 55, sequence, "501", "bad mode");
- break;
- }
- }
- static void handle_cancel(Octstr *packet, Octstr *out, int sequence) {
- long mode = eat_int_parm(packet, 59, 1);
- Octstr *timestamp = eat_string_parm(packet, 60, 12);
- Octstr *destination = eat_string_parm(packet, 21, 20);
- if (logging == LOG_packets) {
- printf("RCV: Cancel");
- if (mode != INT_MIN)
- printf(", mode %ld", mode);
- if (destination)
- printf(", dest '%s'", octstr_get_cstr(destination));
- if (timestamp)
- printf(", time '%s'", octstr_get_cstr(timestamp));
- printf("n");
- }
- if (mode < 0 || mode > 2)
- send_error(out, 56, sequence, "602", "bad mode");
- else {
- if (logging == LOG_packets)
- printf("SND: OKn");
- send_packet(out, 56, sequence, 0);
- }
- }
- static void handle_set(Octstr *packet, Octstr *out, int sequence) {
- Octstr *pass = eat_string_parm(packet, 11, 32);
- if (pass) {
- if (logging == LOG_packets)
- printf("RCV: Set password to '%s'n",
- octstr_get_cstr(pass));
- send_error(out, 58, sequence,
- "801", "changing password not allowed");
- } else {
- if (logging == LOG_packets)
- printf("RCV: Set, unknown parametersn");
- send_error(out, 58, sequence, "3", "cannot set");
- }
- }
- static void handle_get(Octstr *packet, Octstr *out, int sequence) {
- long number = eat_int_parm(packet, 500, 3);
- if (logging == LOG_packets)
- printf("RCV: Get parameter #%ldn", number);
- if (number == INT_MIN) {
- send_error(out, 59, sequence, "900", "missing parameter");
- } else if (number == 501) {
- unsigned char buf[TIMESTAMP_MAXLEN];
- make_timestamp(buf, time(NULL));
- if (logging == LOG_packets)
- printf("SND: OK, SMSC timestamp is '%s'n", buf);
- send_packet(out, 59, sequence,
- 501, buf,
- 0);
- } else {
- send_error(out, 59, sequence, "900", "unknown parameter");
- }
- }
- static void handle_alive(Octstr *packet, Octstr *out, int sequence) {
- if (logging == LOG_packets)
- printf("RCV: Alive?n");
- if (logging == LOG_packets)
- printf("SND: Alive.n");
- send_packet(out, 90, sequence, 0);
- }
- static void handle_deliver_response(Octstr *packet, Octstr *out, int sequence) {
- awaiting_response = 0;
- if (logging == LOG_packets)
- printf("RCV: Deliver responsen");
- deliveries++;
- if (max_deliveries > 0 && deliveries == max_deliveries) {
- time_t elapsed = time(NULL) - start_time;
- printf("LOG: %ld deliveries in %ld secondsn",
- (long) max_deliveries, (long) elapsed);
- }
- /* No need to respond to a response */
- }
- static void handle_deliver_status_report_response(Octstr *packet, Octstr *out, int sequence) {
- awaiting_response = 0;
- if (logging == LOG_packets)
- printf("RCV: Deliver status report responsen");
- /* No need to respond to a response */
- }
- static void handle_alive_response(Octstr *packet, Octstr *out, int sequence) {
- awaiting_response = 0;
- if (logging == LOG_packets)
- printf("RCV: Alive.n");
- /* No need to respond to a response */
- }
- static void handle_nack(Octstr *packet, Octstr *out, int sequence) {
- awaiting_response = 0;
- if (logging == LOG_packets)
- printf("RCV: NACKn");
- /* TODO: We should retransmit if we get a nack, but there's
- * no record of what request we sent. */
- }
- typedef void (*packet_handler)(Octstr *, Octstr *, int);
- struct {
- int opcode;
- packet_handler handler;
- } handlers[] = {
- { 1, handle_login },
- { 2, handle_logout },
- { 3, handle_submit },
- { 4, handle_enquire },
- { 5, handle_delivery_request },
- { 6, handle_cancel },
- { 8, handle_set },
- { 9, handle_get },
- { 40, handle_alive },
- { 70, handle_deliver_response },
- { 73, handle_deliver_status_report_response },
- { 90, handle_alive_response },
- { 99, handle_nack },
- { -1, NULL },
- };
- static void parse_packet(Octstr *packet, Octstr *out) {
- int opcode, sequence;
- int i;
- eat_checksum(packet);
- opcode = eat_number(packet);
- if (opcode < 0 || eat_char(packet, ':') < 0)
- return;
- sequence = eat_number(packet);
- if (sequence < 0)
- return;
- for (i = 0; handlers[i].opcode >= 0; i++) {
- if (handlers[i].opcode == opcode) {
- (handlers[i].handler)(packet, out, sequence);
- break;
- }
- }
- if (handlers[i].opcode < 0) { /* Loop failed */
- if (logging == LOG_packets)
- printf("RCV: unknown operation %ldn",
- (long) handlers[i].opcode);
- send_error(out, 98, sequence, "1", "unexpected operation");
- }
- }
- /* Parse the data stream for packets, and send out replies. */
- static void parse_data(Octstr *in, Octstr *out) {
- int stx, etx;
- Octstr *packet;
- for (;;) {
- /* Look for start of packet. Delete everything up to the start
- * marker. (CIMD2 section 3.1 says we can ignore any data
- * transmitted between packets.) */
- stx = octstr_search_char(in, STX, 0);
- if (stx < 0)
- octstr_delete(in, 0, octstr_len(in));
- else if (stx > 0)
- octstr_delete(in, 0, stx);
- etx = octstr_search_char(in, ETX, 0);
- if (etx < 0)
- return; /* Incomplete packet; wait for more data. */
- /* Copy the data between stx and etx */
- packet = octstr_copy(in, 1, etx - 1);
- /* Then cut the packet (including stx and etx) from inbuffer */
- octstr_delete(in, 0, etx + 1);
- parse_packet(packet, out);
- octstr_destroy(packet);
- }
- }
- static void random_address(unsigned char *buf, int size) {
- int len = random() % size;
- while (len--) {
- *buf++ = '0' + random() % 10;
- }
- *buf++ = ' ';
- }
- static void random_message(unsigned char *buf, int size) {
- int len = random() % size;
- while (len--) {
- do {
- *buf = random() % 256;
- } while (*buf == STX || *buf == ETX || *buf == TAB);
- buf++;
- }
- *buf++ = ' ';
- }
- static void random_hex(unsigned char *buf, int size) {
- int len = random() % size;
- /* Make even */
- len -= (len % 2);
- while (len--) {
- int c = random() % 16;
- if (c < 10)
- *buf++ = c + '0';
- else
- *buf++ = c - 10 + 'a';
- }
- *buf++ = ' ';
- }
- static void gen_message(Octstr *out) {
- static int send_seq = 0;
- unsigned char dest[21];
- unsigned char orig[21];
- unsigned char scts[TIMESTAMP_MAXLEN];
- unsigned char message[481];
- unsigned char udh[281];
- if (awaiting_response == 1)
- return;
- random_address(dest, sizeof(dest));
- random_address(orig, sizeof(orig));
- make_timestamp(scts, time(NULL));
- random_message(message, sizeof(message));
- if (random() % 2 == 0)
- random_hex(udh, sizeof(udh));
- else
- *udh = 0;
- if (logging == LOG_packets)
- printf("SND: Deliver message (random)n");
- if (*udh) {
- send_packet(out, 20, send_seq,
- 21, dest,
- 23, orig,
- 60, scts,
- 32, udh,
- 33, message,
- 0);
- } else {
- send_packet(out, 20, send_seq,
- 21, dest,
- 23, orig,
- 60, scts,
- 33, message,
- 0);
- }
- send_seq += 2;
- if (send_seq > 255)
- send_seq = 0;
- awaiting_response = 1;
- }
- /************************** CIMD 2 specific code ends ************************/
- static void main_loop(void) {
- fd_set readfds, writefds;
- int n;
- static int reported_outfull = 0;
- int interval = -1;
- inbuffer = octstr_create("");
- outbuffer = octstr_create(intro);
- start_time = time(NULL);
- for (;;) {
- if (octstr_len(outbuffer) < OUTBUFFER_LIMIT) {
- interval = gen_data(outbuffer);
- } else if (!reported_outfull) {
- warning(0, "outbuffer getting full; waiting...");
- reported_outfull = 1;
- }
- FD_ZERO(&readfds);
- FD_SET(sockfd, &readfds);
- if (octstr_len(outbuffer) > 0) {
- FD_ZERO(&writefds);
- FD_SET(sockfd, &writefds);
- n = select(sockfd+1, &readfds, &writefds, NULL, NULL);
- } else {
- struct timeval tv;
- struct timeval *tvp;
- if (interval >= 0) {
- tv.tv_sec = 0;
- tv.tv_usec = interval;
- tvp = &tv;
- } else {
- tvp = NULL;
- }
- n = select(sockfd+1, &readfds, NULL, NULL, tvp);
- }
- if (n < 0) {
- if (errno == EINTR) {
- warning(errno, "main loop, select");
- continue;
- }
- error(errno, "main loop, select");
- sleep(1);
- continue;
- }
- if (n > 0) {
- if (FD_ISSET(sockfd, &readfds)) {
- read_data(inbuffer, sockfd);
- parse_data(inbuffer, outbuffer);
- }
- if (octstr_len(outbuffer) > 0 &&
- FD_ISSET(sockfd, &writefds)) {
- write_data(outbuffer, sockfd);
- }
- if (octstr_len(outbuffer) < OUTBUFFER_LIMIT) {
- reported_outfull = 0;
- }
- }
- }
- }
- static struct {
- unsigned char *option;
- void *location;
- int number;
- } options[] = {
- { "--user", &username, 0 },
- { "--password", &password, 0 },
- { "--port", &port, 1 },
- { "--intro", &intro, 0 },
- { "--activity", &activity, 1 },
- { "--spew", &spew, 1 },
- { "--logging", &logging, 1 },
- { "--checking", &checking, 1 },
- { "--max", &max_deliveries, 1 },
- { NULL, NULL, 0 },
- };
- static int wait_for_client(int port) {
- struct sockaddr_in sin;
- socklen_t addrlen;
- int listenfd;
- int clientfd;
- Octstr *addr;
- listenfd = make_server_socket(port, NULL);
- if (listenfd < 0) {
- fprintf(stderr, "%s: failed to open socket at port %dn",
- progname, port);
- exit(1);
- }
- do {
- addrlen = sizeof(sin);
- clientfd = accept(listenfd, (struct sockaddr *)&sin, &addrlen);
- if (clientfd < 0) {
- error(errno, "failed to accept new connection");
- }
- } while (clientfd < 0);
- if (socket_set_blocking(clientfd, 0) < 0) {
- panic(0, "failed to make client socket nonblocking");
- }
- addr = gw_netaddr_to_octstr(AF_INET, &sin.sin_addr);
- info(0, "Accepted client from %s:%d",
- octstr_get_cstr(addr), ntohs(sin.sin_port));
- octstr_destroy(addr);
- close(listenfd);
- return clientfd;
- }
- int main(int argc, char *argv[]) {
- int i;
- int opt;
- gwlib_init();
- progname = argv[0];
- srandom(0); /* Make "random" data reproducible */
- for (i = 1; i < argc; i++) {
- for (opt = 0; options[opt].option; opt++) {
- if (strcmp(argv[i], options[opt].option) == 0) {
- if (i + 1 >= argc) {
- fprintf(stderr, "%s: missing argument to %s",
- progname, argv[i]);
- exit(2);
- }
- if (options[opt].number) {
- * (int *) options[opt].location = atoi(argv[i+1]);
- } else {
- * (char **) options[opt].location = argv[i+1];
- }
- i++;
- break;
- }
- }
- if (options[opt].option)
- continue;
- if (strcmp(argv[i], "--help") == 0) {
- usage(stdout);
- exit(0);
- }
- if (argv[i][0] == '-') {
- fprintf(stderr, "%s: unknown option %sn",
- progname, argv[i]);
- usage(stderr);
- exit(2);
- }
- }
- sockfd = wait_for_client(port);
- main_loop();
- return 0;
- }