mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
minimal-examples: add ws pmd example
This commit is contained in:
parent
4d36bc1f46
commit
388c0677ee
18 changed files with 928 additions and 20 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* ./lib/extension-permessage-deflate.c
|
||||
*
|
||||
* Copyright (C) 2016 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2016 - 2018 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
|
||||
|
@ -83,7 +83,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
if (!oa->option_name)
|
||||
break;
|
||||
for (n = 0; n < (int)ARRAY_SIZE(lws_ext_pm_deflate_options); n++)
|
||||
if (!strcmp(lws_ext_pm_deflate_options[n].name, oa->option_name))
|
||||
if (!strcmp(lws_ext_pm_deflate_options[n].name,
|
||||
oa->option_name))
|
||||
break;
|
||||
|
||||
if (n == (int)ARRAY_SIZE(lws_ext_pm_deflate_options))
|
||||
|
@ -123,8 +124,9 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
n = (int)wsi->protocol->rx_buffer_size;
|
||||
|
||||
if (n < 128) {
|
||||
lwsl_info(" permessage-deflate requires the protocol (%s) to have an RX buffer >= 128\n",
|
||||
wsi->protocol->name);
|
||||
lwsl_info(" permessage-deflate requires the protocol "
|
||||
"(%s) to have an RX buffer >= 128\n",
|
||||
wsi->protocol->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -186,14 +188,16 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
printf("\n");
|
||||
#endif
|
||||
if (!priv->rx_init)
|
||||
if (inflateInit2(&priv->rx, -priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) {
|
||||
if (inflateInit2(&priv->rx,
|
||||
-priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) {
|
||||
lwsl_err("%s: iniflateInit failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
priv->rx_init = 1;
|
||||
if (!priv->buf_rx_inflated)
|
||||
priv->buf_rx_inflated = lws_malloc(LWS_PRE + 7 + 5 +
|
||||
(1 << priv->args[PMD_RX_BUF_PWR2]), "pmd rx inflate buf");
|
||||
(1 << priv->args[PMD_RX_BUF_PWR2]),
|
||||
"pmd rx inflate buf");
|
||||
if (!priv->buf_rx_inflated) {
|
||||
lwsl_err("%s: OOM\n", __func__);
|
||||
return -1;
|
||||
|
@ -205,7 +209,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
* rx buffer by the caller, so this assumption is safe while
|
||||
* we block new rx while draining the existing rx
|
||||
*/
|
||||
if (!priv->rx.avail_in && eff_buf->token && eff_buf->token_len) {
|
||||
if (!priv->rx.avail_in && eff_buf->token &&
|
||||
eff_buf->token_len) {
|
||||
priv->rx.next_in = (unsigned char *)eff_buf->token;
|
||||
priv->rx.avail_in = eff_buf->token_len;
|
||||
}
|
||||
|
@ -266,8 +271,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
priv->rx.next_in = trail;
|
||||
priv->rx.avail_in = sizeof(trail);
|
||||
n = inflate(&priv->rx, Z_SYNC_FLUSH);
|
||||
lwsl_ext("RX trailer inf returned %d, avi %d, avo %d\n", n,
|
||||
priv->rx.avail_in, priv->rx.avail_out);
|
||||
lwsl_ext("RX trailer inf returned %d, avi %d, avo %d\n",
|
||||
n, priv->rx.avail_in, priv->rx.avail_out);
|
||||
switch (n) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_STREAM_ERROR:
|
||||
|
@ -302,7 +307,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
priv->rx_held_valid = 1;
|
||||
}
|
||||
|
||||
eff_buf->token_len = lws_ptr_diff(priv->rx.next_out, eff_buf->token);
|
||||
eff_buf->token_len = lws_ptr_diff(priv->rx.next_out,
|
||||
eff_buf->token);
|
||||
priv->count_rx_between_fin += eff_buf->token_len;
|
||||
|
||||
lwsl_ext(" %s: RX leaving with new effbuff len %d, "
|
||||
|
@ -343,7 +349,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
|
|||
priv->tx_init = 1;
|
||||
if (!priv->buf_tx_deflated)
|
||||
priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 +
|
||||
(1 << priv->args[PMD_TX_BUF_PWR2]), "pmd tx deflate buf");
|
||||
(1 << priv->args[PMD_TX_BUF_PWR2]),
|
||||
"pmd tx deflate buf");
|
||||
if (!priv->buf_tx_deflated) {
|
||||
lwsl_err("%s: OOM\n", __func__);
|
||||
return -1;
|
||||
|
|
|
@ -84,7 +84,8 @@ int main(int argc, char **argv)
|
|||
struct lws_context *context;
|
||||
int n = 0;
|
||||
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER, NULL);
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER
|
||||
/* | LLL_INFO */ /* | LLL_DEBUG */, NULL);
|
||||
lwsl_user("LWS minimal http client\n");
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
static int interrupted;
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ NULL, /* linked-list "next" */
|
||||
|
@ -35,17 +38,26 @@ static const struct lws_http_mount mount = {
|
|||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
interrupted = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_context *context;
|
||||
int n = 0;
|
||||
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER, NULL);
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER
|
||||
/* | LLL_INFO */ /* | LLL_DEBUG */, NULL);
|
||||
|
||||
lwsl_user("LWS minimal http server | visit http://localhost:7681\n");
|
||||
|
||||
context = lws_create_context(&info);
|
||||
|
@ -54,7 +66,7 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
while (n >=0)
|
||||
while (n >= 0 && !interrupted)
|
||||
n = lws_service(context, 1000);
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
|
16
minimal-examples/minimal-ws-server-pmd-bulk/CMakeLists.txt
Normal file
16
minimal-examples/minimal-ws-server-pmd-bulk/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
cmake_minimum_required(VERSION 2.8.9)
|
||||
include(CheckFunctionExists)
|
||||
|
||||
set(SAMP lws-minimal-ws-server-pmd-bulk)
|
||||
set(SRCS minimal-ws-server-pmd-bulk.c)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES websockets)
|
||||
|
||||
CHECK_FUNCTION_EXISTS(lws_extension_callback_pm_deflate HAVE_PMD)
|
||||
if (HAVE_PMD)
|
||||
else()
|
||||
message(FATAL_ERROR "LWS need to have been built for extensions")
|
||||
endif()
|
||||
|
||||
add_executable(${SAMP} ${SRCS})
|
||||
target_link_libraries(${SAMP} -lwebsockets)
|
21
minimal-examples/minimal-ws-server-pmd-bulk/README.md
Normal file
21
minimal-examples/minimal-ws-server-pmd-bulk/README.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# lws minimal ws server + permessage-deflate for bulk traffic
|
||||
|
||||
## build
|
||||
|
||||
```
|
||||
$ cmake . && make
|
||||
```
|
||||
|
||||
## usage
|
||||
|
||||
```
|
||||
$ ./lws-minimal-ws-server-pmd-bulk
|
||||
[2018/03/04 09:30:02:7986] USER: LWS minimal ws server | visit http://localhost:7681
|
||||
[2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on
|
||||
```
|
||||
|
||||
Visit http://localhost:7681 in your browser
|
||||
|
||||
One or another kind of bulk ws transfer is made to the browser.
|
||||
|
||||
The ws connection is made via permessage-deflate extension.
|
87
minimal-examples/minimal-ws-server-pmd-bulk/index.html
Normal file
87
minimal-examples/minimal-ws-server-pmd-bulk/index.html
Normal file
|
@ -0,0 +1,87 @@
|
|||
<meta charset="UTF-8">
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<img src="libwebsockets.org-logo.png"><br>
|
||||
|
||||
LWS bulk transfer example</b>.<br>
|
||||
A large ws message is sent to all browsers open on this page.<br>
|
||||
<br>
|
||||
<span id=status>Ws closed</span><br>
|
||||
<br>
|
||||
<textarea id=r readonly cols=40 rows=10></textarea><br>
|
||||
<input type="text" id=m cols=40 rows=1>
|
||||
<button id=b onclick="sendmsg();">Send</button>
|
||||
</body>
|
||||
|
||||
|
||||
<script>
|
||||
function get_appropriate_ws_url(extra_url)
|
||||
{
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
}
|
||||
|
||||
u = u.split('/');
|
||||
|
||||
/* + "/xxx" bit is for IE10 workaround */
|
||||
|
||||
return pcol + u[0] + "/" + extra_url;
|
||||
}
|
||||
|
||||
function new_ws(urlpath, protocol)
|
||||
{
|
||||
if (typeof MozWebSocket != "undefined")
|
||||
return new MozWebSocket(urlpath, protocol);
|
||||
|
||||
return new WebSocket(urlpath, protocol);
|
||||
}
|
||||
|
||||
ws = new_ws(get_appropriate_ws_url(""), "lws-minimal-pmd-bulk");
|
||||
try {
|
||||
ws.onopen = function() {
|
||||
document.getElementById("m").disabled = 0;
|
||||
document.getElementById("b").disabled = 0;
|
||||
document.getElementById("status").textContent = "ws open "+ ws.extensions;
|
||||
}
|
||||
|
||||
ws.onmessage =function got_packet(msg) {
|
||||
console.log("Received ws message len " + msg.data.length);
|
||||
document.getElementById("r").value =
|
||||
document.getElementById("r").value + msg.data + "\n";
|
||||
document.getElementById("r").scrollTop =
|
||||
document.getElementById("r").scrollHeight;
|
||||
}
|
||||
|
||||
ws.onclose = function(){
|
||||
document.getElementById("m").disabled = 1;
|
||||
document.getElementById("b").disabled = 1;
|
||||
document.getElementById("status").textContent = "ws closed";
|
||||
}
|
||||
} catch(exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
|
||||
function sendmsg()
|
||||
{
|
||||
ws.send(document.getElementById("m").value);
|
||||
document.getElementById("m").value = "";
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* lws-minimal-ws-server
|
||||
*
|
||||
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates the most minimal http server you can make with lws.
|
||||
*
|
||||
* To keep it simple, it serves stuff in the directory it was started in.
|
||||
* You can change that by changing mount.origin
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "protocol_lws_minimal_pmd_bulk.c"
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
{ "http", lws_callback_http_dummy, 0, 0 },
|
||||
LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
static int interrupted;
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ NULL, /* linked-list "next" */
|
||||
/* .mountpoint */ "/", /* mountpoint URL */
|
||||
/* .origin */ ".", /* serve from dir */
|
||||
/* .def */ "index.html", /* default filename */
|
||||
/* .protocol */ NULL,
|
||||
/* .cgienv */ NULL,
|
||||
/* .extra_mimetypes */ NULL,
|
||||
/* .interpret */ NULL,
|
||||
/* .cgi_timeout */ 0,
|
||||
/* .cache_max_age */ 0,
|
||||
/* .auth_mask */ 0,
|
||||
/* .cache_reusable */ 0,
|
||||
/* .cache_revalidate */ 0,
|
||||
/* .cache_intermediaries */ 0,
|
||||
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
|
||||
/* .mountpoint_len */ 1, /* char count */
|
||||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
static const struct lws_extension extensions[] = {
|
||||
{
|
||||
"permessage-deflate",
|
||||
lws_extension_callback_pm_deflate,
|
||||
"permessage-deflate"
|
||||
"; client_no_context_takeover"
|
||||
"; client_max_window_bits"
|
||||
},
|
||||
{ NULL, NULL, NULL /* terminator */ }
|
||||
};
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
interrupted = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_context *context;
|
||||
int n = 0;
|
||||
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.protocols = protocols;
|
||||
info.extensions = extensions;
|
||||
info.pt_serv_buf_size = 32 * 1024;
|
||||
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER
|
||||
/* | LLL_INFO */ /* | LLL_DEBUG */, NULL);
|
||||
|
||||
lwsl_user("LWS minimal ws server + permessage-deflate | visit http://localhost:7681\n");
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
lwsl_err("lws init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (n >= 0 && !interrupted)
|
||||
n = lws_service(context, 1000);
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* ws protocol handler plugin for "lws-minimal-pmd-bulk"
|
||||
*
|
||||
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* The protocol shows how to send and receive bulk messages over a ws connection
|
||||
* that optionally may have the permessage-deflate extension negotiated on it.
|
||||
*/
|
||||
|
||||
#if !defined (LWS_PLUGIN_STATIC)
|
||||
#define LWS_DLL
|
||||
#define LWS_INTERNAL
|
||||
#include <libwebsockets.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* We will produce a large ws message either from this text repeated many times,
|
||||
* or from 0x40 + a 6-bit pseudorandom number
|
||||
*/
|
||||
|
||||
static const char * const redundant_string =
|
||||
"No one would have believed in the last years of the nineteenth "
|
||||
"century that this world was being watched keenly and closely by "
|
||||
"intelligences greater than man's and yet as mortal as his own; that as "
|
||||
"men busied themselves about their various concerns they were "
|
||||
"scrutinised and studied, perhaps almost as narrowly as a man with a "
|
||||
"microscope might scrutinise the transient creatures that swarm and "
|
||||
"multiply in a drop of water. With infinite complacency men went to "
|
||||
"and fro over this globe about their little affairs, serene in their "
|
||||
"assurance of their empire over matter. It is possible that the "
|
||||
"infusoria under the microscope do the same. No one gave a thought to "
|
||||
"the older worlds of space as sources of human danger, or thought of "
|
||||
"them only to dismiss the idea of life upon them as impossible or "
|
||||
"improbable. It is curious to recall some of the mental habits of "
|
||||
"those departed days. At most terrestrial men fancied there might be "
|
||||
"other men upon Mars, perhaps inferior to themselves and ready to "
|
||||
"welcome a missionary enterprise. Yet across the gulf of space, minds "
|
||||
"that are to our minds as ours are to those of the beasts that perish, "
|
||||
"intellects vast and cool and unsympathetic, regarded this earth with "
|
||||
"envious eyes, and slowly and surely drew their plans against us. And "
|
||||
"early in the twentieth century came the great disillusionment. "
|
||||
;
|
||||
|
||||
/* this reflects the length of the string above */
|
||||
#define REPEAT_STRING_LEN 1337
|
||||
/* this is the total size of the ws message we will send */
|
||||
#define MESSAGE_SIZE (100 * REPEAT_STRING_LEN)
|
||||
/* this is how much we will send each time the connection is writable */
|
||||
#define MESSAGE_CHUNK_SIZE (1 * 1024)
|
||||
|
||||
|
||||
/* one of these is created for each client connecting to us */
|
||||
|
||||
struct per_session_data__minimal_pmd_bulk {
|
||||
struct per_session_data__minimal_pmd_bulk *pss_list;
|
||||
struct lws *wsi;
|
||||
int position; /* byte position we got up to sending the message */
|
||||
uint64_t rng;
|
||||
};
|
||||
|
||||
/* one of these is created for each vhost our protocol is used with */
|
||||
|
||||
struct per_vhost_data__minimal_pmd_bulk {
|
||||
struct lws_context *context;
|
||||
struct lws_vhost *vhost;
|
||||
const struct lws_protocols *protocol;
|
||||
|
||||
/* linked-list of live pss */
|
||||
struct per_session_data__minimal_pmd_bulk *pss_list;
|
||||
};
|
||||
|
||||
static int
|
||||
callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__minimal_pmd_bulk **ppss, *pss =
|
||||
(struct per_session_data__minimal_pmd_bulk *)user;
|
||||
struct per_vhost_data__minimal_pmd_bulk *vhd =
|
||||
(struct per_vhost_data__minimal_pmd_bulk *)
|
||||
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
uint8_t buf[LWS_PRE + MESSAGE_CHUNK_SIZE], *p;
|
||||
uint32_t oldest;
|
||||
int n, m, s, msg_flag = LWS_WRITE_CONTINUATION;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi),
|
||||
sizeof(struct per_vhost_data__minimal_pmd_bulk));
|
||||
vhd->context = lws_get_context(wsi);
|
||||
vhd->protocol = lws_get_protocol(wsi);
|
||||
vhd->vhost = lws_get_vhost(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
/* add ourselves to the list of live pss held in the vhd */
|
||||
pss->pss_list = vhd->pss_list;
|
||||
vhd->pss_list = pss;
|
||||
pss->wsi = wsi;
|
||||
pss->position = 0;
|
||||
pss->rng = 4;
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
/* remove our closing pss from the list of live pss */
|
||||
lws_start_foreach_llp(struct per_session_data__minimal_pmd_bulk **,
|
||||
ppss, vhd->pss_list) {
|
||||
if (*ppss == pss) {
|
||||
*ppss = pss->pss_list;
|
||||
break;
|
||||
}
|
||||
} lws_end_foreach_llp(ppss, pss_list);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
||||
if (pss->position == MESSAGE_SIZE)
|
||||
break;
|
||||
|
||||
if (pss->position == 0)
|
||||
msg_flag = LWS_WRITE_TEXT;
|
||||
|
||||
/* fill up one chunk's worth of message content */
|
||||
|
||||
p = &buf[LWS_PRE];
|
||||
n = MESSAGE_CHUNK_SIZE;
|
||||
if (n > MESSAGE_SIZE - pss->position)
|
||||
n = MESSAGE_SIZE - pss->position;
|
||||
/*
|
||||
* select between producing compressible repeated text,
|
||||
* or uncompressible PRNG output
|
||||
*/
|
||||
#if 0
|
||||
while (n) {
|
||||
m = pss->position % REPEAT_STRING_LEN;
|
||||
s = REPEAT_STRING_LEN - m;
|
||||
if (s > n)
|
||||
s = n;
|
||||
memcpy(p, &redundant_string[m], s);
|
||||
pss->position += s;
|
||||
p += s;
|
||||
n -= s;
|
||||
}
|
||||
#else
|
||||
pss->position += n;
|
||||
while (n--) {
|
||||
pss->rng ^= pss->rng << 21;
|
||||
pss->rng ^= pss->rng >> 35;
|
||||
pss->rng ^= pss->rng << 4;
|
||||
*p++ = 0x40 + ((pss->rng >> (n & 15)) & 0x3f);
|
||||
}
|
||||
#endif
|
||||
if (pss->position != MESSAGE_SIZE) /* if not the end, no FIN */
|
||||
msg_flag |= LWS_WRITE_NO_FIN;
|
||||
|
||||
n = lws_ptr_diff(p, &buf[LWS_PRE]);
|
||||
m = lws_write(wsi, &buf[LWS_PRE], n, msg_flag);
|
||||
lwsl_notice("write done\n");
|
||||
if (m < n) {
|
||||
lwsl_err("ERROR %d writing to di socket\n", n);
|
||||
return -1;
|
||||
}
|
||||
if (pss->position != MESSAGE_SIZE) /* if more to do... */
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK \
|
||||
{ \
|
||||
"lws-minimal-pmd-bulk", \
|
||||
callback_minimal_pmd_bulk, \
|
||||
sizeof(struct per_session_data__minimal_pmd_bulk), \
|
||||
4096, \
|
||||
0, NULL, 0 \
|
||||
}
|
||||
|
||||
#if !defined (LWS_PLUGIN_STATIC)
|
||||
|
||||
/* boilerplate needed if we are built as a dynamic plugin */
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK
|
||||
};
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
init_protocol_minimal_pmd_bulk(struct lws_context *context,
|
||||
struct lws_plugin_capability *c)
|
||||
{
|
||||
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
|
||||
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
|
||||
c->api_magic);
|
||||
return 1;
|
||||
}
|
||||
|
||||
c->protocols = protocols;
|
||||
c->count_protocols = ARRAY_SIZE(protocols);
|
||||
c->extensions = NULL;
|
||||
c->count_extensions = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
destroy_protocol_minimal_pmd_bulk(struct lws_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
16
minimal-examples/minimal-ws-server-pmd/CMakeLists.txt
Normal file
16
minimal-examples/minimal-ws-server-pmd/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
cmake_minimum_required(VERSION 2.8.9)
|
||||
include(CheckFunctionExists)
|
||||
|
||||
set(SAMP lws-minimal-ws-server-pmd)
|
||||
set(SRCS minimal-ws-server-pmd.c)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES websockets)
|
||||
|
||||
CHECK_FUNCTION_EXISTS(lws_extension_callback_pm_deflate HAVE_PMD)
|
||||
if (HAVE_PMD)
|
||||
else()
|
||||
message(FATAL_ERROR "LWS need to have been built for extensions")
|
||||
endif()
|
||||
|
||||
add_executable(${SAMP} ${SRCS})
|
||||
target_link_libraries(${SAMP} -lwebsockets)
|
23
minimal-examples/minimal-ws-server-pmd/README.md
Normal file
23
minimal-examples/minimal-ws-server-pmd/README.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# lws minimal ws server + permessage-deflate
|
||||
|
||||
## build
|
||||
|
||||
```
|
||||
$ cmake . && make
|
||||
```
|
||||
|
||||
## usage
|
||||
|
||||
```
|
||||
$ ./lws-minimal-ws-server
|
||||
[2018/03/04 09:30:02:7986] USER: LWS minimal ws server | visit http://localhost:7681
|
||||
[2018/03/04 09:30:02:7986] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 on
|
||||
```
|
||||
|
||||
Visit http://localhost:7681 on multiple browser windows
|
||||
|
||||
Text you type in any browser window is sent to all of them.
|
||||
|
||||
For simplicity of this example, only one line of text is cached at the server.
|
||||
|
||||
The ws connection is made via permessage-deflate extension.
|
BIN
minimal-examples/minimal-ws-server-pmd/favicon.ico
Normal file
BIN
minimal-examples/minimal-ws-server-pmd/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
86
minimal-examples/minimal-ws-server-pmd/index.html
Normal file
86
minimal-examples/minimal-ws-server-pmd/index.html
Normal file
|
@ -0,0 +1,86 @@
|
|||
<meta charset="UTF-8">
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<img src="libwebsockets.org-logo.png"><br>
|
||||
|
||||
LWS chat <b>minimal ws server example</b>.<br>
|
||||
Chat is sent to all browsers open on this page.<br>
|
||||
<br>
|
||||
<span id=status>Ws closed</span><br>
|
||||
<br>
|
||||
<textarea id=r readonly cols=40 rows=10></textarea><br>
|
||||
<input type="text" id=m cols=40 rows=1>
|
||||
<button id=b onclick="sendmsg();">Send</button>
|
||||
</body>
|
||||
|
||||
|
||||
<script>
|
||||
function get_appropriate_ws_url(extra_url)
|
||||
{
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
}
|
||||
|
||||
u = u.split('/');
|
||||
|
||||
/* + "/xxx" bit is for IE10 workaround */
|
||||
|
||||
return pcol + u[0] + "/" + extra_url;
|
||||
}
|
||||
|
||||
function new_ws(urlpath, protocol)
|
||||
{
|
||||
if (typeof MozWebSocket != "undefined")
|
||||
return new MozWebSocket(urlpath, protocol);
|
||||
|
||||
return new WebSocket(urlpath, protocol);
|
||||
}
|
||||
|
||||
ws = new_ws(get_appropriate_ws_url(""), "lws-minimal");
|
||||
try {
|
||||
ws.onopen = function() {
|
||||
document.getElementById("m").disabled = 0;
|
||||
document.getElementById("b").disabled = 0;
|
||||
document.getElementById("status").textContent = "ws open "+ ws.extensions;
|
||||
}
|
||||
|
||||
ws.onmessage =function got_packet(msg) {
|
||||
document.getElementById("r").value =
|
||||
document.getElementById("r").value + msg.data + "\n";
|
||||
document.getElementById("r").scrollTop =
|
||||
document.getElementById("r").scrollHeight;
|
||||
}
|
||||
|
||||
ws.onclose = function(){
|
||||
document.getElementById("m").disabled = 1;
|
||||
document.getElementById("b").disabled = 1;
|
||||
document.getElementById("status").textContent = "ws closed";
|
||||
}
|
||||
} catch(exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
|
||||
function sendmsg()
|
||||
{
|
||||
ws.send(document.getElementById("m").value);
|
||||
document.getElementById("m").value = "";
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* lws-minimal-ws-server
|
||||
*
|
||||
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates the most minimal http server you can make with lws.
|
||||
*
|
||||
* To keep it simple, it serves stuff in the directory it was started in.
|
||||
* You can change that by changing mount.origin
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "protocol_lws_minimal.c"
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
{ "http", lws_callback_http_dummy, 0, 0 },
|
||||
LWS_PLUGIN_PROTOCOL_MINIMAL,
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
static int interrupted;
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ NULL, /* linked-list "next" */
|
||||
/* .mountpoint */ "/", /* mountpoint URL */
|
||||
/* .origin */ ".", /* serve from dir */
|
||||
/* .def */ "index.html", /* default filename */
|
||||
/* .protocol */ NULL,
|
||||
/* .cgienv */ NULL,
|
||||
/* .extra_mimetypes */ NULL,
|
||||
/* .interpret */ NULL,
|
||||
/* .cgi_timeout */ 0,
|
||||
/* .cache_max_age */ 0,
|
||||
/* .auth_mask */ 0,
|
||||
/* .cache_reusable */ 0,
|
||||
/* .cache_revalidate */ 0,
|
||||
/* .cache_intermediaries */ 0,
|
||||
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
|
||||
/* .mountpoint_len */ 1, /* char count */
|
||||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
static const struct lws_extension extensions[] = {
|
||||
{
|
||||
"permessage-deflate",
|
||||
lws_extension_callback_pm_deflate,
|
||||
"permessage-deflate"
|
||||
"; client_no_context_takeover"
|
||||
"; client_max_window_bits"
|
||||
},
|
||||
{ NULL, NULL, NULL /* terminator */ }
|
||||
};
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
interrupted = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_context *context;
|
||||
int n = 0;
|
||||
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.protocols = protocols;
|
||||
info.extensions = extensions;
|
||||
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER
|
||||
/* | LLL_INFO */ /* | LLL_DEBUG */, NULL);
|
||||
|
||||
lwsl_user("LWS minimal ws server + permessage-deflate | visit http://localhost:7681\n");
|
||||
|
||||
context = lws_create_context(&info);
|
||||
if (!context) {
|
||||
lwsl_err("lws init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (n >= 0 && !interrupted)
|
||||
n = lws_service(context, 1000);
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
||||
return 0;
|
||||
}
|
194
minimal-examples/minimal-ws-server-pmd/protocol_lws_minimal.c
Normal file
194
minimal-examples/minimal-ws-server-pmd/protocol_lws_minimal.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* ws protocol handler plugin for "lws-minimal"
|
||||
*
|
||||
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This version holds a single message at a time, which may be lost if a new
|
||||
* message comes. See the minimal-ws-server-ring sample for the same thing
|
||||
* but using an lws_ring ringbuffer to hold up to 8 messages at a time.
|
||||
*/
|
||||
|
||||
#if !defined (LWS_PLUGIN_STATIC)
|
||||
#define LWS_DLL
|
||||
#define LWS_INTERNAL
|
||||
#include <libwebsockets.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* one of these created for each message */
|
||||
|
||||
struct msg {
|
||||
void *payload; /* is malloc'd */
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/* one of these is created for each client connecting to us */
|
||||
|
||||
struct per_session_data__minimal {
|
||||
struct per_session_data__minimal *pss_list;
|
||||
struct lws *wsi;
|
||||
int last; /* the last message number we sent */
|
||||
};
|
||||
|
||||
/* one of these is created for each vhost our protocol is used with */
|
||||
|
||||
struct per_vhost_data__minimal {
|
||||
struct lws_context *context;
|
||||
struct lws_vhost *vhost;
|
||||
const struct lws_protocols *protocol;
|
||||
|
||||
struct per_session_data__minimal *pss_list; /* linked-list of live pss*/
|
||||
|
||||
struct msg amsg; /* the one pending message... */
|
||||
int current; /* the current message number we are caching */
|
||||
};
|
||||
|
||||
/* destroys the message when everyone has had a copy of it */
|
||||
|
||||
static void
|
||||
__minimal_destroy_message(void *_msg)
|
||||
{
|
||||
struct msg *msg = _msg;
|
||||
|
||||
free(msg->payload);
|
||||
msg->payload = NULL;
|
||||
msg->len = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__minimal **ppss, *pss =
|
||||
(struct per_session_data__minimal *)user;
|
||||
struct per_vhost_data__minimal *vhd =
|
||||
(struct per_vhost_data__minimal *)
|
||||
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
uint32_t oldest;
|
||||
int n, m;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_PROTOCOL_INIT:
|
||||
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi),
|
||||
sizeof(struct per_vhost_data__minimal));
|
||||
vhd->context = lws_get_context(wsi);
|
||||
vhd->protocol = lws_get_protocol(wsi);
|
||||
vhd->vhost = lws_get_vhost(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
/* add ourselves to the list of live pss held in the vhd */
|
||||
pss->pss_list = vhd->pss_list;
|
||||
vhd->pss_list = pss;
|
||||
pss->wsi = wsi;
|
||||
pss->last = vhd->current;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
/* remove our closing pss from the list of live pss */
|
||||
lws_start_foreach_llp(struct per_session_data__minimal **,
|
||||
ppss, vhd->pss_list) {
|
||||
if (*ppss == pss) {
|
||||
*ppss = pss->pss_list;
|
||||
break;
|
||||
}
|
||||
} lws_end_foreach_llp(ppss, pss_list);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
if (!vhd->amsg.payload)
|
||||
break;
|
||||
|
||||
if (pss->last == vhd->current)
|
||||
break;
|
||||
|
||||
/* notice we allowed for LWS_PRE in the payload already */
|
||||
m = lws_write(wsi, vhd->amsg.payload + LWS_PRE, vhd->amsg.len,
|
||||
LWS_WRITE_TEXT);
|
||||
if (m < vhd->amsg.len) {
|
||||
lwsl_err("ERROR %d writing to di socket\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pss->last = vhd->current;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
if (vhd->amsg.payload)
|
||||
__minimal_destroy_message(&vhd->amsg);
|
||||
|
||||
vhd->amsg.len = len;
|
||||
/* notice we over-allocate by LWS_PRE */
|
||||
vhd->amsg.payload = malloc(LWS_PRE + len);
|
||||
if (!vhd->amsg.payload) {
|
||||
lwsl_user("OOM: dropping\n");
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy((char *)vhd->amsg.payload + LWS_PRE, in, len);
|
||||
vhd->current++;
|
||||
|
||||
/*
|
||||
* let everybody know we want to write something on them
|
||||
* as soon as they are ready
|
||||
*/
|
||||
lws_start_foreach_llp(struct per_session_data__minimal **,
|
||||
ppss, vhd->pss_list) {
|
||||
lws_callback_on_writable((*ppss)->wsi);
|
||||
} lws_end_foreach_llp(ppss, pss_list);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LWS_PLUGIN_PROTOCOL_MINIMAL \
|
||||
{ \
|
||||
"lws-minimal", \
|
||||
callback_minimal, \
|
||||
sizeof(struct per_session_data__minimal), \
|
||||
128, \
|
||||
0, NULL, 0 \
|
||||
}
|
||||
|
||||
#if !defined (LWS_PLUGIN_STATIC)
|
||||
|
||||
/* boilerplate needed if we are built as a dynamic plugin */
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
LWS_PLUGIN_PROTOCOL_MINIMAL
|
||||
};
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
init_protocol_minimal(struct lws_context *context,
|
||||
struct lws_plugin_capability *c)
|
||||
{
|
||||
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
|
||||
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
|
||||
c->api_magic);
|
||||
return 1;
|
||||
}
|
||||
|
||||
c->protocols = protocols;
|
||||
c->count_protocols = ARRAY_SIZE(protocols);
|
||||
c->extensions = NULL;
|
||||
c->count_extensions = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
destroy_protocol_minimal(struct lws_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -6,7 +6,8 @@
|
|||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates the most minimal http server you can make with lws.
|
||||
* This demonstrates the most minimal http server you can make with lws,
|
||||
* with an added websocket chat server using a ringbuffer.
|
||||
*
|
||||
* To keep it simple, it serves stuff in the directory it was started in.
|
||||
* You can change that by changing mount.origin
|
||||
|
@ -14,6 +15,7 @@
|
|||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "protocol_lws_minimal.c"
|
||||
|
@ -24,6 +26,8 @@ static struct lws_protocols protocols[] = {
|
|||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
static int interrupted;
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ NULL, /* linked-list "next" */
|
||||
/* .mountpoint */ "/", /* mountpoint URL */
|
||||
|
@ -44,18 +48,27 @@ static const struct lws_http_mount mount = {
|
|||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
interrupted = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_context *context;
|
||||
int n = 0;
|
||||
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.protocols = protocols;
|
||||
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER, NULL);
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER
|
||||
/* | LLL_INFO */ /* | LLL_DEBUG */, NULL);
|
||||
|
||||
lwsl_user("LWS minimal ws server (lws_ring) | visit http://localhost:7681\n");
|
||||
|
||||
context = lws_create_context(&info);
|
||||
|
@ -64,7 +77,7 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
while (n >=0)
|
||||
while (n >= 0 && !interrupted)
|
||||
n = lws_service(context, 1000);
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
* This file is made available under the Creative Commons CC0 1.0
|
||||
* Universal Public Domain Dedication.
|
||||
*
|
||||
* This demonstrates the most minimal http server you can make with lws.
|
||||
* This demonstrates the most minimal http server you can make with lws,
|
||||
* with an added websocket chat server.
|
||||
*
|
||||
* To keep it simple, it serves stuff in the directory it was started in.
|
||||
* You can change that by changing mount.origin
|
||||
|
@ -14,6 +15,7 @@
|
|||
|
||||
#include <libwebsockets.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define LWS_PLUGIN_STATIC
|
||||
#include "protocol_lws_minimal.c"
|
||||
|
@ -24,6 +26,8 @@ static struct lws_protocols protocols[] = {
|
|||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
static int interrupted;
|
||||
|
||||
static const struct lws_http_mount mount = {
|
||||
/* .mount_next */ NULL, /* linked-list "next" */
|
||||
/* .mountpoint */ "/", /* mountpoint URL */
|
||||
|
@ -44,18 +48,27 @@ static const struct lws_http_mount mount = {
|
|||
/* .basic_auth_login_file */ NULL,
|
||||
};
|
||||
|
||||
void sigint_handler(int sig)
|
||||
{
|
||||
interrupted = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct lws_context_creation_info info;
|
||||
struct lws_context *context;
|
||||
int n = 0;
|
||||
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
||||
info.port = 7681;
|
||||
info.mounts = &mount;
|
||||
info.protocols = protocols;
|
||||
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER, NULL);
|
||||
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER
|
||||
/* | LLL_INFO */ /* | LLL_DEBUG */, NULL);
|
||||
|
||||
lwsl_user("LWS minimal ws server | visit http://localhost:7681\n");
|
||||
|
||||
context = lws_create_context(&info);
|
||||
|
@ -64,7 +77,7 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
while (n >=0)
|
||||
while (n >= 0 && !interrupted)
|
||||
n = lws_service(context, 1000);
|
||||
|
||||
lws_context_destroy(context);
|
||||
|
|
Loading…
Add table
Reference in a new issue