test_cimd2.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:25k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /* test_cimd2.c - fake cimd2 smsc
  2.  *
  3.  * This program pretends to be an CIMD 2 SMS center, accessible via IP.
  4.  * It is used to test the Kannel smsc_cimd2 code.
  5.  * 
  6.  * Richard Braakman
  7.  */
  8. /* Note: The CIMD2 parsing code was written as a prototype, and currently
  9.  * its main use is to exercise the *real* CIMD2 code in gw/smsc_cimd2.c.
  10.  * Please don't use this code for anything real.
  11.  * Richard Braakman */
  12. /*
  13.  * TODO: If log level is high and activity level is low, there will be
  14.  * "SND" log entries for packets that are not sent, which is confusing
  15.  * and should be fixed.
  16.  */
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <ctype.h>
  22. #include <stdarg.h>
  23. #include <limits.h>
  24. #include <unistd.h>
  25. #include <time.h>
  26. #include <sys/types.h>
  27. #include <sys/time.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <arpa/inet.h>
  31. #include "gwlib/gwlib.h"
  32. enum { TIMESTAMP_MAXLEN = 13 };
  33. unsigned char *progname;
  34. /* Set up a fake account for Kannel to use */
  35. unsigned char *username = "foo";
  36. unsigned char *password = "bar";
  37. int port = 6789;
  38. /* This can be useful to get past protocol-ID checks when testing spew. */
  39. unsigned char *intro = "";
  40. enum ACT {
  41. ACT_listen = 0,
  42. ACT_reply = 1,
  43. ACT_deliver = 2,
  44. ACT_flood = 3
  45. };
  46. enum SPEW {
  47. SPEW_nothing = 0,
  48. SPEW_binary = 1,
  49. SPEW_characters = 2,
  50. SPEW_packets = 3
  51. };
  52. enum LOG {
  53. LOG_nothing = 0,
  54. LOG_data = 1,
  55. LOG_packets = 2,
  56. LOG_sms = 3
  57. };
  58. enum CHK {
  59. CHK_nothing = 0,
  60. CHK_packets = 1,
  61. CHK_sums = 2,
  62. CHK_protocol = 3,
  63. CHK_sms = 4
  64. };
  65. int activity = ACT_listen;
  66. int spew = SPEW_nothing;
  67. int logging = LOG_nothing;
  68. int checking = CHK_nothing;
  69. int max_deliveries = -1;
  70. int deliveries = 0;
  71. time_t start_time = 0;
  72. int sockfd = -1;
  73. Octstr *inbuffer;
  74. Octstr *outbuffer;
  75. /* Maximum reasonable outbuffer size.  It can go above this, but we don't
  76.  * deliberately add data when it's already more than this. */
  77. enum { OUTBUFFER_LIMIT = 65536 };
  78. /* Test dependencies on neatly-sized read and write chunks, by using
  79.  * a deliberately evil buffer size.  1021 is the largest prime smaller
  80.  * than 1024. */
  81. enum { EVIL_BUFSIZE = 1021 };
  82. enum CHARS {
  83. STX = 2,
  84. ETX = 3,
  85. TAB = 9,
  86. LF = 10,
  87. CR = 13
  88. };
  89. static void usage(FILE *out) {
  90. fprintf(out, "Usage: %s [options...]n"
  91. "  --help          Print this messagen"
  92. "  --user USER     Allow clients to log in with username USER (default %s)n"
  93. "  --password PASS Allow clients to log in with password PASS (default %s)n"
  94. "  --intro INTRO   Send INTRO string before anything else (default nothing)n"
  95. "  --port PORT     TCP port to listen on (default %d)n"
  96. "  --activity ACT  Activity level of test server (default %d)n"
  97. "      ACT = 0     send nothing, just listenn"
  98. "      ACT = 1     send valid replies, do not initiate any transactionsn"
  99. "      ACT = 2     attempt to deliver a random SMS every few seconds (NI)n"
  100. "      ACT = 3     deliver many random SMSes, measure throughput (NI)n"
  101. "  --spew SPEW     Flood client, overrides --activity (default %d)n"
  102. "      SPEW = 0    don't spew, use --activity insteadn"
  103. "      SPEW = 1    spew random binary gunk at clientn"
  104. "      SPEW = 2    spew random data of the right character set at client (NI)n"
  105. "      SPEW = 3    spew valid packets with random contents at client (NI)n"
  106. "  --logging LOG   Log level of test server (default %d)n"
  107. "      LOG = 0     log nothingn"
  108. "      LOG = 1     log all datan"
  109. "      LOG = 2     log summaries of valid packetsn"
  110. "      LOG = 3     log successfully sent and received SMSes (NI)n"
  111. "  --checking CHK  Check level of test server (default %d)n"
  112. "      CHK = 0     check nothingn"
  113. "      CHK = 1     signal invalid packets (NI)n"
  114. "      CHK = 2     signal checksum errors (NI)n"
  115. "      CHK = 3     signal protocol errors (NI)n"
  116. "      CHK = 4     signal invalid SMS contents (NI)n"
  117. "  --max MAX       With high activity values, stop after MAX deliveriesn"
  118. " NI means Not Implementedn"
  119. , progname, username, password, port,
  120. activity, spew, logging, checking);
  121. }
  122. static void pretty_print(unsigned char *data, size_t length) {
  123. size_t i;
  124. int c;
  125. for (i = 0; i < length; i++) {
  126. c = data[i];
  127. switch(c) {
  128. default:
  129. if (isprint(c))
  130. putchar(c);
  131. else
  132. printf("<%d>", c);
  133. break;
  134. case TAB: fputs("<TAB>", stdout); break;
  135. case LF: fputs("<LF>n", stdout); break;
  136. case CR: fputs("<CR>", stdout); break;
  137. case STX: fputs("<STX>", stdout); break;
  138. case ETX: fputs("<ETX>n", stdout); break;
  139. }
  140. }
  141. fflush(stdout);
  142. }
  143. static void read_data(Octstr *in, int fd) {
  144. unsigned char buf[EVIL_BUFSIZE];
  145. int ret;
  146. ret = read(fd, buf, sizeof(buf));
  147. if (ret > 0) {
  148. octstr_append_data(in, buf, ret);
  149. if (logging == LOG_data)
  150. pretty_print(buf, ret);
  151. } else if (ret == 0) {
  152. fprintf(stderr, "Client closed socketn");
  153. exit(0);
  154. } else {
  155. if (errno == EINTR || errno == EAGAIN)
  156. return;
  157. error(errno, "read_data");
  158. exit(1);
  159. }
  160. }
  161. static void write_data(Octstr *out, int fd) {
  162. unsigned char buf[EVIL_BUFSIZE];
  163. int len;
  164. ssize_t ret;
  165. len = sizeof(buf);
  166. if (len > octstr_len(out))
  167. len = octstr_len(out);
  168. if (len == 0)
  169. return;
  170. octstr_get_many_chars(buf, out, 0, len);
  171. ret = write(fd, buf, len);
  172. if (ret > 0) {
  173. if (logging == LOG_data)
  174. pretty_print(buf, ret);
  175. octstr_delete(out, 0, ret);
  176. } else if (ret == 0) {
  177. warning(0, "empty write");
  178. } else {
  179. if (errno == EINTR || errno == EAGAIN)
  180. return;
  181. error(errno, "write_data");
  182. exit(1);
  183. }
  184. }
  185. static void gen_message(Octstr *out);
  186. /* Return the minimum interval (in microseconds) after which we will
  187.  * want to be called again.  This value is only used if we _don't_
  188.  * generate data this time through. */
  189. static long gen_data(Octstr *out) {
  190. unsigned char buf[EVIL_BUFSIZE];
  191. size_t i;
  192. long interval = -1;
  193. static int last_sms;  /* Used by ACT_deliver */
  194. time_t now;
  195. if (max_deliveries < 0 || deliveries < max_deliveries) {
  196. switch (activity) {
  197. case ACT_deliver:
  198. now = time(NULL);
  199. if (last_sms == 0)
  200. last_sms = now;
  201. while (last_sms < now) {
  202. if (random() % 7 == 1) {
  203. gen_message(out);
  204. last_sms = now;
  205. } else
  206. last_sms++;
  207. }
  208. interval = 1000000;
  209. break;
  210. case ACT_flood:
  211. gen_message(out);
  212. break;
  213. }
  214. }
  215. switch (spew) {
  216. case SPEW_binary:
  217. for (i = 0; i < sizeof(buf); i++) {
  218. buf[i] = random() % 256;
  219. }
  220. octstr_append_data(out, buf, sizeof(buf));
  221. break;
  222. }
  223. return interval;
  224. }
  225. /******************************* CIMD 2 specific code ************************/
  226. int awaiting_response = 0;
  227. /* buf must be at least TIMESTAMP_MAXLEN bytes long. */
  228. static void make_timestamp(unsigned char *buf, time_t fortime) {
  229. /* Is there a thread-safe version of gmtime? */
  230. struct tm tm = gw_gmtime(fortime);
  231. sprintf(buf, "%02d%02d%02d%02d%02d%02d",
  232. tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
  233. tm.tm_hour, tm.tm_min, tm.tm_sec);
  234. }
  235. static void send_packet(Octstr *out, int opcode, int sequence, ...) {
  236. va_list ap;
  237. int parm;
  238. unsigned char *value;
  239. int checksum;
  240. int old_len, new_len;
  241. if (activity == ACT_listen)
  242. return;
  243. old_len = octstr_len(out);
  244. octstr_format_append(out, "%c%02d:%03d%c", STX, opcode, sequence, TAB);
  245. va_start(ap, sequence);
  246. for (parm = va_arg(ap, int); parm != 0; parm = va_arg(ap, int)) {
  247. value = va_arg(ap, unsigned char *);
  248. octstr_format_append(out, "%03d:%s11", parm, value);
  249. }
  250. va_end(ap);
  251. /* Calculate checksum */
  252. checksum = 0;
  253. for (new_len = octstr_len(out); old_len < new_len; old_len++) {
  254. checksum = (checksum + octstr_get_char(out, old_len)) & 0xff;
  255. }
  256. octstr_format_append(out, "%02X%c", checksum, ETX);
  257. }
  258. static void send_error(Octstr *out, int opcode, int sequence,
  259. unsigned char *errorcode, unsigned char *errortext) {
  260. if (logging == LOG_packets)
  261. printf("SND: ERROR, %sn", errortext);
  262. send_packet(out, opcode, sequence, 900, errorcode, 901, errortext, 0);
  263. }
  264. static int eat_char(Octstr *packet, int ch) {
  265. if (octstr_get_char(packet, 0) == ch) {
  266. octstr_delete(packet, 0, 1);
  267. return 0;
  268. }
  269. return -1;
  270. }
  271. static Octstr *eat_string_parm(Octstr *packet, int parm, int maxlen) {
  272. long start, datastart;
  273. long tab;
  274. Octstr *result;
  275. Octstr *parmheader;
  276.      parmheader = octstr_format("%c%03d:", TAB, parm);
  277. start = octstr_search(packet, parmheader, 0);
  278. if (start < 0) {
  279. octstr_destroy(parmheader);
  280. return NULL;
  281. }
  282. datastart = start + octstr_len(parmheader);
  283. tab = octstr_search_char(packet, TAB, datastart + 1);
  284. if (tab < 0) {
  285. tab = octstr_len(packet);
  286. }
  287. result = octstr_copy(packet, datastart, tab - datastart);
  288. octstr_delete(packet, start, tab - start);
  289. octstr_destroy(parmheader);
  290. return result;
  291. }
  292. static long eat_number(Octstr *ostr) {
  293. long result;
  294. long pos;
  295. pos = octstr_parse_long(&result, ostr, 0, 10);
  296. if (pos < 0)
  297. return INT_MIN;
  298. octstr_delete(ostr, 0, pos);
  299. return result;
  300. }
  301. static long eat_int_parm(Octstr *packet, int parm, int maxlen) {
  302. Octstr *value;
  303. long result;
  304. value = eat_string_parm(packet, parm, maxlen);
  305. if (!value)
  306. return INT_MIN;
  307. result = eat_number(value);
  308. if (octstr_len(value) > 0)
  309. result = INT_MIN;
  310. octstr_destroy(value);
  311. return result;
  312. }
  313. static void eat_checksum(Octstr *packet) {
  314. int len;
  315. int ch1, ch2, ch3;
  316. len = octstr_len(packet);
  317. if (len < 3)
  318. return;
  319. ch1 = octstr_get_char(packet, len - 3);
  320. ch2 = octstr_get_char(packet, len - 2);
  321. ch3 = octstr_get_char(packet, len - 1);
  322. if (isxdigit(ch3) && isxdigit(ch2) && ch1 == TAB)
  323. octstr_delete(packet, len - 3, 3);
  324. }
  325. static void handle_login(Octstr *packet, Octstr *out, int sequence) {
  326. Octstr *user = eat_string_parm(packet, 10, 32);
  327. Octstr *pass = eat_string_parm(packet, 11, 32);
  328. if (user == NULL)
  329. user = octstr_create("");
  330. if (pass == NULL)
  331. pass = octstr_create("");
  332. if (logging == LOG_packets)
  333. printf("RCV: Login user '%s', password '%s'n",
  334. octstr_get_cstr(user), octstr_get_cstr(pass));
  335. if (octstr_str_compare(user, username) == 0 &&
  336.     octstr_str_compare(pass, password) == 0) {
  337. if (logging == LOG_packets)
  338. printf("SND: Login OKn");
  339. send_packet(out, 51, sequence, 0);
  340. } else {
  341. send_error(out, 51, sequence, "100", "invalid login");
  342. }
  343. octstr_destroy(user);
  344. octstr_destroy(pass);
  345. }
  346. static void handle_logout(Octstr *packet, Octstr *out, int sequence) {
  347. if (logging == LOG_packets)
  348. printf("RCV: Logoutn");
  349. if (logging == LOG_packets)
  350. printf("SND: Logout OKn");
  351. send_packet(out, 52, sequence, 0);
  352. }
  353. static void handle_submit(Octstr *packet, Octstr *out, int sequence) {
  354. Octstr *dest_addr = eat_string_parm(packet, 21, 20);
  355. Octstr *orig_addr = eat_string_parm(packet, 23, 20);
  356. long DCS = eat_int_parm(packet, 30, 3);
  357. Octstr *UDH = eat_string_parm(packet, 32, 280);
  358. Octstr *text = eat_string_parm(packet, 33, 480);
  359. Octstr *textb = eat_string_parm(packet, 34, 280);
  360. long valid_rel = eat_int_parm(packet, 50, 3);
  361. Octstr *valid_abs = eat_string_parm(packet, 51, 12);
  362. long proto_id = eat_int_parm(packet, 52, 3);
  363. long delivery_rel = eat_int_parm(packet, 53, 3);
  364. Octstr *delivery_abs = eat_string_parm(packet, 54, 12);
  365. long reply_path = eat_int_parm(packet, 55, 1);
  366. long SRR = eat_int_parm(packet, 56, 2);
  367. long cancel = eat_int_parm(packet, 58, 1);
  368. long tariff_class = eat_int_parm(packet, 64, 2);
  369. long service_desc = eat_int_parm(packet, 65, 1);
  370. long priority = eat_int_parm(packet, 67, 1);
  371. List *other_dests = list_create();
  372. Octstr *tmp;
  373. while ((tmp = eat_string_parm(packet, 21, 20)))
  374. list_append(other_dests, tmp);
  375. if (logging == LOG_packets) {
  376. int i;
  377. printf("RCV: Submit to %s", octstr_get_cstr(dest_addr));
  378. for (i = 0; i < list_len(other_dests); i++) {
  379. printf(", %s",
  380. octstr_get_cstr(list_get(other_dests, i)));
  381. }
  382. printf("n");
  383. if (orig_addr)
  384. printf("    From: %sn", octstr_get_cstr(orig_addr));
  385. if (DCS > INT_MIN)
  386. printf("    Data coding: %ldn", DCS);
  387. if (UDH)
  388. printf("    User data header: %sn",
  389. octstr_get_cstr(UDH));
  390. if (text)
  391. printf("    Text: %sn", octstr_get_cstr(text));
  392. if (textb)
  393. printf("    Text (binary): %sn",
  394. octstr_get_cstr(textb));
  395. if (valid_rel > INT_MIN)
  396. printf("    Validity period: %ld (relative)n",
  397. valid_rel);
  398. if (valid_abs)
  399. printf("    Validity period: %s (absolute)n",
  400. octstr_get_cstr(valid_abs));
  401. if (proto_id > INT_MIN)
  402. printf("    Protocol ID: %ldn", proto_id);
  403. if (delivery_rel > INT_MIN)
  404. printf("    First delivery: %ld (relative)n",
  405. delivery_rel);
  406. if (delivery_abs)
  407. printf("    First delivery: %s (absolute)n",
  408. octstr_get_cstr(delivery_abs));
  409. if (reply_path == 0)
  410. printf("    Reply path disabledn");
  411. else if (reply_path == 1)
  412. printf("    Reply path enabledn");
  413. else if (reply_path > INT_MAX)
  414. printf("    Reply path: %ldn", reply_path);
  415. if (SRR > INT_MAX)
  416. printf("    Status report flags: %ldn", SRR);
  417. if (cancel == 0)
  418. printf("    Cancel disabledn");
  419. else if (cancel == 1)
  420. printf("    Cancel enabledn");
  421. else if (cancel > INT_MAX)
  422. printf("    Cancel enabled: %ldn", cancel);
  423. if (tariff_class > INT_MAX)
  424. printf("    Tariff class: %ldn", tariff_class);
  425. if (service_desc > INT_MAX)
  426. printf("    Service description: %ldn", service_desc);
  427. if (priority > INT_MAX)
  428. printf("    Priority: %ldn", priority);
  429. }
  430. if (!dest_addr) {
  431. send_error(out, 53, sequence, "300", "no destination");
  432. } else if (list_len(other_dests) > 0) {
  433. send_error(out, 53, sequence, "301", "too many destinations");
  434. /* TODO: Report many other possible errors here */
  435. } else {
  436. unsigned char buf[TIMESTAMP_MAXLEN];
  437. make_timestamp(buf, time(NULL));
  438. if (logging == LOG_packets)
  439. printf("SND: Submit OKn");
  440. send_packet(out, 53, sequence,
  441.             21, octstr_get_cstr(dest_addr),
  442.     60, buf,
  443.     0);
  444. }
  445. octstr_destroy(dest_addr);
  446. octstr_destroy(orig_addr);
  447. octstr_destroy(UDH);
  448. octstr_destroy(text);
  449. octstr_destroy(textb);
  450. octstr_destroy(valid_abs);
  451. octstr_destroy(delivery_abs);
  452. list_destroy(other_dests, octstr_destroy_item);
  453. }
  454. static void handle_enquire(Octstr *packet, Octstr *out, int sequence) {
  455. Octstr *dest_addr = eat_string_parm(packet, 21, 20);
  456. Octstr *timestamp = eat_string_parm(packet, 60, 12);
  457. if (logging == LOG_packets)
  458. printf("RCV: Enquire status, dest='%s', time='%s'n",
  459. dest_addr ? octstr_get_cstr(dest_addr) : "",
  460. timestamp ? octstr_get_cstr(timestamp) : "");
  461. if (!dest_addr) {
  462. send_error(out, 54, sequence, "400", "no destination");
  463. } else if (!timestamp) {
  464. send_error(out, 54, sequence, "401", "no timestamp");
  465. } else {
  466. if (logging == LOG_packets)
  467. printf("SND: Respond: status unknownn");
  468. send_packet(out, 54, sequence,
  469.     21, octstr_get_cstr(dest_addr),
  470.     60, octstr_get_cstr(timestamp),
  471.     61, "0",
  472.     0);
  473. }
  474. octstr_destroy(dest_addr);
  475. octstr_destroy(timestamp);
  476. }
  477. static void handle_delivery_request(Octstr *packet, Octstr *out, int sequence) {
  478. long mode = eat_int_parm(packet, 68, 1);
  479. if (logging == LOG_packets) {
  480. switch (mode) {
  481. case 0: printf("RCV: Delivery request, messages waiting?n");
  482. break;
  483. case 1: printf("RCV: Delivery request, one messagen");
  484. break;
  485. case 2: printf("RCV: Delivery request, all messagesn");
  486. break;
  487. case INT_MIN:
  488. printf("RCV: Delivery request, no moden");
  489. break;
  490. default:
  491. printf("RCV: Delivery request, mode %ldn", mode);
  492. }
  493. }
  494. if (mode == INT_MIN)
  495. mode = 1;
  496. switch (mode) {
  497. case 0:
  498. if (logging == LOG_packets)
  499. printf("SND: Respond: 0 messagesn");
  500. send_packet(out, 55, sequence,
  501.     66, "0",
  502.     0);
  503. break;
  504. case 1:
  505. send_error(out, 55, sequence, "500", "no messages available");
  506. break;
  507. case 2:
  508. send_error(out, 55, sequence, "500", "no messages available");
  509. break;
  510. default:
  511. send_error(out, 55, sequence, "501", "bad mode");
  512. break;
  513. }
  514. }
  515. static void handle_cancel(Octstr *packet, Octstr *out, int sequence) {
  516. long mode = eat_int_parm(packet, 59, 1);
  517. Octstr *timestamp = eat_string_parm(packet, 60, 12);
  518. Octstr *destination = eat_string_parm(packet, 21, 20);
  519. if (logging == LOG_packets) {
  520. printf("RCV: Cancel");
  521. if (mode != INT_MIN)
  522. printf(", mode %ld", mode);
  523. if (destination)
  524. printf(", dest '%s'", octstr_get_cstr(destination));
  525. if (timestamp)
  526. printf(", time '%s'", octstr_get_cstr(timestamp));
  527. printf("n");
  528. }
  529. if (mode < 0 || mode > 2)
  530. send_error(out, 56, sequence, "602", "bad mode");
  531. else {
  532. if (logging == LOG_packets)
  533. printf("SND: OKn");
  534. send_packet(out, 56, sequence, 0);
  535. }
  536. }
  537. static void handle_set(Octstr *packet, Octstr *out, int sequence) {
  538. Octstr *pass = eat_string_parm(packet, 11, 32);
  539. if (pass) {
  540. if (logging == LOG_packets)
  541. printf("RCV: Set password to '%s'n",
  542. octstr_get_cstr(pass));
  543. send_error(out, 58, sequence,
  544. "801", "changing password not allowed");
  545. } else {
  546. if (logging == LOG_packets)
  547. printf("RCV: Set, unknown parametersn");
  548. send_error(out, 58, sequence, "3", "cannot set");
  549. }
  550. }
  551. static void handle_get(Octstr *packet, Octstr *out, int sequence) {
  552. long number = eat_int_parm(packet, 500, 3);
  553. if (logging == LOG_packets)
  554. printf("RCV: Get parameter #%ldn", number);
  555. if (number == INT_MIN) {
  556. send_error(out, 59, sequence, "900", "missing parameter");
  557. } else if (number == 501) {
  558. unsigned char buf[TIMESTAMP_MAXLEN];
  559. make_timestamp(buf, time(NULL));
  560. if (logging == LOG_packets)
  561. printf("SND: OK, SMSC timestamp is '%s'n", buf);
  562. send_packet(out, 59, sequence,
  563.     501, buf,
  564.     0);
  565. } else {
  566. send_error(out, 59, sequence, "900", "unknown parameter");
  567. }
  568. }
  569. static void handle_alive(Octstr *packet, Octstr *out, int sequence) {
  570. if (logging == LOG_packets)
  571. printf("RCV: Alive?n");
  572. if (logging == LOG_packets)
  573. printf("SND: Alive.n");
  574. send_packet(out, 90, sequence, 0);
  575. }
  576. static void handle_deliver_response(Octstr *packet, Octstr *out, int sequence) {
  577. awaiting_response = 0;
  578. if (logging == LOG_packets)
  579. printf("RCV: Deliver responsen");
  580. deliveries++;
  581. if (max_deliveries > 0 && deliveries == max_deliveries) {
  582. time_t elapsed = time(NULL) - start_time;
  583. printf("LOG: %ld deliveries in %ld secondsn",
  584. (long) max_deliveries, (long) elapsed);
  585. }
  586. /* No need to respond to a response */
  587. }
  588. static void handle_deliver_status_report_response(Octstr *packet, Octstr *out, int sequence) {
  589. awaiting_response = 0;
  590. if (logging == LOG_packets)
  591. printf("RCV: Deliver status report responsen");
  592. /* No need to respond to a response */
  593. }
  594. static void handle_alive_response(Octstr *packet, Octstr *out, int sequence) {
  595. awaiting_response = 0;
  596. if (logging == LOG_packets)
  597. printf("RCV: Alive.n");
  598. /* No need to respond to a response */
  599. }
  600. static void handle_nack(Octstr *packet, Octstr *out, int sequence) {
  601. awaiting_response = 0;
  602. if (logging == LOG_packets)
  603. printf("RCV: NACKn");
  604. /* TODO: We should retransmit if we get a nack, but there's
  605.  * no record of what request we sent. */
  606. }
  607. typedef void (*packet_handler)(Octstr *, Octstr *, int);
  608. struct {
  609. int opcode;
  610. packet_handler handler;
  611. } handlers[] = {
  612. { 1, handle_login },
  613. { 2, handle_logout },
  614. { 3, handle_submit },
  615. { 4, handle_enquire },
  616. { 5, handle_delivery_request },
  617. { 6, handle_cancel },
  618. { 8, handle_set },
  619. { 9, handle_get },
  620. { 40, handle_alive },
  621. { 70, handle_deliver_response },
  622. { 73, handle_deliver_status_report_response },
  623. { 90, handle_alive_response },
  624. { 99, handle_nack },
  625. { -1, NULL },
  626. };
  627. static void parse_packet(Octstr *packet, Octstr *out) {
  628. int opcode, sequence;
  629. int i;
  630. eat_checksum(packet);
  631. opcode = eat_number(packet);
  632. if (opcode < 0 || eat_char(packet, ':') < 0)
  633. return;
  634. sequence = eat_number(packet);
  635. if (sequence < 0)
  636. return;
  637. for (i = 0; handlers[i].opcode >= 0; i++) {
  638. if (handlers[i].opcode == opcode) {
  639. (handlers[i].handler)(packet, out, sequence);
  640. break;
  641. }
  642. }
  643. if (handlers[i].opcode < 0) { /* Loop failed */
  644. if (logging == LOG_packets)
  645. printf("RCV: unknown operation %ldn",
  646. (long) handlers[i].opcode);
  647. send_error(out, 98, sequence, "1", "unexpected operation");
  648. }
  649. }
  650. /* Parse the data stream for packets, and send out replies. */
  651. static void parse_data(Octstr *in, Octstr *out) {
  652. int stx, etx;
  653. Octstr *packet;
  654. for (;;) {
  655. /* Look for start of packet.  Delete everything up to the start
  656.  * marker.  (CIMD2 section 3.1 says we can ignore any data
  657.  * transmitted between packets.) */
  658. stx = octstr_search_char(in, STX, 0);
  659. if (stx < 0)
  660. octstr_delete(in, 0, octstr_len(in));
  661. else if (stx > 0)
  662. octstr_delete(in, 0, stx);
  663. etx = octstr_search_char(in, ETX, 0);
  664. if (etx < 0)
  665. return;  /* Incomplete packet; wait for more data. */
  666. /* Copy the data between stx and etx */
  667. packet = octstr_copy(in, 1, etx - 1);
  668. /* Then cut the packet (including stx and etx) from inbuffer */
  669. octstr_delete(in, 0, etx + 1);
  670. parse_packet(packet, out);
  671. octstr_destroy(packet);
  672. }
  673. }
  674. static void random_address(unsigned char *buf, int size) {
  675. int len = random() % size;
  676. while (len--) {
  677. *buf++ = '0' + random() % 10;
  678. }
  679. *buf++ = '';
  680. }
  681. static void random_message(unsigned char *buf, int size) {
  682. int len = random() % size;
  683. while (len--) {
  684. do {
  685. *buf = random() % 256;
  686. } while (*buf == STX || *buf == ETX || *buf == TAB);
  687. buf++;
  688. }
  689. *buf++ = '';
  690. }
  691. static void random_hex(unsigned char *buf, int size) {
  692. int len = random() % size;
  693. /* Make even */
  694. len -= (len % 2);
  695. while (len--) {
  696. int c = random() % 16;
  697. if (c < 10)
  698. *buf++ = c + '0';
  699. else
  700. *buf++ = c - 10 + 'a';
  701. }
  702. *buf++ = '';
  703. }
  704. static void gen_message(Octstr *out) {
  705. static int send_seq = 0;
  706. unsigned char dest[21];
  707. unsigned char orig[21];
  708. unsigned char scts[TIMESTAMP_MAXLEN];
  709. unsigned char message[481];
  710. unsigned char udh[281];
  711. if (awaiting_response == 1)
  712. return;
  713. random_address(dest, sizeof(dest));
  714. random_address(orig, sizeof(orig));
  715. make_timestamp(scts, time(NULL));
  716. random_message(message, sizeof(message));
  717. if (random() % 2 == 0)
  718. random_hex(udh, sizeof(udh));
  719. else
  720. *udh = 0;
  721. if (logging == LOG_packets)
  722. printf("SND: Deliver message (random)n");
  723. if (*udh) {
  724. send_packet(out, 20, send_seq,
  725. 21, dest,
  726. 23, orig,
  727. 60, scts,
  728. 32, udh,
  729. 33, message,
  730. 0);
  731. } else {
  732. send_packet(out, 20, send_seq,
  733. 21, dest,
  734. 23, orig,
  735. 60, scts,
  736. 33, message,
  737. 0);
  738. }
  739. send_seq += 2;
  740. if (send_seq > 255)
  741. send_seq = 0;
  742. awaiting_response = 1;
  743. }
  744. /************************** CIMD 2 specific code ends ************************/
  745. static void main_loop(void) {
  746. fd_set readfds, writefds;
  747. int n;
  748. static int reported_outfull = 0;
  749. int interval = -1;
  750. inbuffer = octstr_create("");
  751. outbuffer = octstr_create(intro);
  752. start_time = time(NULL);
  753. for (;;) {
  754. if (octstr_len(outbuffer) < OUTBUFFER_LIMIT) {
  755. interval = gen_data(outbuffer);
  756. } else if (!reported_outfull) {
  757. warning(0, "outbuffer getting full; waiting...");
  758. reported_outfull = 1;
  759. }
  760. FD_ZERO(&readfds);
  761. FD_SET(sockfd, &readfds);
  762. if (octstr_len(outbuffer) > 0) {
  763. FD_ZERO(&writefds);
  764. FD_SET(sockfd, &writefds);
  765. n = select(sockfd+1, &readfds, &writefds, NULL, NULL);
  766. } else {
  767. struct timeval tv;
  768. struct timeval *tvp;
  769. if (interval >= 0) {
  770. tv.tv_sec = 0;
  771. tv.tv_usec = interval;
  772. tvp = &tv;
  773. } else {
  774. tvp = NULL;
  775. }
  776. n = select(sockfd+1, &readfds, NULL, NULL, tvp);
  777. }
  778. if (n < 0) {
  779. if (errno == EINTR) {
  780. warning(errno, "main loop, select");
  781. continue;
  782. }
  783. error(errno, "main loop, select");
  784. sleep(1);
  785. continue;
  786. }
  787. if (n > 0) {
  788. if (FD_ISSET(sockfd, &readfds)) {
  789. read_data(inbuffer, sockfd);
  790. parse_data(inbuffer, outbuffer);
  791. }
  792. if (octstr_len(outbuffer) > 0 &&
  793.     FD_ISSET(sockfd, &writefds)) {
  794. write_data(outbuffer, sockfd);
  795. }
  796. if (octstr_len(outbuffer) < OUTBUFFER_LIMIT) {
  797. reported_outfull = 0;
  798. }
  799. }
  800. }
  801. }
  802. static struct {
  803. unsigned char *option;
  804. void *location;
  805. int number;
  806. } options[] = {
  807. { "--user", &username, 0 },
  808. { "--password", &password, 0 },
  809. { "--port", &port, 1 },
  810. { "--intro", &intro, 0 },
  811. { "--activity", &activity, 1 },
  812. { "--spew", &spew, 1 },
  813. { "--logging", &logging, 1 },
  814. { "--checking", &checking, 1 },
  815. { "--max", &max_deliveries, 1 },
  816. { NULL, NULL, 0 },
  817. };
  818. static int wait_for_client(int port) {
  819. struct sockaddr_in sin;
  820. socklen_t addrlen;
  821. int listenfd;
  822. int clientfd;
  823. Octstr *addr;
  824. listenfd = make_server_socket(port, NULL);
  825. if (listenfd < 0) {
  826. fprintf(stderr, "%s: failed to open socket at port %dn",
  827. progname, port);
  828. exit(1);
  829. }
  830. do {
  831. addrlen = sizeof(sin);
  832. clientfd = accept(listenfd, (struct sockaddr *)&sin, &addrlen);
  833. if (clientfd < 0) {
  834. error(errno, "failed to accept new connection");
  835. }
  836. } while (clientfd < 0);
  837. if (socket_set_blocking(clientfd, 0) < 0) {
  838. panic(0, "failed to make client socket nonblocking");
  839. }
  840.      addr = gw_netaddr_to_octstr(AF_INET, &sin.sin_addr);
  841. info(0, "Accepted client from %s:%d",
  842. octstr_get_cstr(addr), ntohs(sin.sin_port));
  843.      octstr_destroy(addr);
  844. close(listenfd);
  845. return clientfd;
  846. }
  847. int main(int argc, char *argv[]) {
  848. int i;
  849. int opt;
  850. gwlib_init();
  851. progname = argv[0];
  852. srandom(0);  /* Make "random" data reproducible */
  853. for (i = 1; i < argc; i++) {
  854. for (opt = 0; options[opt].option; opt++) {
  855. if (strcmp(argv[i], options[opt].option) == 0) {
  856. if (i + 1 >= argc) {
  857. fprintf(stderr, "%s: missing argument to %s",
  858. progname, argv[i]);
  859. exit(2);
  860. }
  861. if (options[opt].number) {
  862. * (int *) options[opt].location = atoi(argv[i+1]);
  863. } else {
  864. * (char **) options[opt].location = argv[i+1];
  865. }
  866. i++;
  867. break;
  868. }
  869. }
  870. if (options[opt].option)
  871. continue;
  872. if (strcmp(argv[i], "--help") == 0) {
  873. usage(stdout);
  874. exit(0);
  875. }
  876. if (argv[i][0] == '-') {
  877. fprintf(stderr, "%s: unknown option %sn",
  878. progname, argv[i]);
  879. usage(stderr);
  880. exit(2);
  881. }
  882. }
  883. sockfd = wait_for_client(port);
  884. main_loop();
  885. return 0;
  886. }