summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy@warmcat.com>2011-01-27 20:06:03 +0000
committerAndy Green <andy@warmcat.com>2011-01-27 20:06:03 +0000
commita6cbece1acc046c8fadaf7bb82713b9290e6a807 (patch)
tree3eb9ff4780c098c5ede456942264c746adeb6761
parentf1d2113d6e7c2da2183837d6896fde56037bedc4 (diff)
introduce-test-ping-app.patchrelease-0.3
Signed-off-by: Andy Green <andy@warmcat.com>
-rw-r--r--README-test-server52
-rwxr-xr-xconfigure28
-rw-r--r--configure.ac11
-rw-r--r--lib/libwebsockets.c15
-rw-r--r--lib/libwebsockets.h7
-rw-r--r--lib/parsers.c15
-rw-r--r--lib/private-libwebsockets.h2
-rw-r--r--libwebsockets-api-doc.html21
-rw-r--r--libwebsockets.spec3
-rw-r--r--test-server/Makefile.am10
-rw-r--r--test-server/Makefile.in37
-rw-r--r--test-server/test-ping.c462
12 files changed, 653 insertions, 10 deletions
diff --git a/README-test-server b/README-test-server
index f10520e..cb9e6b5 100644
--- a/README-test-server
+++ b/README-test-server
@@ -37,6 +37,11 @@ There are a couple of other possible configure options
look for trust certificates to validate
the remote certificate against.
+--enable-noping Don't try to build the ping test app
+ It needs some unixy environment that
+ may choke in other build contexts, this
+ lets you cleanly stop it being built
+
Testing server with a browser
-----------------------------
@@ -107,6 +112,53 @@ use_ssl var being set to 2. Set it to 1 to reject any server
certificate that it doesn't have a trusted CA cert for.
+Using the websocket ping utility
+--------------------------------
+
+libwebsockets-test-ping connects as a client to a remote
+websocket server using 04 protocol and pings it like the
+normal unix ping utility.
+
+$ libwebsockets-test-ping localhost
+handshake OK for protocol lws-mirror-protocol
+Websocket PING localhost.localdomain (127.0.0.1) 64 bytes of data.
+64 bytes from localhost: req=1 time=0.1ms
+64 bytes from localhost: req=2 time=0.1ms
+64 bytes from localhost: req=3 time=0.1ms
+64 bytes from localhost: req=4 time=0.2ms
+64 bytes from localhost: req=5 time=0.1ms
+64 bytes from localhost: req=6 time=0.2ms
+64 bytes from localhost: req=7 time=0.2ms
+64 bytes from localhost: req=8 time=0.1ms
+^C
+--- localhost.localdomain websocket ping statistics ---
+8 packets transmitted, 8 received, 0% packet loss, time 7458ms
+rtt min/avg/max = 0.110/0.185/0.218 ms
+$
+
+By default it sends 64 byte payload packets using the 04
+PING packet opcode type. You can change the payload size
+using the -s= flag, up to a maximum of 125 mandated by the
+04 standard.
+
+Using the lws-mirror protocol that is provided by the test
+server, libwebsockets-test-ping can also use larger payload
+sizes up to 4096 is BINARY packets; lws-mirror will copy
+them back to the client and they appear as a PONG. Use the
+-m flag to select this operation.
+
+The default interval between pings is 1s, you can use the -i=
+flag to set this, including fractions like -i=0.01 for 10ms
+interval.
+
+Before you can even use the PING opcode that is part of the
+standard, you must complete a handshake with a specified
+protocol. By default lws-mirror-protocol is used which is
+supported by the test server. But if you are using it on
+another server, you can specify the protcol to handshake with
+by --protocol=protocolname
+
+
Websocket version supported
---------------------------
diff --git a/configure b/configure
index e301a98..c39b140 100755
--- a/configure
+++ b/configure
@@ -616,6 +616,8 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+NOPING_FALSE
+NOPING_TRUE
clientcertdir
LIBCRYPTO_FALSE
LIBCRYPTO_TRUE
@@ -741,6 +743,7 @@ enable_openssl
enable_nofork
enable_libcrypto
with_client_cert_dir
+enable_noping
'
ac_precious_vars='build_alias
host_alias
@@ -1386,6 +1389,7 @@ Optional Features:
--enable-openssl Enables https support and needs openssl libs
--enable-nofork Disables fork-related options
--enable-libcrypto Use libcrypto MD5 and SHA1 implementations
+ --enable-noping Do not build ping test app, which has some unixy stuff in sources
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -12307,6 +12311,26 @@ fi
+#
+#
+#
+# Check whether --enable-noping was given.
+if test "${enable_noping+set}" = set; then :
+ enableval=$enable_noping; noping=yes
+
+fi
+
+
+ if test x$noping = xyes; then
+ NOPING_TRUE=
+ NOPING_FALSE='#'
+else
+ NOPING_TRUE='#'
+ NOPING_FALSE=
+fi
+
+
+
# Checks for header files.
for ac_header in fcntl.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h
@@ -12621,6 +12645,10 @@ if test -z "${LIBCRYPTO_TRUE}" && test -z "${LIBCRYPTO_FALSE}"; then
as_fn_error $? "conditional \"LIBCRYPTO\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${NOPING_TRUE}" && test -z "${NOPING_FALSE}"; then
+ as_fn_error $? "conditional \"NOPING\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
diff --git a/configure.ac b/configure.ac
index 251a49d..c7d91b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,6 +73,17 @@ AC_SUBST([clientcertdir])
AC_SUBST([CFLAGS])
+#
+#
+#
+AC_ARG_ENABLE(noping,
+ [ --enable-noping Do not build ping test app, which has some unixy stuff in sources],
+ [ noping=yes
+ ])
+
+AM_CONDITIONAL(NOPING, test x$noping = xyes)
+
+
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h])
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 8d46209..e6db157 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -514,6 +514,21 @@ libwebsocket_callback_on_writable_all_protocol(
return 0;
}
+
+/**
+ * libwebsocket_get_socket_fd() - returns the socket file descriptor
+ *
+ * You will not need this unless you are doing something special
+ *
+ * @wsi: Websocket connection instance
+ */
+
+int
+libwebsocket_get_socket_fd(struct libwebsocket *wsi)
+{
+ return wsi->sock;
+}
+
/**
* libwebsocket_rx_flow_control() - Enable and disable socket servicing for
* receieved packets.
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index a486221..ac28abf 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -30,6 +30,7 @@ enum libwebsocket_callback_reasons {
LWS_CALLBACK_CLOSED,
LWS_CALLBACK_RECEIVE,
LWS_CALLBACK_CLIENT_RECEIVE,
+ LWS_CALLBACK_CLIENT_RECEIVE_PONG,
LWS_CALLBACK_CLIENT_WRITEABLE,
LWS_CALLBACK_HTTP,
LWS_CALLBACK_BROADCAST
@@ -87,6 +88,10 @@ struct libwebsocket_context;
* remote client, it can be found at *in and is
* len bytes long
*
+ * LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets,
+ * they appear with this callback reason. PONG
+ * packets only exist in 04+ protocol
+ *
* LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the
* client connection, it can be found at *in and
* is len bytes long
@@ -225,6 +230,8 @@ extern int
libwebsocket_callback_on_writable_all_protocol(
const struct libwebsocket_protocols *protocol);
+extern int
+libwebsocket_get_socket_fd(struct libwebsocket *wsi);
extern int
libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable);
diff --git a/lib/parsers.c b/lib/parsers.c
index d023e9b..ef68382 100644
--- a/lib/parsers.c
+++ b/lib/parsers.c
@@ -560,7 +560,9 @@ spill:
n = libwebsocket_write(wsi, (unsigned char *)
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
wsi->rx_user_buffer_head, LWS_WRITE_PONG);
- break;
+ /* ... then just drop it */
+ wsi->rx_user_buffer_head = 0;
+ return 0;
case LWS_WS_OPCODE_04__PONG:
/* keep the statistics... */
@@ -599,6 +601,7 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
{
int n;
unsigned char buf[20 + 4];
+ int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
switch (wsi->lws_rx_parse_state) {
case LWS_RXPS_NEW:
@@ -875,9 +878,10 @@ spill:
case LWS_WS_OPCODE_04__PONG:
/* keep the statistics... */
wsi->pings_vs_pongs--;
- /* ... then just drop it */
- wsi->rx_user_buffer_head = 0;
- return 0;
+
+ /* issue it */
+ callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
+ break;
default:
break;
@@ -890,8 +894,7 @@ spill:
*/
if (wsi->protocol->callback)
- wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_RECEIVE,
+ wsi->protocol->callback(wsi, callback_action,
wsi->user_space,
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
wsi->rx_user_buffer_head);
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index dfeb373..c3bce43 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -73,7 +73,7 @@ static inline void debug(const char *format, ...)
#define LWS_MAX_HEADER_LEN 4096
#define LWS_INITIAL_HDR_ALLOC 256
#define LWS_ADDITIONAL_HDR_ALLOC 64
-#define MAX_USER_RX_BUFFER 512
+#define MAX_USER_RX_BUFFER 4096
#define MAX_BROADCAST_PAYLOAD 2048
#define LWS_MAX_PROTOCOLS 10
diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html
index f649d79..d070343 100644
--- a/libwebsockets-api-doc.html
+++ b/libwebsockets-api-doc.html
@@ -78,6 +78,21 @@ nothing is pending, or as soon as it services whatever was pending.
<dd>Protocol whose connections will get callbacks
</dl>
<hr>
+<h2>libwebsocket_get_socket_fd - returns the socket file descriptor</h2>
+<i>int</i>
+<b>libwebsocket_get_socket_fd</b>
+(<i>struct libwebsocket *</i> <b>wsi</b>)
+<h3>Arguments</h3>
+<dl>
+<dt><b>wsi</b>
+<dd>Websocket connection instance
+</dl>
+<h3>Description</h3>
+<blockquote>
+<p>
+You will not need this unless you are doing something special
+</blockquote>
+<hr>
<h2>libwebsocket_rx_flow_control - Enable and disable socket servicing for receieved packets.</h2>
<i>int</i>
<b>libwebsocket_rx_flow_control</b>
@@ -394,6 +409,12 @@ data has appeared for this server endpoint from a
remote client, it can be found at *in and is
len bytes long
</blockquote>
+<h3>LWS_CALLBACK_CLIENT_RECEIVE_PONG</h3>
+<blockquote>
+if you elected to see PONG packets,
+they appear with this callback reason. PONG
+packets only exist in 04+ protocol
+</blockquote>
<h3>LWS_CALLBACK_CLIENT_RECEIVE</h3>
<blockquote>
data has appeared from the server for the
diff --git a/libwebsockets.spec b/libwebsockets.spec
index 31a770f..07215c7 100644
--- a/libwebsockets.spec
+++ b/libwebsockets.spec
@@ -1,6 +1,6 @@
Name: libwebsockets
Version: 0.1
-Release: 44.gmaster_f55830db%{?dist}
+Release: 45.gmaster_f1d2113d%{?dist}
Summary: Websocket Server Library
Group: System
@@ -50,6 +50,7 @@ rm -rf $RPM_BUILD_ROOT
/%{_libdir}/libwebsockets.la
%attr(755,root,root) /usr/share/libwebsockets-test-server
%attr(755,root,root) /usr/share/libwebsockets-test-client
+%attr(755,root,root) /usr/share/libwebsockets-test-ping
%doc
%files devel
%defattr(-,root,root,-)
diff --git a/test-server/Makefile.am b/test-server/Makefile.am
index c1083a5..c94d313 100644
--- a/test-server/Makefile.am
+++ b/test-server/Makefile.am
@@ -5,10 +5,18 @@ libwebsockets_test_client_SOURCES=test-client.c
libwebsockets_test_client_LDADD=-L../lib -lwebsockets
-
libwebsockets_test_server_CFLAGS:= -Wall -Werror -std=gnu99 -pedantic -DDATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
libwebsockets_test_client_CFLAGS:= -Wall -Werror -std=gnu99 -pedantic -DDATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
+if NOPING
+else
+bin_PROGRAMS+=libwebsockets-test-ping
+libwebsockets_test_ping_SOURCES=test-ping.c
+libwebsockets_test_ping_LDADD=-L../lib -lwebsockets
+libwebsockets_test_ping_CFLAGS:= -Wall -Werror -std=gnu99 -pedantic -DDATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
+endif
+
+
#
# cook a random test cert and key
# notice your real cert and key will want to be 0600 permissions
diff --git a/test-server/Makefile.in b/test-server/Makefile.in
index c7555af..d6f0da6 100644
--- a/test-server/Makefile.in
+++ b/test-server/Makefile.in
@@ -35,7 +35,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = libwebsockets-test-server$(EXEEXT) \
- libwebsockets-test-client$(EXEEXT)
+ libwebsockets-test-client$(EXEEXT) $(am__EXEEXT_1)
+@NOPING_FALSE@am__append_1 = libwebsockets-test-ping
subdir = test-server
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -46,6 +47,7 @@ mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+@NOPING_FALSE@am__EXEEXT_1 = libwebsockets-test-ping$(EXEEXT)
am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
am_libwebsockets_test_client_OBJECTS = \
@@ -57,6 +59,16 @@ libwebsockets_test_client_LINK = $(LIBTOOL) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(libwebsockets_test_client_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
+am__libwebsockets_test_ping_SOURCES_DIST = test-ping.c
+@NOPING_FALSE@am_libwebsockets_test_ping_OBJECTS = \
+@NOPING_FALSE@ libwebsockets_test_ping-test-ping.$(OBJEXT)
+libwebsockets_test_ping_OBJECTS = \
+ $(am_libwebsockets_test_ping_OBJECTS)
+libwebsockets_test_ping_DEPENDENCIES =
+libwebsockets_test_ping_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libwebsockets_test_ping_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
am_libwebsockets_test_server_OBJECTS = \
libwebsockets_test_server-test-server.$(OBJEXT)
libwebsockets_test_server_OBJECTS = \
@@ -80,8 +92,10 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libwebsockets_test_client_SOURCES) \
+ $(libwebsockets_test_ping_SOURCES) \
$(libwebsockets_test_server_SOURCES)
DIST_SOURCES = $(libwebsockets_test_client_SOURCES) \
+ $(am__libwebsockets_test_ping_SOURCES_DIST) \
$(libwebsockets_test_server_SOURCES)
ETAGS = etags
CTAGS = ctags
@@ -206,6 +220,9 @@ libwebsockets_test_client_SOURCES = test-client.c
libwebsockets_test_client_LDADD = -L../lib -lwebsockets
libwebsockets_test_server_CFLAGS := -Wall -Werror -std=gnu99 -pedantic -DDATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
libwebsockets_test_client_CFLAGS := -Wall -Werror -std=gnu99 -pedantic -DDATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
+@NOPING_FALSE@libwebsockets_test_ping_SOURCES = test-ping.c
+@NOPING_FALSE@libwebsockets_test_ping_LDADD = -L../lib -lwebsockets
+@NOPING_FALSE@libwebsockets_test_ping_CFLAGS := -Wall -Werror -std=gnu99 -pedantic -DDATADIR=\"@datadir@\" -DLWS_OPENSSL_CLIENT_CERTS=\"@clientcertdir@\"
all: all-am
.SUFFIXES:
@@ -286,6 +303,9 @@ clean-binPROGRAMS:
libwebsockets-test-client$(EXEEXT): $(libwebsockets_test_client_OBJECTS) $(libwebsockets_test_client_DEPENDENCIES)
@rm -f libwebsockets-test-client$(EXEEXT)
$(libwebsockets_test_client_LINK) $(libwebsockets_test_client_OBJECTS) $(libwebsockets_test_client_LDADD) $(LIBS)
+libwebsockets-test-ping$(EXEEXT): $(libwebsockets_test_ping_OBJECTS) $(libwebsockets_test_ping_DEPENDENCIES)
+ @rm -f libwebsockets-test-ping$(EXEEXT)
+ $(libwebsockets_test_ping_LINK) $(libwebsockets_test_ping_OBJECTS) $(libwebsockets_test_ping_LDADD) $(LIBS)
libwebsockets-test-server$(EXEEXT): $(libwebsockets_test_server_OBJECTS) $(libwebsockets_test_server_DEPENDENCIES)
@rm -f libwebsockets-test-server$(EXEEXT)
$(libwebsockets_test_server_LINK) $(libwebsockets_test_server_OBJECTS) $(libwebsockets_test_server_LDADD) $(LIBS)
@@ -297,6 +317,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_test_client-test-client.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_test_ping-test-ping.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwebsockets_test_server-test-server.Po@am__quote@
.c.o:
@@ -334,6 +355,20 @@ libwebsockets_test_client-test-client.obj: test-client.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_test_client_CFLAGS) $(CFLAGS) -c -o libwebsockets_test_client-test-client.obj `if test -f 'test-client.c'; then $(CYGPATH_W) 'test-client.c'; else $(CYGPATH_W) '$(srcdir)/test-client.c'; fi`
+libwebsockets_test_ping-test-ping.o: test-ping.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_test_ping_CFLAGS) $(CFLAGS) -MT libwebsockets_test_ping-test-ping.o -MD -MP -MF $(DEPDIR)/libwebsockets_test_ping-test-ping.Tpo -c -o libwebsockets_test_ping-test-ping.o `test -f 'test-ping.c' || echo '$(srcdir)/'`test-ping.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libwebsockets_test_ping-test-ping.Tpo $(DEPDIR)/libwebsockets_test_ping-test-ping.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-ping.c' object='libwebsockets_test_ping-test-ping.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_test_ping_CFLAGS) $(CFLAGS) -c -o libwebsockets_test_ping-test-ping.o `test -f 'test-ping.c' || echo '$(srcdir)/'`test-ping.c
+
+libwebsockets_test_ping-test-ping.obj: test-ping.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_test_ping_CFLAGS) $(CFLAGS) -MT libwebsockets_test_ping-test-ping.obj -MD -MP -MF $(DEPDIR)/libwebsockets_test_ping-test-ping.Tpo -c -o libwebsockets_test_ping-test-ping.obj `if test -f 'test-ping.c'; then $(CYGPATH_W) 'test-ping.c'; else $(CYGPATH_W) '$(srcdir)/test-ping.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libwebsockets_test_ping-test-ping.Tpo $(DEPDIR)/libwebsockets_test_ping-test-ping.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-ping.c' object='libwebsockets_test_ping-test-ping.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_test_ping_CFLAGS) $(CFLAGS) -c -o libwebsockets_test_ping-test-ping.obj `if test -f 'test-ping.c'; then $(CYGPATH_W) 'test-ping.c'; else $(CYGPATH_W) '$(srcdir)/test-ping.c'; fi`
+
libwebsockets_test_server-test-server.o: test-server.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwebsockets_test_server_CFLAGS) $(CFLAGS) -MT libwebsockets_test_server-test-server.o -MD -MP -MF $(DEPDIR)/libwebsockets_test_server-test-server.Tpo -c -o libwebsockets_test_server-test-server.o `test -f 'test-server.c' || echo '$(srcdir)/'`test-server.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libwebsockets_test_server-test-server.Tpo $(DEPDIR)/libwebsockets_test_server-test-server.Po
diff --git a/test-server/test-ping.c b/test-server/test-ping.c
new file mode 100644
index 0000000..6911923
--- /dev/null
+++ b/test-server/test-ping.c
@@ -0,0 +1,462 @@
+/*
+ * libwebsockets-test-ping - libwebsockets floodping
+ *
+ * Copyright (C) 2011 Andy Green <andy@warmcat.com>
+ *
+ * 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 <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <sys/ioctl.h>
+
+#include "../lib/libwebsockets.h"
+#include <poll.h>
+
+/*
+ * 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
+
+static unsigned int interval_us = 1000000;
+static unsigned int size = 64;
+static int flood = 0;
+static const char *address;
+static unsigned char pingbuf[LWS_SEND_BUFFER_PRE_PADDING + MAX_MIRROR_PAYLOAD +
+ LWS_SEND_BUFFER_POST_PADDING];
+static unsigned long oldus = 0;
+static unsigned long ping_index = 1;
+static char *hname = "(unknown)";
+static unsigned long rx_count = 0;
+static unsigned long started;
+
+static unsigned long rtt_min = 100000000;
+static unsigned long rtt_max = 0;
+static unsigned long rtt_avg = 0;
+static int screen_width = 80;
+static int use_mirror = 0;
+
+struct ping {
+ unsigned long issue_timestamp;
+ unsigned long index;
+ unsigned int seen;
+};
+
+#define PING_RINGBUFFER_SIZE 256
+
+struct ping ringbuffer[PING_RINGBUFFER_SIZE];
+int ringbuffer_head;
+int ringbuffer_tail;
+
+/*
+ * 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
+callback_lws_mirror(struct libwebsocket *wsi,
+ enum libwebsocket_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ struct timeval tv;
+ unsigned char *p;
+ int shift;
+ unsigned long l;
+ unsigned long iv;
+ int n;
+ int match = 0;
+
+ switch (reason) {
+ case LWS_CALLBACK_CLIENT_ESTABLISHED:
+
+ /*
+ * start the ball rolling,
+ * LWS_CALLBACK_CLIENT_WRITEABLE will come next service
+ */
+
+ libwebsocket_callback_on_writable(wsi);
+ break;
+
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
+ gettimeofday(&tv, NULL);
+ iv = (tv.tv_sec * 1000000) + tv.tv_usec;
+
+ rx_count++;
+
+ shift = 56;
+ p = in;
+ l = 0;
+
+ while (shift >= 0) {
+ l |= (*p++) << shift;
+ shift -= 8;
+ }
+
+ /* find it in the ringbuffer, look backwards from head */
+ n = ringbuffer_head;
+ while (!match) {
+
+ if (ringbuffer[n].index == l) {
+ ringbuffer[n].seen++;
+ match = 1;
+ continue;
+ }
+
+ if (n == ringbuffer_tail) {
+ match = -1;
+ continue;
+ }
+
+ if (n == 0)
+ n = PING_RINGBUFFER_SIZE - 1;
+ else
+ n--;
+ }
+
+ if (match < 1) {
+
+ if (!flood)
+ fprintf(stderr, "%d bytes from %s: req=%ld "
+ "time=(unknown)\n", (int)len, address, l);
+ else
+ fprintf(stderr, "\b \b");
+
+ break;
+ }
+
+ if (ringbuffer[n].seen > 1)
+ fprintf(stderr, "DUP! ");
+
+ if ((iv - ringbuffer[n].issue_timestamp) < rtt_min)
+ rtt_min = iv - ringbuffer[n].issue_timestamp;
+
+ if ((iv - ringbuffer[n].issue_timestamp) > rtt_max)
+ rtt_max = iv - ringbuffer[n].issue_timestamp;
+
+ rtt_avg += iv - ringbuffer[n].issue_timestamp;
+
+
+ if (!flood)
+ fprintf(stderr, "%d bytes from %s: req=%ld "
+ "time=%lu.%lums\n", (int)len, address, l,
+ (iv - ringbuffer[n].issue_timestamp) / 1000,
+ ((iv - ringbuffer[n].issue_timestamp) / 100) % 10
+ );
+ else
+ fprintf(stderr, "\b \b");
+ break;
+
+ case LWS_CALLBACK_CLIENT_WRITEABLE:
+
+ shift = 56;
+ p = &pingbuf[LWS_SEND_BUFFER_PRE_PADDING];
+
+ while (shift >= 0) {
+ *p++ = ping_index >> shift;
+ shift -= 8;
+ }
+
+ gettimeofday(&tv, NULL);
+
+ ringbuffer[ringbuffer_head].issue_timestamp =
+ (tv.tv_sec * 1000000) + tv.tv_usec;
+ ringbuffer[ringbuffer_head].index = ping_index++;
+ ringbuffer[ringbuffer_head].seen = 0;
+
+ if (ringbuffer_head == PING_RINGBUFFER_SIZE - 1)
+ ringbuffer_head = 0;
+ else
+ ringbuffer_head++;
+
+ /* snip any re-used tail so we keep the whole buffer length */
+
+ if (ringbuffer_tail == ringbuffer_head) {
+ if (ringbuffer_tail == PING_RINGBUFFER_SIZE - 1)
+ ringbuffer_tail = 0;
+ else
+ ringbuffer_tail++;
+ }
+
+ if (use_mirror)
+ libwebsocket_write(wsi,
+ &pingbuf[LWS_SEND_BUFFER_PRE_PADDING],
+ size, LWS_WRITE_BINARY);
+ else
+ libwebsocket_write(wsi,
+ &pingbuf[LWS_SEND_BUFFER_PRE_PADDING],
+ size, LWS_WRITE_PING);
+
+ if (flood && (ping_index - rx_count) < (screen_width - 1))
+ fprintf(stderr, ".");
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+/* list of supported protocols and callbacks */
+
+static struct libwebsocket_protocols protocols[] = {
+
+ [PROTOCOL_LWS_MIRROR] = {
+ .name = "lws-mirror-protocol",
+ .callback = callback_lws_mirror,
+ },
+ [DEMO_PROTOCOL_COUNT] = { /* end of list */
+ .callback = NULL
+ }
+};
+
+static struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "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' },
+ { NULL, 0, 0, 0 }
+};
+
+
+static void
+signal_handler(int sig, siginfo_t *si, void *v)
+{
+ struct timeval tv;
+ unsigned long l;
+
+ gettimeofday(&tv, NULL);
+ l = (tv.tv_sec * 1000000) + tv.tv_usec;
+
+ fprintf(stderr, "\n--- %s websocket ping statistics ---\n"
+ "%lu packets transmitted, %lu received, %lu%% packet loss, time %ldms\n"
+ "rtt min/avg/max = %0.3f/%0.3f/%0.3f ms\n",
+ hname, ping_index - 1, rx_count,
+ (((ping_index - 1) - rx_count) * 100) / (ping_index - 1),
+ (l - started) / 1000,
+ ((double)rtt_min) / 1000.0,
+ ((double)rtt_avg / rx_count) / 1000.0,
+ ((double)rtt_max) / 1000.0
+ );
+
+ exit(0);
+}
+
+
+int main(int argc, char **argv)
+{
+ int n = 0;
+ int port = 7681;
+ int use_ssl = 0;
+ struct libwebsocket_context *context;
+ struct libwebsocket *wsi_mirror;
+ char protocol_name[256];
+ unsigned int len;
+ struct sockaddr_in sin;
+ struct hostent *host;
+ struct hostent *host1;
+ char ip[30];
+ char *p;
+ struct sigaction sa;
+ struct timeval tv;
+ struct winsize w;
+
+ if (argc < 2)
+ goto usage;
+
+ address = argv[1];
+ optind++;
+
+ while (n >= 0) {
+ n = getopt_long(argc, argv, "hmfts:n:i:p:", options, NULL);
+ if (n < 0)
+ continue;
+ switch (n) {
+ 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);
+ protocol_name[(sizeof protocol_name) -1] = '\0';
+ protocols[PROTOCOL_LWS_MIRROR].name = protocol_name;
+ break;
+ case 'i':
+ interval_us = 1000000.0 * atof(optarg);
+ break;
+ case 's':
+ size = atoi(optarg);
+ break;
+ case 'f':
+ flood = 1;
+ break;
+ 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;
+ }
+ }
+
+
+ if (isatty(STDOUT_FILENO))
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
+ if (w.ws_col > 0)
+ screen_width = w.ws_col;
+
+ context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN,
+ protocols, NULL, NULL, -1, -1);
+ if (context == NULL) {
+ fprintf(stderr, "Creating libwebsocket context failed\n");
+ return 1;
+ }
+
+ /* create a client websocket using dumb increment protocol */
+
+ wsi_mirror = libwebsocket_client_connect(context, address, port, use_ssl,
+ "/", "http://host", "origin",
+ protocols[PROTOCOL_LWS_MIRROR].name);
+
+ if (wsi_mirror == NULL) {
+ fprintf(stderr, "libwebsocket connect failed\n");
+ return -1;
+ }
+
+ strcpy(ip, "(unknown)");
+ len = sizeof sin;
+ if (getpeername(libwebsocket_get_socket_fd(wsi_mirror),
+ (struct sockaddr *) &sin, &len) < 0)
+ perror("getpeername");
+ else {
+ host = gethostbyaddr((char *) &sin.sin_addr,
+ sizeof sin.sin_addr,
+ AF_INET);
+ if (host == NULL)
+ perror("gethostbyaddr");
+ else {
+ hname = host->h_name;
+
+ host1 = gethostbyname(hname);
+ if (host1 != NULL) {
+ p = (char *)host1;
+ n = 0;
+ while (p != NULL) {
+ p = host1->h_addr_list[n++];
+ if (p == NULL)
+ continue;
+ if (host1->h_addrtype != AF_INET)
+ continue;
+
+ sprintf(ip, "%d.%d.%d.%d",
+ p[0], p[1], p[2], p[3]);
+ p = NULL;
+ }
+ }
+ }
+ }
+
+ fprintf(stderr, "Websocket PING %s (%s) %d bytes of data.\n",
+ hname, ip, size);
+
+ /* set the ^C handler */
+
+ sa.sa_sigaction = signal_handler;
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, NULL);
+
+ gettimeofday(&tv, NULL);
+ started = (tv.tv_sec * 1000000) + tv.tv_usec;
+
+ /* service loop */
+
+ n = 0;
+ while (n >= 0) {
+ unsigned long l;
+
+ gettimeofday(&tv, NULL);
+
+ l = (tv.tv_sec * 1000000) + tv.tv_usec;
+ if ((l - oldus) > interval_us) {
+ libwebsocket_callback_on_writable(wsi_mirror);
+ oldus = l;
+ }
+
+ if (!interval_us)
+ n = libwebsocket_service(context, 0);
+ else
+ n = libwebsocket_service(context, 1);
+ }
+
+ libwebsocket_client_close(wsi_mirror);
+ libwebsocket_context_destroy(context);
+
+ return 0;
+
+usage:
+ fprintf(stderr, "Usage: libwebsockets-test-ping "
+ "<server address> [--port=<p>] "
+ "[--ssl] [--interval=<float sec>] "
+ "[--size=<bytes>] "
+ "[--protocol=<protocolname>] "
+ "[--mirror] "
+ "\n");
+ return 1;
+}