mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-16 00:00:07 +01:00

Adapt the pt sul owner list to be an array, and define two different lists, one that acts like before and is the default for existing users, and another that has the ability to cooperate with systemwide suspend to restrict the interval spent suspended so that it will wake in time for the earliest thing on this wake-suspend sul list. Clean the api a bit and add lws_sul_cancel() that only needs the sul as the argument. Add a flag for client creation info to indicate that this client connection is important enough that, eg, validity checking it to detect silently dead connections should go on the wake-suspend sul list. That flag is exposed in secure streams policy so it can be added to a streamtype with "swake_validity": true Deprecate out the old vhost timer stuff that predates sul. Add a flag LWS_WITH_DEPRECATED_THINGS in cmake so users can get it back temporarily before it will be removed in a v4.2. Adapt all remaining in-tree users of it to use explicit suls.
156 lines
3.8 KiB
C
156 lines
3.8 KiB
C
/*
|
|
* lws-minimal-http-server-h2-long-poll
|
|
*
|
|
* Written in 2010-2019 by Andy Green <andy@warmcat.com>
|
|
*
|
|
* This file is made available under the Creative Commons CC0 1.0
|
|
* Universal Public Domain Dedication.
|
|
*
|
|
* This demonstrates an h2 server that supports "long poll"
|
|
* immortal client connections. For simplicity it doesn't serve
|
|
* any regular files, you can add a mount to do it if you want.
|
|
*
|
|
* The protocol keeps the long poll h2 stream open, and sends
|
|
* the time on the stream once per minute. Normally idle h2
|
|
* connections are closed by default within 30s, so this demonstrates
|
|
* the stream and network connection are operating as "immortal"
|
|
* on both sides.
|
|
*
|
|
* See http-client/minimal-http-client-h2-long-poll for the
|
|
* client example that connects and transitions the stream to the
|
|
* immortal long poll mode.
|
|
*/
|
|
|
|
#include <libwebsockets.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
|
|
static int interrupted;
|
|
|
|
struct pss {
|
|
struct lws *wsi;
|
|
lws_sorted_usec_list_t sul;
|
|
char pending;
|
|
};
|
|
|
|
static const lws_retry_bo_t retry = {
|
|
.secs_since_valid_ping = 5,
|
|
.secs_since_valid_hangup = 10,
|
|
};
|
|
|
|
static void
|
|
sul_cb(lws_sorted_usec_list_t *sul)
|
|
{
|
|
struct pss *pss = (struct pss *)lws_container_of(sul, struct pss, sul);
|
|
|
|
pss->pending = 1;
|
|
lws_callback_on_writable(pss->wsi);
|
|
/* interval 1min... longer than any normal timeout */
|
|
lws_sul_schedule(lws_get_context(pss->wsi), 0, &pss->sul, sul_cb,
|
|
60 * LWS_US_PER_SEC);
|
|
}
|
|
|
|
static int
|
|
callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|
void *in, size_t len)
|
|
{
|
|
struct pss * pss = (struct pss *)user;
|
|
uint8_t buf[LWS_PRE + LWS_RECOMMENDED_MIN_HEADER_SPACE],
|
|
*start = &buf[LWS_PRE], *p = start,
|
|
*end = p + sizeof(buf) - LWS_PRE;
|
|
int m, n;
|
|
|
|
switch (reason) {
|
|
case LWS_CALLBACK_HTTP:
|
|
lwsl_user("%s: connect\n", __func__);
|
|
pss->wsi = wsi;
|
|
|
|
if (lws_add_http_common_headers(wsi, HTTP_STATUS_OK,
|
|
"text/html",
|
|
LWS_ILLEGAL_HTTP_CONTENT_LEN, /* no content len */
|
|
&p, end))
|
|
return 1;
|
|
if (lws_finalize_write_http_header(wsi, start, &p, end))
|
|
return 1;
|
|
|
|
sul_cb(&pss->sul);
|
|
return 0;
|
|
|
|
case LWS_CALLBACK_CLOSED_HTTP:
|
|
if (!pss)
|
|
break;
|
|
lws_sul_cancel(&pss->sul);
|
|
break;
|
|
|
|
case LWS_CALLBACK_HTTP_WRITEABLE:
|
|
if (!pss->pending)
|
|
break;
|
|
n = lws_snprintf((char *)p, sizeof(buf) - LWS_PRE, "%llu",
|
|
(unsigned long long)lws_now_usecs());
|
|
m = lws_write(wsi, p, n, LWS_WRITE_HTTP);
|
|
if (m < n) {
|
|
lwsl_err("ERROR %d writing to socket\n", n);
|
|
return -1;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
|
}
|
|
|
|
static struct lws_protocols protocols[] = {
|
|
{ "http", callback_http, sizeof(struct pss), 0 },
|
|
{ NULL, NULL, 0, 0 } /* terminator */
|
|
};
|
|
|
|
|
|
void sigint_handler(int sig)
|
|
{
|
|
interrupted = 1;
|
|
}
|
|
|
|
int main(int argc, const char **argv)
|
|
{
|
|
struct lws_context_creation_info info;
|
|
struct lws_context *context;
|
|
const char *p;
|
|
int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
|
|
|
|
signal(SIGINT, sigint_handler);
|
|
|
|
if ((p = lws_cmdline_option(argc, argv, "-d")))
|
|
logs = atoi(p);
|
|
|
|
lws_set_log_level(logs, NULL);
|
|
lwsl_user("LWS minimal http server h2 long poll\n");
|
|
|
|
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
|
|
info.port = 7681;
|
|
info.ssl_cert_filepath = "localhost-100y.cert";
|
|
info.ssl_private_key_filepath = "localhost-100y.key";
|
|
info.protocols = protocols;
|
|
info.options =
|
|
LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
|
|
LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL |
|
|
LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
|
|
|
|
/* the default validity check is 5m / 5m10s... -v = 5s / 10s */
|
|
|
|
if (lws_cmdline_option(argc, argv, "-v"))
|
|
info.retry_and_idle_policy = &retry;
|
|
|
|
context = lws_create_context(&info);
|
|
if (!context) {
|
|
lwsl_err("lws init failed\n");
|
|
return 1;
|
|
}
|
|
|
|
while (n >= 0 && !interrupted)
|
|
n = lws_service(context, 0);
|
|
|
|
lws_context_destroy(context);
|
|
|
|
return 0;
|
|
}
|