Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
test_smsc.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 #include <unistd.h>
58 #include "gwlib/gwlib.h"
59 #include "gw/smsc/smpp_pdu.h"
60 #include <string.h>
61 
62 /***********************************************************************
63  * Configurable stuff.
64  */
65 
66 
67 /*
68  * The port at which our HTTP server emulator listens.
69  */
70 static long http_port = 8080;
71 
72 
73 /*
74  * The HTTP admin port and password for Kannel, needed to do shutdown.
75  */
76 static long admin_port = 13000;
77 static char *admin_password = "bar";
78 
79 
80 /*
81  * The port at which the SMPP SMS center emulator listens.
82  */
83 static long smpp_port = 2345;
84 
85 
86 /*
87  * Number of messages to use in the "Send N messages as fast as possible"
88  * benchmark.
89  */
90 static long num_messages = 1;
91 
92 
93 /***********************************************************************
94  * Events and event queues.
95  */
96 
97 typedef List EventQueue;
98 
99 
100 typedef struct Event {
101  enum event_type {
109  } type;
110  long id;
111  long time;
112 
113  Connection *conn; /* SMPP: Connection for response PDU */
114  long sequence_number; /* SMPP: Sequence number of resp PDU */
115 
116  /* HTTP related stuff */
119 } Event;
120 
121 
122 static Counter *event_id_counter = NULL;
123 
124 
125 static const char *eq_type(Event *e)
126 {
127 #define TYPE(name) case name: return #name;
128  switch (e->type) {
129  TYPE(got_smsc)
130  TYPE(deliver)
131  TYPE(deliver_ack)
132  TYPE(http_request)
133  TYPE(http_response)
134  TYPE(submit)
135  TYPE(got_enquire_link)
136  }
137 #undef TYPE
138  return "unknown";
139 }
140 
141 
142 static Event *eq_create_event(enum event_type type)
143 {
144  Event *e;
145 
146  e = gw_malloc(sizeof(*e));
147  e->type = type;
148  e->time = date_universal_now();
149  e->id = counter_increase(event_id_counter);
150  e->conn = NULL;
151  e->sequence_number = -1;
152  e->client = NULL;
153  e->body = NULL;
154  return e;
155 }
156 
157 
158 static Event *eq_create_submit(Connection *conn, long sequence_number,
159  Octstr *body)
160 {
161  Event *e;
162 
163  gw_assert(conn != NULL);
164  gw_assert(sequence_number >= 0);
165 
166  e = eq_create_event(submit);
167  e->conn = conn;
168  e->sequence_number = sequence_number;
169  e->body = octstr_duplicate(body);
170  return e;
171 }
172 
173 
175 {
176  Event *e;
177 
178  gw_assert(client != NULL);
179  gw_assert(body != NULL);
180 
181  e = eq_create_event(http_request);
182  e->client = client;
183  e->body = octstr_duplicate(body);
184  return e;
185 }
186 
187 
188 static void eq_destroy_event(Event *e)
189 {
190  octstr_destroy(e->body);
191  gw_free(e);
192 }
193 
194 
195 static EventQueue *eq_create(void)
196 {
197  return gwlist_create();
198 }
199 
200 
201 static void eq_add_producer(EventQueue *eq)
202 {
204 }
205 
206 
208 {
210 }
211 
212 
213 static void eq_destroy(EventQueue *eq)
214 {
215  gwlist_destroy(eq, NULL);
216 }
217 
218 
219 static void eq_append(EventQueue *eq, Event *e)
220 {
221  gwlist_produce(eq, e);
222 }
223 
224 
226 {
227  return gwlist_consume(eq);
228 }
229 
230 
231 static void eq_log(Event *e)
232 {
233  info(0, "Event %ld, type %s, time %ld", e->id, eq_type(e), e->time);
234 }
235 
236 
237 static void eq_init(void)
238 {
239  event_id_counter = counter_create();
240 }
241 
242 
243 static void eq_shutdown(void)
244 {
245  counter_destroy(event_id_counter);
246 }
247 
248 
249 static long eq_round_trip_time(Event *e)
250 {
251  long now, then;
252 
253  now = date_universal_now();
254  if (octstr_parse_long(&then, e->body, 0, 10) == -1)
255  return 0;
256  return now - then;
257 }
258 
259 
260 /***********************************************************************
261  * SMS center emulator, declarations.
262  */
263 
264 
265 struct smsc_emu_arg {
268 };
269 
270 
272 
273 
274 /***********************************************************************
275  * SMS center emulator, SMPP internals.
276  */
277 
278 
279 enum { MAX_THREADS = 2 };
280 enum { SMPP_MAX_QUEUE = 10 };
281 
282 
283 struct smpp_emu_arg {
286  long id;
288  long writer_id;
289  int quit;
290 };
291 
292 
293 static Counter *smpp_emu_counter = NULL;
294 
295 
296 static void smpp_emu_writer(void *arg)
297 {
298  Event *e;
299  SMPP_PDU *pdu;
300  Octstr *os;
301  struct smpp_emu_arg *p;
302 
303  p = arg;
304  for (;;) {
306  e = eq_extract(undelivered_messages);
307  if (e == NULL)
308  break;
309  e->time = date_universal_now();
310  eq_log(e);
311  pdu = smpp_pdu_create(deliver_sm,
312  counter_increase(smpp_emu_counter));
313  pdu->u.deliver_sm.source_addr = octstr_create("123");
314  pdu->u.deliver_sm.destination_addr = octstr_create("456");
315  pdu->u.deliver_sm.short_message = octstr_format("%ld", e->time);
316  os = smpp_pdu_pack(NULL, pdu);
317  conn_write(p->conn, os);
318  octstr_destroy(os);
319  smpp_pdu_destroy(pdu);
320  eq_destroy_event(e);
321  }
322 }
323 
324 
325 static void smpp_emu_handle_pdu(struct smpp_emu_arg *p, SMPP_PDU *pdu)
326 {
327  SMPP_PDU *resp;
328  Octstr *os;
329 
330  resp = NULL;
331  switch (pdu->type) {
332  case bind_transmitter:
333  resp = smpp_pdu_create(bind_transmitter_resp,
334  pdu->u.bind_transmitter.sequence_number);
335  break;
336 
337  case bind_receiver:
338  resp = smpp_pdu_create(bind_receiver_resp,
339  pdu->u.bind_receiver.sequence_number);
340  eq_append(p->eq, eq_create_event(got_smsc));
341  gw_assert(p->writer_id == -1);
343  if (p->writer_id == -1)
344  panic(0, "Couldn't create SMPP helper thread.");
345  break;
346 
347  case submit_sm:
348  eq_append(p->eq,
349  eq_create_submit(p->conn, pdu->u.submit_sm.sequence_number,
350  pdu->u.submit_sm.short_message));
351  break;
352 
353  case deliver_sm_resp:
354  eq_append(p->eq, eq_create_event(deliver_ack));
356  break;
357 
358  case enquire_link:
359  eq_append(p->eq, eq_create_event(got_enquire_link));
360  resp = smpp_pdu_create(enquire_link_resp,
361  pdu->u.enquire_link.sequence_number);
362  break;
363 
364  case unbind:
365  resp = smpp_pdu_create(unbind_resp,
366  pdu->u.unbind.sequence_number);
367  break;
368 
369  default:
370  error(0, "SMPP: Unhandled PDU type %s", pdu->type_name);
371  break;
372  }
373 
374  if (resp != NULL) {
375  os = smpp_pdu_pack(NULL, resp);
376  conn_write(p->conn, os);
377  octstr_destroy(os);
378  smpp_pdu_destroy(resp);
379  }
380 }
381 
382 
383 static void smpp_emu_reader(void *arg)
384 {
385  Octstr *os;
386  long len;
387  SMPP_PDU *pdu;
388  struct smpp_emu_arg *p;
389 
390  p = arg;
391 
392  len = 0;
393  while (!p->quit && conn_wait(p->conn, -1.0) != -1) {
394  for (;;) {
395  if (len == 0) {
396  len = smpp_pdu_read_len(p->conn);
397  if (len == -1) {
398  error(0, "Client sent garbage, closing connection.");
399  goto error;
400  } else if (len == 0) {
401  if (conn_eof(p->conn) || conn_error(p->conn))
402  goto error;
403  break;
404  }
405  }
406 
407  gw_assert(len > 0);
408  os = smpp_pdu_read_data(p->conn, len);
409  if (os != NULL) {
410  len = 0;
411  pdu = smpp_pdu_unpack(NULL, os);
412  if (pdu == NULL) {
413  error(0, "PDU unpacking failed!");
414  octstr_dump(os, 0);
415  } else {
416  smpp_emu_handle_pdu(p, pdu);
417  smpp_pdu_destroy(pdu);
418  }
419  octstr_destroy(os);
420  } else if (conn_eof(p->conn) || conn_error(p->conn))
421  goto error;
422  else
423  break;
424  }
425  }
426 
427 error:
428  if (p->writer_id != -1)
430 }
431 
432 
433 static void smpp_emu(void *arg)
434 {
435  EventQueue *eq;
436  struct smsc_emu_arg *p;
437  int fd;
438  int new_fd;
439  Octstr *client_addr;
440  long i;
441  long num_threads;
442  struct smpp_emu_arg *thread[MAX_THREADS];
443 
444  p = arg;
445  eq = p->eq;
446  eq_add_producer(eq);
447  semaphore_up(p->sema);
448 
449  /*
450  * Wait for SMPP clients.
451  */
452  fd = make_server_socket(smpp_port, NULL);
453  if (fd == -1)
454  panic(0, "Couldn't create SMPP listen port.");
455 
456  num_threads = 0;
457  for (;;) {
458  new_fd = gw_accept(fd, &client_addr);
459  if (new_fd == -1)
460  break;
461  octstr_destroy(client_addr);
462  if (num_threads == MAX_THREADS) {
463  warning(0, "Too many SMPP client connections.");
464  (void) close(new_fd);
465  } else {
466  thread[num_threads] = gw_malloc(sizeof(*thread[0]));
467  thread[num_threads]->conn = conn_wrap_fd(new_fd, 0);
468  thread[num_threads]->eq = eq;
469  thread[num_threads]->quit = 0;
470  thread[num_threads]->writer_id = -1;
471  thread[num_threads]->ok_to_send =
473  thread[num_threads]->id =
474  gwthread_create(smpp_emu_reader, thread[num_threads]);
475  if (thread[num_threads]->id == -1)
476  panic(0, "Couldn't start SMPP subthread.");
477  ++num_threads;
478  }
479  }
480 
481  for (i = 0; i < num_threads; ++i) {
482  thread[i]->quit = 1;
483  gwthread_wakeup(thread[i]->id);
484  gwthread_join(thread[i]->id);
485  conn_destroy(thread[i]->conn);
486  semaphore_destroy(thread[i]->ok_to_send);
487  gw_free(thread[i]);
488  }
489 
490  eq_remove_producer(eq);
491 }
492 
493 
494 /***********************************************************************
495  * SMS center emulator, generic interface.
496  */
497 
498 
499 static long smpp_emu_id = -1;
500 
501 
502 /*
503  * Start all SMS center emulators.
504  */
506 {
507  struct smsc_emu_arg *arg;
508 
509  gw_assert(smpp_emu_id == -1);
510 
511  arg = gw_malloc(sizeof(*arg));
512  arg->sema = semaphore_create(0);
513  arg->eq = eq;
515  if (smpp_emu_id == -1)
516  panic(0, "Couldn't start SMPP emulator thread.");
517  semaphore_down(arg->sema);
518  semaphore_destroy(arg->sema);
519  gw_free(arg);
520 }
521 
522 
523 static void smsc_emu_destroy(void)
524 {
525  eq_remove_producer(undelivered_messages);
526  gw_assert(smpp_emu_id != -1);
529 }
530 
531 
532 static void smsc_emu_deliver(void)
533 {
534  eq_append(undelivered_messages, eq_create_event(deliver));
535 }
536 
537 
538 static void smsc_emu_submit_ack(Event *e)
539 {
540  SMPP_PDU *resp;
541  Octstr *os;
542 
543  resp = smpp_pdu_create(submit_sm_resp, e->sequence_number);
544  os = smpp_pdu_pack(NULL, resp);
545  conn_write(e->conn, os);
546  octstr_destroy(os);
547  smpp_pdu_destroy(resp);
548 }
549 
550 
551 static void smsc_emu_init(void)
552 {
553  smpp_emu_counter = counter_create();
554  undelivered_messages = eq_create();
555  eq_add_producer(undelivered_messages);
556 }
557 
558 
559 static void smsc_emu_shutdown(void)
560 {
561  counter_destroy(smpp_emu_counter);
562  eq_destroy(undelivered_messages);
563 }
564 
565 
566 /***********************************************************************
567  * HTTP server emulator.
568  */
569 
570 
571 static List *httpd_emu_headers = NULL;
572 
573 
575  int port;
578 };
579 
580 
581 /*
582  * This is the HTTP server emulator thread.
583  */
584 static void httpd_emu(void *arg)
585 {
587  Octstr *ip;
588  Octstr *url;
589  List *headers;
590  Octstr *body;
591  List *cgivars;
592  struct httpd_emu_arg *p;
593  EventQueue *eq;
594 
595  p = arg;
596  eq = p->eq;
597  eq_add_producer(eq);
598  semaphore_up(p->sema);
599 
600  for (;;) {
601  client = http_accept_request(p->port, &ip, &url, &headers, &body,
602  &cgivars);
603  if (client == NULL)
604  break;
605 
606  eq_append(eq, eq_create_http_request(client,
607  http_cgi_variable(cgivars, "arg")));
608  octstr_destroy(ip);
609  octstr_destroy(url);
610  http_destroy_headers(headers);
611  octstr_destroy(body);
612  http_destroy_cgiargs(cgivars);
613  }
614  eq_remove_producer(eq);
615  gw_free(p);
616 }
617 
618 
619 /*
620  * Thread id for HTTP server emulator thread. It is needed for proper
621  * shutdown.
622  */
623 static long httpd_emu_tid = -1;
624 
625 
626 /*
627  * Start the HTTP server emulator thread and return when it is
628  * ready to accept clients.
629  */
631 {
632  struct httpd_emu_arg *arg;
633  int ssl = 0; /* indicate if SSL-enabled server should be used */
634 
635  if (http_open_port(http_port, ssl) == -1)
636  panic(0, "Can't open HTTP server emulator port %ld.", http_port);
637 
638  gw_assert(httpd_emu_tid == -1);
639  arg = gw_malloc(sizeof(*arg));
640  arg->port = http_port;
641  arg->sema = semaphore_create(0);
642  arg->eq = eq;
644  if (httpd_emu_tid == -1)
645  panic(0, "Can't start the HTTP server emulator thread.");
646  semaphore_down(arg->sema);
647  semaphore_destroy(arg->sema);
648 }
649 
650 
651 /*
652  * Terminate the HTTP server emulator thread. Return when the thread
653  * is quite dead.
654  */
655 static void httpd_emu_destroy(void)
656 {
657  gw_assert(httpd_emu_tid != -1);
660  httpd_emu_tid = -1;
661 }
662 
663 
664 /*
665  * Send a reply to an HTTP response.
666  */
667 static void httpd_emu_reply(Event *e)
668 {
669  http_send_reply(e->client, HTTP_OK, httpd_emu_headers, e->body);
670 }
671 
672 
673 static void httpd_emu_init(void)
674 {
675  httpd_emu_headers = http_create_empty_headers();
676  http_header_add(httpd_emu_headers, "Content-Type", "text/plain");
677 }
678 
679 
680 static void httpd_emu_shutdown(void)
681 {
682  http_destroy_headers(httpd_emu_headers);
683 }
684 
685 
686 /***********************************************************************
687  * Main program for N SMS messages benchmark.
688  */
689 
690 
691 static void kill_kannel(void)
692 {
693  Octstr *url;
694  Octstr *final_url;
695  List *req_headers;
696  List *reply_headers;
697  Octstr *reply_body;
698  int ret;
699 
700  url = octstr_format("http://localhost:%ld/shutdown?password=%s",
702  req_headers = http_create_empty_headers();
703  http_header_add(req_headers, "Content-Type", "text/plain");
704  ret = http_get_real(HTTP_METHOD_GET, url, req_headers, &final_url,
705  &reply_headers, &reply_body);
706  if (ret != -1) {
707  octstr_destroy(final_url);
708  http_destroy_headers(reply_headers);
709  octstr_destroy(reply_body);
710  }
711  octstr_destroy(url);
712  http_destroy_headers(req_headers);
713 }
714 
715 
716 /*
717  * This will try to have as large a sustained level of traffic as possible.
718  */
719 
720 enum { MAX_IN_AVERAGE = 100 };
721 enum { MAX_RTT = 1 };
722 enum { MAX_WAITING = 100 };
723 
724 static void sustained_level_benchmark(void)
725 {
726  EventQueue *eq;
727  Event *e;
728  long i;
729  long num_deliver;
730  long num_submit;
731  long rtt;
732  long times[MAX_IN_AVERAGE];
733  long next_time;
734  double time_sum;
735  long num_unanswered;
736 
737  eq = eq_create();
738 
739  httpd_emu_create(eq);
740  smsc_emu_create(eq);
741 
742  /* Wait for an SMS center client to appear. */
743  while ((e = eq_extract(eq)) != NULL && e->type != got_smsc)
744  debug("test_smsc", 0, "Discarding event of type %s", eq_type(e));
745  debug("test_smsc", 0, "Got event got_smsc.");
746  eq_destroy_event(e);
747 
748  /*
749  * Send message when there are at most MAX_WAITING unanswered messages
750  * and current average round trip time is less than MAX_RTT.
751  */
752  num_submit = 0;
753  for (i = 0; i < MAX_IN_AVERAGE; ++i)
754  times[i] = 0;
755  next_time = 0;
756  time_sum = 0.0;
757  num_unanswered = 0;
758  num_deliver = 0;
759 
760  while (num_submit < num_messages) {
761  for (;;) {
762  if (num_deliver >= num_messages || num_unanswered >= MAX_WAITING)
763  break;
764  if (time_sum / MAX_IN_AVERAGE >= MAX_RTT && num_unanswered > 0)
765  break;
767  ++num_unanswered;
768  ++num_deliver;
769  }
770 
771  e = eq_extract(eq);
772  if (e == NULL)
773  break;
774  eq_log(e);
775 
776  switch (e->type) {
777  case deliver_ack:
778  break;
779 
780  case http_request:
781  httpd_emu_reply(e);
782  break;
783 
784  case submit:
785  rtt = eq_round_trip_time(e);
786  time_sum -= times[next_time];
787  times[next_time] = rtt;
788  time_sum += times[next_time];
789  debug("", 0, "RTT = %ld", rtt);
790  next_time = (next_time + 1) % MAX_IN_AVERAGE;
791  ++num_submit;
792  --num_unanswered;
794  break;
795 
796  case got_enquire_link:
797  break;
798 
799  default:
800  debug("test_smsc", 0, "Ignoring event of type %s", eq_type(e));
801  break;
802  }
803 
804  eq_destroy_event(e);
805  }
806 
807  kill_kannel();
808 
809  debug("test_smsc", 0, "Terminating benchmark.");
812  eq_destroy(eq);
813 }
814 
815 
816 /*
817  * This will send `num_messages' SMS messages as quickly as possible.
818  */
819 
820 enum { MAX_IN_QUEUE = 1000 };
821 
822 static void n_messages_benchmark(void)
823 {
824  EventQueue *eq;
825  Event *e;
826  long i;
827  long num_submit;
828  long num_in_queue;
829  long num_deliver;
830 
831  eq = eq_create();
832 
833  httpd_emu_create(eq);
834  smsc_emu_create(eq);
835 
836  /* Wait for an SMS center client to appear. */
837  while ((e = eq_extract(eq)) != NULL && e->type != got_smsc)
838  debug("test_smsc", 0, "Discarding event of type %s", eq_type(e));
839  debug("test_smsc", 0, "Got event got_smsc.");
840  eq_destroy_event(e);
841 
842  /* Send the SMS messages, or at least fill the send queue. */
843  for (i = 0; i < num_messages && i < MAX_IN_QUEUE; ++i)
845  num_in_queue = i;
846  num_deliver = i;
847 
848  /*
849  * Wait for results to be processed. When send queue is not full,
850  * fill it.
851  */
852  num_submit = 0;
853  while (num_submit < num_messages && (e = eq_extract(eq)) != NULL) {
854  while (num_deliver < num_messages && num_in_queue < MAX_IN_QUEUE) {
856  ++num_in_queue;
857  ++num_deliver;
858  }
859 
860  eq_log(e);
861 
862  switch (e->type) {
863  case deliver_ack:
864  break;
865 
866  case http_request:
867  httpd_emu_reply(e);
868  break;
869 
870  case submit:
871  debug("", 0, "RTT = %ld", eq_round_trip_time(e));
873  ++num_submit;
874  --num_in_queue;
875  break;
876 
877  case got_enquire_link:
878  break;
879 
880  default:
881  debug("test_smsc", 0, "Ignoring event of type %s", eq_type(e));
882  break;
883  }
884 
885  eq_destroy_event(e);
886  }
887 
888  kill_kannel();
889 
890  debug("test_smsc", 0, "Terminating benchmark.");
893  eq_destroy(eq);
894 }
895 
896 
897 /***********************************************************************
898  * Main program.
899  */
900 
901 
902 int main(int argc, char **argv)
903 {
904  int opt;
905  char *main_name;
906  int i;
907  static struct {
908  char *name;
909  void (*func)(void);
910  } tab[] = {
911  { "n_messages", n_messages_benchmark },
912  { "sustained_level", sustained_level_benchmark },
913  };
914 
915  gwlib_init();
916  eq_init();
917  httpd_emu_init();
918  smsc_emu_init();
919 
920  main_name = "n_messages_benchmark";
921 
922  while ((opt = getopt(argc, argv, "m:r:")) != EOF) {
923  switch (opt) {
924  case 'm':
925  main_name = optarg;
926  break;
927  case 'r':
928  num_messages = atoi(optarg);
929  break;
930  }
931  }
932 
933  for (i = 0; (size_t) i < sizeof(tab) / sizeof(tab[0]); ++i) {
934  if (strcmp(main_name, tab[i].name) == 0) {
935  tab[i].func();
936  break;
937  }
938  }
939 
942  eq_shutdown();
943  gwlib_shutdown();
944  return 0;
945 }
void smpp_pdu_destroy(SMPP_PDU *pdu)
Definition: smpp_pdu.c:381
static long num_messages
Definition: test_smsc.c:90
static Event * eq_extract(EventQueue *eq)
Definition: test_smsc.c:225
void error(int err, const char *fmt,...)
Definition: log.c:612
#define TYPE(name)
void info(int err, const char *fmt,...)
Definition: log.c:636
long time
Definition: test_smsc.c:111
Semaphore * ok_to_send
Definition: test_smsc.c:287
void semaphore_up(Semaphore *semaphore)
Definition: semaphore.c:118
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2863
int ssl
void counter_destroy(Counter *counter)
Definition: counter.c:110
int main(int argc, char **argv)
Definition: test_smsc.c:902
static void smpp_emu_writer(void *arg)
Definition: test_smsc.c:296
Semaphore * semaphore_create(long n)
Definition: semaphore.c:81
static void smsc_emu_shutdown(void)
Definition: test_smsc.c:559
static void n_messages_benchmark(void)
Definition: test_smsc.c:822
Octstr * body
Definition: test_smsc.c:118
void gwlist_produce(List *list, void *item)
Definition: list.c:411
void gwthread_join(long thread)
static void client(int port)
Definition: test_udp.c:77
static void eq_log(Event *e)
Definition: test_smsc.c:231
const char * type_name
Definition: smpp_pdu.h:92
static void smpp_emu_handle_pdu(struct smpp_emu_arg *p, SMPP_PDU *pdu)
Definition: test_smsc.c:325
int type
Definition: smsc_cimd2.c:215
unsigned long type
Definition: smpp_pdu.h:91
void semaphore_down(Semaphore *semaphore)
Definition: semaphore.c:132
static void eq_destroy_event(Event *e)
Definition: test_smsc.c:188
EventQueue * eq
Definition: test_smsc.c:267
static long httpd_emu_tid
Definition: test_smsc.c:623
long smpp_pdu_read_len(Connection *conn)
Definition: smpp_pdu.c:816
static Counter * smpp_emu_counter
Definition: test_smsc.c:293
static void httpd_emu_destroy(void)
Definition: test_smsc.c:655
long id
Definition: test_smsc.c:110
int conn_eof(Connection *conn)
Definition: conn.c:697
static void smsc_emu_deliver(void)
Definition: test_smsc.c:532
static void httpd_emu_create(EventQueue *eq)
Definition: test_smsc.c:630
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
static void eq_append(EventQueue *eq, Event *e)
Definition: test_smsc.c:219
static void eq_add_producer(EventQueue *eq)
Definition: test_smsc.c:201
Octstr * http_cgi_variable(List *list, char *name)
Definition: http.c:2813
static void smsc_emu_destroy(void)
Definition: test_smsc.c:523
static char * admin_password
Definition: test_smsc.c:77
EventQueue * eq
Definition: test_smsc.c:284
void http_destroy_headers(List *headers)
Definition: http.c:2856
static void httpd_emu(void *arg)
Definition: test_smsc.c:584
int getopt(int argc, char **argv, char *opts)
Definition: attgetopt.c:84
Connection * conn
Definition: test_smsc.c:285
void http_destroy_cgiargs(List *args)
Definition: http.c:2795
static void httpd_emu_shutdown(void)
Definition: test_smsc.c:680
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2671
Definition: http.h:142
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1043
static Event * eq_create_event(enum event_type type)
Definition: test_smsc.c:142
Semaphore * sema
Definition: test_smsc.c:576
Counter * counter_create(void)
Definition: counter.c:94
int gw_accept(int fd, Octstr **client_addr)
Definition: socket.c:700
HTTPClient * http_accept_request(int port, Octstr **client_ip, Octstr **url, List **headers, Octstr **body, List **cgivars)
Definition: http.c:2574
static EventQueue * eq_create(void)
Definition: test_smsc.c:195
void gwlist_remove_producer(List *list)
Definition: list.c:401
void conn_destroy(Connection *conn)
Definition: conn.c:619
List * http_create_empty_headers(void)
Definition: http.c:2849
static void smsc_emu_init(void)
Definition: test_smsc.c:551
static void eq_shutdown(void)
Definition: test_smsc.c:243
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
Octstr * smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu)
Definition: smpp_pdu.c:405
static void eq_remove_producer(EventQueue *eq)
Definition: test_smsc.c:207
void semaphore_destroy(Semaphore *semaphore)
Definition: semaphore.c:104
SMPP_PDU * smpp_pdu_unpack(Octstr *smsc_id, Octstr *data_without_len)
Definition: smpp_pdu.c:544
static void httpd_emu_init(void)
Definition: test_smsc.c:673
long writer_id
Definition: test_smsc.c:288
static void sustained_level_benchmark(void)
Definition: test_smsc.c:724
char * name
Definition: smsc_cimd2.c:212
int make_server_socket(int port, const char *interface_name)
Definition: socket.c:93
void warning(int err, const char *fmt,...)
Definition: log.c:624
Semaphore * sema
Definition: test_smsc.c:266
static void eq_init(void)
Definition: test_smsc.c:237
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
long sequence_number
Definition: test_smsc.c:114
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
gw_assert(wtls_machine->packet_to_send!=NULL)
static Event * eq_create_http_request(HTTPClient *client, Octstr *body)
Definition: test_smsc.c:174
static long smpp_port
Definition: test_smsc.c:83
int http_open_port(int port, int ssl)
Definition: http.c:2498
static void smpp_emu(void *arg)
Definition: test_smsc.c:433
static void smsc_emu_submit_ack(Event *e)
Definition: test_smsc.c:538
static const char * eq_type(Event *e)
Definition: test_smsc.c:125
static EventQueue * undelivered_messages
Definition: test_smsc.c:271
long date_universal_now(void)
Definition: date.c:304
Octstr * smpp_pdu_read_data(Connection *conn, long len)
Definition: smpp_pdu.c:842
void http_close_all_ports(void)
Definition: http.c:2515
static void kill_kannel(void)
Definition: test_smsc.c:691
static void smsc_emu_create(EventQueue *eq)
Definition: test_smsc.c:505
List EventQueue
Definition: test_smsc.c:97
int http_get_real(int method, Octstr *url, List *request_headers, Octstr **final_url, List **reply_headers, Octstr **reply_body)
Definition: http.c:1806
static List * httpd_emu_headers
Definition: test_smsc.c:571
enum Event::event_type type
Definition: octstr.c:118
int conn_wait(Connection *conn, double seconds)
Definition: conn.c:896
void * gwlist_consume(List *list)
Definition: list.c:427
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
char * optarg
Definition: attgetopt.c:82
EventQueue * eq
Definition: test_smsc.c:577
#define panic
Definition: log.h:87
static void httpd_emu_reply(Event *e)
Definition: test_smsc.c:667
void gwthread_wakeup(long thread)
static void eq_destroy(EventQueue *eq)
Definition: test_smsc.c:213
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
Definition: octstr.c:747
Connection * conn
Definition: test_smsc.c:113
void gwlib_shutdown(void)
Definition: gwlib.c:94
#define gwlist_create()
Definition: list.h:136
union SMPP_PDU::@14 u
struct Event Event
void gwlib_init(void)
Definition: gwlib.c:78
int conn_error(Connection *conn)
Definition: conn.c:708
static long smpp_emu_id
Definition: test_smsc.c:499
event_type
Definition: test_smsc.c:101
static void smpp_emu_reader(void *arg)
Definition: test_smsc.c:383
static Counter * event_id_counter
Definition: test_smsc.c:122
HTTPClient * client
Definition: test_smsc.c:117
void gwlist_add_producer(List *list)
Definition: list.c:383
static long admin_port
Definition: test_smsc.c:76
static Octstr * url
Definition: test_xmlrpc.c:84
static Event * eq_create_submit(Connection *conn, long sequence_number, Octstr *body)
Definition: test_smsc.c:158
Definition: list.c:102
SMPP_PDU * smpp_pdu_create(unsigned long type, unsigned long seq_no)
Definition: smpp_pdu.c:347
static long eq_round_trip_time(Event *e)
Definition: test_smsc.c:249
static long http_port
Definition: test_smsc.c:70
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:558
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.