Kannel: Open Source WAP and SMS gateway  svn-r5335
drive_wapbox.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 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 /* drive_wapbox.c - test wapbox through its bearerbox and http interfaces
58  *
59  * This program starts a wapbox and pretends to be both the bearer box
60  * and the http server, so that it can test and benchmark the wapbox in
61  * isolation.
62  *
63  * Richard Braakman
64  */
65 
66 #include <string.h>
67 #include <stdlib.h>
68 #include <unistd.h>
69 #include <errno.h>
70 #include <signal.h>
71 
72 #include <sys/time.h>
73 #include <sys/types.h>
74 #include <sys/socket.h>
75 
76 #include "gwlib/gwlib.h"
77 #include "gw/msg.h"
78 
79 /* These should really be in a header file */
80 enum wsp_types {
81  Bad_PDU = -1,
82  Connect_PDU = 0x01,
84  Redirect_PDU = 0x03,
85  Reply_PDU = 0x04,
87  Push_PDU = 0x06,
89  Suspend_PDU = 0x08,
90  Resume_PDU = 0x09,
91  Get_PDU = 0x40,
92  Options_PDU = 0x41,
93  Head_PDU = 0x42,
94  Delete_PDU = 0x43,
95  Trace_PDU = 0x44,
96  Post_PDU = 0x60,
97  Put_PDU = 0x61
98 };
99 
100 enum wtp_types {
101  INVOKE = 1,
102  RESULT = 2,
103  ACK = 3
104 };
105 
106 #define WSP_VERSION 0x10
107 
108 #define TIMEOUT 10.0 /* seconds */
109 
110 static long max_requests = 1;
111 static long max_clients = 1;
112 static long req_per_session = 1;
113 static unsigned short http_port;
114 static int wapbox_port = 30188;
115 static Octstr *http_url = NULL;
116 
117 static int verbose_debug = 0;
118 static int user_ack = 0;
119 
120 static long requests_complete = 0;
121 static volatile sig_atomic_t dying = 0;
122 
123 enum WTP_type {
126  TR_Ack = 3,
128 };
129 
131  /* True if we expect a WTP reply */
133 
134  /* Transaction number for WTP level */
135  int wtp_tid; /* current tid if wtp_invoked, else next tid to use */
136 
137  /* True if we're connected at the WSP level */
138  /* Equal to 2 if we're trying to disconnect */
140 
141  /* -1 if we're not connected */
143 
144  /* Number of successful page fetches this session */
146 
147  /* Source port to use for this client; should be unique. */
148  unsigned short port;
149 };
150 typedef struct client_status Client;
151 
152 static Client *clients;
154 
155 static unsigned long get_varint(Octstr *pdu, int pos) {
156  int c;
157  long result = 0;
158 
159  do {
160  c = octstr_get_char(pdu, pos++);
161  result = (result << 7) | (c & 0x7f);
162  } while (c & 0x80);
163 
164  return c;
165 }
166 
167 static void http_thread(void *arg) {
169  Octstr *ip;
170  Octstr *url;
171  List *headers;
172  Octstr *body;
173  List *cgivars;
174  Octstr *reply_body = octstr_create(
175  "<?xml version=\"1.0\"?>\n"
176  "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"\n"
177  " \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n"
178  "<wml>\n"
179  "<card id=\"main\" title=\"Hello, world\" newcontext=\"true\">\n"
180  " <p>Hello, world.</p>\n"
181  "</card></wml>\n");
182  List *reply_headers = gwlist_create();
183  int port;
184 
185  port = *(int *) arg;
186  gw_free(arg);
187 
188  gwlist_append(reply_headers,
189  octstr_create("Content-Type: text/vnd.wap.wml"));
190 
191  for (;!dying;) {
192  client = http_accept_request(port, &ip, &url, &headers,
193  &body, &cgivars);
194  if (client == NULL)
195  break;
196  http_send_reply(client, HTTP_OK, reply_headers, reply_body);
197  http_destroy_headers(headers);
198  octstr_destroy(ip);
200  octstr_destroy(body);
201  http_destroy_cgiargs(cgivars);
202  }
203 
204  octstr_destroy(reply_body);
205  http_destroy_headers(reply_headers);
206 }
207 
208 
209 static long http_thread_id;
210 
211 static int start_http_thread(void) {
212  unsigned short port;
213  int *port_copy;
214  int ssl = 0; /* indicate if SSL-enabled server should be used */
215 
216  for (port = 40000; port < 41000; port += 13) {
217  if (http_open_port(port, ssl) != -1)
218  break;
219  }
220  if (port == 41000)
221  panic(0, "No ports available for http server");
222 
223  port_copy = gw_malloc(sizeof(*port_copy));
224  *port_copy = port;
226  if (http_thread_id == -1)
227  panic(0, "Cannot start http thread");
228  return port;
229 }
230 
231 static Connection *start_wapbox(void) {
232  int wap_socket;
233  int wapbox;
234 
235  wap_socket = make_server_socket(wapbox_port, NULL);
236  if (wap_socket < 0)
237  panic(0, "Couldn't make wapbox port\n");
238 
239  wapbox = accept(wap_socket, NULL, NULL);
240  if (wapbox < 0)
241  panic(errno, "Wapbox could not connect\n");
242 
243  close(wap_socket);
244 
245  return conn_wrap_fd(wapbox, 0);
246 }
247 
248 static void initialize_clients(void) {
249  long i;
250 
252 
253  clients = gw_malloc(max_clients * sizeof(*clients));
254  for (i = 0; i < max_clients; i++) {
255  clients[i].wtp_invoked = 0;
256  clients[i].wtp_tid = 0;
257  clients[i].wsp_connected = 0;
258  clients[i].wsp_session_id = -1;
259  clients[i].pages_fetched = 0;
260  clients[i].port = i;
262  }
263 }
264 
265 static void destroy_clients(void) {
266  gw_free(clients);
268 }
269 
270 static Client *find_client(unsigned short port) {
271  /* It's easy and fast since we assign ports in linear order */
272  if (port >= max_clients)
273  return NULL;
274 
275  return clients + port;
276 }
277 
278 static void client_done(Client *client) {
281 }
282 
283 static void increment_tid(Client *client) {
284  if (client->wtp_tid == 0x7fff)
285  client->wtp_tid = 0;
286  else
287  client->wtp_tid++;
288 }
289 
290 /* Set the U/P flag on an Invoke PDU */
291 static void set_user_ack(Octstr *pdu) {
292  octstr_set_bits(pdu, 3 * 8 + 3, 1, 1);
293 }
294 
295 static Octstr *wtp_invoke_create(int class) {
296  Octstr *pdu;
297  /* data describes a TR-Invoke PDU, with GTR=1 and TTR=1 (segmentation
298  * not supported), and Transaction class 0 (which we replace below) */
299  static unsigned char data[] = { 0x0e, 0x00, 0x00, 0x00 };
300  gw_assert(class >= 0);
301  gw_assert(class <= 2);
302  pdu = octstr_create_from_data(data, sizeof(data));
303  octstr_set_char(pdu, 3, class);
304 
305  if (user_ack)
306  set_user_ack(pdu);
307 
308  return pdu;
309 }
310 
311 static Octstr *wtp_ack_create(void) {
312  static unsigned char data[] = { 0x18, 0x00, 0x00 };
313  return octstr_create_from_data(data, sizeof(data));
314 }
315 
316 static void add_wsp_connect(Octstr *pdu) {
317  static unsigned char data[] = { Connect_PDU, WSP_VERSION, 68, 0x00,
318  0x03, 0x80, 0x90, 0x00, 0x03, 0x81, 0x90, 0x00,
319  0x02, 0x82, 0x30, 0x02, 0x83, 0x01, 0x02, 0x84,
320  0x01, 0x28, 0x85, 0x50, 0x58, 0x2d, 0x55, 0x50,
321  0x2d, 0x41, 0x47, 0x45, 0x54, 0x00, 0x51, 0x58,
322  0x2d, 0x55, 0x50, 0x2d, 0x47, 0x45, 0x54, 0x4e,
323  0x4f, 0x54, 0x49, 0x46, 0x59, 0x00, 0x70, 0x58,
324  0x2d, 0x55, 0x50, 0x2d, 0x41, 0x50, 0x4f, 0x53,
325  0x54, 0x00, 0x09, 0x86, 0x02, 0x78, 0x2d, 0x75,
326  0x70, 0x2d, 0x31, 0x00 };
327  octstr_append_data(pdu, data, sizeof(data));
328 }
329 
330 static void add_wsp_get(Octstr *pdu) {
331  Octstr *urlbuf;
332 
334  if (http_url) {
336  octstr_append(pdu, http_url);
337  } else {
338  urlbuf = octstr_format("http://localhost:%ld/hello.wml",
339  (long) http_port);
340  octstr_append_uintvar(pdu, octstr_len(urlbuf));
341  octstr_append(pdu, urlbuf);
342  octstr_destroy(urlbuf);
343  }
344 }
345 
346 static void add_wsp_disconnect(Octstr *pdu, long session_id) {
348  octstr_append_uintvar(pdu, session_id);
349 }
350 
351 static void set_tid(Octstr *pdu, int tid) {
352  int c;
353 
354  /* Tid wraps at 15 bits. */
355  tid &= 0x7fff;
356 
357  c = octstr_get_char(pdu, 1);
358  c = (tid >> 8) | (c & 0x80);
359  octstr_set_char(pdu, 1, c);
360  octstr_set_char(pdu, 2, tid & 0xff);
361 }
362 
363 static int get_tid(Octstr *pdu) {
364  return octstr_get_bits(pdu, 8, 16);
365 }
366 
367 static int wtp_type(Octstr *pdu) {
368  return octstr_get_bits(pdu, 1, 4);
369 }
370 
371 static Msg *wdp_create(Octstr *data, Client *client) {
372  Msg *msg;
373 
374  msg = msg_create(wdp_datagram);
375  msg->wdp_datagram.source_address = octstr_create("127.0.0.1");
376  msg->wdp_datagram.source_port = client->port;
377  msg->wdp_datagram.destination_address = octstr_create("127.0.0.1");
378  msg->wdp_datagram.destination_port = 9201;
379  msg->wdp_datagram.user_data = octstr_duplicate(data);
380 
381  return msg;
382 }
383 
384 static void send_pdu(Octstr *pdu, Connection *boxc, Client *client) {
385  Msg *msg;
386  Octstr *data;
387 
388  if (verbose_debug) {
389  debug("test", 0, "Sending:");
390  octstr_dump(pdu, 0);
391  }
392 
393  msg = wdp_create(pdu, client);
394  data = msg_pack(msg);
395  conn_write_withlen(boxc, data);
396 
397  octstr_destroy(data);
398  msg_destroy(msg);
399 }
400 
402  Octstr *pdu;
403 
404  gw_assert(client != NULL);
405  gw_assert(client->wtp_invoked == 0);
406  gw_assert(client->wsp_connected == 0);
407 
408  pdu = wtp_invoke_create(2);
409  set_tid(pdu, client->wtp_tid);
410  add_wsp_connect(pdu);
411 
412  send_pdu(pdu, boxc, client);
413  octstr_destroy(pdu);
414 
415  client->wtp_invoked = 1;
416 }
417 
418 static void send_invoke_get(Connection *boxc, Client *client) {
419  Octstr *pdu;
420 
421  gw_assert(client != NULL);
422  gw_assert(client->wtp_invoked == 0);
423  gw_assert(client->wsp_connected == 1);
424 
425  pdu = wtp_invoke_create(2);
426  set_tid(pdu, client->wtp_tid);
427  add_wsp_get(pdu);
428 
429  send_pdu(pdu, boxc, client);
430  octstr_destroy(pdu);
431 
432  client->wtp_invoked = 1;
433 }
434 
436  client->wsp_connected = 0;
437  client->wsp_session_id = -1;
438  client->pages_fetched = 0;
440 }
441 
443  Octstr *pdu;
444 
445  gw_assert(client != NULL);
446  gw_assert(client->wtp_invoked == 0);
447  gw_assert(client->wsp_connected == 1);
448 
449  /* Kannel can't handle it as class 1 yet, so send class 0 */
450  pdu = wtp_invoke_create(0);
451  set_tid(pdu, client->wtp_tid);
452  add_wsp_disconnect(pdu, client->wsp_session_id);
453 
454  send_pdu(pdu, boxc, client);
455  octstr_destroy(pdu);
456 
459 }
460 
461 static void handle_connect_reply(Connection *boxc, Client *client, Octstr *pdu) {
462  Octstr *ack;
463 
464  gw_assert(client);
465  gw_assert(client->wtp_invoked);
466  gw_assert(!client->wsp_connected);
467 
468  if (octstr_get_char(pdu, 3) != ConnectReply_PDU) {
469  error(0, "Unexpected CONNECT reply");
470  octstr_dump(pdu, 0);
471  return;
472  }
473 
474  ack = wtp_ack_create();
475  set_tid(ack, client->wtp_tid);
476  send_pdu(ack, boxc, client);
477  octstr_destroy(ack);
478 
479  client->wtp_invoked = 0;
481  client->wsp_connected = 1;
482  client->wsp_session_id = get_varint(pdu, 4);
483 
484  send_invoke_get(boxc, client);
485 }
486 
487 static void handle_get_reply(Connection *boxc, Client *client, Octstr *pdu) {
488  Octstr *ack;
489 
490  gw_assert(client);
491  gw_assert(client->wtp_invoked);
492  gw_assert(client->wsp_connected);
493 
494  if (octstr_get_char(pdu, 3) != Reply_PDU) {
495  error(0, "Unexpected GET reply");
496  octstr_dump(pdu, 0);
497  return;
498  }
499 
500  ack = wtp_ack_create();
501  set_tid(ack, client->wtp_tid);
502  send_pdu(ack, boxc, client);
503  octstr_destroy(ack);
504 
505  client->wtp_invoked = 0;
507  client->pages_fetched++;
508 
509  if (client->pages_fetched == req_per_session) {
511  } else {
513  }
514 }
515 
516 static void handle_reply(Connection *boxc, Msg *reply) {
517  Client *client;
518  Octstr *wtp;
519  int type;
520  int dumped = 0;
521 
522  gw_assert(reply != NULL);
523  gw_assert(reply->type == wdp_datagram);
524 
525  client = find_client(reply->wdp_datagram.destination_port);
526  if (client == NULL)
527  panic(0, "got packet for nonexisting client %ld",
528  (long) reply->wdp_datagram.destination_port);
529 
530  wtp = reply->wdp_datagram.user_data;
531  type = wtp_type(wtp);
532 
533  if (verbose_debug) {
534  debug("test", 0, "Received:");
535  octstr_dump(wtp, 0);
536  dumped = 1;
537  }
538 
539  if (client->wtp_invoked == 0) {
540  error(0, "Got packet for client that wasn't waiting");
541  if (!dumped) {
542  octstr_dump(wtp, 0);
543  dumped = 1;
544  }
545  return;
546  }
547 
548  /* Server should invert the MSB of the tid in its replies */
549  if (get_tid(wtp) != (client->wtp_tid ^ 0x8000)) {
550  error(0, "Got packet with wrong tid %d, expected %d.",
551  get_tid(wtp), client->wtp_tid ^ 0x8000);
552  if (!dumped) {
553  octstr_dump(wtp, 0);
554  dumped = 1;
555  }
556  return;
557  }
558 
559  /* We're going to be stupid here, and assume that replies that
560  * look vaguely like what we expect are actually what we wanted. */
561  if (client->wsp_connected == 0 && type == RESULT) {
562  handle_connect_reply(boxc, client, wtp);
563  } else if (client->wsp_connected == 1 && type == RESULT) {
564  handle_get_reply(boxc, client, wtp);
565  } else if (client->wsp_connected == 2 && type == ACK) {
568  } else {
569  error(0, "Got unexpected packet");
570  if (!dumped) {
571  octstr_dump(wtp, 0);
572  dumped = 1;
573  }
574  }
575 }
576 
577 static void start_request(Connection *boxc, Client *client) {
578  gw_assert(client != NULL);
579  gw_assert(client->wsp_connected != 2);
580  gw_assert(client->wtp_invoked == 0);
581 
582  if (client->wsp_connected == 0) {
583  send_invoke_connect(boxc, client);
584  } else {
585  send_invoke_get(boxc, client);
586  }
587 }
588 
589 static long run_requests(Connection *boxc) {
590  int requests_sent;
591  Octstr *data;
592  Msg *msg;
593  int ret;
594 
595  requests_sent = 0;
596  requests_complete = 0;
597 
598  while (requests_complete < max_requests) {
599  data = conn_read_withlen(boxc);
600  if (!data) {
601  Client *client;
602 
603  if (requests_sent < max_requests
605  start_request(boxc, client);
606  requests_sent++;
607  }
608  ret = conn_wait(boxc, TIMEOUT);
609  if (ret < 0 || conn_eof(boxc))
610  panic(0, "Wapbox dead.");
611  if (ret == 1)
612  break; /* Timed out. */
613  } else {
614  msg = msg_unpack(data);
615  if (!msg) {
616  octstr_dump(data, 0);
617  panic(0, "Received bad data from wapbox.");
618  }
619  if (msg->type == wdp_datagram)
620  handle_reply(boxc, msg);
621  msg_destroy(msg);
622  }
623  octstr_destroy(data);
624  }
625 
627  info(0, "Timeout. %ld requests unsatisfied.",
629 
630  return requests_complete;
631 }
632 
633 static void help(void) {
634  info(0, "Usage: drive_wapbox [options...]\n");
635  info(0, " -r requests Stop after this many; default 1.");
636  info(0, " -c clients # of concurrent clients; default 1.");
637  info(0, " -w wapport Port wapbox should connect to; default 30188");
638  info(0, " -u url Use this url instead of internal http server");
639  info(0, " -g requests Number of requests per WSP session; default 1");
640  info(0, " -U Set the User ack flag on all WTP transactions");
641 }
642 
643 int main(int argc, char **argv) {
644  int opt;
645  struct timeval start, end;
646  Connection *boxc;
647  long completed;
648  double run_time;
649 
650  gwlib_init();
651 
652  while ((opt = getopt(argc, argv, "hv:r:c:w:du:Ug:")) != EOF) {
653  switch (opt) {
654  case 'v':
656  break;
657 
658  case 'r':
659  max_requests = atol(optarg);
660  break;
661 
662  case 'c':
663  max_clients = atol(optarg);
664  break;
665 
666  case 'w':
667  wapbox_port = atoi(optarg);
668  break;
669 
670  case 'u':
672  break;
673 
674  case 'U':
675  user_ack = 1;
676  break;
677 
678  case 'h':
679  help();
680  exit(0);
681 
682  case 'd':
683  verbose_debug = 1;
684  break;
685 
686  case 'g':
687  req_per_session = atoi(optarg);
688  break;
689 
690  case '?':
691  default:
692  error(0, "Invalid option %c", opt);
693  help();
694  panic(0, "Stopping.");
695  }
696  }
697 
698  if (!http_url)
700  boxc = start_wapbox();
701 
703 
704  if (gettimeofday(&start, NULL) < 0)
705  panic(errno, "gettimeofday failed");
706  completed = run_requests(boxc);
707  if (gettimeofday(&end, NULL) < 0)
708  panic(errno, "gettimeofday failed");
709 
710  conn_destroy(boxc);
711 
712  run_time = end.tv_sec - start.tv_sec;
713  run_time += (double) (end.tv_usec - start.tv_usec) / 1000000.0;
714 
715  /* We must have timed out. Don't count the waiting time. */
716  if (completed < max_requests)
717  run_time -= TIMEOUT;
718 
719  info(0, "%ld request%s in %0.1f seconds, %0.1f requests/s.",
720  completed, completed != 1 ? "s" : "",
721  run_time, max_requests / run_time);
722 
723  dying = 1;
725  if (!http_url)
727 
728  destroy_clients();
730 
731  gwlib_shutdown();
732 
733  return 0;
734 }
static int user_ack
Definition: drive_wapbox.c:118
static Client * find_client(unsigned short port)
Definition: drive_wapbox.c:270
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
static int start_http_thread(void)
Definition: drive_wapbox.c:211
static Octstr * wtp_ack_create(void)
Definition: drive_wapbox.c:311
Definition: http.c:2014
static void add_wsp_connect(Octstr *pdu)
Definition: drive_wapbox.c:316
static long requests_complete
Definition: drive_wapbox.c:120
void octstr_append_data(Octstr *ostr, const char *data, long len)
Definition: octstr.c:1497
#define msg_unpack(os)
Definition: msg.h:183
static unsigned short http_port
Definition: drive_wapbox.c:113
gw_assert(wtls_machine->packet_to_send !=NULL)
int ssl
static void http_thread(void *arg)
Definition: drive_wapbox.c:167
void gwlist_append(List *list, void *item)
Definition: list.c:179
static void start_request(Connection *boxc, Client *client)
Definition: drive_wapbox.c:577
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
void gwthread_join(long thread)
static long max_clients
Definition: drive_wapbox.c:111
static void client(int port)
Definition: test_udp.c:77
void octstr_set_bits(Octstr *ostr, long bitpos, int numbits, unsigned long value)
Definition: octstr.c:1849
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
int type
Definition: smsc_cimd2.c:215
static void set_tid(Octstr *pdu, int tid)
Definition: drive_wapbox.c:351
#define msg_create(type)
Definition: msg.h:136
static Octstr * wtp_invoke_create(int class)
Definition: drive_wapbox.c:295
int conn_eof(Connection *conn)
Definition: conn.c:705
static long run_requests(Connection *boxc)
Definition: drive_wapbox.c:589
#define TIMEOUT
Definition: drive_wapbox.c:108
List * ready_clients
Definition: drive_wapbox.c:153
static void help(void)
Definition: drive_wapbox.c:633
static volatile sig_atomic_t dying
Definition: drive_wapbox.c:121
static void handle_connect_reply(Connection *boxc, Client *client, Octstr *pdu)
Definition: drive_wapbox.c:461
void http_destroy_headers(List *headers)
Definition: http.c:2879
static int port
Definition: fakesmsc.c:121
int getopt(int argc, char **argv, char *opts)
Definition: attgetopt.c:84
static long max_requests
Definition: drive_wapbox.c:110
void http_destroy_cgiargs(List *args)
Definition: http.c:2818
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2695
Definition: http.h:142
Definition: msg.h:79
WTP_type
Definition: drive_wapbox.c:123
long octstr_get_bits(Octstr *ostr, long bitpos, int numbits)
Definition: octstr.c:1803
void * gwlist_extract_first(List *list)
Definition: list.c:305
void log_set_output_level(enum output_level level)
Definition: log.c:253
HTTPClient * http_accept_request(int port, Octstr **client_ip, Octstr **url, List **headers, Octstr **body, List **cgivars)
Definition: http.c:2571
void conn_destroy(Connection *conn)
Definition: conn.c:627
static void handle_reply(Connection *boxc, Msg *reply)
Definition: drive_wapbox.c:516
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
static void handle_get_reply(Connection *boxc, Client *client, Octstr *pdu)
Definition: drive_wapbox.c:487
static void add_wsp_get(Octstr *pdu)
Definition: drive_wapbox.c:330
void msg_destroy(Msg *msg)
Definition: msg.c:132
int make_server_socket(int port, const char *interface_name)
Definition: socket.c:93
static unsigned long get_varint(Octstr *pdu, int pos)
Definition: drive_wapbox.c:155
static Client * clients
Definition: drive_wapbox.c:152
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
static void initialize_clients(void)
Definition: drive_wapbox.c:248
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
wtp_types
Definition: drive_wapbox.c:100
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
static int wtp_type(Octstr *pdu)
Definition: drive_wapbox.c:367
static int wapbox_port
Definition: drive_wapbox.c:114
Octstr * conn_read_withlen(Connection *conn)
Definition: conn.c:1169
static void send_invoke_disconnect(Connection *boxc, Client *client)
Definition: drive_wapbox.c:442
int http_open_port(int port, int ssl)
Definition: http.c:2509
int conn_write_withlen(Connection *conn, Octstr *data)
Definition: conn.c:1075
wsp_types
Definition: drive_wapbox.c:80
static Octstr * http_url
Definition: drive_wapbox.c:115
#define WSP_VERSION
Definition: drive_wapbox.c:106
void http_close_all_ports(void)
Definition: http.c:2526
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
static void destroy_clients(void)
Definition: drive_wapbox.c:265
void octstr_append_uintvar(Octstr *ostr, unsigned long value)
Definition: octstr.c:1931
static long http_thread_id
Definition: drive_wapbox.c:209
static int get_tid(Octstr *pdu)
Definition: drive_wapbox.c:363
static void client_done(Client *client)
Definition: drive_wapbox.c:278
Definition: octstr.c:118
int conn_wait(Connection *conn, double seconds)
Definition: conn.c:904
static long req_per_session
Definition: drive_wapbox.c:112
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
char * optarg
Definition: attgetopt.c:82
#define panic
Definition: log.h:87
static void send_invoke_connect(Connection *boxc, Client *client)
Definition: drive_wapbox.c:401
void gwlib_shutdown(void)
Definition: gwlib.c:94
Octstr * msg_pack(Msg *msg)
Definition: msg.c:181
#define gwlist_create()
Definition: list.h:136
static int verbose_debug
Definition: drive_wapbox.c:117
static Connection * start_wapbox(void)
Definition: drive_wapbox.c:231
static Msg * wdp_create(Octstr *data, Client *client)
Definition: drive_wapbox.c:371
unsigned short port
Definition: drive_wapbox.c:148
void gwlib_init(void)
Definition: gwlib.c:78
static void set_user_ack(Octstr *pdu)
Definition: drive_wapbox.c:291
static Octstr * url
Definition: test_xmlrpc.c:84
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:415
int main(int argc, char **argv)
Definition: drive_wapbox.c:643
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static void send_invoke_get(Connection *boxc, Client *client)
Definition: drive_wapbox.c:418
Definition: list.c:102
static void send_pdu(Octstr *pdu, Connection *boxc, Client *client)
Definition: drive_wapbox.c:384
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static int start
static void add_wsp_disconnect(Octstr *pdu, long session_id)
Definition: drive_wapbox.c:346
static void record_disconnect(Client *client)
Definition: drive_wapbox.c:435
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:566
static void reply(HTTPClient *c, List *push_headers)
static void increment_tid(Client *client)
Definition: drive_wapbox.c:283
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.