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

wsi timeout, wsi hrtimer, sequencer timeout and vh-protocol timer all now participate on a single sorted us list. The whole idea of polling wakes is thrown out, poll waits ignore the timeout field and always use infinite timeouts. Introduce a public api that can schedule its own callback from the event loop with us resolution (usually ms is all the platform can do). Upgrade timeouts and sequencer timeouts to also be able to use us resolution. Introduce a prepared fakewsi in the pt, so we don't have to allocate one on the heap when we need it. Directly handle vh-protocol timer if LWS_MAX_SMP == 1
315 lines
7.6 KiB
C
315 lines
7.6 KiB
C
/*
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
*
|
|
* Copyright (C) 2010-2019 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 "core/private.h"
|
|
|
|
#if defined(LWS_WITH_SERVER_STATUS)
|
|
|
|
void
|
|
lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs)
|
|
{
|
|
const struct lws_vhost *vh = ctx->vhost_list;
|
|
|
|
while (vh) {
|
|
|
|
cs->rx += vh->conn_stats.rx;
|
|
cs->tx += vh->conn_stats.tx;
|
|
cs->h1_conn += vh->conn_stats.h1_conn;
|
|
cs->h1_trans += vh->conn_stats.h1_trans;
|
|
cs->h2_trans += vh->conn_stats.h2_trans;
|
|
cs->ws_upg += vh->conn_stats.ws_upg;
|
|
cs->h2_upg += vh->conn_stats.h2_upg;
|
|
cs->h2_alpn += vh->conn_stats.h2_alpn;
|
|
cs->h2_subs += vh->conn_stats.h2_subs;
|
|
cs->rejected += vh->conn_stats.rejected;
|
|
|
|
vh = vh->vhost_next;
|
|
}
|
|
}
|
|
|
|
LWS_EXTERN int
|
|
lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
|
|
{
|
|
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
|
static const char * const prots[] = {
|
|
"http://",
|
|
"https://",
|
|
"file://",
|
|
"cgi://",
|
|
">http://",
|
|
">https://",
|
|
"callback://"
|
|
};
|
|
#endif
|
|
char *orig = buf, *end = buf + len - 1, first = 1;
|
|
int n = 0;
|
|
|
|
if (len < 100)
|
|
return 0;
|
|
|
|
buf += lws_snprintf(buf, end - buf,
|
|
"{\n \"name\":\"%s\",\n"
|
|
" \"port\":\"%d\",\n"
|
|
" \"use_ssl\":\"%d\",\n"
|
|
" \"sts\":\"%d\",\n"
|
|
" \"rx\":\"%llu\",\n"
|
|
" \"tx\":\"%llu\",\n"
|
|
" \"h1_conn\":\"%lu\",\n"
|
|
" \"h1_trans\":\"%lu\",\n"
|
|
" \"h2_trans\":\"%lu\",\n"
|
|
" \"ws_upg\":\"%lu\",\n"
|
|
" \"rejected\":\"%lu\",\n"
|
|
" \"h2_upg\":\"%lu\",\n"
|
|
" \"h2_alpn\":\"%lu\",\n"
|
|
" \"h2_subs\":\"%lu\""
|
|
,
|
|
vh->name, vh->listen_port,
|
|
#if defined(LWS_WITH_TLS)
|
|
vh->tls.use_ssl & LCCSCF_USE_SSL,
|
|
#else
|
|
0,
|
|
#endif
|
|
!!(vh->options & LWS_SERVER_OPTION_STS),
|
|
vh->conn_stats.rx, vh->conn_stats.tx,
|
|
vh->conn_stats.h1_conn,
|
|
vh->conn_stats.h1_trans,
|
|
vh->conn_stats.h2_trans,
|
|
vh->conn_stats.ws_upg,
|
|
vh->conn_stats.rejected,
|
|
vh->conn_stats.h2_upg,
|
|
vh->conn_stats.h2_alpn,
|
|
vh->conn_stats.h2_subs
|
|
);
|
|
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
|
if (vh->http.mount_list) {
|
|
const struct lws_http_mount *m = vh->http.mount_list;
|
|
|
|
buf += lws_snprintf(buf, end - buf, ",\n \"mounts\":[");
|
|
while (m) {
|
|
if (!first)
|
|
buf += lws_snprintf(buf, end - buf, ",");
|
|
buf += lws_snprintf(buf, end - buf,
|
|
"\n {\n \"mountpoint\":\"%s\",\n"
|
|
" \"origin\":\"%s%s\",\n"
|
|
" \"cache_max_age\":\"%d\",\n"
|
|
" \"cache_reuse\":\"%d\",\n"
|
|
" \"cache_revalidate\":\"%d\",\n"
|
|
" \"cache_intermediaries\":\"%d\"\n"
|
|
,
|
|
m->mountpoint,
|
|
prots[m->origin_protocol],
|
|
m->origin,
|
|
m->cache_max_age,
|
|
m->cache_reusable,
|
|
m->cache_revalidate,
|
|
m->cache_intermediaries);
|
|
if (m->def)
|
|
buf += lws_snprintf(buf, end - buf,
|
|
",\n \"default\":\"%s\"",
|
|
m->def);
|
|
buf += lws_snprintf(buf, end - buf, "\n }");
|
|
first = 0;
|
|
m = m->mount_next;
|
|
}
|
|
buf += lws_snprintf(buf, end - buf, "\n ]");
|
|
}
|
|
#endif
|
|
if (vh->protocols) {
|
|
n = 0;
|
|
first = 1;
|
|
|
|
buf += lws_snprintf(buf, end - buf, ",\n \"ws-protocols\":[");
|
|
while (n < vh->count_protocols) {
|
|
if (!first)
|
|
buf += lws_snprintf(buf, end - buf, ",");
|
|
buf += lws_snprintf(buf, end - buf,
|
|
"\n {\n \"%s\":{\n"
|
|
" \"status\":\"ok\"\n }\n }"
|
|
,
|
|
vh->protocols[n].name);
|
|
first = 0;
|
|
n++;
|
|
}
|
|
buf += lws_snprintf(buf, end - buf, "\n ]");
|
|
}
|
|
|
|
buf += lws_snprintf(buf, end - buf, "\n}");
|
|
|
|
return buf - orig;
|
|
}
|
|
|
|
|
|
LWS_EXTERN LWS_VISIBLE int
|
|
lws_json_dump_context(const struct lws_context *context, char *buf, int len,
|
|
int hide_vhosts)
|
|
{
|
|
char *orig = buf, *end = buf + len - 1, first = 1;
|
|
const struct lws_vhost *vh = context->vhost_list;
|
|
const struct lws_context_per_thread *pt;
|
|
int n, listening = 0, cgi_count = 0, fd;
|
|
struct lws_conn_stats cs;
|
|
double d = 0;
|
|
#ifdef LWS_WITH_CGI
|
|
struct lws_cgi * const *pcgi;
|
|
#endif
|
|
|
|
#ifdef LWS_WITH_LIBUV
|
|
uv_uptime(&d);
|
|
#endif
|
|
|
|
buf += lws_snprintf(buf, end - buf, "{ "
|
|
"\"version\":\"%s\",\n"
|
|
"\"uptime\":\"%ld\",\n",
|
|
lws_get_library_version(),
|
|
(long)d);
|
|
|
|
#ifdef LWS_HAVE_GETLOADAVG
|
|
{
|
|
double d[3];
|
|
int m;
|
|
|
|
m = getloadavg(d, 3);
|
|
for (n = 0; n < m; n++) {
|
|
buf += lws_snprintf(buf, end - buf,
|
|
"\"l%d\":\"%.2f\",\n",
|
|
n + 1, d[n]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
fd = lws_open("/proc/self/statm", LWS_O_RDONLY);
|
|
if (fd >= 0) {
|
|
char contents[96], pure[96];
|
|
n = read(fd, contents, sizeof(contents) - 1);
|
|
if (n > 0) {
|
|
contents[n] = '\0';
|
|
if (contents[n - 1] == '\n')
|
|
contents[--n] = '\0';
|
|
lws_json_purify(pure, contents, sizeof(pure));
|
|
|
|
buf += lws_snprintf(buf, end - buf,
|
|
"\"statm\": \"%s\",\n", pure);
|
|
}
|
|
close(fd);
|
|
}
|
|
|
|
buf += lws_snprintf(buf, end - buf, "\"heap\":%lld,\n\"contexts\":[\n",
|
|
(long long)lws_get_allocated_heap());
|
|
|
|
buf += lws_snprintf(buf, end - buf, "{ "
|
|
"\"context_uptime\":\"%llu\",\n"
|
|
"\"cgi_spawned\":\"%d\",\n"
|
|
"\"pt_fd_max\":\"%d\",\n"
|
|
"\"ah_pool_max\":\"%d\",\n"
|
|
"\"deprecated\":\"%d\",\n"
|
|
"\"wsi_alive\":\"%d\",\n",
|
|
(unsigned long long)(lws_now_usecs() - context->time_up),
|
|
context->count_cgi_spawned,
|
|
context->fd_limit_per_thread,
|
|
context->max_http_header_pool,
|
|
context->deprecated,
|
|
context->count_wsi_allocated);
|
|
|
|
buf += lws_snprintf(buf, end - buf, "\"pt\":[\n ");
|
|
for (n = 0; n < context->count_threads; n++) {
|
|
pt = &context->pt[n];
|
|
if (n)
|
|
buf += lws_snprintf(buf, end - buf, ",");
|
|
buf += lws_snprintf(buf, end - buf,
|
|
"\n {\n"
|
|
" \"fds_count\":\"%d\",\n"
|
|
" \"ah_pool_inuse\":\"%d\",\n"
|
|
" \"ah_wait_list\":\"%d\"\n"
|
|
" }",
|
|
pt->fds_count,
|
|
pt->http.ah_count_in_use,
|
|
pt->http.ah_wait_list_length);
|
|
}
|
|
|
|
buf += lws_snprintf(buf, end - buf, "]");
|
|
|
|
buf += lws_snprintf(buf, end - buf, ", \"vhosts\":[\n ");
|
|
|
|
first = 1;
|
|
vh = context->vhost_list;
|
|
listening = 0;
|
|
cs = context->conn_stats;
|
|
lws_sum_stats(context, &cs);
|
|
while (vh) {
|
|
|
|
if (!hide_vhosts) {
|
|
if (!first)
|
|
if(buf != end)
|
|
*buf++ = ',';
|
|
buf += lws_json_dump_vhost(vh, buf, end - buf);
|
|
first = 0;
|
|
}
|
|
if (vh->lserv_wsi)
|
|
listening++;
|
|
vh = vh->vhost_next;
|
|
}
|
|
|
|
buf += lws_snprintf(buf, end - buf,
|
|
"],\n\"listen_wsi\":\"%d\",\n"
|
|
" \"rx\":\"%llu\",\n"
|
|
" \"tx\":\"%llu\",\n"
|
|
" \"h1_conn\":\"%lu\",\n"
|
|
" \"h1_trans\":\"%lu\",\n"
|
|
" \"h2_trans\":\"%lu\",\n"
|
|
" \"ws_upg\":\"%lu\",\n"
|
|
" \"rejected\":\"%lu\",\n"
|
|
" \"h2_alpn\":\"%lu\",\n"
|
|
" \"h2_subs\":\"%lu\",\n"
|
|
" \"h2_upg\":\"%lu\"",
|
|
listening, cs.rx, cs.tx,
|
|
cs.h1_conn,
|
|
cs.h1_trans,
|
|
cs.h2_trans,
|
|
cs.ws_upg,
|
|
cs.rejected,
|
|
cs.h2_alpn,
|
|
cs.h2_subs,
|
|
cs.h2_upg);
|
|
|
|
#ifdef LWS_WITH_CGI
|
|
for (n = 0; n < context->count_threads; n++) {
|
|
pt = &context->pt[n];
|
|
pcgi = &pt->http.cgi_list;
|
|
|
|
while (*pcgi) {
|
|
pcgi = &(*pcgi)->cgi_list;
|
|
|
|
cgi_count++;
|
|
}
|
|
}
|
|
#endif
|
|
buf += lws_snprintf(buf, end - buf, ",\n \"cgi_alive\":\"%d\"\n ",
|
|
cgi_count);
|
|
|
|
buf += lws_snprintf(buf, end - buf, "}");
|
|
|
|
|
|
buf += lws_snprintf(buf, end - buf, "]}\n ");
|
|
|
|
return buf - orig;
|
|
}
|
|
|
|
#endif
|