86 #include <sys/types.h> 88 #include <sys/socket.h> 89 #include <netinet/in.h> 90 #include <arpa/inet.h> 168 fprintf(out,
"Usage: %s [options...]\n" 169 " --help Print this message\n" 170 " --user USER Allow clients to log in with username USER (default %s)\n" 171 " --password PASS Allow clients to log in with password PASS (default %s)\n" 172 " --intro INTRO Send INTRO string before anything else (default nothing)\n" 173 " --port PORT TCP port to listen on (default %d)\n" 174 " --activity ACT Activity level of test server (default %d)\n" 175 " ACT = 0 send nothing, just listen\n" 176 " ACT = 1 send valid replies, do not initiate any transactions\n" 177 " ACT = 2 attempt to deliver a random SMS every few seconds (NI)\n" 178 " ACT = 3 deliver many random SMSes, measure throughput (NI)\n" 179 " --spew SPEW Flood client, overrides --activity (default %d)\n" 180 " SPEW = 0 don't spew, use --activity instead\n" 181 " SPEW = 1 spew random binary gunk at client\n" 182 " SPEW = 2 spew random data of the right character set at client (NI)\n" 183 " SPEW = 3 spew valid packets with random contents at client (NI)\n" 184 " --logging LOG Log level of test server (default %d)\n" 185 " LOG = 0 log nothing\n" 186 " LOG = 1 log all data\n" 187 " LOG = 2 log summaries of valid packets\n" 188 " LOG = 3 log successfully sent and received SMSes (NI)\n" 189 " --checking CHK Check level of test server (default %d)\n" 190 " CHK = 0 check nothing\n" 191 " CHK = 1 signal invalid packets (NI)\n" 192 " CHK = 2 signal checksum errors (NI)\n" 193 " CHK = 3 signal protocol errors (NI)\n" 194 " CHK = 4 signal invalid SMS contents (NI)\n" 195 " --max MAX With high activity values, stop after MAX deliveries\n" 196 " NI means Not Implemented\n" 205 for (i = 0; i < length; i++) {
214 case TAB: fputs(
"<TAB>", stdout);
break;
215 case LF: fputs(
"<LF>\n", stdout);
break;
216 case CR: fputs(
"<CR>", stdout);
break;
217 case STX: fputs(
"<STX>", stdout);
break;
218 case ETX: fputs(
"<ETX>\n", stdout);
break;
228 ret = read(fd, buf,
sizeof(buf));
233 }
else if (ret == 0) {
234 fprintf(stderr,
"Client closed socket\n");
237 if (errno == EINTR || errno == EAGAIN)
239 error(errno,
"read_data");
255 ret = write(fd, buf, len);
260 }
else if (ret == 0) {
263 if (errno == EINTR || errno == EAGAIN)
265 error(errno,
"write_data");
288 while (last_sms < now) {
305 for (i = 0; i <
sizeof(buf); i++) {
324 sprintf(buf,
"%02d%02d%02d%02d%02d%02d",
325 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
326 tm.tm_hour, tm.tm_min, tm.tm_sec);
333 unsigned char *value;
335 int old_len, new_len;
344 va_start(ap, sequence);
345 for (
parm = va_arg(ap,
int);
parm != 0;
parm = va_arg(ap,
int)) {
346 value = va_arg(ap,
unsigned char *);
353 for (new_len =
octstr_len(out); old_len < new_len; old_len++) {
361 unsigned char *errorcode,
unsigned char *errortext) {
363 printf(
"SND: ERROR, %s\n", errortext);
377 long start, datastart;
442 if (isxdigit(ch3) && isxdigit(ch2) && ch1 ==
TAB)
456 printf(
"RCV: Login user '%s', password '%s'\n",
462 printf(
"SND: Login OK\n");
465 send_error(out, 51, sequence,
"100",
"invalid login");
474 printf(
"RCV: Logout\n");
476 printf(
"SND: Logout OK\n");
507 for (i = 0; i <
gwlist_len(other_dests); i++) {
516 printf(
" Data coding: %ld\n", DCS);
518 printf(
" User data header: %s\n",
523 printf(
" Text (binary): %s\n",
525 if (valid_rel > INT_MIN)
526 printf(
" Validity period: %ld (relative)\n",
529 printf(
" Validity period: %s (absolute)\n",
531 if (proto_id > INT_MIN)
532 printf(
" Protocol ID: %ld\n", proto_id);
533 if (delivery_rel > INT_MIN)
534 printf(
" First delivery: %ld (relative)\n",
537 printf(
" First delivery: %s (absolute)\n",
540 printf(
" Reply path disabled\n");
541 else if (reply_path == 1)
542 printf(
" Reply path enabled\n");
543 else if (reply_path > INT_MAX)
544 printf(
" Reply path: %ld\n", reply_path);
546 printf(
" Status report flags: %ld\n", SRR);
548 printf(
" Cancel disabled\n");
549 else if (cancel == 1)
550 printf(
" Cancel enabled\n");
551 else if (cancel > INT_MAX)
552 printf(
" Cancel enabled: %ld\n", cancel);
553 if (tariff_class > INT_MAX)
554 printf(
" Tariff class: %ld\n", tariff_class);
555 if (service_desc > INT_MAX)
556 printf(
" Service description: %ld\n", service_desc);
557 if (priority > INT_MAX)
558 printf(
" Priority: %ld\n", priority);
562 send_error(out, 53, sequence,
"300",
"no destination");
564 send_error(out, 53, sequence,
"301",
"too many destinations");
571 printf(
"SND: Submit OK\n");
593 printf(
"RCV: Enquire status, dest='%s', time='%s'\n",
598 send_error(out, 54, sequence,
"400",
"no destination");
599 }
else if (!timestamp) {
600 send_error(out, 54, sequence,
"401",
"no timestamp");
603 printf(
"SND: Respond: status unknown\n");
619 case 0: printf(
"RCV: Delivery request, messages waiting?\n");
621 case 1: printf(
"RCV: Delivery request, one message\n");
623 case 2: printf(
"RCV: Delivery request, all messages\n");
626 printf(
"RCV: Delivery request, no mode\n");
629 printf(
"RCV: Delivery request, mode %ld\n", mode);
639 printf(
"SND: Respond: 0 messages\n");
646 send_error(out, 55, sequence,
"500",
"no messages available");
650 send_error(out, 55, sequence,
"500",
"no messages available");
654 send_error(out, 55, sequence,
"501",
"bad mode");
665 printf(
"RCV: Cancel");
667 printf(
", mode %ld", mode);
675 if (mode < 0 || mode > 2)
676 send_error(out, 56, sequence,
"602",
"bad mode");
690 printf(
"RCV: Set password to '%s'\n",
693 "801",
"changing password not allowed");
696 printf(
"RCV: Set, unknown parameters\n");
697 send_error(out, 58, sequence,
"3",
"cannot set");
706 printf(
"RCV: Get parameter #%ld\n",
number);
709 send_error(out, 59, sequence,
"900",
"missing parameter");
710 }
else if (
number == 501) {
714 printf(
"SND: OK, SMSC timestamp is '%s'\n", buf);
719 send_error(out, 59, sequence,
"900",
"unknown parameter");
725 printf(
"RCV: Alive?\n");
727 printf(
"SND: Alive.\n");
734 printf(
"RCV: Deliver response\n");
738 printf(
"LOG: %ld deliveries in %ld seconds\n",
747 printf(
"RCV: Deliver status report response\n");
754 printf(
"RCV: Alive.\n");
761 printf(
"RCV: NACK\n");
801 for (i = 0;
handlers[i].opcode >= 0; i++) {
810 printf(
"RCV: unknown operation %ld\n",
812 send_error(out, 98, sequence,
"1",
"unexpected operation");
850 *buf++ =
'0' +
random() % 10;
862 }
while (*buf ==
STX || *buf ==
ETX || *buf ==
TAB);
880 *buf++ = c - 10 +
'a';
887 static int send_seq = 0;
888 unsigned char dest[21];
889 unsigned char orig[21];
891 unsigned char message[481];
892 unsigned char udh[281];
907 printf(
"SND: Deliver message (random)\n");
936 fd_set readfds, writefds;
938 static int reported_outfull = 0;
948 }
else if (!reported_outfull) {
949 warning(0,
"outbuffer getting full; waiting...");
950 reported_outfull = 1;
958 FD_SET(
sockfd, &writefds);
959 n = select(
sockfd+1, &readfds, &writefds, NULL, NULL);
971 n = select(
sockfd+1, &readfds, NULL, NULL, tvp);
975 if (errno == EINTR) {
976 warning(errno,
"main loop, select");
979 error(errno,
"main loop, select");
984 if (FD_ISSET(
sockfd, &readfds)) {
989 FD_ISSET(
sockfd, &writefds)) {
993 reported_outfull = 0;
1006 {
"--port", &
port, 1 },
1007 {
"--intro", &
intro, 0 },
1009 {
"--spew", &
spew, 1 },
1017 struct sockaddr_in sin;
1025 fprintf(stderr,
"%s: failed to open socket at port %d\n",
1031 addrlen =
sizeof(sin);
1032 clientfd = accept(listenfd, (
struct sockaddr *)&sin, &addrlen);
1034 error(errno,
"failed to accept new connection");
1036 }
while (clientfd < 0);
1039 panic(0,
"failed to make client socket nonblocking");
1043 info(0,
"Accepted client from %s:%d",
1062 for (i = 1; i < argc; i++) {
1063 for (opt = 0;
options[opt].option; opt++) {
1065 if (i + 1 >= argc) {
1066 fprintf(stderr,
"%s: missing argument to %s",
1081 if (strcmp(argv[i],
"--help") == 0) {
1085 if (argv[i][0] ==
'-') {
1086 fprintf(stderr,
"%s: unknown option %s\n",
void error(int err, const char *fmt,...)
void info(int err, const char *fmt,...)
static long eat_int_parm(Octstr *packet, int parm, int maxlen)
int socket_set_blocking(int fd, int blocking)
void(* packet_handler)(Octstr *, Octstr *, int)
static long gen_data(Octstr *out)
void octstr_append_data(Octstr *ostr, const char *data, long len)
static void handle_deliver_status_report_response(Octstr *packet, Octstr *out, int sequence)
void gwlist_append(List *list, void *item)
struct tm gw_gmtime(time_t t)
long gwlist_len(List *list)
void * gwlist_get(List *list, long pos)
static long eat_number(Octstr *ostr)
static void send_packet(Octstr *out, int opcode, int sequence,...)
long octstr_search(const Octstr *haystack, const Octstr *needle, long pos)
static void handle_delivery_request(Octstr *packet, Octstr *out, int sequence)
static void main_loop(void)
static void handle_submit(Octstr *packet, Octstr *out, int sequence)
#define octstr_get_cstr(ostr)
#define octstr_copy(ostr, from, len)
long octstr_search_char(const Octstr *ostr, int ch, long pos)
static int eat_char(Octstr *packet, int ch)
static void parse_packet(Octstr *packet, Octstr *out)
static void handle_logout(Octstr *packet, Octstr *out, int sequence)
static void random_hex(unsigned char *buf, int size)
void octstr_delete(Octstr *ostr1, long pos, long len)
static void handle_nack(Octstr *packet, Octstr *out, int sequence)
static void handle_login(Octstr *packet, Octstr *out, int sequence)
static void eat_checksum(Octstr *packet)
Octstr * gw_netaddr_to_octstr(int af, void *src)
static void read_data(Octstr *in, int fd)
static void handle_alive(Octstr *packet, Octstr *out, int sequence)
int main(int argc, char *argv[])
int make_server_socket(int port, const char *interface_name)
void warning(int err, const char *fmt,...)
Octstr * octstr_format(const char *fmt,...)
void octstr_destroy(Octstr *ostr)
#define octstr_create(cstr)
void octstr_destroy_item(void *os)
static void pretty_print(unsigned char *data, size_t length)
static void handle_set(Octstr *packet, Octstr *out, int sequence)
static void parse_data(Octstr *in, Octstr *out)
static void write_data(Octstr *out, int fd)
static void random_address(unsigned char *buf, int size)
static void gen_message(Octstr *out)
long octstr_len(const Octstr *ostr)
static void make_timestamp(unsigned char *buf, time_t fortime)
static void random_message(unsigned char *buf, int size)
static void handle_alive_response(Octstr *packet, Octstr *out, int sequence)
static struct @78 options[]
static Octstr * eat_string_parm(Octstr *packet, int parm, int maxlen)
static void handle_get(Octstr *packet, Octstr *out, int sequence)
static void handle_deliver_response(Octstr *packet, Octstr *out, int sequence)
int octstr_str_compare(const Octstr *ostr, const char *str)
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
void octstr_format_append(Octstr *os, const char *fmt,...)
static void send_error(Octstr *out, int opcode, int sequence, unsigned char *errorcode, unsigned char *errortext)
static void handle_cancel(Octstr *packet, Octstr *out, int sequence)
static void handle_enquire(Octstr *packet, Octstr *out, int sequence)
static int wait_for_client(int port)
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
int octstr_get_char(const Octstr *ostr, long pos)
static void usage(FILE *out)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)