mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
test servers: convert to static inclusion of plugins
This eliminates the duplicated implementations of the test protocols, except dumb-increment (which requires libuv). This has various advantages, including bringing all the test servers up to the same set of protocols support. Triggered by finding a bug in server status protocol that was long ago fixed in the plugins version.
This commit is contained in:
parent
55d9037c32
commit
5939d3a961
9 changed files with 96 additions and 587 deletions
|
@ -1241,9 +1241,9 @@ if (NOT LWS_WITHOUT_TESTAPPS)
|
|||
create_test_app(test-server "test-server/test-server.c"
|
||||
"test-server/test-server-http.c"
|
||||
"test-server/test-server-dumb-increment.c"
|
||||
"test-server/test-server-mirror.c"
|
||||
"test-server/test-server-status.c"
|
||||
"test-server/test-server-echogen.c")
|
||||
""
|
||||
""
|
||||
"")
|
||||
if (UNIX)
|
||||
create_test_app(test-fuzxy "test-server/fuzxy.c"
|
||||
""
|
||||
|
@ -1257,9 +1257,9 @@ if (NOT LWS_WITHOUT_TESTAPPS)
|
|||
"test-server/test-server-pthreads.c"
|
||||
"test-server/test-server-http.c"
|
||||
"test-server/test-server-dumb-increment.c"
|
||||
"test-server/test-server-mirror.c"
|
||||
"test-server/test-server-status.c"
|
||||
"test-server/test-server-echogen.c")
|
||||
""
|
||||
""
|
||||
"")
|
||||
endif()
|
||||
if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
AND LWS_WITH_LIBEV)
|
||||
|
@ -1267,19 +1267,19 @@ if (NOT LWS_WITHOUT_TESTAPPS)
|
|||
"test-server/test-server-libev.c"
|
||||
"test-server/test-server-http.c"
|
||||
"test-server/test-server-dumb-increment.c"
|
||||
"test-server/test-server-mirror.c"
|
||||
"test-server/test-server-status.c"
|
||||
"test-server/test-server-echogen.c")
|
||||
""
|
||||
""
|
||||
"")
|
||||
endif()
|
||||
if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
AND LWS_WITH_LIBUV)
|
||||
create_test_app(test-server-libuv
|
||||
"test-server/test-server-libuv.c"
|
||||
"test-server/test-server-http.c"
|
||||
"test-server/test-server-dumb-increment.c"
|
||||
"test-server/test-server-mirror.c"
|
||||
"test-server/test-server-status.c"
|
||||
"test-server/test-server-echogen.c")
|
||||
""
|
||||
""
|
||||
""
|
||||
"")
|
||||
endif()
|
||||
if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
AND LWS_WITH_LIBEVENT)
|
||||
|
@ -1287,9 +1287,9 @@ if (NOT LWS_WITHOUT_TESTAPPS)
|
|||
"test-server/test-server-libevent.c"
|
||||
"test-server/test-server-http.c"
|
||||
"test-server/test-server-dumb-increment.c"
|
||||
"test-server/test-server-mirror.c"
|
||||
"test-server/test-server-status.c"
|
||||
"test-server/test-server-echogen.c")
|
||||
""
|
||||
""
|
||||
"")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -1300,9 +1300,9 @@ if (NOT LWS_WITHOUT_TESTAPPS)
|
|||
create_test_app(test-server-extpoll "test-server/test-server.c"
|
||||
"test-server/test-server-http.c"
|
||||
"test-server/test-server-dumb-increment.c"
|
||||
"test-server/test-server-mirror.c"
|
||||
"test-server/test-server-status.c"
|
||||
"test-server/test-server-echogen.c")
|
||||
""
|
||||
""
|
||||
"")
|
||||
# Set defines for this executable only.
|
||||
set_property(
|
||||
TARGET test-server-extpoll
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* libwebsockets-test-server - libwebsockets test implementation
|
||||
*
|
||||
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* The person who associated a work with this deed has dedicated
|
||||
* the work to the public domain by waiving all of his or her rights
|
||||
* to the work worldwide under copyright law, including all related
|
||||
* and neighboring rights, to the extent allowed by law. You can copy,
|
||||
* modify, distribute and perform the work, even for commercial purposes,
|
||||
* all without asking permission.
|
||||
*
|
||||
* The test apps are intended to be adapted for use in your code, which
|
||||
* may be proprietary. So unlike the library itself, they are licensed
|
||||
* Public Domain.
|
||||
*/
|
||||
#include "test-server.h"
|
||||
|
||||
/* echogen protocol
|
||||
*
|
||||
* if you connect to him using his protocol, he'll send you a file chopped
|
||||
* up in various frame sizes repeated until he reaches a limit.
|
||||
*/
|
||||
|
||||
#define TOTAL 993840
|
||||
|
||||
int
|
||||
callback_lws_echogen(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
unsigned char buf[LWS_PRE + 8192];
|
||||
struct per_session_data__echogen *pss =
|
||||
(struct per_session_data__echogen *)user;
|
||||
unsigned char *p = &buf[LWS_PRE];
|
||||
int n, m;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
pss->total = TOTAL;
|
||||
pss->fragsize = 2048;
|
||||
pss->total_rx = 0;
|
||||
sprintf((char *)buf, "%s/test.html", resource_path);
|
||||
pss->fd = open((char *)buf, LWS_O_RDONLY);
|
||||
if (pss->fd < 0) {
|
||||
lwsl_err("Failed to open %s\n", buf);
|
||||
return -1;
|
||||
}
|
||||
pss->wr = LWS_WRITE_TEXT | LWS_WRITE_NO_FIN;
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
if (pss->fd >= 0)
|
||||
close(pss->fd);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
||||
// pss->fragsize += 16;
|
||||
// if (pss->fragsize >= 4096)
|
||||
// pss->fragsize = 32;
|
||||
|
||||
lwsl_err("%s: cb writeable, total left %ld\n", __func__, (long)pss->total);
|
||||
m = pss->fragsize;
|
||||
if ((size_t)m >= pss->total) {
|
||||
m = (int)pss->total;
|
||||
pss->wr = LWS_WRITE_CONTINUATION; /* ie, FIN */
|
||||
}
|
||||
n = read(pss->fd, p, m);
|
||||
if (n < 0) {
|
||||
lwsl_err("failed read\n");
|
||||
return -1;
|
||||
}
|
||||
if (n < m) {
|
||||
lseek(pss->fd, 0, SEEK_SET);
|
||||
m = read(pss->fd, p + n, m - n);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
} else
|
||||
m = 0;
|
||||
pss->total -= n + m;
|
||||
m = lws_write(wsi, p, n + m, pss->wr);
|
||||
if (m < n) {
|
||||
lwsl_err("ERROR %d writing to di socket\n", n);
|
||||
return -1;
|
||||
}
|
||||
if (!pss->total) {
|
||||
lwsl_err("Completed OK\n");
|
||||
break;
|
||||
}
|
||||
pss->wr = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN;
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
pss->total_rx += len;
|
||||
lwsl_err("rx %ld\n", (long)pss->total_rx);
|
||||
if (pss->total_rx == TOTAL) {
|
||||
lws_close_reason(wsi, LWS_CLOSE_STATUS_NORMAL,
|
||||
(unsigned char *)"done", 4);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
|
||||
lwsl_notice("LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: len %lu\n",
|
||||
(unsigned long)len);
|
||||
for (n = 0; n < (int)len; n++)
|
||||
lwsl_notice(" %d: 0x%02X\n", n,
|
||||
((unsigned char *)in)[n]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -34,35 +34,9 @@ char *resource_path = LOCAL_RESOURCE_PATH;
|
|||
char crl_path[1024] = "";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* libev dumps their hygiene problems on their users blaming compiler
|
||||
* http://lists.schmorp.de/pipermail/libev/2008q4/000442.html
|
||||
*/
|
||||
|
||||
#if EV_MINPRI == EV_MAXPRI
|
||||
# define _ev_set_priority(ev, pri) ((ev), (pri))
|
||||
#else
|
||||
# define _ev_set_priority(ev, pri) { \
|
||||
ev_watcher *evw = (ev_watcher *)(void *)ev; \
|
||||
evw->priority = pri; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define _ev_init(ev,cb_) { \
|
||||
ev_watcher *evw = (ev_watcher *)(void *)ev; \
|
||||
\
|
||||
evw->active = evw->pending = 0; \
|
||||
_ev_set_priority((ev), 0); \
|
||||
ev_set_cb((ev), cb_); \
|
||||
}
|
||||
|
||||
#define _ev_timer_init(ev, cb, after, _repeat) { \
|
||||
ev_watcher_time *evwt = (ev_watcher_time *)(void *)ev; \
|
||||
\
|
||||
_ev_init(ev, cb); \
|
||||
evwt->at = after; \
|
||||
(ev)->repeat = _repeat; \
|
||||
}
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "../plugins/protocol_lws_mirror.c"
|
||||
#include "../plugins/protocol_lws_status.c"
|
||||
|
||||
/* singlethreaded version --> no locks */
|
||||
|
||||
|
@ -94,6 +68,7 @@ enum demo_protocols {
|
|||
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_LWS_STATUS,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
|
@ -114,20 +89,13 @@ static struct lws_protocols protocols[] = {
|
|||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
sizeof(struct per_session_data__dumb_increment),
|
||||
10,
|
||||
},
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
sizeof(struct per_session_data__lws_mirror),
|
||||
128,
|
||||
},
|
||||
{
|
||||
"lws-status",
|
||||
callback_lws_status,
|
||||
sizeof(struct per_session_data__lws_status),
|
||||
128,
|
||||
10, /* rx buf size must be >= permessage-deflate rx size
|
||||
* dumb-increment only sends very small packets, so we set
|
||||
* this accordingly. If your protocol will send bigger
|
||||
* things, adjust this to match */
|
||||
},
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
|
@ -296,7 +264,7 @@ int main(int argc, char **argv)
|
|||
#endif
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(sigs); n++) {
|
||||
_ev_init(&signals[n], signal_cb);
|
||||
ev_init(&signals[n], signal_cb);
|
||||
ev_signal_set(&signals[n], sigs[n]);
|
||||
ev_signal_start(loop, &signals[n]);
|
||||
}
|
||||
|
@ -364,7 +332,7 @@ int main(int argc, char **argv)
|
|||
|
||||
lws_ev_initloop(context, loop, 0);
|
||||
|
||||
_ev_timer_init(&timeout_watcher, ev_timeout_cb, 0.05, 0.05);
|
||||
ev_timer_init(&timeout_watcher, ev_timeout_cb, 0.05, 0.05);
|
||||
ev_timer_start(loop, &timeout_watcher);
|
||||
ev_run(loop, 0);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define DI_HANDLED_BY_PLUGIN
|
||||
#include "test-server.h"
|
||||
#include <uv.h>
|
||||
|
||||
|
@ -45,6 +46,11 @@ void test_server_unlock(int care)
|
|||
{
|
||||
}
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "../plugins/protocol_dumb_increment.c"
|
||||
#include "../plugins/protocol_lws_mirror.c"
|
||||
#include "../plugins/protocol_lws_status.c"
|
||||
|
||||
/*
|
||||
* This demo server shows how to use libwebsockets for one or more
|
||||
* websocket protocols in the same server
|
||||
|
@ -66,6 +72,7 @@ enum demo_protocols {
|
|||
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_LWS_STATUS,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
|
@ -82,24 +89,9 @@ static struct lws_protocols protocols[] = {
|
|||
sizeof (struct per_session_data__http), /* per_session_data_size */
|
||||
0, /* max frame size / rx buffer */
|
||||
},
|
||||
{
|
||||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
sizeof(struct per_session_data__dumb_increment),
|
||||
10,
|
||||
},
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
sizeof(struct per_session_data__lws_mirror),
|
||||
128,
|
||||
},
|
||||
{
|
||||
"lws-status",
|
||||
callback_lws_status,
|
||||
sizeof(struct per_session_data__lws_status),
|
||||
128,
|
||||
},
|
||||
LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT,
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
|
@ -132,16 +124,6 @@ void signal_cb(uv_signal_t *watcher, int signum)
|
|||
lws_libuv_stop(context);
|
||||
}
|
||||
|
||||
static void
|
||||
uv_timeout_cb_dumb_increment(uv_timer_t *w
|
||||
#if UV_VERSION_MAJOR == 0
|
||||
, int status
|
||||
#endif
|
||||
)
|
||||
{
|
||||
lws_callback_on_writable_all_protocol(context,
|
||||
&protocols[PROTOCOL_DUMB_INCREMENT]);
|
||||
}
|
||||
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
|
@ -222,7 +204,6 @@ int main(int argc, char **argv)
|
|||
int foreign_libuv_loop = 0;
|
||||
/* <--- only needed for foreign loop test --- */
|
||||
#endif
|
||||
uv_timer_t timeout_watcher;
|
||||
const char *iface = NULL;
|
||||
char cert_path[1024];
|
||||
char key_path[1024];
|
||||
|
@ -406,9 +387,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
uv_timer_init(lws_uv_getloop(context, 0), &timeout_watcher);
|
||||
uv_timer_start(&timeout_watcher, uv_timeout_cb_dumb_increment, 50, 50);
|
||||
|
||||
#if UV_VERSION_MAJOR > 0
|
||||
if (foreign_libuv_loop) {
|
||||
/*
|
||||
|
@ -437,8 +415,6 @@ int main(int argc, char **argv)
|
|||
uv_timer_stop(&timer_inner);
|
||||
uv_close((uv_handle_t*)&timer_inner, timer_close_cb);
|
||||
|
||||
/* stop the dumb increment timer */
|
||||
uv_timer_stop(&timeout_watcher);
|
||||
|
||||
lwsl_notice("Destroying lws context\n");
|
||||
|
||||
|
@ -491,5 +467,7 @@ bail:
|
|||
|
||||
lwsl_notice("libwebsockets-test-server exited cleanly\n");
|
||||
|
||||
context = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* libwebsockets-test-server - libwebsockets test implementation
|
||||
*
|
||||
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* The person who associated a work with this deed has dedicated
|
||||
* the work to the public domain by waiving all of his or her rights
|
||||
* to the work worldwide under copyright law, including all related
|
||||
* and neighboring rights, to the extent allowed by law. You can copy,
|
||||
* modify, distribute and perform the work, even for commercial purposes,
|
||||
* all without asking permission.
|
||||
*
|
||||
* The test apps are intended to be adapted for use in your code, which
|
||||
* may be proprietary. So unlike the library itself, they are licensed
|
||||
* Public Domain.
|
||||
*/
|
||||
#include "test-server.h"
|
||||
|
||||
/* lws-mirror_protocol */
|
||||
|
||||
#define MAX_MESSAGE_QUEUE 512
|
||||
|
||||
struct a_message {
|
||||
void *payload;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
|
||||
static int ringbuffer_head;
|
||||
|
||||
int
|
||||
callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__lws_mirror *pss =
|
||||
(struct per_session_data__lws_mirror *)user;
|
||||
int n, m;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__);
|
||||
pss->ringbuffer_tail = ringbuffer_head;
|
||||
pss->wsi = wsi;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||
lwsl_notice("%s: mirror protocol cleaning up\n", __func__);
|
||||
for (n = 0; n < sizeof ringbuffer / sizeof ringbuffer[0]; n++)
|
||||
if (ringbuffer[n].payload)
|
||||
free(ringbuffer[n].payload);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
if (close_testing)
|
||||
break;
|
||||
while (pss->ringbuffer_tail != ringbuffer_head) {
|
||||
m = ringbuffer[pss->ringbuffer_tail].len;
|
||||
n = lws_write(wsi, (unsigned char *)
|
||||
ringbuffer[pss->ringbuffer_tail].payload +
|
||||
LWS_PRE, m, LWS_WRITE_TEXT);
|
||||
if (n < 0) {
|
||||
lwsl_err("ERROR %d writing to mirror socket\n", n);
|
||||
return -1;
|
||||
}
|
||||
if (n < m)
|
||||
lwsl_err("mirror partial write %d vs %d\n", n, m);
|
||||
|
||||
if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
|
||||
pss->ringbuffer_tail = 0;
|
||||
else
|
||||
pss->ringbuffer_tail++;
|
||||
|
||||
if (((ringbuffer_head - pss->ringbuffer_tail) &
|
||||
(MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 15))
|
||||
lws_rx_flow_allow_all_protocol(lws_get_context(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
|
||||
if (lws_send_pipe_choked(wsi)) {
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
if (((ringbuffer_head - pss->ringbuffer_tail) &
|
||||
(MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 1)) {
|
||||
lwsl_err("dropping!\n");
|
||||
goto choke;
|
||||
}
|
||||
|
||||
if (ringbuffer[ringbuffer_head].payload)
|
||||
free(ringbuffer[ringbuffer_head].payload);
|
||||
|
||||
ringbuffer[ringbuffer_head].payload = malloc(LWS_PRE + len);
|
||||
ringbuffer[ringbuffer_head].len = len;
|
||||
memcpy((char *)ringbuffer[ringbuffer_head].payload +
|
||||
LWS_PRE, in, len);
|
||||
if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
|
||||
ringbuffer_head = 0;
|
||||
else
|
||||
ringbuffer_head++;
|
||||
|
||||
if (((ringbuffer_head - pss->ringbuffer_tail) &
|
||||
(MAX_MESSAGE_QUEUE - 1)) != (MAX_MESSAGE_QUEUE - 2))
|
||||
goto done;
|
||||
|
||||
choke:
|
||||
lwsl_debug("LWS_CALLBACK_RECEIVE: throttling %p\n", wsi);
|
||||
lws_rx_flow_control(wsi, 0);
|
||||
|
||||
done:
|
||||
lws_callback_on_writable_all_protocol(lws_get_context(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
break;
|
||||
|
||||
/*
|
||||
* this just demonstrates how to use the protocol filter. If you won't
|
||||
* study and reject connections based on header content, you don't need
|
||||
* to handle this callback
|
||||
*/
|
||||
|
||||
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
||||
dump_handshake_info(wsi);
|
||||
/* you could return non-zero here and kill the connection */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -37,6 +37,10 @@ struct lws_context *context;
|
|||
char crl_path[1024] = "";
|
||||
#endif
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "../plugins/protocol_lws_mirror.c"
|
||||
#include "../plugins/protocol_lws_status.c"
|
||||
|
||||
/*
|
||||
* This mutex lock protects code that changes or relies on wsi list outside of
|
||||
* the service thread. The service thread will acquire it when changing the
|
||||
|
@ -87,6 +91,7 @@ enum demo_protocols {
|
|||
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_LWS_STATUS,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
|
@ -107,14 +112,13 @@ static struct lws_protocols protocols[] = {
|
|||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
sizeof(struct per_session_data__dumb_increment),
|
||||
10,
|
||||
},
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
sizeof(struct per_session_data__lws_mirror),
|
||||
128,
|
||||
10, /* rx buf size must be >= permessage-deflate rx size
|
||||
* dumb-increment only sends very small packets, so we set
|
||||
* this accordingly. If your protocol will send bigger
|
||||
* things, adjust this to match */
|
||||
},
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* libwebsockets-test-server - libwebsockets test implementation
|
||||
*
|
||||
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* The person who associated a work with this deed has dedicated
|
||||
* the work to the public domain by waiving all of his or her rights
|
||||
* to the work worldwide under copyright law, including all related
|
||||
* and neighboring rights, to the extent allowed by law. You can copy,
|
||||
* modify, distribute and perform the work, even for commercial purposes,
|
||||
* all without asking permission.
|
||||
*
|
||||
* The test apps are intended to be adapted for use in your code, which
|
||||
* may be proprietary. So unlike the library itself, they are licensed
|
||||
* Public Domain.
|
||||
*/
|
||||
#include "test-server.h"
|
||||
#include <time.h>
|
||||
|
||||
static unsigned char server_info[1024];
|
||||
static int server_info_len;
|
||||
static int current;
|
||||
static char cache[16384];
|
||||
static int cache_len;
|
||||
static struct per_session_data__lws_status *list;
|
||||
static int live_wsi;
|
||||
|
||||
|
||||
static void
|
||||
update_status(struct lws *wsi, struct per_session_data__lws_status *pss)
|
||||
{
|
||||
struct per_session_data__lws_status **pp = &list;
|
||||
int subsequent = 0;
|
||||
char *p = cache + LWS_PRE, *start = p;
|
||||
char date[128];
|
||||
time_t t;
|
||||
struct tm *ptm;
|
||||
#ifndef WIN32
|
||||
struct tm tm;
|
||||
#endif
|
||||
|
||||
p += lws_snprintf(p, 512, " { %s, \"wsi\":\"%d\", \"conns\":[",
|
||||
server_info, live_wsi);
|
||||
|
||||
/* render the list */
|
||||
while (*pp) {
|
||||
t = (*pp)->tv_established.tv_sec;
|
||||
#ifdef WIN32
|
||||
ptm = localtime(&t);
|
||||
if (!ptm)
|
||||
#else
|
||||
ptm = &tm;
|
||||
if (!localtime_r(&t, &tm))
|
||||
#endif
|
||||
strcpy(date, "unknown");
|
||||
else
|
||||
#ifdef WIN32
|
||||
strftime(date, sizeof(date), "%Y %H:%M %Z", ptm);
|
||||
#else
|
||||
strftime(date, sizeof(date), "%F %H:%M %Z", ptm);
|
||||
#endif
|
||||
if ((p - start) > (sizeof(cache) - 512))
|
||||
break;
|
||||
if (subsequent)
|
||||
*p++ = ',';
|
||||
subsequent = 1;
|
||||
p += lws_snprintf(p, sizeof(cache) - (p - start) - 1,
|
||||
"{\"peer\":\"%s\",\"time\":\"%s\","
|
||||
"\"ua\":\"%s\"}",
|
||||
(*pp)->ip, date, (*pp)->user_agent);
|
||||
pp = &((*pp)->list);
|
||||
}
|
||||
|
||||
p += sprintf(p, "]}");
|
||||
cache_len = p - start;
|
||||
lwsl_err("cache_len %d\n", cache_len);
|
||||
*p = '\0';
|
||||
|
||||
/* since we changed the list, increment the 'version' */
|
||||
current++;
|
||||
/* update everyone */
|
||||
lws_callback_on_writable_all_protocol(lws_get_context(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
}
|
||||
|
||||
|
||||
/* lws-status protocol */
|
||||
|
||||
int
|
||||
callback_lws_status(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__lws_status *pss =
|
||||
(struct per_session_data__lws_status *)user,
|
||||
**pp;
|
||||
char name[128], rip[128];
|
||||
int m;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||
/*
|
||||
* Prepare the static server info
|
||||
*/
|
||||
server_info_len = sprintf((char *)server_info,
|
||||
"\"version\":\"%s\","
|
||||
" \"hostname\":\"%s\"",
|
||||
lws_get_library_version(),
|
||||
lws_canonical_hostname(
|
||||
lws_get_context(wsi)));
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
/*
|
||||
* we keep a linked list of live pss, so we can walk it
|
||||
*/
|
||||
pss->last = 0;
|
||||
pss->list = list;
|
||||
list = pss;
|
||||
live_wsi++;
|
||||
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name,
|
||||
sizeof(name), rip, sizeof(rip));
|
||||
sprintf(pss->ip, "%s (%s)", name, rip);
|
||||
gettimeofday(&pss->tv_established, NULL);
|
||||
strcpy(pss->user_agent, "unknown");
|
||||
lws_hdr_copy(wsi, pss->user_agent, sizeof(pss->user_agent),
|
||||
WSI_TOKEN_HTTP_USER_AGENT);
|
||||
update_status(wsi, pss);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
lwsl_notice("pmd test: RX len %d\n", (int)len);
|
||||
puts(in);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
m = lws_write(wsi, (unsigned char *)cache + LWS_PRE, cache_len,
|
||||
LWS_WRITE_TEXT);
|
||||
if (m < server_info_len) {
|
||||
lwsl_err("ERROR %d writing to di socket\n", m);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
/*
|
||||
* remove ourselves from live pss list
|
||||
*/
|
||||
lwsl_debug("CLOSING pss %p ********\n", pss);
|
||||
|
||||
pp = &list;
|
||||
while (*pp) {
|
||||
if (*pp == pss) {
|
||||
*pp = pss->list;
|
||||
pss->list = NULL;
|
||||
live_wsi--;
|
||||
break;
|
||||
}
|
||||
pp = &((*pp)->list);
|
||||
}
|
||||
|
||||
update_status(wsi, pss);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -40,6 +40,34 @@ char *resource_path = LOCAL_RESOURCE_PATH;
|
|||
char crl_path[1024] = "";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This demonstrates how to use the clean protocol service separation of
|
||||
* plugins, but with static inclusion instead of runtime dynamic loading
|
||||
* (which requires libuv).
|
||||
*
|
||||
* dumb-increment doesn't use the plugin, both to demonstrate how to
|
||||
* do the protocols directly, and because it wants libuv for a timer.
|
||||
*
|
||||
* Please consider using test-server-v2.0.c instead of this: it has the
|
||||
* same functionality but
|
||||
*
|
||||
* 1) uses lws built-in http handling so you don't need to deal with it in
|
||||
* your callback
|
||||
*
|
||||
* 2) Links with libuv and uses the plugins at runtime
|
||||
*
|
||||
* 3) Uses advanced lws features like mounts to bind parts of the filesystem
|
||||
* to the served URL space
|
||||
*
|
||||
* Another option is lwsws, this operates like test-server-v2,0.c but is
|
||||
* configured using JSON, do you do not need to provide any code for the
|
||||
* serving action at all, just implement your protocols in plugins.
|
||||
*/
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "../plugins/protocol_lws_mirror.c"
|
||||
#include "../plugins/protocol_lws_status.c"
|
||||
|
||||
/* singlethreaded version --> no locks */
|
||||
|
||||
void test_server_lock(int care)
|
||||
|
@ -62,6 +90,9 @@ void test_server_unlock(int care)
|
|||
*
|
||||
* lws-mirror-protocol: copies any received packet to every connection also
|
||||
* using this protocol, including the sender
|
||||
*
|
||||
* lws-status: informs connected browsers of who else is
|
||||
* connected.
|
||||
*/
|
||||
|
||||
enum demo_protocols {
|
||||
|
@ -70,7 +101,6 @@ enum demo_protocols {
|
|||
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
PROTOCOL_LWS_ECHOGEN,
|
||||
PROTOCOL_LWS_STATUS,
|
||||
|
||||
/* always last */
|
||||
|
@ -92,26 +122,13 @@ static struct lws_protocols protocols[] = {
|
|||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
sizeof(struct per_session_data__dumb_increment),
|
||||
10, /* rx buf size must be >= permessage-deflate rx size */
|
||||
},
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
sizeof(struct per_session_data__lws_mirror),
|
||||
128, /* rx buf size must be >= permessage-deflate rx size */
|
||||
},
|
||||
{
|
||||
"lws-echogen",
|
||||
callback_lws_echogen,
|
||||
sizeof(struct per_session_data__echogen),
|
||||
128, /* rx buf size must be >= permessage-deflate rx size */
|
||||
},
|
||||
{
|
||||
"lws-status",
|
||||
callback_lws_status,
|
||||
sizeof(struct per_session_data__lws_status),
|
||||
512, /* rx buf size must be >= permessage-deflate rx size */
|
||||
10, /* rx buf size must be >= permessage-deflate rx size
|
||||
* dumb-increment only sends very small packets, so we set
|
||||
* this accordingly. If your protocol will send bigger
|
||||
* things, adjust this to match */
|
||||
},
|
||||
LWS_PLUGIN_PROTOCOL_MIRROR,
|
||||
LWS_PLUGIN_PROTOCOL_LWS_STATUS,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
|
|
|
@ -96,48 +96,22 @@ struct per_session_data__http {
|
|||
* connection.
|
||||
*/
|
||||
|
||||
#if !defined(DI_HANDLED_BY_PLUGIN)
|
||||
struct per_session_data__dumb_increment {
|
||||
int number;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct per_session_data__lws_mirror {
|
||||
struct lws *wsi;
|
||||
int ringbuffer_tail;
|
||||
};
|
||||
|
||||
struct per_session_data__echogen {
|
||||
size_t total;
|
||||
size_t total_rx;
|
||||
int fd;
|
||||
int fragsize;
|
||||
int wr;
|
||||
};
|
||||
|
||||
struct per_session_data__lws_status {
|
||||
struct per_session_data__lws_status *list;
|
||||
struct timeval tv_established;
|
||||
int last;
|
||||
char ip[270];
|
||||
char user_agent[512];
|
||||
const char *pos;
|
||||
int len;
|
||||
};
|
||||
|
||||
extern int
|
||||
callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
extern int
|
||||
callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
|
||||
#if !defined(DI_HANDLED_BY_PLUGIN)
|
||||
extern int
|
||||
callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
extern int
|
||||
callback_lws_echogen(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
extern int
|
||||
callback_lws_status(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
#endif
|
||||
|
||||
|
||||
extern void
|
||||
|
|
Loading…
Add table
Reference in a new issue