Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
drive_wapbox.c File Reference
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "gwlib/gwlib.h"
#include "gw/msg.h"

Go to the source code of this file.

Data Structures

struct  client_status
 

Macros

#define WSP_VERSION   0x10
 
#define TIMEOUT   10.0 /* seconds */
 

Typedefs

typedef struct client_status Client
 

Enumerations

enum  wsp_types {
  Bad_PDU = -1, Connect_PDU = 0x01, ConnectReply_PDU = 0x02, Redirect_PDU = 0x03,
  Reply_PDU = 0x04, Disconnect_PDU = 0x05, Push_PDU = 0x06, ConfirmedPush_PDU = 0x07,
  Suspend_PDU = 0x08, Resume_PDU = 0x09, Get_PDU = 0x40, Options_PDU = 0x41,
  Head_PDU = 0x42, Delete_PDU = 0x43, Trace_PDU = 0x44, Post_PDU = 0x60,
  Put_PDU = 0x61
}
 
enum  wtp_types { INVOKE = 1, RESULT = 2, ACK = 3 }
 
enum  WTP_type { TR_Invoke = 1, TR_Result = 2, TR_Ack = 3, TR_Abort = 4 }
 

Functions

static unsigned long get_varint (Octstr *pdu, int pos)
 
static void http_thread (void *arg)
 
static int start_http_thread (void)
 
static Connectionstart_wapbox (void)
 
static void initialize_clients (void)
 
static void destroy_clients (void)
 
static Clientfind_client (unsigned short port)
 
static void client_done (Client *client)
 
static void increment_tid (Client *client)
 
static void set_user_ack (Octstr *pdu)
 
static Octstrwtp_invoke_create (int class)
 
static Octstrwtp_ack_create (void)
 
static void add_wsp_connect (Octstr *pdu)
 
static void add_wsp_get (Octstr *pdu)
 
static void add_wsp_disconnect (Octstr *pdu, long session_id)
 
static void set_tid (Octstr *pdu, int tid)
 
static int get_tid (Octstr *pdu)
 
static int wtp_type (Octstr *pdu)
 
static Msgwdp_create (Octstr *data, Client *client)
 
static void send_pdu (Octstr *pdu, Connection *boxc, Client *client)
 
static void send_invoke_connect (Connection *boxc, Client *client)
 
static void send_invoke_get (Connection *boxc, Client *client)
 
static void record_disconnect (Client *client)
 
static void send_invoke_disconnect (Connection *boxc, Client *client)
 
static void handle_connect_reply (Connection *boxc, Client *client, Octstr *pdu)
 
static void handle_get_reply (Connection *boxc, Client *client, Octstr *pdu)
 
static void handle_reply (Connection *boxc, Msg *reply)
 
static void start_request (Connection *boxc, Client *client)
 
static long run_requests (Connection *boxc)
 
static void help (void)
 
int main (int argc, char **argv)
 

Variables

static long max_requests = 1
 
static long max_clients = 1
 
static long req_per_session = 1
 
static unsigned short http_port
 
static int wapbox_port = 30188
 
static Octstrhttp_url = NULL
 
static int verbose_debug = 0
 
static int user_ack = 0
 
static long requests_complete = 0
 
static volatile sig_atomic_t dying = 0
 
static Clientclients
 
Listready_clients
 
static long http_thread_id
 

Macro Definition Documentation

#define TIMEOUT   10.0 /* seconds */

Definition at line 108 of file drive_wapbox.c.

Referenced by main(), and run_requests().

#define WSP_VERSION   0x10

Definition at line 106 of file drive_wapbox.c.

Referenced by add_wsp_connect().

Typedef Documentation

typedef struct client_status Client

Definition at line 150 of file drive_wapbox.c.

Enumeration Type Documentation

enum wsp_types
Enumerator
Bad_PDU 
Connect_PDU 
ConnectReply_PDU 
Redirect_PDU 
Reply_PDU 
Disconnect_PDU 
Push_PDU 
ConfirmedPush_PDU 
Suspend_PDU 
Resume_PDU 
Get_PDU 
Options_PDU 
Head_PDU 
Delete_PDU 
Trace_PDU 
Post_PDU 
Put_PDU 

Definition at line 80 of file drive_wapbox.c.

80  {
81  Bad_PDU = -1,
82  Connect_PDU = 0x01,
83  ConnectReply_PDU = 0x02,
84  Redirect_PDU = 0x03,
85  Reply_PDU = 0x04,
86  Disconnect_PDU = 0x05,
87  Push_PDU = 0x06,
88  ConfirmedPush_PDU = 0x07,
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 };
enum WTP_type
Enumerator
TR_Invoke 
TR_Result 
TR_Ack 
TR_Abort 

Definition at line 123 of file drive_wapbox.c.

123  {
124  TR_Invoke = 1,
125  TR_Result = 2,
126  TR_Ack = 3,
127  TR_Abort = 4
128 };
enum wtp_types
Enumerator
INVOKE 
RESULT 
ACK 

Definition at line 100 of file drive_wapbox.c.

100  {
101  INVOKE = 1,
102  RESULT = 2,
103  ACK = 3
104 };

Function Documentation

static void add_wsp_connect ( Octstr pdu)
static

Definition at line 316 of file drive_wapbox.c.

References Connect_PDU, octstr_append_data(), and WSP_VERSION.

Referenced by send_invoke_connect().

316  {
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 }
void octstr_append_data(Octstr *ostr, const char *data, long len)
Definition: octstr.c:1495
#define WSP_VERSION
Definition: drive_wapbox.c:106
static void add_wsp_disconnect ( Octstr pdu,
long  session_id 
)
static

Definition at line 346 of file drive_wapbox.c.

References Disconnect_PDU, octstr_append_char(), and octstr_append_uintvar().

Referenced by send_invoke_disconnect().

346  {
348  octstr_append_uintvar(pdu, session_id);
349 }
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
void octstr_append_uintvar(Octstr *ostr, unsigned long value)
Definition: octstr.c:1929
static void add_wsp_get ( Octstr pdu)
static

Definition at line 330 of file drive_wapbox.c.

References Get_PDU, http_port, octstr_append(), octstr_append_char(), octstr_append_uintvar(), octstr_destroy(), octstr_format(), and octstr_len().

Referenced by send_invoke_get().

330  {
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 }
static unsigned short http_port
Definition: drive_wapbox.c:113
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
static Octstr * http_url
Definition: drive_wapbox.c:115
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
void octstr_append_uintvar(Octstr *ostr, unsigned long value)
Definition: octstr.c:1929
Definition: octstr.c:118
static void client_done ( Client client)
static

Definition at line 278 of file drive_wapbox.c.

References gwlist_append(), and requests_complete.

Referenced by handle_get_reply(), handle_reply(), and send_invoke_disconnect().

278  {
280  gwlist_append(ready_clients, client);
281 }
static long requests_complete
Definition: drive_wapbox.c:120
void gwlist_append(List *list, void *item)
Definition: list.c:179
List * ready_clients
Definition: drive_wapbox.c:153
static void destroy_clients ( void  )
static

Definition at line 265 of file drive_wapbox.c.

References gwlist_destroy().

Referenced by main().

265  {
266  gw_free(clients);
268 }
List * ready_clients
Definition: drive_wapbox.c:153
static Client * clients
Definition: drive_wapbox.c:152
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
static Client* find_client ( unsigned short  port)
static

Definition at line 270 of file drive_wapbox.c.

References max_clients, and port.

Referenced by handle_reply().

270  {
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 }
Definition: http.c:1998
static long max_clients
Definition: drive_wapbox.c:111
static int port
Definition: fakesmsc.c:120
static Client * clients
Definition: drive_wapbox.c:152
static int get_tid ( Octstr pdu)
static

Definition at line 363 of file drive_wapbox.c.

References octstr_get_bits().

Referenced by handle_reply().

363  {
364  return octstr_get_bits(pdu, 8, 16);
365 }
long octstr_get_bits(Octstr *ostr, long bitpos, int numbits)
Definition: octstr.c:1801
static unsigned long get_varint ( Octstr pdu,
int  pos 
)
static

Definition at line 155 of file drive_wapbox.c.

References octstr_get_char().

Referenced by handle_connect_reply().

155  {
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 }
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static void handle_connect_reply ( Connection boxc,
Client client,
Octstr pdu 
)
static

Definition at line 461 of file drive_wapbox.c.

References ConnectReply_PDU, error(), get_varint(), gw_assert(), increment_tid(), octstr_destroy(), octstr_dump, octstr_get_char(), send_invoke_get(), send_pdu(), set_tid(), client_status::wsp_connected, client_status::wsp_session_id, wtp_ack_create(), client_status::wtp_invoked, and client_status::wtp_tid.

Referenced by handle_reply().

461  {
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;
480  increment_tid(client);
481  client->wsp_connected = 1;
482  client->wsp_session_id = get_varint(pdu, 4);
483 
484  send_invoke_get(boxc, client);
485 }
void error(int err, const char *fmt,...)
Definition: log.c:612
static Octstr * wtp_ack_create(void)
Definition: drive_wapbox.c:311
static void set_tid(Octstr *pdu, int tid)
Definition: drive_wapbox.c:351
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
static unsigned long get_varint(Octstr *pdu, int pos)
Definition: drive_wapbox.c:155
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
Definition: octstr.c:118
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static void send_invoke_get(Connection *boxc, Client *client)
Definition: drive_wapbox.c:418
static void send_pdu(Octstr *pdu, Connection *boxc, Client *client)
Definition: drive_wapbox.c:384
static void increment_tid(Client *client)
Definition: drive_wapbox.c:283
static void handle_get_reply ( Connection boxc,
Client client,
Octstr pdu 
)
static

Definition at line 487 of file drive_wapbox.c.

References client_done(), error(), gw_assert(), increment_tid(), octstr_destroy(), octstr_dump, octstr_get_char(), client_status::pages_fetched, Reply_PDU, req_per_session, send_invoke_disconnect(), send_pdu(), set_tid(), client_status::wsp_connected, wtp_ack_create(), client_status::wtp_invoked, and client_status::wtp_tid.

Referenced by handle_reply().

487  {
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;
506  increment_tid(client);
507  client->pages_fetched++;
508 
509  if (client->pages_fetched == req_per_session) {
510  send_invoke_disconnect(boxc, client);
511  } else {
512  client_done(client);
513  }
514 }
void error(int err, const char *fmt,...)
Definition: log.c:612
static Octstr * wtp_ack_create(void)
Definition: drive_wapbox.c:311
static void set_tid(Octstr *pdu, int tid)
Definition: drive_wapbox.c:351
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
static void send_invoke_disconnect(Connection *boxc, Client *client)
Definition: drive_wapbox.c:442
static void client_done(Client *client)
Definition: drive_wapbox.c:278
Definition: octstr.c:118
static long req_per_session
Definition: drive_wapbox.c:112
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static void send_pdu(Octstr *pdu, Connection *boxc, Client *client)
Definition: drive_wapbox.c:384
static void increment_tid(Client *client)
Definition: drive_wapbox.c:283
static void handle_reply ( Connection boxc,
Msg reply 
)
static

Definition at line 516 of file drive_wapbox.c.

References ACK, client(), client_done(), debug(), error(), find_client(), get_tid(), gw_assert(), handle_connect_reply(), handle_get_reply(), octstr_dump, panic, record_disconnect(), RESULT, Msg::type, type, verbose_debug, client_status::wsp_connected, client_status::wtp_invoked, client_status::wtp_tid, and wtp_type().

Referenced by run_requests().

516  {
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) {
566  record_disconnect(client);
567  client_done(client);
568  } else {
569  error(0, "Got unexpected packet");
570  if (!dumped) {
571  octstr_dump(wtp, 0);
572  dumped = 1;
573  }
574  }
575 }
static Client * find_client(unsigned short port)
Definition: drive_wapbox.c:270
void error(int err, const char *fmt,...)
Definition: log.c:612
static void client(int port)
Definition: test_udp.c:77
int type
Definition: smsc_cimd2.c:215
static void handle_connect_reply(Connection *boxc, Client *client, Octstr *pdu)
Definition: drive_wapbox.c:461
#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 int wtp_type(Octstr *pdu)
Definition: drive_wapbox.c:367
gw_assert(wtls_machine->packet_to_send!=NULL)
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
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#define panic
Definition: log.h:87
enum msg_type type
Definition: msg.h:80
static int verbose_debug
Definition: drive_wapbox.c:117
static void record_disconnect(Client *client)
Definition: drive_wapbox.c:435
static void help ( void  )
static

Definition at line 633 of file drive_wapbox.c.

References info().

Referenced by main().

633  {
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 }
void info(int err, const char *fmt,...)
Definition: log.c:636
static void http_thread ( void *  arg)
static

Definition at line 167 of file drive_wapbox.c.

References client(), dying, gwlist_append(), gwlist_create, http_accept_request(), http_destroy_cgiargs(), http_destroy_headers(), HTTP_OK, http_send_reply(), octstr_create, octstr_destroy(), port, and url.

Referenced by start_http_thread().

167  {
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);
199  octstr_destroy(url);
200  octstr_destroy(body);
201  http_destroy_cgiargs(cgivars);
202  }
203 
204  octstr_destroy(reply_body);
205  http_destroy_headers(reply_headers);
206 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
static void client(int port)
Definition: test_udp.c:77
static volatile sig_atomic_t dying
Definition: drive_wapbox.c:121
void http_destroy_headers(List *headers)
Definition: http.c:2856
static int port
Definition: fakesmsc.c:120
void http_destroy_cgiargs(List *args)
Definition: http.c:2795
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2671
Definition: http.h:142
HTTPClient * http_accept_request(int port, Octstr **client_ip, Octstr **url, List **headers, Octstr **body, List **cgivars)
Definition: http.c:2574
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
Definition: octstr.c:118
#define gwlist_create()
Definition: list.h:136
static Octstr * url
Definition: test_xmlrpc.c:84
Definition: list.c:102
static void increment_tid ( Client client)
static

Definition at line 283 of file drive_wapbox.c.

References client_status::wtp_tid.

Referenced by handle_connect_reply(), handle_get_reply(), and record_disconnect().

283  {
284  if (client->wtp_tid == 0x7fff)
285  client->wtp_tid = 0;
286  else
287  client->wtp_tid++;
288 }
static void initialize_clients ( void  )
static

Definition at line 248 of file drive_wapbox.c.

References gwlist_append(), gwlist_create, max_clients, client_status::pages_fetched, client_status::port, client_status::wsp_connected, client_status::wsp_session_id, client_status::wtp_invoked, and client_status::wtp_tid.

Referenced by main().

248  {
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 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
static long max_clients
Definition: drive_wapbox.c:111
List * ready_clients
Definition: drive_wapbox.c:153
static Client * clients
Definition: drive_wapbox.c:152
#define gwlist_create()
Definition: list.h:136
unsigned short port
Definition: drive_wapbox.c:148
int main ( int  argc,
char **  argv 
)

Definition at line 643 of file drive_wapbox.c.

References conn_destroy(), destroy_clients(), dying, error(), getopt(), gwlib_init(), gwlib_shutdown(), gwthread_join(), help(), http_close_all_ports(), http_port, http_thread_id, info(), initialize_clients(), log_set_output_level(), max_clients, max_requests, octstr_create, octstr_destroy(), optarg, panic, req_per_session, run_requests(), start_http_thread(), start_wapbox(), TIMEOUT, user_ack, verbose_debug, and wapbox_port.

643  {
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
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
static int start_http_thread(void)
Definition: drive_wapbox.c:211
static unsigned short http_port
Definition: drive_wapbox.c:113
void gwthread_join(long thread)
static long max_clients
Definition: drive_wapbox.c:111
static long run_requests(Connection *boxc)
Definition: drive_wapbox.c:589
#define TIMEOUT
Definition: drive_wapbox.c:108
static void help(void)
Definition: drive_wapbox.c:633
static volatile sig_atomic_t dying
Definition: drive_wapbox.c:121
int getopt(int argc, char **argv, char *opts)
Definition: attgetopt.c:84
static long max_requests
Definition: drive_wapbox.c:110
void log_set_output_level(enum output_level level)
Definition: log.c:217
void conn_destroy(Connection *conn)
Definition: conn.c:619
static void initialize_clients(void)
Definition: drive_wapbox.c:248
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
static int wapbox_port
Definition: drive_wapbox.c:114
static Octstr * http_url
Definition: drive_wapbox.c:115
void http_close_all_ports(void)
Definition: http.c:2515
static void destroy_clients(void)
Definition: drive_wapbox.c:265
static long http_thread_id
Definition: drive_wapbox.c:209
static long req_per_session
Definition: drive_wapbox.c:112
char * optarg
Definition: attgetopt.c:82
#define panic
Definition: log.h:87
void gwlib_shutdown(void)
Definition: gwlib.c:94
static int verbose_debug
Definition: drive_wapbox.c:117
static Connection * start_wapbox(void)
Definition: drive_wapbox.c:231
void gwlib_init(void)
Definition: gwlib.c:78
static int start
static void record_disconnect ( Client client)
static

Definition at line 435 of file drive_wapbox.c.

References increment_tid(), client_status::pages_fetched, client_status::wsp_connected, and client_status::wsp_session_id.

Referenced by handle_reply(), and send_invoke_disconnect().

435  {
436  client->wsp_connected = 0;
437  client->wsp_session_id = -1;
438  client->pages_fetched = 0;
439  increment_tid(client);
440 }
static void increment_tid(Client *client)
Definition: drive_wapbox.c:283
static long run_requests ( Connection boxc)
static

Definition at line 589 of file drive_wapbox.c.

References client(), conn_eof(), conn_read_withlen(), conn_wait(), gwlist_extract_first(), handle_reply(), info(), max_requests, msg, msg_destroy(), msg_unpack, octstr_destroy(), octstr_dump, panic, requests_complete, start_request(), TIMEOUT, and Msg::type.

Referenced by main().

589  {
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
604  && (client = gwlist_extract_first(ready_clients))) {
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 }
void info(int err, const char *fmt,...)
Definition: log.c:636
static long requests_complete
Definition: drive_wapbox.c:120
#define msg_unpack(os)
Definition: msg.h:183
static void start_request(Connection *boxc, Client *client)
Definition: drive_wapbox.c:577
static void client(int port)
Definition: test_udp.c:77
int conn_eof(Connection *conn)
Definition: conn.c:697
#define TIMEOUT
Definition: drive_wapbox.c:108
List * ready_clients
Definition: drive_wapbox.c:153
static long max_requests
Definition: drive_wapbox.c:110
Definition: msg.h:79
void * gwlist_extract_first(List *list)
Definition: list.c:305
static void handle_reply(Connection *boxc, Msg *reply)
Definition: drive_wapbox.c:516
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void msg_destroy(Msg *msg)
Definition: msg.c:132
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Octstr * conn_read_withlen(Connection *conn)
Definition: conn.c:1161
Definition: octstr.c:118
int conn_wait(Connection *conn, double seconds)
Definition: conn.c:896
#define panic
Definition: log.h:87
enum msg_type type
Definition: msg.h:80
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static void send_invoke_connect ( Connection boxc,
Client client 
)
static

Definition at line 401 of file drive_wapbox.c.

References add_wsp_connect(), gw_assert(), octstr_destroy(), send_pdu(), set_tid(), client_status::wsp_connected, wtp_invoke_create(), client_status::wtp_invoked, and client_status::wtp_tid.

Referenced by start_request().

401  {
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 }
static void add_wsp_connect(Octstr *pdu)
Definition: drive_wapbox.c:316
static void set_tid(Octstr *pdu, int tid)
Definition: drive_wapbox.c:351
static Octstr * wtp_invoke_create(int class)
Definition: drive_wapbox.c:295
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
Definition: octstr.c:118
static void send_pdu(Octstr *pdu, Connection *boxc, Client *client)
Definition: drive_wapbox.c:384
static void send_invoke_disconnect ( Connection boxc,
Client client 
)
static

Definition at line 442 of file drive_wapbox.c.

References add_wsp_disconnect(), client_done(), gw_assert(), octstr_destroy(), record_disconnect(), send_pdu(), set_tid(), client_status::wsp_connected, client_status::wsp_session_id, wtp_invoke_create(), client_status::wtp_invoked, and client_status::wtp_tid.

Referenced by handle_get_reply().

442  {
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 
457  record_disconnect(client);
458  client_done(client);
459 }
static void set_tid(Octstr *pdu, int tid)
Definition: drive_wapbox.c:351
static Octstr * wtp_invoke_create(int class)
Definition: drive_wapbox.c:295
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
static void client_done(Client *client)
Definition: drive_wapbox.c:278
Definition: octstr.c:118
static void send_pdu(Octstr *pdu, Connection *boxc, Client *client)
Definition: drive_wapbox.c:384
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
static void send_invoke_get ( Connection boxc,
Client client 
)
static

Definition at line 418 of file drive_wapbox.c.

References add_wsp_get(), gw_assert(), octstr_destroy(), send_pdu(), set_tid(), client_status::wsp_connected, wtp_invoke_create(), client_status::wtp_invoked, and client_status::wtp_tid.

Referenced by handle_connect_reply(), and start_request().

418  {
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 }
static void set_tid(Octstr *pdu, int tid)
Definition: drive_wapbox.c:351
static Octstr * wtp_invoke_create(int class)
Definition: drive_wapbox.c:295
static void add_wsp_get(Octstr *pdu)
Definition: drive_wapbox.c:330
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
Definition: octstr.c:118
static void send_pdu(Octstr *pdu, Connection *boxc, Client *client)
Definition: drive_wapbox.c:384
static void send_pdu ( Octstr pdu,
Connection boxc,
Client client 
)
static

Definition at line 384 of file drive_wapbox.c.

References conn_write_withlen(), debug(), msg, msg_destroy(), msg_pack(), octstr_destroy(), octstr_dump, verbose_debug, and wdp_create().

Referenced by handle_connect_reply(), handle_get_reply(), send_invoke_connect(), send_invoke_disconnect(), and send_invoke_get().

384  {
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 }
Definition: msg.h:79
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void msg_destroy(Msg *msg)
Definition: msg.c:132
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
int conn_write_withlen(Connection *conn, Octstr *data)
Definition: conn.c:1067
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
Octstr * msg_pack(Msg *msg)
Definition: msg.c:181
static int verbose_debug
Definition: drive_wapbox.c:117
static Msg * wdp_create(Octstr *data, Client *client)
Definition: drive_wapbox.c:371
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static void set_tid ( Octstr pdu,
int  tid 
)
static

Definition at line 351 of file drive_wapbox.c.

References octstr_get_char(), and octstr_set_char().

Referenced by handle_connect_reply(), handle_get_reply(), send_invoke_connect(), send_invoke_disconnect(), and send_invoke_get().

351  {
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 }
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:413
static void set_user_ack ( Octstr pdu)
static

Definition at line 291 of file drive_wapbox.c.

References octstr_set_bits().

Referenced by wtp_invoke_create().

291  {
292  octstr_set_bits(pdu, 3 * 8 + 3, 1, 1);
293 }
void octstr_set_bits(Octstr *ostr, long bitpos, int numbits, unsigned long value)
Definition: octstr.c:1847
static int start_http_thread ( void  )
static

Definition at line 211 of file drive_wapbox.c.

References gwthread_create, http_open_port(), http_thread(), http_thread_id, panic, port, and ssl.

Referenced by main().

211  {
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 }
int ssl
static void http_thread(void *arg)
Definition: drive_wapbox.c:167
static int port
Definition: fakesmsc.c:120
#define gwthread_create(func, arg)
Definition: gwthread.h:90
int http_open_port(int port, int ssl)
Definition: http.c:2498
static long http_thread_id
Definition: drive_wapbox.c:209
#define panic
Definition: log.h:87
static void start_request ( Connection boxc,
Client client 
)
static

Definition at line 577 of file drive_wapbox.c.

References gw_assert(), send_invoke_connect(), send_invoke_get(), client_status::wsp_connected, and client_status::wtp_invoked.

Referenced by run_requests().

577  {
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 }
gw_assert(wtls_machine->packet_to_send!=NULL)
static void send_invoke_connect(Connection *boxc, Client *client)
Definition: drive_wapbox.c:401
static void send_invoke_get(Connection *boxc, Client *client)
Definition: drive_wapbox.c:418
static Connection* start_wapbox ( void  )
static

Definition at line 231 of file drive_wapbox.c.

References conn_wrap_fd(), make_server_socket(), panic, and wapbox_port.

Referenced by main().

231  {
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 }
int make_server_socket(int port, const char *interface_name)
Definition: socket.c:93
static int wapbox_port
Definition: drive_wapbox.c:114
#define panic
Definition: log.h:87
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:558
static Msg* wdp_create ( Octstr data,
Client client 
)
static

Definition at line 371 of file drive_wapbox.c.

References msg, msg_create, octstr_create, octstr_duplicate, and client_status::port.

Referenced by send_pdu().

371  {
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 }
#define msg_create(type)
Definition: msg.h:136
Definition: msg.h:79
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_create(cstr)
Definition: octstr.h:125
unsigned short port
Definition: drive_wapbox.c:148
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static Octstr* wtp_ack_create ( void  )
static

Definition at line 311 of file drive_wapbox.c.

References octstr_create_from_data.

Referenced by handle_connect_reply(), and handle_get_reply().

311  {
312  static unsigned char data[] = { 0x18, 0x00, 0x00 };
313  return octstr_create_from_data(data, sizeof(data));
314 }
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static Octstr* wtp_invoke_create ( int  class)
static

Definition at line 295 of file drive_wapbox.c.

References gw_assert(), octstr_create_from_data, octstr_set_char(), set_user_ack(), and user_ack.

Referenced by send_invoke_connect(), send_invoke_disconnect(), and send_invoke_get().

295  {
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 }
static int user_ack
Definition: drive_wapbox.c:118
gw_assert(wtls_machine->packet_to_send!=NULL)
Definition: octstr.c:118
static void set_user_ack(Octstr *pdu)
Definition: drive_wapbox.c:291
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:413
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static int wtp_type ( Octstr pdu)
static

Definition at line 367 of file drive_wapbox.c.

References octstr_get_bits().

Referenced by handle_reply().

367  {
368  return octstr_get_bits(pdu, 1, 4);
369 }
long octstr_get_bits(Octstr *ostr, long bitpos, int numbits)
Definition: octstr.c:1801

Variable Documentation

Client* clients
static

Definition at line 152 of file drive_wapbox.c.

volatile sig_atomic_t dying = 0
static

Definition at line 121 of file drive_wapbox.c.

Referenced by http_thread(), and main().

unsigned short http_port
static

Definition at line 113 of file drive_wapbox.c.

Referenced by add_wsp_get(), and main().

long http_thread_id
static

Definition at line 209 of file drive_wapbox.c.

Referenced by main(), and start_http_thread().

Octstr* http_url = NULL
static

Definition at line 115 of file drive_wapbox.c.

long max_clients = 1
static

Definition at line 111 of file drive_wapbox.c.

Referenced by find_client(), initialize_clients(), and main().

long max_requests = 1
static

Definition at line 110 of file drive_wapbox.c.

Referenced by main(), and run_requests().

List* ready_clients

Definition at line 153 of file drive_wapbox.c.

long req_per_session = 1
static

Definition at line 112 of file drive_wapbox.c.

Referenced by handle_get_reply(), and main().

long requests_complete = 0
static

Definition at line 120 of file drive_wapbox.c.

Referenced by client_done(), and run_requests().

int user_ack = 0
static

Definition at line 118 of file drive_wapbox.c.

Referenced by main(), and wtp_invoke_create().

int verbose_debug = 0
static

Definition at line 117 of file drive_wapbox.c.

Referenced by handle_reply(), main(), and send_pdu().

int wapbox_port = 30188
static

Definition at line 114 of file drive_wapbox.c.

Referenced by main(), and start_wapbox().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.