144 fakewap version 1.6\n\   145 Usage: fakewap [options] url ...\n\   147 where options are:\n\   150 -g hostname hostname or IP number of gateway (default: localhost)\n\   151 -p port     port number of gateway (default: 9201)\n\   152 -m max      maximum number of requests fakewap will make (default: 1)\n\   153 -i interval interval between requests (default: 1.0 seconds)\n\   154 -c threads  number of concurrent clients simulated (default: 1)\n\   155 -V protoversion protocol version field, as an integer (default: 0)\n\   156 -T pdu-type PDU type, as an integer (default: 1)\n\   157 -t tcl      transaction class, as an integer (default: 2)\n\   158 -n      set tid_new flag in packets, forces gateway to flush cache\n\   160 -s              test separation, by concatenating ack and disconnect pdus\n\   162 -d difference   difference between successive tid numbers (default: 1)\n\   163 -F      Accept failure and continue rather than exiting\n\   164 -A agent        user agent\n\   165 -C content-type Specify content type: text, mms\n\   166 -D level    debug level (0=none(default), 1=brief, 2=verbose\n\   167 -I addr[:port]  Specify source address\n\   168 -M mode         Transaction mode: 0=connectionless, 1=connection-oriented\n\   169 -P in-file  Post data from file\n\   170 -w out-file Write received data to file\n\   171 -l loss-precent Simulate packet loss\n\   173 The urls are fetched in random order.\n\   184 #include <sys/time.h>   185 #include <sys/types.h>   186 #include <sys/socket.h>   187 #include <netinet/in.h>   189 #include <sys/param.h>   193 #include <sys/stat.h>   198 #define GET_WTP_PDU_TYPE(hdr)  ((hdr[0] >> 3) & 0x0f)   204 #define WTP_PDU_INVOKE  1   205 #define WTP_PDU_RESULT  2   206 #define WTP_PDU_ACK     3   207 #define WTP_PDU_ABORT   4   208 #define WTP_PDU_SEGM_INVOKE 5   209 #define WTP_PDU_SEGM_RESULT 6   210 #define WTP_PDU_NACK        7   212 #define WSP_PDU_CONNECT    1   213 #define WSP_PDU_REPLY      4   214 #define WSP_PDU_DISCONNECT 5   215 #define WSP_PDU_GET        0x40   216 #define WSP_PDU_POST       0x60   218 #define TXN_MODE_CONNECTION_LESS      0   219 #define TXN_MODE_CONNECTION_ORIENTED  1   221 #define SAR_SEGM_SIZE            1200   222 #define SAR_GROUP_LEN            4   223 #define SAR_MAX_RETRIES          3   224 #define WAP_MSG_RECEIVE_TIMEOUT  10   266                                0x04, 0x80, 0xc0, 0x80, 0x00, 
   267                                0x04, 0x81, 0xc0, 0x80, 0x00, 
   275 unsigned char WSP_Reply[] =        {0x16, 0x80, 0x00, 0x04, 0x20 };
   278 unsigned char WSP_Concat[] = {0x00, 0x03, 0x18, 0x00, 0x00, 0x05, 0x0E, 0x00, 0x00, 0x00, 0x05 };
   280 unsigned char WTP_Ack[] =          {0x18, 0x00, 0x00 };
   286                                           0x13, 0x04, 0x10, 0x68 };
   290 unsigned char WTP_Nack[] = {  0x38,  0x00, 0x00,  0x00 };
   296 #define SET_GTR( hdr ) hdr[0] |= 0x04   297 #define SET_TID( hdr, tid) \   298     hdr[1] |= (0x7f & ((tid) >> 8)); \   300 #define GET_TID( hdr ) (((hdr[1] & 0x7f) << 8) + hdr[2])   301 #define CONSTRUCT_EXPECTED_REPLY_HDR( dest, template, tid ) \   302     if (sizeof(dest) < sizeof(template)) panic(0,"fakewap: buffer overflow.");\   303     memcpy( dest, template, sizeof(template));\   310     c |= 0x7f & (tid >> 8);
   326 #define min(a,b) (a < b ? a : b)   339         printf( 
"%s (len %d): ", trace, msg_len );
   340         for (i = 0; i < msg_len && i < 16; i++) printf( 
"%02X ", 
msg[i] );
   355         printf( 
"%s (len %d): ", trace, msg_len );
   356         for (i = 0; i < msg_len && i < msg_len; i++)
   357              printf( 
"%c", isprint(
msg[i]) ? 
msg[i] : 
'_');
   372 static unsigned short next_tid(
unsigned short old_tid) { 
   381 static int StoreVarInt( 
unsigned char *buf, 
unsigned long varInt )
   383     int i, len = 1, non_zero_bits = 7;
   388     while ((varInt >> non_zero_bits) != 0) {
   395     for (i = 0; i < len; i++)
   397         buf[i] = ((
unsigned char)(varInt >> (non_zero_bits-7)) & 0x7f) | 0x80;
   412     while (buf[len-1] & 0x80) len++;
   422     int    value = buf[0] & 0x7F;
   423     while (buf[len-1] & 0x80)
   427         value |= buf[len-1] & 0x7F;
   436 wap_msg_send( 
int fd, 
unsigned char* wtp_hdr, 
int wtp_hdr_len, 
unsigned short tid, 
int tid_new,
   437               unsigned char* wsp_hdr, 
int wsp_hdr_len, 
unsigned char* data, 
int data_len )
   443     if (wtp_hdr != NULL) {
   464     debug(
"fakewap", 0, 
"Sending WDP datagram:");
   470         error(0, 
"fakewap: Sending to socket failed");
   484                 debug(
"fakewap", 0, 
"Sent WSP_CONNECT packet");
   487                 debug(
"fakewap", 0, 
"Sent WSP_DISCONNECT packet");
   490                 debug(
"fakewap", 0, 
"Sent WSP_GET packet");
   493                 debug(
"fakewap", 0, 
"Sent WSP_POST packet");
   496                 debug(
"fakewap", 0, 
"Sent WSP ??? packet");
   504                 debug(
"fakewap", 0, 
"Sent WTP_INVOKE packet");
   507                 debug(
"fakewap", 0, 
"Sent WTP_ACK packet");
   510                 debug(
"fakewap", 0, 
"Sent WTP_ABORT packet");
   513                 debug(
"fakewap", 0, 
"Sent WTP_SEGM_INVOKE packet");
   516                 debug(
"fakewap", 0, 
"Sent WTP_NACK packet");
   519                 debug(
"fakewap", 0, 
"Sent ??? packet");
   541               unsigned short tid, 
unsigned char * data, 
int data_len,
   542               int timeout, 
int udp_flags )
   545     unsigned char msg[1024*64];
   547     int    fResponderIsDead = 1;  
   562                 info(0, 
"fakewap: Timeout while receiving from socket.\n");
   566             return fResponderIsDead ? -1 : 0;
   582             timeout -= (int)(currtime - calltime);
   583             debug(
"fakewap", 0, 
"Dropped packet, new timeout %d", timeout);
   594             error(0, 
"fakewap: recv() from socket failed");
   602             if ((msg_len >= hdr_len) &&
   604                 (hdr_len <= 3 || !memcmp( 
msg+3, hdr+3, hdr_len-3 ))) {
   627                 print_msg( 
"Received unexpected message", 
msg, msg_len );
   629             fResponderIsDead = 0;
   639     if (data != NULL && msg_len > hdr_len) {
   640         data_len = 
min( data_len, msg_len );
   641         memcpy( data, 
msg, data_len);
   659     unsigned char wtphdr[32];
   660     unsigned char msgbuf[32*1024];
   661     unsigned char contentlen_buf[8];
   662     unsigned char reply_hdr[32];
   666     int infd = open(
infile, O_RDONLY);
   668         panic(0, 
"fakewap: failed to open input file %s, errno %d", 
infile, errno);
   672     int ret = fstat(infd, &fstats);
   674         panic(0, 
"fakewap: failed to get file stats, errno %d", errno);
   675     if (fstats.st_size == 0)
   676         panic(0, 
"fakewap: input file is empty");
   679         panic(0, 
"fakewap: input file size (%ld) is too large", (
long) fstats.st_size);
   688     ttr = (nsegs==0) ? 1 : 0;
   691     wtphdr[0] = (tpi << 7) | (
WTP_PDU_INVOKE << 3) | (gtr << 2) | (ttr << 1);
   704     int url_len = strlen(
url);
   708     char acceptAll[] = { 0x80, 0x80 };
   709     contentlen_buf[0] = 0x8d; 
   710     if (fstats.st_size <= 127)
   712         contentlen_buf[1] = 0x80 | (char)fstats.st_size;
   716         contentlen_buf[1] = 2;
   717         contentlen_buf[2] = (char)(fstats.st_size >> 8);
   718         contentlen_buf[3] = (char)(fstats.st_size);
   722     memcpy( &msgbuf[off], 
url, url_len );
   725     off += content_type_len;
   728     memcpy( &msgbuf[off], contentlen_buf, contentlen_len );
   729     off += contentlen_len;
   730     memcpy( &msgbuf[off], acceptAll, 
sizeof(acceptAll) );
   731     off += 
sizeof(acceptAll);
   736         ret = read(infd, msgbuf, 
sizeof(msgbuf));
   741         panic(0, 
"fakewap: input file read error, errno %d", errno);
   743     debug(
"fakewap", 0, 
"Sending WSP_POST, url %s, Content-Type %s, User-Agent %s, Content-Length %lu",
   751             error(0, 
"fakewap: failure sending connection-less wtp invoke");
   762                 error(0, 
"fakewap: failure sending connection-oriented wtp invoke");
   768                                 tid, msgbuf, 
sizeof(msgbuf), timeout, 0 );
   772                     error(0, 
"fakewap: failure receiving WTP Ack, psn %u, giving up", psn);
   775                 warning(0, 
"fakewap: timeout receiving WTP Ack, resend wtp invoke");
   778             debug(
"fakewap", 0, 
"Received WTP_ACK, psn 0");
   802                 ttr = (nsegs==psn) ? 1 : 0;
   804                 grpwtphdr[grppktnum][0] = (tpi << 7) | (
WTP_PDU_SEGM_INVOKE << 3) | (gtr << 2) | (ttr << 1);
   805                 grpwtphdr[grppktnum][3] = psn;
   808                 grpmsglen[grppktnum] = read(infd, (
char*)grpmsgbuf[grppktnum], 
SAR_SEGM_SIZE);
   809                 if (grpmsglen[grppktnum] <= 0)
   810                     panic(0, 
"fakewap: input file read error, errno %d", errno);
   820                 for (grppktnum = 0; grppktnum < grpsize; grppktnum++)
   822                     debug(
"fakewap", 0, 
"Sending WTP_SEGM_INVOKE, psn %u, payload len %d",
   823                           psn-grpsize+grppktnum+1, grpmsglen[grppktnum]);
   825                                         NULL, 0, grpmsgbuf[grppktnum], grpmsglen[grppktnum] );
   828                         error(0, 
"fakewap: failure sending wtp invoke");
   837                                         tid, msgbuf, 
sizeof(msgbuf), timeout, MSG_PEEK );
   843                                         tid, msgbuf, 
sizeof(msgbuf), timeout, 0 );
   848                         error(0, 
"fakewap: failure receiving WTP Segm Ack, psn %u, giving up", psn);
   851                     warning(0, 
"fakewap: failure receiving WTP Segm Ack, psn %u, retrying", psn);
   856                     debug(
"fakewap", 0, 
"Received WTP_RESULT");
   858                     debug(
"fakewap", 0, 
"Received WTP_ACK, psn %d", psn);
   879     int url_len = 0, url_off = 0;
   880     double nowsec, lastsec, tmp, sleepTime;
   885     unsigned char  sid[20];
   887     unsigned char  buf[64*1024];
   888     unsigned char reply_hdr[32];
   890     static unsigned short tid = 0;
   891     unsigned short old_tid;
   893     int connection_retries = 0;
   898         panic(0, 
"fakewap: Couldn't create socket.");
   901         if (bind(fd, (
const struct sockaddr *)&
src_addr, (
int)
sizeof(
src_addr)) == -1)
   902             panic(0, 
"fakewap: Couldn't bind socket, errno %d", errno);
   911         gettimeofday(&now, &tz);
   912         lastsec = (double) now.tv_sec + now.tv_usec / 1e6;
   926             tid_new = (tid < old_tid);  
   933             if (ret == -1) 
panic(0, 
"fakewap: Send WSP_Connect failed");
   937                                 tid, buf, 
sizeof(buf), timeout, 0 );
   938             if (ret == -1) 
panic(0, 
"fakewap: Receive WSP_ConnectReply failed");
   943                 memcpy( sid, &buf[4], sid_len);
   951                 if (connection_retries++ > 3) {
   952                     panic(0, 
"fakewap: Cannot connect WAP GW!");
   958                 connection_retries = 0;
   962             if (ret == -1) 
panic(0, 
"fakewap: Send WTP_Ack failed");
   970     tid_new = (tid < old_tid);  
   972         url_len = strlen(
url);
   974         memcpy( buf+url_off, 
url, url_len );
   975         buf[url_len+url_off] = 0x80; 
   976         buf[url_len+url_off+1] = 0x80; 
   986                 unsigned char wsphdr[32];
   990                                     wsphdr, 
sizeof(
WSP_Get)+1, buf, url_len+url_off+2 );
   995             if (ret == -1) 
break;
  1004                                 tid, buf, 
sizeof(buf), timeout, 0 );
  1005             if (ret == -1) 
break;
  1012             int gtr = 0, ttr = 0, psn, gtr_psn = -1, ttr_psn = -1;
  1013             unsigned char segment_data[256][1500];
  1014             int segment_len[256];
  1016             memset(segment_len, 0, 
sizeof(segment_len));
  1021                                     tid, buf, 
sizeof(buf), timeout, 0 );
  1023                 if (ret == -1) 
break;
  1025                 gtr = (buf[0] & 0x04) ? 1 : 0;
  1026                 ttr = (buf[0] & 0x02) ? 1 : 0;
  1031                     debug(
"fakewap", 0, 
"Received WTP_RESULT pdu, gtr %d, ttr %d, payload len %d", gtr, ttr, ret - data_offset);
  1037                     debug(
"fakewap", 0, 
"Received WTP_SEGM_RESULT pdu, psn %d, gtr %d, ttr %d, payload len %d", psn, gtr, ttr, ret - data_offset);
  1039                 segment_len[psn] = ret - data_offset;
  1040                 if (segment_len[psn] > 1500)
  1041                     panic(0, 
"fakewap: Segment %d exceeds 1500 bytes!?!", psn);
  1042                 memcpy(segment_data[psn], &buf[data_offset], segment_len[psn]);
  1044                 if (gtr || ttr || (psn < gtr_psn))
  1052                     unsigned char lost_segs[256];
  1053                     int i, num_lost = 0;
  1054                     for (i = 0; i <= gtr_psn; i++)
  1055                         if (!segment_len[i])
  1056                         lost_segs[num_lost++] = i;
  1062                         memcpy(buf+
sizeof(
WTP_Nack), lost_segs, num_lost);
  1063                         debug(
"fakewap", 0, 
"Sending WTP_NACK pdu, num_lost %d, lost_seg0 %d", num_lost, lost_segs[0]);
  1071                         debug(
"fakewap", 0, 
"Sending WTP_ACK pdu, gtr_psn %d", gtr_psn);
  1077                         debug(
"fakewap", 0, 
"Sending WTP_ACK pdu, psn 0");
  1082                     if ((ttr_psn >= 0) && (num_lost==0)) {
  1089                 panic(0, 
"fakewap: Failed to receive entire message!?!");
  1093             for (psn = 0; psn <= gtr_psn; psn++)
  1101             panic(0, 
"fakewap: Failed to unpack wsp message!?!");
  1102         if (wsppdu->
type != Reply) {
  1103             error(0, 
"fakewap: Received WSP message type %u is not Reply!?!", 
octstr_get_char(wspreply, 0));
  1107             struct Reply* wspreply = &wsppdu->
u.Reply;
  1109             if (wspreply->status <= 0x4f)
  1110                 status = (wspreply->status >> 4) * 100 + (wspreply->status & 0x0f);
  1111             else if ((wspreply->status & 0xf0) == 0x50)
  1112                 status = 431 + (wspreply->status & 0x0f);
  1114                 status = (wspreply->status >> 4) * 100 - 100 + (wspreply->status & 0x0f);
  1116                 warning(0, 
"fakewap: Warning - received reply with status %d", 
status);
  1118                 info(0, 
"fakewap: Received WSP Reply with status code 200OK");
  1124                 int outfd = creat(
outfile, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
  1126                     panic(0, 
"fakewap: failed to create output file %s, errno %d", 
outfile, errno);
  1131                     panic(0, 
"fakewap: failed to write to output file %s, errno %d", 
outfile, errno);
  1135                 debug(
"fakewap", 0, 
"Wrote %d bytes of response payload to output file %s", ret, 
outfile);
  1147                 if (ret == -1) 
break;
  1154         gettimeofday(&now, &tz);
  1155         nowsec = (double) now.tv_sec + now.tv_usec / 1e6;
  1156         tmp = nowsec - lastsec; 
  1158         uSleepTime = sleepTime * 1e6;
  1168             info(0, 
"fakewap: finished session # %d", i_this);
  1177             usleep( uSleepTime );
  1200     int proto_version, tcl, tid_new;
  1202     struct sigaction alrm;
  1204     alrm.sa_handler = SIG_IGN;
  1206     sigaction(SIGALRM,&alrm,NULL);
  1237     src_addr.sin_addr.s_addr = INADDR_ANY;
  1243     const char firstchar[] = {0xa9, 0}; 
  1249     while ((opt = 
getopt(argc, argv, 
"Fhc:g:p:m:i:t:V:t:nsd:A:C:D:I:M:P:w:l:")) != EOF)
  1274         proto_version = atoi(
optarg);
  1322             if (!strcmp(
"mms", 
optarg))
  1330             unsigned int  byte0, byte1, byte2, byte3, srcport;
  1331             int ret = sscanf(
optarg, 
"%u.%u.%u.%u:%u", &byte0, &byte1, &byte2, &byte3, &srcport);
  1332             if (ret!=4 && ret!=5)
  1333                 panic(0, 
"fakewap: invalid source address %s", 
optarg);
  1334             src_addr.sin_addr.s_addr = htonl(byte0<<24 | byte1<<16 | byte2<<8 | byte3);
  1336                 src_addr.sin_port = htons(srcport);
  1343                 error(0, 
"fakewap: invalid transaction mode %s", 
optarg);
  1355                 error(0, 
"fakewap: invalid packet loss rate %s, expect 0-99", 
optarg);
  1362         error(0, 
"fakewap: Unknown option %c", opt);
  1364         panic(0, 
"fakewap: Stopping.");
  1395     srand((
unsigned int) time(NULL));
  1399     info(0, 
"fakewap: starting");
  1414     info(0, 
"fakewap: complete.");
  1415     info(0, 
"fakewap: %d client threads made total %d transactions.", 
  1418     info( 0, 
"fakewap: total running time %.1f seconds", delta);
  1419     info( 0, 
"fakewap: %.1f messages/seconds on average", 
num_sent / delta);
  1420     info( 0, 
"fakewap: time of best, worst and average transaction: "  1421              "%.1f s, %.1f s, %.1f s",
 
static char * choose_message(char **urls, int num_urls)
 
void error(int err, const char *fmt,...)
 
void info(int err, const char *fmt,...)
 
static unsigned short next_tid(unsigned short old_tid)
 
unsigned char WSP_ConnectReply[]
 
static void set_tid_new(Octstr *hdr)
 
void octstr_append_data(Octstr *ostr, const char *data, long len)
 
unsigned char WTP_Segm_Invoke[]
 
unsigned char WTP_Segm_Result[]
 
static void print_data(const char *trace, unsigned char *msg, int msg_len)
 
#define GET_WTP_PDU_TYPE(hdr)
 
unsigned char WSP_Reply[]
 
unsigned char WTP_Invoke_Cl2[]
 
static int get_next_transaction(void)
 
static int wap_msg_send(int fd, unsigned char *wtp_hdr, int wtp_hdr_len, unsigned short tid, int tid_new, unsigned char *wsp_hdr, int wsp_hdr_len, unsigned char *data, int data_len)
 
#define TXN_MODE_CONNECTION_LESS
 
static void print_msg(const char *trace, unsigned char *msg, int msg_len)
 
static int wap_msg_recv(int fd, const unsigned char *hdr, int hdr_len, unsigned short tid, unsigned char *data, int data_len, int timeout, int udp_flags)
 
unsigned char WTP_Abort[]
 
#define octstr_get_cstr(ostr)
 
int send_post(int fd, unsigned short tid, int tid_new, char *url)
 
void gwthread_join_every(gwthread_func_t *func)
 
unsigned char WSP_Concat[]
 
static void set_tid(Octstr *hdr, int tid)
 
unsigned short tid_addition
 
int getopt(int argc, char **argv, char *opts)
 
struct sockaddr_in src_addr
 
#define WAP_MSG_RECEIVE_TIMEOUT
 
#define TXN_MODE_CONNECTION_ORIENTED
 
unsigned char WSP_Connect[]
 
int udp_recvfrom_flags(int s, Octstr **datagram, Octstr **addr, int sockrcvflags)
 
int udp_client_socket(void)
 
void log_set_output_level(enum output_level level)
 
static int ReadVarIntVal(const unsigned char *buf)
 
#define WSP_PDU_DISCONNECT
 
#define octstr_dump(ostr, level,...)
 
void warning(int err, const char *fmt,...)
 
void octstr_destroy(Octstr *ostr)
 
#define gwthread_create(func, arg)
 
#define octstr_create(cstr)
 
void mutex_destroy(Mutex *mutex)
 
const char * content_type
 
unsigned char WTP_Invoke_Cl2MaxGrp[]
 
static void client_session(void *arg)
 
unsigned char WTP_TidVe[]
 
long octstr_len(const Octstr *ostr)
 
unsigned char WTP_Result[]
 
int read_available(int fd, long wait_usec)
 
void debug(const char *place, int err, const char *fmt,...)
 
static int StoreVarInt(unsigned char *buf, unsigned long varInt)
 
static int ReadVarIntLen(const unsigned char *buf)
 
void gwlib_shutdown(void)
 
int main(int argc, char **argv)
 
int udp_sendto(int s, Octstr *datagram, Octstr *addr)
 
#define CONSTRUCT_EXPECTED_REPLY_HDR(dest, template, tid)
 
static int get_wtp_pdu_type(Octstr *hdr)
 
unsigned char WTP_Segm_Ack[]
 
unsigned char WTP_Invoke_Cl0[]
 
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
 
int octstr_get_char(const Octstr *ostr, long pos)
 
void octstr_set_char(Octstr *ostr, long pos, int ch)
 
unsigned char WSP_Disconnect[]
 
static XMLRPCDocument * msg
 
#define WTP_PDU_SEGM_INVOKE
 
WSP_PDU * wsp_pdu_unpack(Octstr *data)
 
Octstr * udp_create_address(Octstr *host_or_ip, int port)
 
#define WTP_PDU_SEGM_RESULT