
1) This makes lwsws run a parent process with the original permissions. But this process is only able to respond to SIGHUP, it doesn't do anything else. 2) You can send this parent process a SIGHUP now to cause it to - close listening sockets in existing lwsws processes - mark those processes as to exit when the number of active connections on the falls to zero - spawn a fresh child process from scratch, using latest configuration file content, latest plugins, etc. It can now reopen listening sockets if it chooses to, or open different listen ports or whatever. Notes: 1) lws_context_destroy() has been split into two pieces... the reason for the split is the first part closes the per-vhost protocols, but since they may have created libuv objects in the per-vhost protocol storage, these cannot be freed until after the loop has been run. That's the purpose of the second part of the context destruction, lws_context_destroy2(). For compatibility, if you are not using libuv, the first part calls the second part. However if you are using libuv, you must now call the second part from your own main.c after the first part.
374 lines
12 KiB
HTML
374 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset=utf-8 http-equiv="Content-Language" content="en"/>
|
|
<script src="/lws-common.js"></script>
|
|
<title>LWS Server Status</title>
|
|
<style type="text/css">
|
|
span.title { font-size:18pt; font: Arial; font-weight:normal;
|
|
text-align:center; color:#000000; }
|
|
span.mount { font-size:10pt; font: Arial; font-weight:normal;
|
|
text-align:center; color:#000000; }
|
|
span.mountname { font-size:14pt; font: Arial; font-weight:bold;
|
|
text-align:center; color:#404010; }
|
|
span.n { font-size:12pt; font: Arial; font-weight:normal;
|
|
text-align:center; color:#808020; }
|
|
span.v { font-size:12pt; font: Arial; font-weight:bold;
|
|
text-align:center; color:#202020; }
|
|
span.m1 { font-size:12pt; font: Arial; font-weight:bold;
|
|
text-align:center; color:#202020; }
|
|
span.m2 { font-size:12pt; font: Arial; font-weight:normal;
|
|
text-align:center; color:#202020; }
|
|
.browser { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#ffff00; vertical-align:middle; text-align:center; background:#d0b070; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px;}
|
|
.group2 { vertical-align:middle;
|
|
text-align:center;
|
|
background:#f0f0e0;
|
|
padding:12px;
|
|
-webkit-border-radius:10px;
|
|
-moz-border-radius:10px;
|
|
border-radius:10px; }
|
|
.explain { vertical-align:middle;
|
|
text-align:center;
|
|
background:#f0f0c0; padding:12px;
|
|
-webkit-border-radius:10px;
|
|
-moz-border-radius:10px;
|
|
border-radius:10px;
|
|
color:#404000; }
|
|
td.wsstatus { vertical-align:middle; width:200px; height:50px;
|
|
text-align:center;
|
|
background:#f0f0c0; padding:6px;
|
|
-webkit-border-radius:8px;
|
|
-moz-border-radius:8px;
|
|
border-radius:8px;
|
|
color:#404000; }
|
|
td.l { vertical-align:middle;
|
|
text-align:center;
|
|
background:#d0d0b0;
|
|
padding:3px;
|
|
-webkit-border-radius:3px;
|
|
-moz-border-radius:3px;
|
|
border-radius:3px; }
|
|
td.dl { vertical-align:middle;
|
|
text-align:center;
|
|
background:#c0c0c0;
|
|
padding:3px;
|
|
-webkit-border-radius:3px;
|
|
-moz-border-radius:3px;
|
|
border-radius:3px; }
|
|
td.c { vertical-align:middle;
|
|
text-align:center;
|
|
background:#c0c0a0;
|
|
padding:3px;
|
|
-webkit-border-radius:3px;
|
|
-moz-border-radius:3px;
|
|
border-radius:3px; }
|
|
td.c0 { vertical-align:middle;
|
|
text-align:center;
|
|
background:#b0b090;
|
|
padding:3px;
|
|
-webkit-border-radius:3px;
|
|
-moz-border-radius:3px;
|
|
border-radius:3px; }
|
|
td.dc0 { vertical-align:middle;
|
|
text-align:center;
|
|
background:#a0a0a0;
|
|
padding:3px;
|
|
-webkit-border-radius:3px;
|
|
-moz-border-radius:3px;
|
|
border-radius:3px; }
|
|
td.c1 { vertical-align:middle;
|
|
text-align:center;
|
|
background:#c0c0c0;
|
|
padding:3px;
|
|
-webkit-border-radius:3px;
|
|
-moz-border-radius:3px;
|
|
border-radius:3px; }
|
|
td.t { vertical-align:middle;
|
|
text-align:center;
|
|
background:#e0e0c0;
|
|
padding:3px;
|
|
-webkit-border-radius:3px;
|
|
-moz-border-radius:3px;
|
|
border-radius:3px; }
|
|
.content { vertical-align:top; text-align:center; background:#fffff0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
|
.canvas { vertical-align:top; text-align:center; background:#efefd0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
|
.tabs {
|
|
position: relative;
|
|
min-height: 750px; /* This part sucks */
|
|
clear: both;
|
|
margin: 25px 0;
|
|
}
|
|
.tab {
|
|
float: left;
|
|
}
|
|
.tab label {
|
|
background: #eee;
|
|
padding: 10px;
|
|
border: 1px solid #ccc;
|
|
margin-left: -1px;
|
|
position: relative;
|
|
left: 1px;
|
|
}
|
|
.tab [type=radio] {
|
|
display: none;
|
|
}
|
|
.content {
|
|
position: absolute;
|
|
top: 28px;
|
|
left: 0;
|
|
background: white;
|
|
right: 0;
|
|
bottom: 0;
|
|
padding: 20px;
|
|
border: 1px solid #ccc;
|
|
}
|
|
[type=radio]:checked ~ label {
|
|
background: white;
|
|
border-bottom: 1px solid white;
|
|
z-index: 2;
|
|
}
|
|
[type=radio]:checked ~ label ~ .content {
|
|
z-index: 1;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<header></header>
|
|
<article>
|
|
|
|
<table>
|
|
<tr><td><img src="./lwsws-logo.png"></td><td><span id=title class=title>Server status</span></td></tr>
|
|
<tr><td align=center colspan=2>
|
|
<div id="conninfo">...</div>
|
|
<div id="json"></div>
|
|
</td></tr>
|
|
|
|
|
|
</table>
|
|
|
|
</article>
|
|
|
|
<script nonce="lwscaro">
|
|
|
|
lws_gray_out(true,{'zindex':'499'});
|
|
|
|
/*
|
|
* We display untrusted stuff in html context... reject anything
|
|
* that has HTML stuff in it
|
|
*/
|
|
|
|
function san(s)
|
|
{
|
|
if (s.search("<") != -1)
|
|
return "invalid string";
|
|
|
|
return s;
|
|
}
|
|
|
|
function humanize(s)
|
|
{
|
|
i = parseInt(s);
|
|
|
|
if (i > 1000000000)
|
|
return (i / 1000000000).toFixed(3) + "G";
|
|
|
|
if (i > 1000000)
|
|
return (i / 1000000).toFixed(3) + "M";
|
|
|
|
if (i > 1000)
|
|
return (i / 1000).toFixed(3) + "K";
|
|
|
|
return s;
|
|
}
|
|
|
|
var pos = 0;
|
|
|
|
function get_appropriate_ws_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] + "/xxx";
|
|
}
|
|
|
|
|
|
var socket_status, jso, s;
|
|
|
|
if (typeof MozWebSocket != "undefined") {
|
|
socket_status = new MozWebSocket(get_appropriate_ws_url(),
|
|
"lws-server-status");
|
|
} else {
|
|
socket_status = new WebSocket(get_appropriate_ws_url(),
|
|
"lws-server-status");
|
|
}
|
|
|
|
|
|
try {
|
|
socket_status.onopen = function() {
|
|
document.getElementById("title").innerHTML = "Server Status (Active)";
|
|
lws_gray_out(false);
|
|
}
|
|
|
|
socket_status.onmessage =function got_packet(msg) {
|
|
var u, ci, n;
|
|
//document.getElementById("json").innerHTML = "<pre>"+msg.data+"</pre>";
|
|
jso = JSON.parse(msg.data);
|
|
u = parseInt(san(jso.i.uptime));
|
|
|
|
if (parseInt(jso.i.contexts[0].deprecated) == 0)
|
|
s = "<table><tr><td></td><td class=\"c0\">";
|
|
else
|
|
s = "<table><tr><td></td><td class=\"dc0\">";
|
|
s +=
|
|
"Server</td><td>" +
|
|
"<span class=n>Version:</span> <span class=v>" +
|
|
san(jso.i.version) + "</span><br>" +
|
|
"<span class=n>Uptime:</span> <span class=v>" +
|
|
((u / (24 * 3600)) | 0) + "d " +
|
|
(((u % (24 * 3600)) / 3600) | 0) + "h " +
|
|
(((u % 3600) / 60) | 0) + "m</span>";
|
|
if (jso.i.l1)
|
|
s = s + ", <span class=n>Load:</span> <span class=v>" + san(jso.i.l1) + " ";
|
|
if (jso.i.l2)
|
|
s = s + san(jso.i.l2) + " ";
|
|
if (jso.i.l3)
|
|
s = s + san(jso.i.l3);
|
|
if (jso.i.l1)
|
|
s =s + "<span>";
|
|
|
|
for (n = 0; n < jso.files.length; n++) {
|
|
s += "<br><span class=n>" + san(jso.files[n].path) + ":</span><br> " + san(jso.files[n].val);
|
|
}
|
|
s += "</td></tr>";
|
|
|
|
for (ci = 0; ci < jso.i.contexts.length; ci++) {
|
|
|
|
if (parseInt(jso.i.contexts[ci].deprecated) == 0)
|
|
s += "<tr><td></td><td class=\"c\">" +
|
|
"Active Context</td><td>";
|
|
else
|
|
s += "<tr><td></td><td class=\"c1\">" +
|
|
"Deprecated Context " + ci + "</td><td>";
|
|
|
|
u = parseInt(san(jso.i.contexts[ci].context_uptime));
|
|
s += "<span class=n>Uptime:</span> <span class=v>" +
|
|
((u / (24 * 3600)) | 0) + "d " +
|
|
(((u % (24 * 3600)) / 3600) | 0) + "h " +
|
|
(((u % 3600) / 60) | 0) + "m</span>";
|
|
|
|
s = s +
|
|
"<br>" +
|
|
"<span class=n>Listening wsi:</span> <span class=v>" + san(jso.i.contexts[ci].listen_wsi) + "</span>, " +
|
|
"<span class=n>Current wsi alive:</span> <span class=v>" + (parseInt(san(jso.i.contexts[ci].wsi_alive)) -
|
|
parseInt(san(jso.i.contexts[ci].listen_wsi))) + "</span><br>" +
|
|
"<span class=n>Total Rx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].rx)) +"</span>, " +
|
|
"<span class=n>Total Tx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].tx)) +"</span><br>" +
|
|
"<span class=n>Total connections:</span> <span class=v>" + san(jso.i.contexts[ci].conn) +"</span>, " +
|
|
"<span class=n>Total HTTP Transactions:</span> <span class=v>" + san(jso.i.contexts[ci].trans) +"</span><br>" +
|
|
"<span class=n>Total ws upgrades:</span> <span class=v>" + san(jso.i.contexts[ci].ws_upg) +"</span>, " +
|
|
"<span class=n>Total h2 upgrades:</span> <span class=v>" + san(jso.i.contexts[ci].http2_upg) +"</span>, " +
|
|
"<span class=n>Total Rejected:</span> <span class=v>" + san(jso.i.contexts[ci].rejected) +"</span><br>" +
|
|
"<span class=n>Current cgi alive:</span> <span class=v>" + san(jso.i.contexts[ci].cgi_alive) + "</span>, " +
|
|
"<span class=n>Total CGI spawned:</span> <span class=v>" + san(jso.i.contexts[ci].cgi_spawned) +
|
|
"</span><table>";
|
|
|
|
for (n = 0; n < jso.i.contexts[ci].pt.length; n++) {
|
|
|
|
if (parseInt(jso.i.contexts[ci].deprecated) == 0)
|
|
s += "<tr><td> </td><td class=\"l\">service thread " + (n + 1);
|
|
else
|
|
s += "<tr><td> </td><td class=\"dl\">service thread " + (n + 1);
|
|
s += "</td><td>" +
|
|
"<span class=n>fds:</span> <span class=v>" + san(jso.i.contexts[ci].pt[n].fds_count) + " / " +
|
|
san(jso.i.contexts[ci].pt_fd_max) + "</span>, ";
|
|
s = s + "<span class=n>ah pool:</span> <span class=v>" + san(jso.i.contexts[ci].pt[n].ah_pool_inuse) + " / " +
|
|
san(jso.i.contexts[ci].ah_pool_max) + "</span>, " +
|
|
"<span class=n>ah waiting list:</span> <span class=v>" + san(jso.i.contexts[ci].pt[n].ah_wait_list);
|
|
|
|
s = s + "</span></td></tr>";
|
|
|
|
}
|
|
for (n = 0; n < jso.i.contexts[ci].vhosts.length; n++) {
|
|
if (parseInt(jso.i.contexts[ci].deprecated) == 0)
|
|
s += "<tr><td> </td><td class=\"l\">vhost " + (n + 1);
|
|
else
|
|
s += "<tr><td> </td><td class=\"dl\">vhost " + (n + 1);
|
|
s += "</td><td><span class=\"mountname\">";
|
|
if (jso.i.contexts[ci].vhosts[n].use_ssl == '1')
|
|
s = s + "https://";
|
|
else
|
|
s = s + "http://";
|
|
s = s + san(jso.i.contexts[ci].vhosts[n].name) + ":" +
|
|
san(jso.i.contexts[ci].vhosts[n].port) + "</span>";
|
|
if (jso.i.contexts[ci].vhosts[n].sts == '1')
|
|
s = s + " (STS)";
|
|
s = s +"<br>" +
|
|
"<span class=n>rx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].vhosts[n].rx)) + "B</span>, " +
|
|
"<span class=n>tx</span> <span class=v>" + humanize(san(jso.i.contexts[ci].vhosts[n].tx)) + "B</span><br>" +
|
|
"<span class=n>vh connections</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].conn) + "</span>, " +
|
|
"<span class=n>vh http transactions</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].trans) + "</span><br>" +
|
|
"<span class=n>vh upgrades to ws:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].ws_upg) + "</span>, " +
|
|
"<span class=n>to http/2:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].http2_upg) + "</span>, " +
|
|
"<span class=n>rejected:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].rejected) + "</span><br>" +
|
|
"<table style=\"margin-left:16px\"><tr><td class=t>Mountpoint</td><td class=t>Origin</td><td class=t>Cache Policy</td></tr>";
|
|
|
|
var m;
|
|
for (m = 0; m < jso.i.contexts[ci].vhosts[n].mounts.length; m++) {
|
|
s = s + "<tr><td>";
|
|
s = s + "<span class=\"m1\">" + san(jso.i.contexts[ci].vhosts[n].mounts[m].mountpoint) +
|
|
"</span></td><td><span class=\"m2\">" +
|
|
san(jso.i.contexts[ci].vhosts[n].mounts[m].origin) +
|
|
"</span></td><td>";
|
|
if (parseInt(san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_max_age)))
|
|
s = s + "<span class=n>max-age:</span> <span class=v>" +
|
|
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_max_age) +
|
|
"</span>, <span class=n>reuse:</span> <span class=v>" +
|
|
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_reuse) +
|
|
"</span>, <span class=n>reval:</span> <span class=v>" +
|
|
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_revalidate) +
|
|
"</span>, <span class=n>inter:</span> <span class=v>" +
|
|
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_intermediaries);
|
|
s = s + "</span></td></tr>"
|
|
}
|
|
s = s + "</table>";
|
|
s = s + "</td></tr>";
|
|
}
|
|
|
|
s += "</table></td></tr>";
|
|
|
|
} // context
|
|
s = s + "</table>";
|
|
|
|
document.getElementById("conninfo").innerHTML = s;
|
|
}
|
|
|
|
socket_status.onclose = function(){
|
|
document.getElementById("title").innerHTML = "Server Status (Disconnected)";
|
|
lws_gray_out(true,{'zindex':'499'});
|
|
}
|
|
} catch(exception) {
|
|
alert('<p>Error' + exception);
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|