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)