blob: 7cc2c2d5f2bb1621cbf07af2a79e0abed54b1345 [file] [log] [blame]
Andy Greena6cbece2011-01-27 20:06:03 +00001/*
2 * libwebsockets-test-ping - libwebsockets floodping
3 *
4 * Copyright (C) 2011 Andy Green <andy@warmcat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <getopt.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29
30#include <sys/time.h>
31#include <sys/types.h>
Joakim Soderberg4c531232013-02-06 15:26:58 +090032#ifndef WIN32
Andy Greena6cbece2011-01-27 20:06:03 +000033#include <sys/socket.h>
Joakim Soderberg4c531232013-02-06 15:26:58 +090034#include <sys/ioctl.h>
35#include <poll.h>
36#endif
37
Joakim Soderberg7eadd582013-02-22 09:28:04 +080038#ifdef CMAKE_BUILD
39#include "lws_config.h"
40#endif
41
Andy Greena6cbece2011-01-27 20:06:03 +000042#include <netdb.h>
43
Andy Greena6cbece2011-01-27 20:06:03 +000044#include "../lib/libwebsockets.h"
Andy Greena6cbece2011-01-27 20:06:03 +000045
46/*
47 * this is specified in the 04 standard, control frames can only have small
48 * payload length styles
49 */
50#define MAX_PING_PAYLOAD 125
51#define MAX_MIRROR_PAYLOAD 4096
Andy Green2f4c2be2011-01-30 12:15:25 +000052#define MAX_PING_CLIENTS 256
53#define PING_RINGBUFFER_SIZE 256
Andy Greena6cbece2011-01-27 20:06:03 +000054
Andy Green62c54d22011-02-14 09:14:25 +000055static struct libwebsocket *ping_wsi[MAX_PING_CLIENTS];
Andy Greena6cbece2011-01-27 20:06:03 +000056static unsigned int interval_us = 1000000;
57static unsigned int size = 64;
Andy Green42f69142011-01-30 08:10:02 +000058static int flood;
Andy Greena6cbece2011-01-27 20:06:03 +000059static const char *address;
60static unsigned char pingbuf[LWS_SEND_BUFFER_PRE_PADDING + MAX_MIRROR_PAYLOAD +
61 LWS_SEND_BUFFER_POST_PADDING];
Andy Greene2acfc82011-02-13 09:05:54 +000062static char peer_name[128];
Andy Greena6cbece2011-01-27 20:06:03 +000063static unsigned long started;
Andy Green2f4c2be2011-01-30 12:15:25 +000064static int screen_width = 80;
65static int use_mirror;
Andy Green8014b292011-01-30 20:57:25 +000066static unsigned int write_options;
Andy Greena6cbece2011-01-27 20:06:03 +000067
68static unsigned long rtt_min = 100000000;
Andy Green42f69142011-01-30 08:10:02 +000069static unsigned long rtt_max;
70static unsigned long rtt_avg;
Andy Green2f4c2be2011-01-30 12:15:25 +000071static unsigned long global_rx_count;
72static unsigned long global_tx_count;
73static int clients = 1;
74static unsigned long interrupted_time;
Andy Greena6cbece2011-01-27 20:06:03 +000075
76struct ping {
77 unsigned long issue_timestamp;
78 unsigned long index;
79 unsigned int seen;
80};
81
Andy Green2f4c2be2011-01-30 12:15:25 +000082struct per_session_data__ping {
83 unsigned long ping_index;
Andy Greena6cbece2011-01-27 20:06:03 +000084
Andy Green2f4c2be2011-01-30 12:15:25 +000085 struct ping ringbuffer[PING_RINGBUFFER_SIZE];
86 int ringbuffer_head;
87 int ringbuffer_tail;
88
89 unsigned long rx_count;
90};
Andy Greena6cbece2011-01-27 20:06:03 +000091
92/*
93 * uses the ping pong protocol features to provide an equivalent for the
94 * ping utility for 04+ websockets
95 */
96
97enum demo_protocols {
98
99 PROTOCOL_LWS_MIRROR,
100
101 /* always last */
102 DEMO_PROTOCOL_COUNT
103};
104
105
106static int
Andy Green62c54d22011-02-14 09:14:25 +0000107callback_lws_mirror(struct libwebsocket_context * this,
108 struct libwebsocket *wsi,
Andy Greena6cbece2011-01-27 20:06:03 +0000109 enum libwebsocket_callback_reasons reason,
110 void *user, void *in, size_t len)
111{
112 struct timeval tv;
113 unsigned char *p;
114 int shift;
115 unsigned long l;
116 unsigned long iv;
117 int n;
118 int match = 0;
Andy Green2f4c2be2011-01-30 12:15:25 +0000119 struct per_session_data__ping *psd = user;
Andy Greena6cbece2011-01-27 20:06:03 +0000120
121 switch (reason) {
Andy Green62c54d22011-02-14 09:14:25 +0000122 case LWS_CALLBACK_CLOSED:
123
124 fprintf(stderr, "LWS_CALLBACK_CLOSED on %p\n", (void *)wsi);
125
126 /* remove closed guy */
127
128 for (n = 0; n < clients; n++)
129 if (ping_wsi[n] == wsi) {
130 clients--;
131 while (n < clients) {
132 ping_wsi[n] = ping_wsi[n + 1];
133 n++;
134 }
135 }
136
137 break;
138
Andy Greena6cbece2011-01-27 20:06:03 +0000139 case LWS_CALLBACK_CLIENT_ESTABLISHED:
140
Andy Green2f4c2be2011-01-30 12:15:25 +0000141 psd->rx_count = 0;
142 psd->ping_index = 1;
143 psd->ringbuffer_head = 0;
144 psd->ringbuffer_tail = 0;
145
Andy Greena6cbece2011-01-27 20:06:03 +0000146 /*
147 * start the ball rolling,
148 * LWS_CALLBACK_CLIENT_WRITEABLE will come next service
149 */
150
Andy Green62c54d22011-02-14 09:14:25 +0000151 libwebsocket_callback_on_writable(this, wsi);
Andy Greena6cbece2011-01-27 20:06:03 +0000152 break;
153
154 case LWS_CALLBACK_CLIENT_RECEIVE:
155 case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
156 gettimeofday(&tv, NULL);
157 iv = (tv.tv_sec * 1000000) + tv.tv_usec;
158
Andy Green2f4c2be2011-01-30 12:15:25 +0000159 psd->rx_count++;
Andy Greena6cbece2011-01-27 20:06:03 +0000160
161 shift = 56;
162 p = in;
163 l = 0;
164
165 while (shift >= 0) {
166 l |= (*p++) << shift;
167 shift -= 8;
168 }
169
170 /* find it in the ringbuffer, look backwards from head */
Andy Green2f4c2be2011-01-30 12:15:25 +0000171 n = psd->ringbuffer_head;
Andy Greena6cbece2011-01-27 20:06:03 +0000172 while (!match) {
173
Andy Green2f4c2be2011-01-30 12:15:25 +0000174 if (psd->ringbuffer[n].index == l) {
175 psd->ringbuffer[n].seen++;
Andy Greena6cbece2011-01-27 20:06:03 +0000176 match = 1;
177 continue;
178 }
179
Andy Green2f4c2be2011-01-30 12:15:25 +0000180 if (n == psd->ringbuffer_tail) {
Andy Greena6cbece2011-01-27 20:06:03 +0000181 match = -1;
182 continue;
183 }
Andy Green42f69142011-01-30 08:10:02 +0000184
Andy Greena6cbece2011-01-27 20:06:03 +0000185 if (n == 0)
186 n = PING_RINGBUFFER_SIZE - 1;
187 else
Andy Green42f69142011-01-30 08:10:02 +0000188 n--;
Andy Greena6cbece2011-01-27 20:06:03 +0000189 }
190
191 if (match < 1) {
Andy Green42f69142011-01-30 08:10:02 +0000192
Andy Greena6cbece2011-01-27 20:06:03 +0000193 if (!flood)
194 fprintf(stderr, "%d bytes from %s: req=%ld "
Andy Green42f69142011-01-30 08:10:02 +0000195 "time=(unknown)\n", (int)len, address, l);
Andy Greena6cbece2011-01-27 20:06:03 +0000196 else
197 fprintf(stderr, "\b \b");
198
199 break;
200 }
201
Andy Green2f4c2be2011-01-30 12:15:25 +0000202 if (psd->ringbuffer[n].seen > 1)
Andy Greena6cbece2011-01-27 20:06:03 +0000203 fprintf(stderr, "DUP! ");
204
Andy Green2f4c2be2011-01-30 12:15:25 +0000205 if ((iv - psd->ringbuffer[n].issue_timestamp) < rtt_min)
206 rtt_min = iv - psd->ringbuffer[n].issue_timestamp;
Andy Greena6cbece2011-01-27 20:06:03 +0000207
Andy Green2f4c2be2011-01-30 12:15:25 +0000208 if ((iv - psd->ringbuffer[n].issue_timestamp) > rtt_max)
209 rtt_max = iv - psd->ringbuffer[n].issue_timestamp;
Andy Greena6cbece2011-01-27 20:06:03 +0000210
Andy Green2f4c2be2011-01-30 12:15:25 +0000211 rtt_avg += iv - psd->ringbuffer[n].issue_timestamp;
212 global_rx_count++;
Andy Green42f69142011-01-30 08:10:02 +0000213
Andy Greena6cbece2011-01-27 20:06:03 +0000214 if (!flood)
215 fprintf(stderr, "%d bytes from %s: req=%ld "
Andy Green42f69142011-01-30 08:10:02 +0000216 "time=%lu.%lums\n", (int)len, address, l,
Andy Green2f4c2be2011-01-30 12:15:25 +0000217 (iv - psd->ringbuffer[n].issue_timestamp) / 1000,
218 ((iv - psd->ringbuffer[n].issue_timestamp) / 100) % 10);
Andy Greena6cbece2011-01-27 20:06:03 +0000219 else
220 fprintf(stderr, "\b \b");
221 break;
222
223 case LWS_CALLBACK_CLIENT_WRITEABLE:
224
225 shift = 56;
226 p = &pingbuf[LWS_SEND_BUFFER_PRE_PADDING];
227
Andy Green2f4c2be2011-01-30 12:15:25 +0000228 /* 64-bit ping index in network byte order */
229
Andy Greena6cbece2011-01-27 20:06:03 +0000230 while (shift >= 0) {
Andy Green2f4c2be2011-01-30 12:15:25 +0000231 *p++ = psd->ping_index >> shift;
Andy Greena6cbece2011-01-27 20:06:03 +0000232 shift -= 8;
233 }
Andy Green42f69142011-01-30 08:10:02 +0000234
Andy Greenf7248f82013-01-16 14:35:12 +0800235 while (p - &pingbuf[LWS_SEND_BUFFER_PRE_PADDING] < size)
236 *p++ = 0;
237
Andy Greena6cbece2011-01-27 20:06:03 +0000238 gettimeofday(&tv, NULL);
Andy Green42f69142011-01-30 08:10:02 +0000239
Andy Green2f4c2be2011-01-30 12:15:25 +0000240 psd->ringbuffer[psd->ringbuffer_head].issue_timestamp =
Andy Greena6cbece2011-01-27 20:06:03 +0000241 (tv.tv_sec * 1000000) + tv.tv_usec;
Andy Green2f4c2be2011-01-30 12:15:25 +0000242 psd->ringbuffer[psd->ringbuffer_head].index = psd->ping_index++;
243 psd->ringbuffer[psd->ringbuffer_head].seen = 0;
Andy Greena6cbece2011-01-27 20:06:03 +0000244
Andy Green2f4c2be2011-01-30 12:15:25 +0000245 if (psd->ringbuffer_head == PING_RINGBUFFER_SIZE - 1)
246 psd->ringbuffer_head = 0;
Andy Greena6cbece2011-01-27 20:06:03 +0000247 else
Andy Green2f4c2be2011-01-30 12:15:25 +0000248 psd->ringbuffer_head++;
Andy Greena6cbece2011-01-27 20:06:03 +0000249
Andy Green2f4c2be2011-01-30 12:15:25 +0000250 /* snip any re-used tail so we keep to the ring length */
Andy Greena6cbece2011-01-27 20:06:03 +0000251
Andy Green2f4c2be2011-01-30 12:15:25 +0000252 if (psd->ringbuffer_tail == psd->ringbuffer_head) {
253 if (psd->ringbuffer_tail == PING_RINGBUFFER_SIZE - 1)
254 psd->ringbuffer_tail = 0;
Andy Greena6cbece2011-01-27 20:06:03 +0000255 else
Andy Green2f4c2be2011-01-30 12:15:25 +0000256 psd->ringbuffer_tail++;
Andy Greena6cbece2011-01-27 20:06:03 +0000257 }
258
Andy Green2f4c2be2011-01-30 12:15:25 +0000259 global_tx_count++;
260
Andy Greena6cbece2011-01-27 20:06:03 +0000261 if (use_mirror)
262 libwebsocket_write(wsi,
263 &pingbuf[LWS_SEND_BUFFER_PRE_PADDING],
Andy Green8014b292011-01-30 20:57:25 +0000264 size, write_options | LWS_WRITE_BINARY);
Andy Greena6cbece2011-01-27 20:06:03 +0000265 else
266 libwebsocket_write(wsi,
267 &pingbuf[LWS_SEND_BUFFER_PRE_PADDING],
Andy Green8014b292011-01-30 20:57:25 +0000268 size, write_options | LWS_WRITE_PING);
Andy Greena6cbece2011-01-27 20:06:03 +0000269
Andy Green2f4c2be2011-01-30 12:15:25 +0000270 if (flood &&
271 (psd->ping_index - psd->rx_count) < (screen_width - 1))
Andy Greena6cbece2011-01-27 20:06:03 +0000272 fprintf(stderr, ".");
273 break;
274
275 default:
276 break;
277 }
278
279 return 0;
280}
281
282
283/* list of supported protocols and callbacks */
284
285static struct libwebsocket_protocols protocols[] = {
286
Joakim Soderberg4c531232013-02-06 15:26:58 +0900287 {
288 "lws-mirror-protocol",
289 callback_lws_mirror,
290 sizeof (struct per_session_data__ping),
Andy Greena6cbece2011-01-27 20:06:03 +0000291 },
Joakim Soderberg4c531232013-02-06 15:26:58 +0900292 {
293 NULL, NULL, 0/* end of list */
Andy Greena6cbece2011-01-27 20:06:03 +0000294 }
295};
296
297static struct option options[] = {
298 { "help", no_argument, NULL, 'h' },
Andy Green46ef0cf2013-01-10 22:28:59 +0800299 { "debug", required_argument, NULL, 'd' },
Andy Greena6cbece2011-01-27 20:06:03 +0000300 { "port", required_argument, NULL, 'p' },
301 { "ssl", no_argument, NULL, 't' },
302 { "interval", required_argument, NULL, 'i' },
303 { "size", required_argument, NULL, 's' },
304 { "protocol", required_argument, NULL, 'n' },
305 { "flood", no_argument, NULL, 'f' },
306 { "mirror", no_argument, NULL, 'm' },
Andy Green2f4c2be2011-01-30 12:15:25 +0000307 { "replicate", required_argument, NULL, 'r' },
Andy Green8014b292011-01-30 20:57:25 +0000308 { "killmask", no_argument, NULL, 'k' },
Andy Greenbfb051f2011-02-09 08:49:14 +0000309 { "version", required_argument, NULL, 'v' },
Andy Greena6cbece2011-01-27 20:06:03 +0000310 { NULL, 0, 0, 0 }
311};
312
Joakim Soderberg4c531232013-02-06 15:26:58 +0900313#ifndef WIN32
Andy Greena6cbece2011-01-27 20:06:03 +0000314static void
315signal_handler(int sig, siginfo_t *si, void *v)
316{
317 struct timeval tv;
Andy Greena6cbece2011-01-27 20:06:03 +0000318
319 gettimeofday(&tv, NULL);
Andy Green2f4c2be2011-01-30 12:15:25 +0000320 interrupted_time = (tv.tv_sec * 1000000) + tv.tv_usec;
Andy Greena6cbece2011-01-27 20:06:03 +0000321}
Joakim Soderberg4c531232013-02-06 15:26:58 +0900322#endif
Andy Greena6cbece2011-01-27 20:06:03 +0000323
324int main(int argc, char **argv)
325{
326 int n = 0;
327 int port = 7681;
328 int use_ssl = 0;
329 struct libwebsocket_context *context;
Andy Greena6cbece2011-01-27 20:06:03 +0000330 char protocol_name[256];
Andy Greena6cbece2011-01-27 20:06:03 +0000331 char ip[30];
Joakim Soderberg4c531232013-02-06 15:26:58 +0900332#ifndef WIN32
Andy Greena6cbece2011-01-27 20:06:03 +0000333 struct sigaction sa;
Andy Greena6cbece2011-01-27 20:06:03 +0000334 struct winsize w;
Joakim Soderberg4c531232013-02-06 15:26:58 +0900335#endif
336 struct timeval tv;
Andy Green42f69142011-01-30 08:10:02 +0000337 unsigned long oldus = 0;
Andy Green2f4c2be2011-01-30 12:15:25 +0000338 unsigned long l;
Andy Greenbfb051f2011-02-09 08:49:14 +0000339 int ietf_version = -1;
Andy Green1b265272013-02-09 14:01:09 +0800340 struct lws_context_creation_info info;
341
342 memset(&info, 0, sizeof info);
Andy Green42f69142011-01-30 08:10:02 +0000343
Andy Greena6cbece2011-01-27 20:06:03 +0000344 if (argc < 2)
345 goto usage;
346
347 address = argv[1];
348 optind++;
349
350 while (n >= 0) {
Andy Green46ef0cf2013-01-10 22:28:59 +0800351 n = getopt_long(argc, argv, "v:kr:hmfts:n:i:p:d:", options, NULL);
Andy Greena6cbece2011-01-27 20:06:03 +0000352 if (n < 0)
353 continue;
354 switch (n) {
Andy Green46ef0cf2013-01-10 22:28:59 +0800355 case 'd':
Andy Greende8f27a2013-01-12 09:17:42 +0800356 lws_set_log_level(atoi(optarg), NULL);
Andy Green46ef0cf2013-01-10 22:28:59 +0800357 break;
Andy Greena6cbece2011-01-27 20:06:03 +0000358 case 'm':
359 use_mirror = 1;
360 break;
361 case 't':
362 use_ssl = 2; /* 2 = allow selfsigned */
363 break;
364 case 'p':
365 port = atoi(optarg);
366 break;
367 case 'n':
368 strncpy(protocol_name, optarg, sizeof protocol_name);
Andy Green42f69142011-01-30 08:10:02 +0000369 protocol_name[(sizeof protocol_name) - 1] = '\0';
Andy Greena6cbece2011-01-27 20:06:03 +0000370 protocols[PROTOCOL_LWS_MIRROR].name = protocol_name;
371 break;
372 case 'i':
373 interval_us = 1000000.0 * atof(optarg);
374 break;
375 case 's':
376 size = atoi(optarg);
377 break;
378 case 'f':
379 flood = 1;
380 break;
Andy Green2f4c2be2011-01-30 12:15:25 +0000381 case 'r':
382 clients = atoi(optarg);
383 if (clients > MAX_PING_CLIENTS || clients < 1) {
384 fprintf(stderr, "Max clients supportd = %d\n",
385 MAX_PING_CLIENTS);
386 return 1;
387 }
388 break;
Andy Green8014b292011-01-30 20:57:25 +0000389 case 'k':
390 write_options = LWS_WRITE_CLIENT_IGNORE_XOR_MASK;
391 break;
Andy Greenbfb051f2011-02-09 08:49:14 +0000392 case 'v':
393 ietf_version = atoi(optarg);
394 break;
Andy Green8014b292011-01-30 20:57:25 +0000395
Andy Greena6cbece2011-01-27 20:06:03 +0000396 case 'h':
397 goto usage;
398 }
399 }
400
401 if (!use_mirror) {
402 if (size > MAX_PING_PAYLOAD) {
403 fprintf(stderr, "Max ping opcode payload size %d\n",
404 MAX_PING_PAYLOAD);
405 return 1;
406 }
407 } else {
408 if (size > MAX_MIRROR_PAYLOAD) {
409 fprintf(stderr, "Max mirror payload size %d\n",
410 MAX_MIRROR_PAYLOAD);
411 return 1;
412 }
413 }
414
Joakim Soderberg4c531232013-02-06 15:26:58 +0900415#ifndef WIN32
Andy Green42f69142011-01-30 08:10:02 +0000416 if (isatty(STDOUT_FILENO))
417 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
418 if (w.ws_col > 0)
419 screen_width = w.ws_col;
Joakim Soderberg4c531232013-02-06 15:26:58 +0900420#endif
Andy Greena6cbece2011-01-27 20:06:03 +0000421
Andy Green1b265272013-02-09 14:01:09 +0800422 info.port = CONTEXT_PORT_NO_LISTEN;
423 info.protocols = protocols;
Andy Green3182ece2013-01-20 17:08:31 +0800424#ifndef LWS_NO_EXTENSIONS
Joakim Soderbergf272cb02013-02-13 09:29:26 +0800425 info.extensions = libwebsocket_get_internal_extensions();
Andy Green3182ece2013-01-20 17:08:31 +0800426#endif
Andy Green1b265272013-02-09 14:01:09 +0800427 info.gid = -1;
428 info.uid = -1;
429
430 context = libwebsocket_create_context(&info);
Andy Greena6cbece2011-01-27 20:06:03 +0000431 if (context == NULL) {
432 fprintf(stderr, "Creating libwebsocket context failed\n");
433 return 1;
434 }
435
Andy Green2f4c2be2011-01-30 12:15:25 +0000436 /* create client websockets using dumb increment protocol */
Andy Greena6cbece2011-01-27 20:06:03 +0000437
Andy Green2f4c2be2011-01-30 12:15:25 +0000438 for (n = 0; n < clients; n++) {
Andy Green62c54d22011-02-14 09:14:25 +0000439 ping_wsi[n] = libwebsocket_client_connect(context, address,
440 port, use_ssl, "/", address,
Andy Greenbfb051f2011-02-09 08:49:14 +0000441 "origin", protocols[PROTOCOL_LWS_MIRROR].name,
442 ietf_version);
Andy Green62c54d22011-02-14 09:14:25 +0000443 if (ping_wsi[n] == NULL) {
Peter Pentchevc74964e2013-02-07 16:17:13 +0200444 fprintf(stderr, "client connection %d failed to "
Andy Green2f4c2be2011-01-30 12:15:25 +0000445 "connect\n", n);
446 return 1;
447 }
Andy Greena6cbece2011-01-27 20:06:03 +0000448 }
449
Andy Greenaaf0b9f2013-01-30 08:12:20 +0800450 libwebsockets_get_peer_addresses(context, ping_wsi[0],
Andy Green62c54d22011-02-14 09:14:25 +0000451 libwebsocket_get_socket_fd(ping_wsi[0]),
Andy Greene2acfc82011-02-13 09:05:54 +0000452 peer_name, sizeof peer_name, ip, sizeof ip);
Andy Greena6cbece2011-01-27 20:06:03 +0000453
454 fprintf(stderr, "Websocket PING %s (%s) %d bytes of data.\n",
Andy Greene2acfc82011-02-13 09:05:54 +0000455 peer_name, ip, size);
Andy Greena6cbece2011-01-27 20:06:03 +0000456
Joakim Soderberg4c531232013-02-06 15:26:58 +0900457#ifndef WIN32
Andy Greena6cbece2011-01-27 20:06:03 +0000458 /* set the ^C handler */
Andy Greena6cbece2011-01-27 20:06:03 +0000459 sa.sa_sigaction = signal_handler;
460 sa.sa_flags = SA_SIGINFO;
461 sigemptyset(&sa.sa_mask);
462 sigaction(SIGINT, &sa, NULL);
Joakim Soderberg4c531232013-02-06 15:26:58 +0900463#endif
Andy Greena6cbece2011-01-27 20:06:03 +0000464
465 gettimeofday(&tv, NULL);
466 started = (tv.tv_sec * 1000000) + tv.tv_usec;
467
468 /* service loop */
469
470 n = 0;
471 while (n >= 0) {
Andy Greena6cbece2011-01-27 20:06:03 +0000472
473 gettimeofday(&tv, NULL);
Andy Greena6cbece2011-01-27 20:06:03 +0000474 l = (tv.tv_sec * 1000000) + tv.tv_usec;
Andy Green2f4c2be2011-01-30 12:15:25 +0000475
Andy Green62c54d22011-02-14 09:14:25 +0000476 /* servers can hang up on us */
477
478 if (clients == 0) {
479 n = -1;
480 continue;
481 }
Andy Green2f4c2be2011-01-30 12:15:25 +0000482
483 if (!interrupted_time) {
484 if ((l - oldus) > interval_us) {
485 for (n = 0; n < clients; n++)
Andy Green8014b292011-01-30 20:57:25 +0000486 libwebsocket_callback_on_writable(
Andy Green62c54d22011-02-14 09:14:25 +0000487 context, ping_wsi[n]);
Andy Green2f4c2be2011-01-30 12:15:25 +0000488 oldus = l;
489 }
490 } else
491
492 /* allow time for in-flight pongs to come */
493
494 if ((l - interrupted_time) > 250000) {
495 n = -1;
496 continue;
497 }
Andy Greena6cbece2011-01-27 20:06:03 +0000498
499 if (!interval_us)
500 n = libwebsocket_service(context, 0);
501 else
502 n = libwebsocket_service(context, 1);
503 }
504
Andy Green2f4c2be2011-01-30 12:15:25 +0000505 /* stats */
506
507 fprintf(stderr, "\n--- %s websocket ping statistics "
508 "using %d connections ---\n"
509 "%lu packets transmitted, %lu received, "
510 "%lu%% packet loss, time %ldms\n"
511 "rtt min/avg/max = %0.3f/%0.3f/%0.3f ms\n"
512 "payload bandwidth average %0.3f KiBytes/sec\n",
Andy Greene2acfc82011-02-13 09:05:54 +0000513 peer_name, clients, global_tx_count, global_rx_count,
Andy Green2f4c2be2011-01-30 12:15:25 +0000514 ((global_tx_count - global_rx_count) * 100) / global_tx_count,
515 (l - started) / 1000,
516 ((double)rtt_min) / 1000.0,
517 ((double)rtt_avg / global_rx_count) / 1000.0,
518 ((double)rtt_max) / 1000.0,
519 ((double)global_rx_count * (double)size) /
520 ((double)(l - started) / 1000000.0) / 1024.0);
521
Andy Greena6cbece2011-01-27 20:06:03 +0000522 libwebsocket_context_destroy(context);
523
524 return 0;
525
526usage:
527 fprintf(stderr, "Usage: libwebsockets-test-ping "
528 "<server address> [--port=<p>] "
529 "[--ssl] [--interval=<float sec>] "
530 "[--size=<bytes>] "
531 "[--protocol=<protocolname>] "
532 "[--mirror] "
Andy Green46ef0cf2013-01-10 22:28:59 +0800533 "[--replicate=clients>] "
534 "[--version <version>] "
535 "[-d <log bitfield> ]"
Andy Greena6cbece2011-01-27 20:06:03 +0000536 "\n");
537 return 1;
538}