2011-01-27 20:06:03 +00:00
|
|
|
/*
|
|
|
|
* libwebsockets-test-ping - libwebsockets floodping
|
|
|
|
*
|
2016-01-29 09:35:58 +08:00
|
|
|
* Copyright (C) 2011-2016 Andy Green <andy@warmcat.com>
|
2011-01-27 20:06:03 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation:
|
|
|
|
* version 2.1 of the License.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/types.h>
|
2014-03-29 07:43:38 +01:00
|
|
|
|
2015-10-23 08:10:55 +02:00
|
|
|
#include "../lib/libwebsockets.h"
|
|
|
|
|
2014-03-29 07:43:38 +01:00
|
|
|
#ifndef _WIN32
|
|
|
|
#include <netdb.h>
|
2011-01-27 20:06:03 +00:00
|
|
|
#include <sys/socket.h>
|
2014-03-29 07:43:38 +01:00
|
|
|
#include <sys/time.h>
|
2011-01-27 20:06:03 +00:00
|
|
|
#include <sys/ioctl.h>
|
2013-02-06 15:26:58 +09:00
|
|
|
#include <poll.h>
|
2014-03-29 07:43:38 +01:00
|
|
|
#include <unistd.h>
|
2015-10-23 08:10:55 +02:00
|
|
|
#else
|
|
|
|
#include "gettimeofday.h"
|
2013-02-06 15:26:58 +09:00
|
|
|
#endif
|
|
|
|
|
2015-12-22 08:17:34 +08:00
|
|
|
#ifdef __ANDROID__
|
|
|
|
#include <termiosh>
|
|
|
|
#endif
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
/*
|
|
|
|
* this is specified in the 04 standard, control frames can only have small
|
|
|
|
* payload length styles
|
|
|
|
*/
|
|
|
|
#define MAX_PING_PAYLOAD 125
|
|
|
|
#define MAX_MIRROR_PAYLOAD 4096
|
2011-01-30 12:15:25 +00:00
|
|
|
#define MAX_PING_CLIENTS 256
|
|
|
|
#define PING_RINGBUFFER_SIZE 256
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2015-12-04 11:08:32 +08:00
|
|
|
static struct lws *ping_wsi[MAX_PING_CLIENTS];
|
2011-01-27 20:06:03 +00:00
|
|
|
static unsigned int interval_us = 1000000;
|
|
|
|
static unsigned int size = 64;
|
2011-01-30 08:10:02 +00:00
|
|
|
static int flood;
|
2011-01-27 20:06:03 +00:00
|
|
|
static const char *address;
|
2016-01-11 11:34:01 +08:00
|
|
|
static unsigned char pingbuf[LWS_PRE + MAX_MIRROR_PAYLOAD];
|
2011-02-13 09:05:54 +00:00
|
|
|
static char peer_name[128];
|
2011-01-27 20:06:03 +00:00
|
|
|
static unsigned long started;
|
2011-01-30 12:15:25 +00:00
|
|
|
static int screen_width = 80;
|
|
|
|
static int use_mirror;
|
2011-01-30 20:57:25 +00:00
|
|
|
static unsigned int write_options;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
static unsigned long rtt_min = 100000000;
|
2011-01-30 08:10:02 +00:00
|
|
|
static unsigned long rtt_max;
|
|
|
|
static unsigned long rtt_avg;
|
2011-01-30 12:15:25 +00:00
|
|
|
static unsigned long global_rx_count;
|
|
|
|
static unsigned long global_tx_count;
|
|
|
|
static int clients = 1;
|
|
|
|
static unsigned long interrupted_time;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
struct ping {
|
|
|
|
unsigned long issue_timestamp;
|
|
|
|
unsigned long index;
|
|
|
|
unsigned int seen;
|
|
|
|
};
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
struct per_session_data__ping {
|
2014-11-30 12:25:36 +08:00
|
|
|
uint64_t ping_index;
|
2011-01-30 12:15:25 +00:00
|
|
|
|
|
|
|
struct ping ringbuffer[PING_RINGBUFFER_SIZE];
|
|
|
|
int ringbuffer_head;
|
|
|
|
int ringbuffer_tail;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
unsigned long rx_count;
|
|
|
|
};
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* uses the ping pong protocol features to provide an equivalent for the
|
|
|
|
* ping utility for 04+ websockets
|
|
|
|
*/
|
|
|
|
|
|
|
|
enum demo_protocols {
|
|
|
|
|
|
|
|
PROTOCOL_LWS_MIRROR,
|
|
|
|
|
|
|
|
/* always last */
|
|
|
|
DEMO_PROTOCOL_COUNT
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2015-12-17 07:54:44 +08:00
|
|
|
callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
|
|
|
|
void *user, void *in, size_t len)
|
2011-01-27 20:06:03 +00:00
|
|
|
{
|
2015-12-17 08:09:13 +08:00
|
|
|
struct per_session_data__ping *psd = user;
|
2011-01-27 20:06:03 +00:00
|
|
|
struct timeval tv;
|
|
|
|
unsigned char *p;
|
|
|
|
unsigned long iv;
|
|
|
|
int match = 0;
|
2015-12-17 08:09:13 +08:00
|
|
|
uint64_t l;
|
|
|
|
int shift;
|
|
|
|
int n;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
switch (reason) {
|
2011-02-14 09:14:25 +00:00
|
|
|
case LWS_CALLBACK_CLOSED:
|
|
|
|
fprintf(stderr, "LWS_CALLBACK_CLOSED on %p\n", (void *)wsi);
|
|
|
|
|
|
|
|
/* remove closed guy */
|
2015-12-14 08:52:03 +08:00
|
|
|
|
2011-02-14 09:14:25 +00:00
|
|
|
for (n = 0; n < clients; n++)
|
2015-12-14 08:52:03 +08:00
|
|
|
if (ping_wsi[n] == wsi) {
|
2011-02-14 09:14:25 +00:00
|
|
|
clients--;
|
|
|
|
while (n < clients) {
|
|
|
|
ping_wsi[n] = ping_wsi[n + 1];
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
psd->rx_count = 0;
|
|
|
|
psd->ping_index = 1;
|
|
|
|
psd->ringbuffer_head = 0;
|
|
|
|
psd->ringbuffer_tail = 0;
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
/*
|
|
|
|
* start the ball rolling,
|
|
|
|
* LWS_CALLBACK_CLIENT_WRITEABLE will come next service
|
|
|
|
*/
|
|
|
|
|
2015-12-16 18:19:08 +08:00
|
|
|
lws_callback_on_writable(wsi);
|
2011-01-27 20:06:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_CLIENT_RECEIVE:
|
|
|
|
case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
iv = (tv.tv_sec * 1000000) + tv.tv_usec;
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
psd->rx_count++;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
shift = 56;
|
|
|
|
p = in;
|
|
|
|
l = 0;
|
|
|
|
|
|
|
|
while (shift >= 0) {
|
2014-11-30 13:37:23 +08:00
|
|
|
l |= ((uint64_t)*p++) << shift;
|
2011-01-27 20:06:03 +00:00
|
|
|
shift -= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find it in the ringbuffer, look backwards from head */
|
2011-01-30 12:15:25 +00:00
|
|
|
n = psd->ringbuffer_head;
|
2011-01-27 20:06:03 +00:00
|
|
|
while (!match) {
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if (psd->ringbuffer[n].index == l) {
|
|
|
|
psd->ringbuffer[n].seen++;
|
2011-01-27 20:06:03 +00:00
|
|
|
match = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if (n == psd->ringbuffer_tail) {
|
2011-01-27 20:06:03 +00:00
|
|
|
match = -1;
|
|
|
|
continue;
|
|
|
|
}
|
2011-01-30 08:10:02 +00:00
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
if (n == 0)
|
|
|
|
n = PING_RINGBUFFER_SIZE - 1;
|
|
|
|
else
|
2011-01-30 08:10:02 +00:00
|
|
|
n--;
|
2011-01-27 20:06:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (match < 1) {
|
2011-01-30 08:10:02 +00:00
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
if (!flood)
|
|
|
|
fprintf(stderr, "%d bytes from %s: req=%ld "
|
2014-12-02 08:42:47 +08:00
|
|
|
"time=(unknown)\n", (int)len, address,
|
|
|
|
(long)l);
|
2011-01-27 20:06:03 +00:00
|
|
|
else
|
|
|
|
fprintf(stderr, "\b \b");
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if (psd->ringbuffer[n].seen > 1)
|
2011-01-27 20:06:03 +00:00
|
|
|
fprintf(stderr, "DUP! ");
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if ((iv - psd->ringbuffer[n].issue_timestamp) < rtt_min)
|
|
|
|
rtt_min = iv - psd->ringbuffer[n].issue_timestamp;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if ((iv - psd->ringbuffer[n].issue_timestamp) > rtt_max)
|
|
|
|
rtt_max = iv - psd->ringbuffer[n].issue_timestamp;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
rtt_avg += iv - psd->ringbuffer[n].issue_timestamp;
|
|
|
|
global_rx_count++;
|
2011-01-30 08:10:02 +00:00
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
if (!flood)
|
|
|
|
fprintf(stderr, "%d bytes from %s: req=%ld "
|
2014-12-02 08:42:47 +08:00
|
|
|
"time=%lu.%lums\n", (int)len, address, (long)l,
|
2011-01-30 12:15:25 +00:00
|
|
|
(iv - psd->ringbuffer[n].issue_timestamp) / 1000,
|
|
|
|
((iv - psd->ringbuffer[n].issue_timestamp) / 100) % 10);
|
2011-01-27 20:06:03 +00:00
|
|
|
else
|
|
|
|
fprintf(stderr, "\b \b");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
|
|
|
|
|
|
|
shift = 56;
|
2016-01-11 11:34:01 +08:00
|
|
|
p = &pingbuf[LWS_PRE];
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
/* 64-bit ping index in network byte order */
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
while (shift >= 0) {
|
2015-12-27 18:16:32 +08:00
|
|
|
*p++ = (unsigned char)(psd->ping_index >> shift);
|
2011-01-27 20:06:03 +00:00
|
|
|
shift -= 8;
|
|
|
|
}
|
2011-01-30 08:10:02 +00:00
|
|
|
|
2016-01-11 11:34:01 +08:00
|
|
|
while ((unsigned int)(p - &pingbuf[LWS_PRE]) < size)
|
2013-01-16 14:35:12 +08:00
|
|
|
*p++ = 0;
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
gettimeofday(&tv, NULL);
|
2011-01-30 08:10:02 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
psd->ringbuffer[psd->ringbuffer_head].issue_timestamp =
|
2011-01-27 20:06:03 +00:00
|
|
|
(tv.tv_sec * 1000000) + tv.tv_usec;
|
2015-12-27 18:16:32 +08:00
|
|
|
psd->ringbuffer[psd->ringbuffer_head].index = (unsigned long)psd->ping_index++;
|
2011-01-30 12:15:25 +00:00
|
|
|
psd->ringbuffer[psd->ringbuffer_head].seen = 0;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if (psd->ringbuffer_head == PING_RINGBUFFER_SIZE - 1)
|
|
|
|
psd->ringbuffer_head = 0;
|
2011-01-27 20:06:03 +00:00
|
|
|
else
|
2011-01-30 12:15:25 +00:00
|
|
|
psd->ringbuffer_head++;
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
/* snip any re-used tail so we keep to the ring length */
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if (psd->ringbuffer_tail == psd->ringbuffer_head) {
|
|
|
|
if (psd->ringbuffer_tail == PING_RINGBUFFER_SIZE - 1)
|
|
|
|
psd->ringbuffer_tail = 0;
|
2011-01-27 20:06:03 +00:00
|
|
|
else
|
2011-01-30 12:15:25 +00:00
|
|
|
psd->ringbuffer_tail++;
|
2011-01-27 20:06:03 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
global_tx_count++;
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
if (use_mirror)
|
2015-12-04 08:43:54 +08:00
|
|
|
n = lws_write(wsi,
|
2016-01-11 11:34:01 +08:00
|
|
|
&pingbuf[LWS_PRE],
|
2011-01-30 20:57:25 +00:00
|
|
|
size, write_options | LWS_WRITE_BINARY);
|
2011-01-27 20:06:03 +00:00
|
|
|
else
|
2015-12-04 08:43:54 +08:00
|
|
|
n = lws_write(wsi,
|
2016-01-11 11:34:01 +08:00
|
|
|
&pingbuf[LWS_PRE],
|
2011-01-30 20:57:25 +00:00
|
|
|
size, write_options | LWS_WRITE_PING);
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2013-02-23 10:50:10 +08:00
|
|
|
if (n < 0)
|
|
|
|
return -1;
|
2015-12-27 18:16:32 +08:00
|
|
|
if (n < (int)size) {
|
2013-02-23 10:50:10 +08:00
|
|
|
lwsl_err("Partial write\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if (flood &&
|
|
|
|
(psd->ping_index - psd->rx_count) < (screen_width - 1))
|
2011-01-27 20:06:03 +00:00
|
|
|
fprintf(stderr, ".");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* list of supported protocols and callbacks */
|
|
|
|
|
2015-12-04 11:08:32 +08:00
|
|
|
static struct lws_protocols protocols[] = {
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2013-02-06 15:26:58 +09:00
|
|
|
{
|
|
|
|
"lws-mirror-protocol",
|
|
|
|
callback_lws_mirror,
|
|
|
|
sizeof (struct per_session_data__ping),
|
2011-01-27 20:06:03 +00:00
|
|
|
},
|
2015-12-14 08:52:03 +08:00
|
|
|
{
|
|
|
|
NULL, NULL, 0/* end of list */
|
2011-01-27 20:06:03 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-02-02 09:02:24 +08:00
|
|
|
static const struct lws_extension exts[] = {
|
|
|
|
{
|
|
|
|
"permessage-deflate",
|
|
|
|
lws_extension_callback_pm_deflate,
|
|
|
|
"permessage-deflate; client_no_context_takeover; client_max_window_bits"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"deflate-frame",
|
|
|
|
lws_extension_callback_pm_deflate,
|
|
|
|
"deflate_frame"
|
|
|
|
},
|
|
|
|
{ NULL, NULL, NULL /* terminator */ }
|
|
|
|
};
|
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
static struct option options[] = {
|
|
|
|
{ "help", no_argument, NULL, 'h' },
|
2013-01-10 22:28:59 +08:00
|
|
|
{ "debug", required_argument, NULL, 'd' },
|
2011-01-27 20:06:03 +00:00
|
|
|
{ "port", required_argument, NULL, 'p' },
|
|
|
|
{ "ssl", no_argument, NULL, 't' },
|
|
|
|
{ "interval", required_argument, NULL, 'i' },
|
|
|
|
{ "size", required_argument, NULL, 's' },
|
|
|
|
{ "protocol", required_argument, NULL, 'n' },
|
|
|
|
{ "flood", no_argument, NULL, 'f' },
|
|
|
|
{ "mirror", no_argument, NULL, 'm' },
|
2011-01-30 12:15:25 +00:00
|
|
|
{ "replicate", required_argument, NULL, 'r' },
|
2011-01-30 20:57:25 +00:00
|
|
|
{ "killmask", no_argument, NULL, 'k' },
|
2011-02-09 08:49:14 +00:00
|
|
|
{ "version", required_argument, NULL, 'v' },
|
2011-01-27 20:06:03 +00:00
|
|
|
{ NULL, 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
2015-10-23 08:10:55 +02:00
|
|
|
#ifndef _WIN32
|
2011-01-27 20:06:03 +00:00
|
|
|
static void
|
|
|
|
signal_handler(int sig, siginfo_t *si, void *v)
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
gettimeofday(&tv, NULL);
|
2011-01-30 12:15:25 +00:00
|
|
|
interrupted_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
2011-01-27 20:06:03 +00:00
|
|
|
}
|
2013-02-06 15:26:58 +09:00
|
|
|
#endif
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
int port = 7681;
|
|
|
|
int use_ssl = 0;
|
2015-12-04 11:08:32 +08:00
|
|
|
struct lws_context *context;
|
2016-02-02 09:02:24 +08:00
|
|
|
char protocol_name[256], ads_port[300];
|
2011-01-27 20:06:03 +00:00
|
|
|
char ip[30];
|
2015-10-23 08:10:55 +02:00
|
|
|
#ifndef _WIN32
|
2011-01-27 20:06:03 +00:00
|
|
|
struct sigaction sa;
|
|
|
|
struct winsize w;
|
2013-02-06 15:26:58 +09:00
|
|
|
#endif
|
|
|
|
struct timeval tv;
|
2011-01-30 08:10:02 +00:00
|
|
|
unsigned long oldus = 0;
|
2011-01-30 12:15:25 +00:00
|
|
|
unsigned long l;
|
2011-02-09 08:49:14 +00:00
|
|
|
int ietf_version = -1;
|
2013-02-09 14:01:09 +08:00
|
|
|
struct lws_context_creation_info info;
|
2016-02-02 09:02:24 +08:00
|
|
|
struct lws_client_connect_info i;
|
2013-02-09 14:01:09 +08:00
|
|
|
|
|
|
|
memset(&info, 0, sizeof info);
|
2011-01-30 08:10:02 +00:00
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
if (argc < 2)
|
|
|
|
goto usage;
|
|
|
|
|
|
|
|
while (n >= 0) {
|
2013-01-10 22:28:59 +08:00
|
|
|
n = getopt_long(argc, argv, "v:kr:hmfts:n:i:p:d:", options, NULL);
|
2011-01-27 20:06:03 +00:00
|
|
|
if (n < 0)
|
|
|
|
continue;
|
|
|
|
switch (n) {
|
2013-01-10 22:28:59 +08:00
|
|
|
case 'd':
|
2013-01-12 09:17:42 +08:00
|
|
|
lws_set_log_level(atoi(optarg), NULL);
|
2013-01-10 22:28:59 +08:00
|
|
|
break;
|
2011-01-27 20:06:03 +00:00
|
|
|
case 'm':
|
|
|
|
use_mirror = 1;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
use_ssl = 2; /* 2 = allow selfsigned */
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
port = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
strncpy(protocol_name, optarg, sizeof protocol_name);
|
2011-01-30 08:10:02 +00:00
|
|
|
protocol_name[(sizeof protocol_name) - 1] = '\0';
|
2011-01-27 20:06:03 +00:00
|
|
|
protocols[PROTOCOL_LWS_MIRROR].name = protocol_name;
|
|
|
|
break;
|
|
|
|
case 'i':
|
2015-12-27 18:16:32 +08:00
|
|
|
interval_us = (unsigned int)(1000000.0 * atof(optarg));
|
2011-01-27 20:06:03 +00:00
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
size = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
flood = 1;
|
|
|
|
break;
|
2011-01-30 12:15:25 +00:00
|
|
|
case 'r':
|
|
|
|
clients = atoi(optarg);
|
|
|
|
if (clients > MAX_PING_CLIENTS || clients < 1) {
|
|
|
|
fprintf(stderr, "Max clients supportd = %d\n",
|
|
|
|
MAX_PING_CLIENTS);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
2011-01-30 20:57:25 +00:00
|
|
|
case 'k':
|
|
|
|
write_options = LWS_WRITE_CLIENT_IGNORE_XOR_MASK;
|
|
|
|
break;
|
2011-02-09 08:49:14 +00:00
|
|
|
case 'v':
|
|
|
|
ietf_version = atoi(optarg);
|
|
|
|
break;
|
2011-01-30 20:57:25 +00:00
|
|
|
|
2011-01-27 20:06:03 +00:00
|
|
|
case 'h':
|
|
|
|
goto usage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!use_mirror) {
|
|
|
|
if (size > MAX_PING_PAYLOAD) {
|
|
|
|
fprintf(stderr, "Max ping opcode payload size %d\n",
|
|
|
|
MAX_PING_PAYLOAD);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (size > MAX_MIRROR_PAYLOAD) {
|
|
|
|
fprintf(stderr, "Max mirror payload size %d\n",
|
|
|
|
MAX_MIRROR_PAYLOAD);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-23 08:10:55 +02:00
|
|
|
#ifndef _WIN32
|
2011-01-30 08:10:02 +00:00
|
|
|
if (isatty(STDOUT_FILENO))
|
|
|
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
|
|
|
|
if (w.ws_col > 0)
|
|
|
|
screen_width = w.ws_col;
|
2013-02-06 15:26:58 +09:00
|
|
|
#endif
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2013-02-09 14:01:09 +08:00
|
|
|
info.port = CONTEXT_PORT_NO_LISTEN;
|
|
|
|
info.protocols = protocols;
|
2016-02-02 09:02:24 +08:00
|
|
|
info.extensions = exts;
|
|
|
|
|
2013-02-09 14:01:09 +08:00
|
|
|
info.gid = -1;
|
|
|
|
info.uid = -1;
|
|
|
|
|
2015-12-04 08:43:54 +08:00
|
|
|
context = lws_create_context(&info);
|
2011-01-27 20:06:03 +00:00
|
|
|
if (context == NULL) {
|
|
|
|
fprintf(stderr, "Creating libwebsocket context failed\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
/* create client websockets using dumb increment protocol */
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2016-02-02 09:02:24 +08:00
|
|
|
address = argv[optind];
|
|
|
|
sprintf(ads_port, "%s:%u", address, port & 65535);
|
|
|
|
lwsl_notice("Connecting to %s...\n", ads_port);
|
|
|
|
memset(&i, 0, sizeof(i));
|
|
|
|
i.context = context;
|
|
|
|
i.address = address;
|
|
|
|
i.port = port;
|
|
|
|
i.ssl_connection = use_ssl;
|
|
|
|
i.path = "/";
|
|
|
|
i.host = ads_port;
|
|
|
|
i.origin = ads_port;
|
|
|
|
i.protocol = protocols[PROTOCOL_LWS_MIRROR].name;
|
|
|
|
i.client_exts = exts;
|
|
|
|
i.ietf_version_or_minus_one = ietf_version;
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
for (n = 0; n < clients; n++) {
|
2016-02-02 09:02:24 +08:00
|
|
|
ping_wsi[n] = lws_client_connect_via_info(&i);
|
2011-02-14 09:14:25 +00:00
|
|
|
if (ping_wsi[n] == NULL) {
|
2016-02-02 09:02:24 +08:00
|
|
|
lwsl_err("client %d failed to connect\n", n);
|
2011-01-30 12:15:25 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2011-01-27 20:06:03 +00:00
|
|
|
}
|
|
|
|
|
2015-12-16 18:19:08 +08:00
|
|
|
lws_get_peer_addresses(ping_wsi[0], lws_get_socket_fd(ping_wsi[0]),
|
2011-02-13 09:05:54 +00:00
|
|
|
peer_name, sizeof peer_name, ip, sizeof ip);
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2016-01-29 09:35:58 +08:00
|
|
|
lwsl_notice("libwebsockets test server ping - license LGPL2.1+SLE\n");
|
|
|
|
lwsl_notice("(C) Copyright 2010-2016 Andy Green <andy@warmcat.com>\n");
|
2011-01-27 20:06:03 +00:00
|
|
|
fprintf(stderr, "Websocket PING %s (%s) %d bytes of data.\n",
|
2011-02-13 09:05:54 +00:00
|
|
|
peer_name, ip, size);
|
2011-01-27 20:06:03 +00:00
|
|
|
|
2015-10-23 08:10:55 +02:00
|
|
|
#ifndef _WIN32
|
2011-01-27 20:06:03 +00:00
|
|
|
/* set the ^C handler */
|
|
|
|
sa.sa_sigaction = signal_handler;
|
|
|
|
sa.sa_flags = SA_SIGINFO;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sigaction(SIGINT, &sa, NULL);
|
2013-02-06 15:26:58 +09:00
|
|
|
#endif
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
started = (tv.tv_sec * 1000000) + tv.tv_usec;
|
|
|
|
|
|
|
|
/* service loop */
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
while (n >= 0) {
|
|
|
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
l = (tv.tv_sec * 1000000) + tv.tv_usec;
|
2011-01-30 12:15:25 +00:00
|
|
|
|
2011-02-14 09:14:25 +00:00
|
|
|
/* servers can hang up on us */
|
|
|
|
|
|
|
|
if (clients == 0) {
|
|
|
|
n = -1;
|
|
|
|
continue;
|
|
|
|
}
|
2011-01-30 12:15:25 +00:00
|
|
|
|
|
|
|
if (!interrupted_time) {
|
|
|
|
if ((l - oldus) > interval_us) {
|
|
|
|
for (n = 0; n < clients; n++)
|
2015-12-16 18:19:08 +08:00
|
|
|
lws_callback_on_writable(ping_wsi[n]);
|
2011-01-30 12:15:25 +00:00
|
|
|
oldus = l;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
|
|
|
|
/* allow time for in-flight pongs to come */
|
2015-12-14 08:52:03 +08:00
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
if ((l - interrupted_time) > 250000) {
|
|
|
|
n = -1;
|
|
|
|
continue;
|
|
|
|
}
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
if (!interval_us)
|
2015-12-04 08:43:54 +08:00
|
|
|
n = lws_service(context, 0);
|
2011-01-27 20:06:03 +00:00
|
|
|
else
|
2015-12-04 08:43:54 +08:00
|
|
|
n = lws_service(context, 1);
|
2011-01-27 20:06:03 +00:00
|
|
|
}
|
|
|
|
|
2011-01-30 12:15:25 +00:00
|
|
|
/* stats */
|
|
|
|
|
|
|
|
fprintf(stderr, "\n--- %s websocket ping statistics "
|
|
|
|
"using %d connections ---\n"
|
|
|
|
"%lu packets transmitted, %lu received, "
|
|
|
|
"%lu%% packet loss, time %ldms\n"
|
|
|
|
"rtt min/avg/max = %0.3f/%0.3f/%0.3f ms\n"
|
|
|
|
"payload bandwidth average %0.3f KiBytes/sec\n",
|
2011-02-13 09:05:54 +00:00
|
|
|
peer_name, clients, global_tx_count, global_rx_count,
|
2011-01-30 12:15:25 +00:00
|
|
|
((global_tx_count - global_rx_count) * 100) / global_tx_count,
|
|
|
|
(l - started) / 1000,
|
|
|
|
((double)rtt_min) / 1000.0,
|
|
|
|
((double)rtt_avg / global_rx_count) / 1000.0,
|
|
|
|
((double)rtt_max) / 1000.0,
|
|
|
|
((double)global_rx_count * (double)size) /
|
|
|
|
((double)(l - started) / 1000000.0) / 1024.0);
|
|
|
|
|
2015-12-04 08:43:54 +08:00
|
|
|
lws_context_destroy(context);
|
2011-01-27 20:06:03 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
usage:
|
|
|
|
fprintf(stderr, "Usage: libwebsockets-test-ping "
|
|
|
|
"<server address> [--port=<p>] "
|
|
|
|
"[--ssl] [--interval=<float sec>] "
|
|
|
|
"[--size=<bytes>] "
|
|
|
|
"[--protocol=<protocolname>] "
|
|
|
|
"[--mirror] "
|
2013-01-10 22:28:59 +08:00
|
|
|
"[--replicate=clients>] "
|
|
|
|
"[--version <version>] "
|
|
|
|
"[-d <log bitfield> ]"
|
2011-01-27 20:06:03 +00:00
|
|
|
"\n");
|
|
|
|
return 1;
|
|
|
|
}
|