#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"Include dependency graph for test_cimd2.c:

Go to the source code of this file.
Typedefs | |
| typedef void(* | packet_handler )(Octstr *, Octstr *, int) |
Enumerations | |
| enum | { TIMESTAMP_MAXLEN = 13 } |
| 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 } |
| enum | { OUTBUFFER_LIMIT = 65536 } |
| enum | { EVIL_BUFSIZE = 1021 } |
| enum | CHARS { STX = 2, ETX = 3, TAB = 9, LF = 10, CR = 13 } |
Functions | |
| void | usage (FILE *out) |
| void | pretty_print (unsigned char *data, size_t length) |
| void | read_data (Octstr *in, int fd) |
| void | write_data (Octstr *out, int fd) |
| void | gen_message (Octstr *out) |
| long | gen_data (Octstr *out) |
| void | make_timestamp (unsigned char *buf, time_t fortime) |
| void | send_packet (Octstr *out, int opcode, int sequence,...) |
| void | send_error (Octstr *out, int opcode, int sequence, unsigned char *errorcode, unsigned char *errortext) |
| int | eat_char (Octstr *packet, int ch) |
| Octstr * | eat_string_parm (Octstr *packet, int parm, int maxlen) |
| long | eat_number (Octstr *ostr) |
| long | eat_int_parm (Octstr *packet, int parm, int maxlen) |
| void | eat_checksum (Octstr *packet) |
| void | handle_login (Octstr *packet, Octstr *out, int sequence) |
| void | handle_logout (Octstr *packet, Octstr *out, int sequence) |
| void | handle_submit (Octstr *packet, Octstr *out, int sequence) |
| void | handle_enquire (Octstr *packet, Octstr *out, int sequence) |
| void | handle_delivery_request (Octstr *packet, Octstr *out, int sequence) |
| void | handle_cancel (Octstr *packet, Octstr *out, int sequence) |
| void | handle_set (Octstr *packet, Octstr *out, int sequence) |
| void | handle_get (Octstr *packet, Octstr *out, int sequence) |
| void | handle_alive (Octstr *packet, Octstr *out, int sequence) |
| void | handle_deliver_response (Octstr *packet, Octstr *out, int sequence) |
| void | handle_deliver_status_report_response (Octstr *packet, Octstr *out, int sequence) |
| void | handle_alive_response (Octstr *packet, Octstr *out, int sequence) |
| void | handle_nack (Octstr *packet, Octstr *out, int sequence) |
| void | parse_packet (Octstr *packet, Octstr *out) |
| void | parse_data (Octstr *in, Octstr *out) |
| void | random_address (unsigned char *buf, int size) |
| void | random_message (unsigned char *buf, int size) |
| void | random_hex (unsigned char *buf, int size) |
| void | main_loop (void) |
| int | wait_for_client (int port) |
| int | main (int argc, char *argv[]) |
Variables | |
| unsigned char * | progname |
| unsigned char * | username = "foo" |
| unsigned char * | password = "bar" |
| int | port = 6789 |
| unsigned char * | intro = "" |
| 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 |
| int | awaiting_response = 0 |
| struct { | |
| int opcode | |
| packet_handler handler | |
| } | handlers [] |
| struct { | |
| unsigned char * option | |
| void * location | |
| int number | |
| } | options [] |
|
|
Definition at line 766 of file test_cimd2.c. |
|
|
Definition at line 94 of file test_cimd2.c. 00094 { TIMESTAMP_MAXLEN = 13 };
|
|
|
Definition at line 151 of file test_cimd2.c. 00151 { OUTBUFFER_LIMIT = 65536 };
|
|
|
Definition at line 156 of file test_cimd2.c. 00156 { EVIL_BUFSIZE = 1021 };
|
|
|
Definition at line 107 of file test_cimd2.c. 00107 {
00108 ACT_listen = 0,
00109 ACT_reply = 1,
00110 ACT_deliver = 2,
00111 ACT_flood = 3
00112 };
|
|
|
Definition at line 159 of file test_cimd2.c.
|
|
|
Definition at line 128 of file test_cimd2.c. 00128 {
00129 CHK_nothing = 0,
00130 CHK_packets = 1,
00131 CHK_sums = 2,
00132 CHK_protocol = 3,
00133 CHK_sms = 4
00134 };
|
|
|
Definition at line 121 of file test_cimd2.c. 00121 {
00122 LOG_nothing = 0,
00123 LOG_data = 1,
00124 LOG_packets = 2,
00125 LOG_sms = 3
00126 };
|
|
|
Definition at line 114 of file test_cimd2.c. 00114 {
00115 SPEW_nothing = 0,
00116 SPEW_binary = 1,
00117 SPEW_characters = 2,
00118 SPEW_packets = 3
00119 };
|
|
||||||||||||
|
Definition at line 368 of file test_cimd2.c. References octstr_delete(), and octstr_get_char(). Referenced by parse_packet(). 00368 {
00369 if (octstr_get_char(packet, 0) == ch) {
00370 octstr_delete(packet, 0, 1);
00371 return 0;
00372 }
00373 return -1;
00374 }
|
Here is the call graph for this function:

|
|
Definition at line 429 of file test_cimd2.c. References octstr_delete(), octstr_get_char(), and octstr_len(). Referenced by parse_packet(). 00429 {
00430 int len;
00431 int ch1, ch2, ch3;
00432
00433 len = octstr_len(packet);
00434
00435 if (len < 3)
00436 return;
00437
00438 ch1 = octstr_get_char(packet, len - 3);
00439 ch2 = octstr_get_char(packet, len - 2);
00440 ch3 = octstr_get_char(packet, len - 1);
00441
00442 if (isxdigit(ch3) && isxdigit(ch2) && ch1 == TAB)
00443 octstr_delete(packet, len - 3, 3);
00444 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 413 of file test_cimd2.c. References eat_number(), eat_string_parm(), maxlen, octstr_destroy(), octstr_len(), and result. Referenced by handle_cancel(), handle_delivery_request(), handle_get(), and handle_submit(). 00413 {
00414 Octstr *value;
00415 long result;
00416
00417 value = eat_string_parm(packet, parm, maxlen);
00418 if (!value)
00419 return INT_MIN;
00420
00421 result = eat_number(value);
00422 if (octstr_len(value) > 0)
00423 result = INT_MIN;
00424
00425 octstr_destroy(value);
00426 return result;
00427 }
|
Here is the call graph for this function:

|
|
Definition at line 401 of file test_cimd2.c. References octstr_delete(), octstr_parse_long(), and result. Referenced by eat_int_parm(), and parse_packet(). 00401 {
00402 long result;
00403 long pos;
00404
00405 pos = octstr_parse_long(&result, ostr, 0, 10);
00406 if (pos < 0)
00407 return INT_MIN;
00408
00409 octstr_delete(ostr, 0, pos);
00410 return result;
00411 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 376 of file test_cimd2.c. References octstr_copy, octstr_delete(), octstr_destroy(), octstr_format(), octstr_len(), octstr_search(), octstr_search_char(), result, and TAB. Referenced by eat_int_parm(), handle_cancel(), handle_enquire(), handle_login(), handle_set(), and handle_submit(). 00376 {
00377 long start, datastart;
00378 long tab;
00379 Octstr *result;
00380 Octstr *parmheader;
00381
00382 parmheader = octstr_format("%c%03d:", TAB, parm);
00383 start = octstr_search(packet, parmheader, 0);
00384 if (start < 0) {
00385 octstr_destroy(parmheader);
00386 return NULL;
00387 }
00388 datastart = start + octstr_len(parmheader);
00389
00390 tab = octstr_search_char(packet, TAB, datastart + 1);
00391 if (tab < 0) {
00392 tab = octstr_len(packet);
00393 }
00394
00395 result = octstr_copy(packet, datastart, tab - datastart);
00396 octstr_delete(packet, start, tab - start);
00397 octstr_destroy(parmheader);
00398 return result;
00399 }
|
Here is the call graph for this function:

|
|
Definition at line 275 of file test_cimd2.c. References ACT_deliver, ACT_flood, deliveries, gen_message(), interval, max_deliveries, octstr_append_data(), and SPEW_binary. Referenced by main_loop(). 00275 {
00276 unsigned char buf[EVIL_BUFSIZE];
00277 size_t i;
00278 long interval = -1;
00279 static int last_sms; /* Used by ACT_deliver */
00280 time_t now;
00281
00282 if (max_deliveries < 0 || deliveries < max_deliveries) {
00283 switch (activity) {
00284 case ACT_deliver:
00285 now = time(NULL);
00286 if (last_sms == 0)
00287 last_sms = now;
00288 while (last_sms < now) {
00289 if (random() % 7 == 1) {
00290 gen_message(out);
00291 last_sms = now;
00292 } else
00293 last_sms++;
00294 }
00295 interval = 1000000;
00296 break;
00297 case ACT_flood:
00298 gen_message(out);
00299 break;
00300 }
00301 }
00302
00303 switch (spew) {
00304 case SPEW_binary:
00305 for (i = 0; i < sizeof(buf); i++) {
00306 buf[i] = random() % 256;
00307 }
00308 octstr_append_data(out, buf, sizeof(buf));
00309 break;
00310 }
00311
00312 return interval;
00313 }
|
Here is the call graph for this function:

|
|
Definition at line 886 of file test_cimd2.c. References awaiting_response, logging, make_timestamp(), message, random_address(), random_hex(), random_message(), and send_packet(). Referenced by gen_data(). 00886 {
00887 static int send_seq = 0;
00888 unsigned char dest[21];
00889 unsigned char orig[21];
00890 unsigned char scts[TIMESTAMP_MAXLEN];
00891 unsigned char message[481];
00892 unsigned char udh[281];
00893
00894 if (awaiting_response == 1)
00895 return;
00896
00897 random_address(dest, sizeof(dest));
00898 random_address(orig, sizeof(orig));
00899 make_timestamp(scts, time(NULL));
00900 random_message(message, sizeof(message));
00901 if (random() % 2 == 0)
00902 random_hex(udh, sizeof(udh));
00903 else
00904 *udh = 0;
00905
00906 if (logging == LOG_packets)
00907 printf("SND: Deliver message (random)\n");
00908
00909 if (*udh) {
00910 send_packet(out, 20, send_seq,
00911 21, dest,
00912 23, orig,
00913 60, scts,
00914 32, udh,
00915 33, message,
00916 0);
00917 } else {
00918 send_packet(out, 20, send_seq,
00919 21, dest,
00920 23, orig,
00921 60, scts,
00922 33, message,
00923 0);
00924 }
00925
00926 send_seq += 2;
00927 if (send_seq > 255)
00928 send_seq = 0;
00929
00930 awaiting_response = 1;
00931 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 723 of file test_cimd2.c. References logging, and send_packet(). 00723 {
00724 if (logging == LOG_packets)
00725 printf("RCV: Alive?\n");
00726 if (logging == LOG_packets)
00727 printf("SND: Alive.\n");
00728 send_packet(out, 90, sequence, 0);
00729 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 751 of file test_cimd2.c. References awaiting_response, and logging. 00751 {
00752 awaiting_response = 0;
00753 if (logging == LOG_packets)
00754 printf("RCV: Alive.\n");
00755 /* No need to respond to a response */
00756 }
|
|
||||||||||||||||
|
Definition at line 659 of file test_cimd2.c. References eat_int_parm(), eat_string_parm(), logging, octstr_get_cstr, send_error(), and send_packet(). 00659 {
00660 long mode = eat_int_parm(packet, 59, 1);
00661 Octstr *timestamp = eat_string_parm(packet, 60, 12);
00662 Octstr *destination = eat_string_parm(packet, 21, 20);
00663
00664 if (logging == LOG_packets) {
00665 printf("RCV: Cancel");
00666 if (mode != INT_MIN)
00667 printf(", mode %ld", mode);
00668 if (destination)
00669 printf(", dest '%s'", octstr_get_cstr(destination));
00670 if (timestamp)
00671 printf(", time '%s'", octstr_get_cstr(timestamp));
00672 printf("\n");
00673 }
00674
00675 if (mode < 0 || mode > 2)
00676 send_error(out, 56, sequence, "602", "bad mode");
00677 else {
00678 if (logging == LOG_packets)
00679 printf("SND: OK\n");
00680 send_packet(out, 56, sequence, 0);
00681 }
00682 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 731 of file test_cimd2.c. References awaiting_response, deliveries, logging, and max_deliveries. 00731 {
00732 awaiting_response = 0;
00733 if (logging == LOG_packets)
00734 printf("RCV: Deliver response\n");
00735 deliveries++;
00736 if (max_deliveries > 0 && deliveries == max_deliveries) {
00737 time_t elapsed = time(NULL) - start_time;
00738 printf("LOG: %ld deliveries in %ld seconds\n",
00739 (long) max_deliveries, (long) elapsed);
00740 }
00741 /* No need to respond to a response */
00742 }
|
|
||||||||||||||||
|
Definition at line 744 of file test_cimd2.c. References awaiting_response, and logging. 00744 {
00745 awaiting_response = 0;
00746 if (logging == LOG_packets)
00747 printf("RCV: Deliver status report response\n");
00748 /* No need to respond to a response */
00749 }
|
|
||||||||||||||||
|
Definition at line 614 of file test_cimd2.c. References eat_int_parm(), logging, send_error(), and send_packet(). 00614 {
00615 long mode = eat_int_parm(packet, 68, 1);
00616
00617 if (logging == LOG_packets) {
00618 switch (mode) {
00619 case 0: printf("RCV: Delivery request, messages waiting?\n");
00620 break;
00621 case 1: printf("RCV: Delivery request, one message\n");
00622 break;
00623 case 2: printf("RCV: Delivery request, all messages\n");
00624 break;
00625 case INT_MIN:
00626 printf("RCV: Delivery request, no mode\n");
00627 break;
00628 default:
00629 printf("RCV: Delivery request, mode %ld\n", mode);
00630 }
00631 }
00632
00633 if (mode == INT_MIN)
00634 mode = 1;
00635
00636 switch (mode) {
00637 case 0:
00638 if (logging == LOG_packets)
00639 printf("SND: Respond: 0 messages\n");
00640 send_packet(out, 55, sequence,
00641 66, "0",
00642 0);
00643 break;
00644
00645 case 1:
00646 send_error(out, 55, sequence, "500", "no messages available");
00647 break;
00648
00649 case 2:
00650 send_error(out, 55, sequence, "500", "no messages available");
00651 break;
00652
00653 default:
00654 send_error(out, 55, sequence, "501", "bad mode");
00655 break;
00656 }
00657 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 588 of file test_cimd2.c. References eat_string_parm(), logging, octstr_destroy(), octstr_get_cstr, send_error(), and send_packet(). 00588 {
00589 Octstr *dest_addr = eat_string_parm(packet, 21, 20);
00590 Octstr *timestamp = eat_string_parm(packet, 60, 12);
00591
00592 if (logging == LOG_packets)
00593 printf("RCV: Enquire status, dest='%s', time='%s'\n",
00594 dest_addr ? octstr_get_cstr(dest_addr) : "",
00595 timestamp ? octstr_get_cstr(timestamp) : "");
00596
00597 if (!dest_addr) {
00598 send_error(out, 54, sequence, "400", "no destination");
00599 } else if (!timestamp) {
00600 send_error(out, 54, sequence, "401", "no timestamp");
00601 } else {
00602 if (logging == LOG_packets)
00603 printf("SND: Respond: status unknown\n");
00604 send_packet(out, 54, sequence,
00605 21, octstr_get_cstr(dest_addr),
00606 60, octstr_get_cstr(timestamp),
00607 61, "0",
00608 0);
00609 }
00610 octstr_destroy(dest_addr);
00611 octstr_destroy(timestamp);
00612 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 702 of file test_cimd2.c. References eat_int_parm(), logging, make_timestamp(), number, send_error(), and send_packet(). 00702 {
00703 long number = eat_int_parm(packet, 500, 3);
00704
00705 if (logging == LOG_packets)
00706 printf("RCV: Get parameter #%ld\n", number);
00707
00708 if (number == INT_MIN) {
00709 send_error(out, 59, sequence, "900", "missing parameter");
00710 } else if (number == 501) {
00711 unsigned char buf[TIMESTAMP_MAXLEN];
00712 make_timestamp(buf, time(NULL));
00713 if (logging == LOG_packets)
00714 printf("SND: OK, SMSC timestamp is '%s'\n", buf);
00715 send_packet(out, 59, sequence,
00716 501, buf,
00717 0);
00718 } else {
00719 send_error(out, 59, sequence, "900", "unknown parameter");
00720 }
00721 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 446 of file test_cimd2.c. References eat_string_parm(), logging, octstr_create, octstr_destroy(), octstr_get_cstr, octstr_str_compare(), password, send_error(), send_packet(), and username. 00446 {
00447 Octstr *user = eat_string_parm(packet, 10, 32);
00448 Octstr *pass = eat_string_parm(packet, 11, 32);
00449
00450 if (user == NULL)
00451 user = octstr_create("");
00452 if (pass == NULL)
00453 pass = octstr_create("");
00454
00455 if (logging == LOG_packets)
00456 printf("RCV: Login user '%s', password '%s'\n",
00457 octstr_get_cstr(user), octstr_get_cstr(pass));
00458
00459 if (octstr_str_compare(user, username) == 0 &&
00460 octstr_str_compare(pass, password) == 0) {
00461 if (logging == LOG_packets)
00462 printf("SND: Login OK\n");
00463 send_packet(out, 51, sequence, 0);
00464 } else {
00465 send_error(out, 51, sequence, "100", "invalid login");
00466 }
00467
00468 octstr_destroy(user);
00469 octstr_destroy(pass);
00470 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 472 of file test_cimd2.c. References logging, and send_packet(). 00472 {
00473 if (logging == LOG_packets)
00474 printf("RCV: Logout\n");
00475 if (logging == LOG_packets)
00476 printf("SND: Logout OK\n");
00477 send_packet(out, 52, sequence, 0);
00478 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 758 of file test_cimd2.c. References awaiting_response, and logging. 00758 {
00759 awaiting_response = 0;
00760 if (logging == LOG_packets)
00761 printf("RCV: NACK\n");
00762 /* TODO: We should retransmit if we get a nack, but there's
00763 * no record of what request we sent. */
00764 }
|
|
||||||||||||||||
|
Definition at line 685 of file test_cimd2.c. References eat_string_parm(), logging, octstr_get_cstr, and send_error(). 00685 {
00686 Octstr *pass = eat_string_parm(packet, 11, 32);
00687
00688 if (pass) {
00689 if (logging == LOG_packets)
00690 printf("RCV: Set password to '%s'\n",
00691 octstr_get_cstr(pass));
00692 send_error(out, 58, sequence,
00693 "801", "changing password not allowed");
00694 } else {
00695 if (logging == LOG_packets)
00696 printf("RCV: Set, unknown parameters\n");
00697 send_error(out, 58, sequence, "3", "cannot set");
00698 }
00699 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 480 of file test_cimd2.c. References eat_int_parm(), eat_string_parm(), gwlist_append(), gwlist_create, gwlist_destroy(), gwlist_get(), gwlist_len(), logging, make_timestamp(), octstr_destroy(), octstr_destroy_item(), octstr_get_cstr, send_error(), send_packet(), and text. 00480 {
00481 Octstr *dest_addr = eat_string_parm(packet, 21, 20);
00482 Octstr *orig_addr = eat_string_parm(packet, 23, 20);
00483 long DCS = eat_int_parm(packet, 30, 3);
00484 Octstr *UDH = eat_string_parm(packet, 32, 280);
00485 Octstr *text = eat_string_parm(packet, 33, 480);
00486 Octstr *textb = eat_string_parm(packet, 34, 280);
00487 long valid_rel = eat_int_parm(packet, 50, 3);
00488 Octstr *valid_abs = eat_string_parm(packet, 51, 12);
00489 long proto_id = eat_int_parm(packet, 52, 3);
00490 long delivery_rel = eat_int_parm(packet, 53, 3);
00491 Octstr *delivery_abs = eat_string_parm(packet, 54, 12);
00492 long reply_path = eat_int_parm(packet, 55, 1);
00493 long SRR = eat_int_parm(packet, 56, 2);
00494 long cancel = eat_int_parm(packet, 58, 1);
00495 long tariff_class = eat_int_parm(packet, 64, 2);
00496 long service_desc = eat_int_parm(packet, 65, 1);
00497 long priority = eat_int_parm(packet, 67, 1);
00498 List *other_dests = gwlist_create();
00499 Octstr *tmp;
00500
00501 while ((tmp = eat_string_parm(packet, 21, 20)))
00502 gwlist_append(other_dests, tmp);
00503
00504 if (logging == LOG_packets) {
00505 int i;
00506 printf("RCV: Submit to %s", octstr_get_cstr(dest_addr));
00507 for (i = 0; i < gwlist_len(other_dests); i++) {
00508 printf(", %s",
00509 octstr_get_cstr(gwlist_get(other_dests, i)));
00510 }
00511 printf("\n");
00512
00513 if (orig_addr)
00514 printf(" From: %s\n", octstr_get_cstr(orig_addr));
00515 if (DCS > INT_MIN)
00516 printf(" Data coding: %ld\n", DCS);
00517 if (UDH)
00518 printf(" User data header: %s\n",
00519 octstr_get_cstr(UDH));
00520 if (text)
00521 printf(" Text: %s\n", octstr_get_cstr(text));
00522 if (textb)
00523 printf(" Text (binary): %s\n",
00524 octstr_get_cstr(textb));
00525 if (valid_rel > INT_MIN)
00526 printf(" Validity period: %ld (relative)\n",
00527 valid_rel);
00528 if (valid_abs)
00529 printf(" Validity period: %s (absolute)\n",
00530 octstr_get_cstr(valid_abs));
00531 if (proto_id > INT_MIN)
00532 printf(" Protocol ID: %ld\n", proto_id);
00533 if (delivery_rel > INT_MIN)
00534 printf(" First delivery: %ld (relative)\n",
00535 delivery_rel);
00536 if (delivery_abs)
00537 printf(" First delivery: %s (absolute)\n",
00538 octstr_get_cstr(delivery_abs));
00539 if (reply_path == 0)
00540 printf(" Reply path disabled\n");
00541 else if (reply_path == 1)
00542 printf(" Reply path enabled\n");
00543 else if (reply_path > INT_MAX)
00544 printf(" Reply path: %ld\n", reply_path);
00545 if (SRR > INT_MAX)
00546 printf(" Status report flags: %ld\n", SRR);
00547 if (cancel == 0)
00548 printf(" Cancel disabled\n");
00549 else if (cancel == 1)
00550 printf(" Cancel enabled\n");
00551 else if (cancel > INT_MAX)
00552 printf(" Cancel enabled: %ld\n", cancel);
00553 if (tariff_class > INT_MAX)
00554 printf(" Tariff class: %ld\n", tariff_class);
00555 if (service_desc > INT_MAX)
00556 printf(" Service description: %ld\n", service_desc);
00557 if (priority > INT_MAX)
00558 printf(" Priority: %ld\n", priority);
00559 }
00560
00561 if (!dest_addr) {
00562 send_error(out, 53, sequence, "300", "no destination");
00563 } else if (gwlist_len(other_dests) > 0) {
00564 send_error(out, 53, sequence, "301", "too many destinations");
00565 /* TODO: Report many other possible errors here */
00566 } else {
00567 unsigned char buf[TIMESTAMP_MAXLEN];
00568
00569 make_timestamp(buf, time(NULL));
00570 if (logging == LOG_packets)
00571 printf("SND: Submit OK\n");
00572 send_packet(out, 53, sequence,
00573 21, octstr_get_cstr(dest_addr),
00574 60, buf,
00575 0);
00576 }
00577
00578 octstr_destroy(dest_addr);
00579 octstr_destroy(orig_addr);
00580 octstr_destroy(UDH);
00581 octstr_destroy(text);
00582 octstr_destroy(textb);
00583 octstr_destroy(valid_abs);
00584 octstr_destroy(delivery_abs);
00585 gwlist_destroy(other_dests, octstr_destroy_item);
00586 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1053 of file test_cimd2.c. References gwlib_init(), main_loop(), option, options, port, progname, sockfd, usage(), and wait_for_client(). 01053 {
01054 int i;
01055 int opt;
01056
01057 gwlib_init();
01058
01059 progname = argv[0];
01060 srandom(0); /* Make "random" data reproducible */
01061
01062 for (i = 1; i < argc; i++) {
01063 for (opt = 0; options[opt].option; opt++) {
01064 if (strcmp(argv[i], options[opt].option) == 0) {
01065 if (i + 1 >= argc) {
01066 fprintf(stderr, "%s: missing argument to %s",
01067 progname, argv[i]);
01068 exit(2);
01069 }
01070 if (options[opt].number) {
01071 * (int *) options[opt].location = atoi(argv[i+1]);
01072 } else {
01073 * (char **) options[opt].location = argv[i+1];
01074 }
01075 i++;
01076 break;
01077 }
01078 }
01079 if (options[opt].option)
01080 continue;
01081 if (strcmp(argv[i], "--help") == 0) {
01082 usage(stdout);
01083 exit(0);
01084 }
01085 if (argv[i][0] == '-') {
01086 fprintf(stderr, "%s: unknown option %s\n",
01087 progname, argv[i]);
01088 usage(stderr);
01089 exit(2);
01090 }
01091 }
01092
01093 sockfd = wait_for_client(port);
01094 main_loop();
01095 return 0;
01096 }
|
Here is the call graph for this function:

|
|
Definition at line 935 of file test_cimd2.c. References error(), gen_data(), inbuffer, interval, intro, octstr_create, octstr_len(), outbuffer, parse_data(), read_data(), sockfd, start_time, warning(), and write_data(). Referenced by main(). 00935 {
00936 fd_set readfds, writefds;
00937 int n;
00938 static int reported_outfull = 0;
00939 int interval = -1;
00940
00941 inbuffer = octstr_create("");
00942 outbuffer = octstr_create(intro);
00943 start_time = time(NULL);
00944
00945 for (;;) {
00946 if (octstr_len(outbuffer) < OUTBUFFER_LIMIT) {
00947 interval = gen_data(outbuffer);
00948 } else if (!reported_outfull) {
00949 warning(0, "outbuffer getting full; waiting...");
00950 reported_outfull = 1;
00951 }
00952
00953 FD_ZERO(&readfds);
00954 FD_SET(sockfd, &readfds);
00955
00956 if (octstr_len(outbuffer) > 0) {
00957 FD_ZERO(&writefds);
00958 FD_SET(sockfd, &writefds);
00959 n = select(sockfd+1, &readfds, &writefds, NULL, NULL);
00960 } else {
00961 struct timeval tv;
00962 struct timeval *tvp;
00963
00964 if (interval >= 0) {
00965 tv.tv_sec = 0;
00966 tv.tv_usec = interval;
00967 tvp = &tv;
00968 } else {
00969 tvp = NULL;
00970 }
00971 n = select(sockfd+1, &readfds, NULL, NULL, tvp);
00972 }
00973
00974 if (n < 0) {
00975 if (errno == EINTR) {
00976 warning(errno, "main loop, select");
00977 continue;
00978 }
00979 error(errno, "main loop, select");
00980 sleep(1);
00981 continue;
00982 }
00983 if (n > 0) {
00984 if (FD_ISSET(sockfd, &readfds)) {
00985 read_data(inbuffer, sockfd);
00986 parse_data(inbuffer, outbuffer);
00987 }
00988 if (octstr_len(outbuffer) > 0 &&
00989 FD_ISSET(sockfd, &writefds)) {
00990 write_data(outbuffer, sockfd);
00991 }
00992 if (octstr_len(outbuffer) < OUTBUFFER_LIMIT) {
00993 reported_outfull = 0;
00994 }
00995 }
00996 }
00997 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 320 of file test_cimd2.c. References gw_gmtime(). Referenced by gen_message(), handle_get(), and handle_submit(). 00320 {
00321 /* Is there a thread-safe version of gmtime? */
00322 struct tm tm = gw_gmtime(fortime);
00323
00324 sprintf(buf, "%02d%02d%02d%02d%02d%02d",
00325 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
00326 tm.tm_hour, tm.tm_min, tm.tm_sec);
00327 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 817 of file test_cimd2.c. References ETX, Octstr, octstr_copy, octstr_delete(), octstr_destroy(), octstr_len(), octstr_search_char(), parse_packet(), and STX. Referenced by main_loop(), parse_array_element(), and parse_data(). 00817 {
00818 int stx, etx;
00819 Octstr *packet;
00820
00821 for (;;) {
00822 /* Look for start of packet. Delete everything up to the start
00823 * marker. (CIMD2 section 3.1 says we can ignore any data
00824 * transmitted between packets.) */
00825 stx = octstr_search_char(in, STX, 0);
00826 if (stx < 0)
00827 octstr_delete(in, 0, octstr_len(in));
00828 else if (stx > 0)
00829 octstr_delete(in, 0, stx);
00830
00831 etx = octstr_search_char(in, ETX, 0);
00832 if (etx < 0)
00833 return; /* Incomplete packet; wait for more data. */
00834
00835 /* Copy the data between stx and etx */
00836 packet = octstr_copy(in, 1, etx - 1);
00837 /* Then cut the packet (including stx and etx) from inbuffer */
00838 octstr_delete(in, 0, etx + 1);
00839
00840 parse_packet(packet, out);
00841
00842 octstr_destroy(packet);
00843 }
00844 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 788 of file test_cimd2.c. References eat_char(), eat_checksum(), eat_number(), handlers, logging, opcode, and send_error(). Referenced by parse_data(). 00788 {
00789 int opcode, sequence;
00790 int i;
00791
00792 eat_checksum(packet);
00793
00794 opcode = eat_number(packet);
00795 if (opcode < 0 || eat_char(packet, ':') < 0)
00796 return;
00797 sequence = eat_number(packet);
00798 if (sequence < 0)
00799 return;
00800
00801 for (i = 0; handlers[i].opcode >= 0; i++) {
00802 if (handlers[i].opcode == opcode) {
00803 (handlers[i].handler)(packet, out, sequence);
00804 break;
00805 }
00806 }
00807
00808 if (handlers[i].opcode < 0) { /* Loop failed */
00809 if (logging == LOG_packets)
00810 printf("RCV: unknown operation %ld\n",
00811 (long) handlers[i].opcode);
00812 send_error(out, 98, sequence, "1", "unexpected operation");
00813 }
00814 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 201 of file test_cimd2.c. References CR, data, ETX, LF, STX, and TAB. Referenced by read_data(), and write_data(). 00201 {
00202 size_t i;
00203 int c;
00204
00205 for (i = 0; i < length; i++) {
00206 c = data[i];
00207 switch(c) {
00208 default:
00209 if (isprint(c))
00210 putchar(c);
00211 else
00212 printf("<%d>", c);
00213 break;
00214 case TAB: fputs("<TAB>", stdout); break;
00215 case LF: fputs("<LF>\n", stdout); break;
00216 case CR: fputs("<CR>", stdout); break;
00217 case STX: fputs("<STX>", stdout); break;
00218 case ETX: fputs("<ETX>\n", stdout); break;
00219 }
00220 }
00221 fflush(stdout);
00222 }
|
|
||||||||||||
|
Definition at line 846 of file test_cimd2.c. Referenced by gen_message(). 00846 {
00847 int len = random() % size;
00848
00849 while (len--) {
00850 *buf++ = '0' + random() % 10;
00851 }
00852
00853 *buf++ = '\0';
00854 }
|
|
||||||||||||
|
Definition at line 869 of file test_cimd2.c. Referenced by gen_message(). 00869 {
00870 int len = random() % size;
00871
00872 /* Make even */
00873 len -= (len % 2);
00874
00875 while (len--) {
00876 int c = random() % 16;
00877 if (c < 10)
00878 *buf++ = c + '0';
00879 else
00880 *buf++ = c - 10 + 'a';
00881 }
00882
00883 *buf++ = '\0';
00884 }
|
|
||||||||||||
|
Definition at line 856 of file test_cimd2.c. Referenced by gen_message(). 00856 {
00857 int len = random() % size;
00858
00859 while (len--) {
00860 do {
00861 *buf = random() % 256;
00862 } while (*buf == STX || *buf == ETX || *buf == TAB);
00863 buf++;
00864 }
00865
00866 *buf++ = '\0';
00867 }
|
|
||||||||||||
|
Definition at line 224 of file test_cimd2.c. References error(), logging, octstr_append_data(), and pretty_print(). Referenced by main_loop(). 00224 {
00225 unsigned char buf[EVIL_BUFSIZE];
00226 int ret;
00227
00228 ret = read(fd, buf, sizeof(buf));
00229 if (ret > 0) {
00230 octstr_append_data(in, buf, ret);
00231 if (logging == LOG_data)
00232 pretty_print(buf, ret);
00233 } else if (ret == 0) {
00234 fprintf(stderr, "Client closed socket\n");
00235 exit(0);
00236 } else {
00237 if (errno == EINTR || errno == EAGAIN)
00238 return;
00239 error(errno, "read_data");
00240 exit(1);
00241 }
00242 }
|
Here is the call graph for this function:

|
||||||||||||||||||||||||
|
Definition at line 360 of file test_cimd2.c. References logging, opcode, and send_packet(). Referenced by handle_cancel(), handle_delivery_request(), handle_enquire(), handle_get(), handle_login(), handle_set(), handle_submit(), and parse_packet(). 00361 {
00362 if (logging == LOG_packets)
00363 printf("SND: ERROR, %s\n", errortext);
00364
00365 send_packet(out, opcode, sequence, 900, errorcode, 901, errortext, 0);
00366 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 330 of file test_cimd2.c. References activity, ETX, octstr_format_append(), octstr_get_char(), octstr_len(), opcode, STX, and TAB. Referenced by gen_message(), handle_alive(), handle_cancel(), handle_delivery_request(), handle_enquire(), handle_get(), handle_login(), handle_logout(), handle_submit(), and send_error(). 00330 {
00331 va_list ap;
00332 int parm;
00333 unsigned char *value;
00334 int checksum;
00335 int old_len, new_len;
00336
00337 if (activity == ACT_listen)
00338 return;
00339
00340 old_len = octstr_len(out);
00341
00342 octstr_format_append(out, "%c%02d:%03d%c", STX, opcode, sequence, TAB);
00343
00344 va_start(ap, sequence);
00345 for (parm = va_arg(ap, int); parm != 0; parm = va_arg(ap, int)) {
00346 value = va_arg(ap, unsigned char *);
00347 octstr_format_append(out, "%03d:%s\11", parm, value);
00348 }
00349 va_end(ap);
00350
00351 /* Calculate checksum */
00352 checksum = 0;
00353 for (new_len = octstr_len(out); old_len < new_len; old_len++) {
00354 checksum = (checksum + octstr_get_char(out, old_len)) & 0xff;
00355 }
00356
00357 octstr_format_append(out, "%02X%c", checksum, ETX);
00358 }
|
Here is the call graph for this function:

|
|
Definition at line 167 of file test_cimd2.c. References activity, checking, logging, password, port, progname, spew, and username. 00167 {
00168 fprintf(out, "Usage: %s [options...]\n"
00169 " --help Print this message\n"
00170 " --user USER Allow clients to log in with username USER (default %s)\n"
00171 " --password PASS Allow clients to log in with password PASS (default %s)\n"
00172 " --intro INTRO Send INTRO string before anything else (default nothing)\n"
00173 " --port PORT TCP port to listen on (default %d)\n"
00174 " --activity ACT Activity level of test server (default %d)\n"
00175 " ACT = 0 send nothing, just listen\n"
00176 " ACT = 1 send valid replies, do not initiate any transactions\n"
00177 " ACT = 2 attempt to deliver a random SMS every few seconds (NI)\n"
00178 " ACT = 3 deliver many random SMSes, measure throughput (NI)\n"
00179 " --spew SPEW Flood client, overrides --activity (default %d)\n"
00180 " SPEW = 0 don't spew, use --activity instead\n"
00181 " SPEW = 1 spew random binary gunk at client\n"
00182 " SPEW = 2 spew random data of the right character set at client (NI)\n"
00183 " SPEW = 3 spew valid packets with random contents at client (NI)\n"
00184 " --logging LOG Log level of test server (default %d)\n"
00185 " LOG = 0 log nothing\n"
00186 " LOG = 1 log all data\n"
00187 " LOG = 2 log summaries of valid packets\n"
00188 " LOG = 3 log successfully sent and received SMSes (NI)\n"
00189 " --checking CHK Check level of test server (default %d)\n"
00190 " CHK = 0 check nothing\n"
00191 " CHK = 1 signal invalid packets (NI)\n"
00192 " CHK = 2 signal checksum errors (NI)\n"
00193 " CHK = 3 signal protocol errors (NI)\n"
00194 " CHK = 4 signal invalid SMS contents (NI)\n"
00195 " --max MAX With high activity values, stop after MAX deliveries\n"
00196 " NI means Not Implemented\n"
00197 , progname, username, password, port,
00198 activity, spew, logging, checking);
00199 }
|
|
|
Definition at line 1016 of file test_cimd2.c. References error(), gw_netaddr_to_octstr(), info(), make_server_socket(), Octstr, octstr_destroy(), octstr_get_cstr, panic, port, progname, and socket_set_blocking(). Referenced by main(). 01016 {
01017 struct sockaddr_in sin;
01018 socklen_t addrlen;
01019 int listenfd;
01020 int clientfd;
01021 Octstr *addr;
01022
01023 listenfd = make_server_socket(port, NULL);
01024 if (listenfd < 0) {
01025 fprintf(stderr, "%s: failed to open socket at port %d\n",
01026 progname, port);
01027 exit(1);
01028 }
01029
01030 do {
01031 addrlen = sizeof(sin);
01032 clientfd = accept(listenfd, (struct sockaddr *)&sin, &addrlen);
01033 if (clientfd < 0) {
01034 error(errno, "failed to accept new connection");
01035 }
01036 } while (clientfd < 0);
01037
01038 if (socket_set_blocking(clientfd, 0) < 0) {
01039 panic(0, "failed to make client socket nonblocking");
01040 }
01041
01042 addr = gw_netaddr_to_octstr(AF_INET, &sin.sin_addr);
01043 info(0, "Accepted client from %s:%d",
01044 octstr_get_cstr(addr), ntohs(sin.sin_port));
01045 octstr_destroy(addr);
01046
01047 close(listenfd);
01048
01049 return clientfd;
01050 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 244 of file test_cimd2.c. References error(), logging, octstr_delete(), octstr_get_many_chars(), octstr_len(), pretty_print(), and warning(). Referenced by main_loop(). 00244 {
00245 unsigned char buf[EVIL_BUFSIZE];
00246 int len;
00247 ssize_t ret;
00248
00249 len = sizeof(buf);
00250 if (len > octstr_len(out))
00251 len = octstr_len(out);
00252 if (len == 0)
00253 return;
00254 octstr_get_many_chars(buf, out, 0, len);
00255 ret = write(fd, buf, len);
00256 if (ret > 0) {
00257 if (logging == LOG_data)
00258 pretty_print(buf, ret);
00259 octstr_delete(out, 0, ret);
00260 } else if (ret == 0) {
00261 warning(0, "empty write");
00262 } else {
00263 if (errno == EINTR || errno == EAGAIN)
00264 return;
00265 error(errno, "write_data");
00266 exit(1);
00267 }
00268 }
|
Here is the call graph for this function:

|
|
Definition at line 136 of file test_cimd2.c. Referenced by send_packet(), and usage(). |
|
|
Definition at line 317 of file test_cimd2.c. Referenced by gen_message(), handle_alive_response(), handle_deliver_response(), handle_deliver_status_report_response(), and handle_nack(). |
|
|
Definition at line 139 of file test_cimd2.c. Referenced by usage(). |
|
|
Definition at line 142 of file test_cimd2.c. Referenced by gen_data(), and handle_deliver_response(). |
|
|
Definition at line 770 of file test_cimd2.c. |
|
|
Referenced by parse_packet(). |
|
|
Definition at line 147 of file test_cimd2.c. Referenced by main_loop(). |
|
|
Definition at line 105 of file test_cimd2.c. Referenced by main_loop(). |
|
|
Definition at line 1001 of file test_cimd2.c. Referenced by at2_read_pending_incoming_messages(). |
|
|
Definition at line 138 of file test_cimd2.c. Referenced by gen_message(), handle_alive(), handle_alive_response(), handle_cancel(), handle_deliver_response(), handle_deliver_status_report_response(), handle_delivery_request(), handle_enquire(), handle_get(), handle_login(), handle_logout(), handle_nack(), handle_set(), handle_submit(), parse_packet(), read_data(), send_error(), usage(), and write_data(). |
|
|
Definition at line 141 of file test_cimd2.c. Referenced by gen_data(), and handle_deliver_response(). |
|
|
Definition at line 1002 of file test_cimd2.c. |
|
|
Definition at line 769 of file test_cimd2.c. Referenced by parse_packet(), send_error(), and send_packet(). |
|
|
Definition at line 1000 of file test_cimd2.c. Referenced by main(), and parse_options(). |
|
|
Referenced by main(). |
|
|
Definition at line 148 of file test_cimd2.c. Referenced by main_loop(). |
|
|
|
Definition at line 102 of file test_cimd2.c. |
|
|
Definition at line 96 of file test_cimd2.c. Referenced by badusage(), build_box_arglist(), do_stop(), fatal(), main(), print_usage(), rebind_standard_streams(), usage(), wait_for_client(), and write_pidfile(). |
|
|
Definition at line 145 of file test_cimd2.c. Referenced by conn_open_tcp_nb_with_port(), conn_open_tcp_with_port(), main(), and main_loop(). |
|
|
Definition at line 137 of file test_cimd2.c. Referenced by usage(). |
|
|
Definition at line 143 of file test_cimd2.c. |
|