Initial webui code (that does nothing useful)
I plan to port over the existing nulldc debugger stuff to a webui so we can do remote debugging on android and more
This commit is contained in:
parent
eb3f1ca687
commit
528d0c6d7a
|
@ -0,0 +1,398 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset=utf-8 http-equiv="Content-Language" content="en"/>
|
||||||
|
<title>Minimal Websocket test app</title>
|
||||||
|
<style type="text/css">
|
||||||
|
div.title { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#000000; }
|
||||||
|
.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 { width:600px; 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; }
|
||||||
|
.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; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header></header>
|
||||||
|
<article>
|
||||||
|
|
||||||
|
<table><tr><td>
|
||||||
|
|
||||||
|
<table width="100%"><tr><td valign=middle align=center><a href="http://libwebsockets.org"><img src="/libwebsockets.org-logo.png"></a></td><td>
|
||||||
|
<section class="browser">Detected Browser: <div id=brow>...</div></section></td></tr></table>
|
||||||
|
|
||||||
|
</td></tr><tr><td>
|
||||||
|
|
||||||
|
<section id="increment" class="group2">
|
||||||
|
<div class="title">libwebsockets "dumb-increment-protocol"</div>
|
||||||
|
<table><tr><td>
|
||||||
|
<table class="content" width="200px">
|
||||||
|
<tr><td align=center><input type=button id=offset value="Reset counter" onclick="reset();" ></td></tr>
|
||||||
|
<tr><td width=200px align=center><div id=number> </div></td></tr>
|
||||||
|
<tr><td id=wsdi_statustd align=center class="explain"><div id=wsdi_status>Not initialized</div></td></tr>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td><td class="explain">
|
||||||
|
The incrementing number is coming from the server and is individual for
|
||||||
|
each connection to the server... try opening a second browser window.
|
||||||
|
<br/><br/>
|
||||||
|
The button zeros just this connection's number.
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
</td></tr></table>
|
||||||
|
</section>
|
||||||
|
<br>
|
||||||
|
<section id="mirror" class="group2">
|
||||||
|
<div class="title">libwebsockets "lws-mirror-protocol"</div>
|
||||||
|
<div class="explain">
|
||||||
|
Use the mouse to draw on the canvas below -- all other browser windows open
|
||||||
|
on this page see your drawing in realtime and you can see any of theirs as
|
||||||
|
well.
|
||||||
|
<br/><br/>
|
||||||
|
The lws-mirror protocol doesn't interpret what is being sent to it, it just
|
||||||
|
re-sends it to every other websocket it has a connection with using that
|
||||||
|
protocol, including the guy who sent the packet.
|
||||||
|
<br/><br/>
|
||||||
|
<b>libwebsockets-test-client</b> joins in by spamming circles on to this shared canvas when
|
||||||
|
run.
|
||||||
|
</div>
|
||||||
|
<table class="content">
|
||||||
|
<tr>
|
||||||
|
<td>Drawing color:
|
||||||
|
<select id="color" onchange="update_color();">
|
||||||
|
<option value=#000000>Black</option>
|
||||||
|
<option value=#0000ff>Blue</option>
|
||||||
|
<option value=#20ff20>Green</option>
|
||||||
|
<option value=#802020>Dark Red</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td id=wslm_statustd align=center class="explain"><div id=wslm_status>Not initialized</div></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan=2 width=500 class="content">
|
||||||
|
<div id="wslm_drawing">
|
||||||
|
</div></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</td></tr><tr><td>
|
||||||
|
Looking for support? <a href="http://libwebsockets.org">http://libwebsockets.org</a><br/>
|
||||||
|
Join the mailing list: <a href="http://ml.libwebsockets.org/mailman/listinfo/libwebsockets">http://ml.libwebsockets.org/mailman/listinfo/libwebsockets</a>
|
||||||
|
|
||||||
|
</td></tr></table>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
/* BrowserDetect came from http://www.quirksmode.org/js/detect.html */
|
||||||
|
|
||||||
|
var BrowserDetect = {
|
||||||
|
init: function () {
|
||||||
|
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
|
||||||
|
this.version = this.searchVersion(navigator.userAgent)
|
||||||
|
|| this.searchVersion(navigator.appVersion)
|
||||||
|
|| "an unknown version";
|
||||||
|
this.OS = this.searchString(this.dataOS) || "an unknown OS";
|
||||||
|
},
|
||||||
|
searchString: function (data) {
|
||||||
|
for (var i=0;i<data.length;i++) {
|
||||||
|
var dataString = data[i].string;
|
||||||
|
var dataProp = data[i].prop;
|
||||||
|
this.versionSearchString = data[i].versionSearch || data[i].identity;
|
||||||
|
if (dataString) {
|
||||||
|
if (dataString.indexOf(data[i].subString) != -1)
|
||||||
|
return data[i].identity;
|
||||||
|
}
|
||||||
|
else if (dataProp)
|
||||||
|
return data[i].identity;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
searchVersion: function (dataString) {
|
||||||
|
var index = dataString.indexOf(this.versionSearchString);
|
||||||
|
if (index == -1) return;
|
||||||
|
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
|
||||||
|
},
|
||||||
|
dataBrowser: [
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Chrome",
|
||||||
|
identity: "Chrome"
|
||||||
|
},
|
||||||
|
{ string: navigator.userAgent,
|
||||||
|
subString: "OmniWeb",
|
||||||
|
versionSearch: "OmniWeb/",
|
||||||
|
identity: "OmniWeb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "Apple",
|
||||||
|
identity: "Safari",
|
||||||
|
versionSearch: "Version"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: window.opera,
|
||||||
|
identity: "Opera",
|
||||||
|
versionSearch: "Version"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "iCab",
|
||||||
|
identity: "iCab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "KDE",
|
||||||
|
identity: "Konqueror"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Firefox",
|
||||||
|
identity: "Firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "Camino",
|
||||||
|
identity: "Camino"
|
||||||
|
},
|
||||||
|
{ // for newer Netscapes (6+)
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Netscape",
|
||||||
|
identity: "Netscape"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "MSIE",
|
||||||
|
identity: "Explorer",
|
||||||
|
versionSearch: "MSIE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Gecko",
|
||||||
|
identity: "Mozilla",
|
||||||
|
versionSearch: "rv"
|
||||||
|
},
|
||||||
|
{ // for older Netscapes (4-)
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Mozilla",
|
||||||
|
identity: "Netscape",
|
||||||
|
versionSearch: "Mozilla"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataOS : [
|
||||||
|
{
|
||||||
|
string: navigator.platform,
|
||||||
|
subString: "Win",
|
||||||
|
identity: "Windows"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.platform,
|
||||||
|
subString: "Mac",
|
||||||
|
identity: "Mac"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "iPhone",
|
||||||
|
identity: "iPhone/iPod"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.platform,
|
||||||
|
subString: "Linux",
|
||||||
|
identity: "Linux"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
};
|
||||||
|
BrowserDetect.init();
|
||||||
|
|
||||||
|
document.getElementById("brow").textContent = " " + BrowserDetect.browser + " "
|
||||||
|
+ BrowserDetect.version +" " + BrowserDetect.OS +" ";
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("number").textContent = get_appropriate_ws_url();
|
||||||
|
|
||||||
|
/* dumb increment protocol */
|
||||||
|
|
||||||
|
var socket_di;
|
||||||
|
|
||||||
|
if (typeof MozWebSocket != "undefined") {
|
||||||
|
socket_di = new MozWebSocket(get_appropriate_ws_url(),
|
||||||
|
"dumb-increment-protocol");
|
||||||
|
} else {
|
||||||
|
socket_di = new WebSocket(get_appropriate_ws_url(),
|
||||||
|
"dumb-increment-protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
socket_di.onopen = function() {
|
||||||
|
document.getElementById("wsdi_statustd").style.backgroundColor = "#40ff40";
|
||||||
|
document.getElementById("wsdi_status").textContent = " websocket connection opened ";
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_di.onmessage =function got_packet(msg) {
|
||||||
|
document.getElementById("number").textContent = msg.data + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_di.onclose = function(){
|
||||||
|
document.getElementById("wsdi_statustd").style.backgroundColor = "#ff4040";
|
||||||
|
document.getElementById("wsdi_status").textContent = " websocket connection CLOSED ";
|
||||||
|
}
|
||||||
|
} catch(exception) {
|
||||||
|
alert('<p>Error' + exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
socket_di.send("reset\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* lws-mirror protocol */
|
||||||
|
|
||||||
|
var down = 0;
|
||||||
|
var no_last = 1;
|
||||||
|
var last_x = 0, last_y = 0;
|
||||||
|
var ctx;
|
||||||
|
var socket_lm;
|
||||||
|
var color = "#000000";
|
||||||
|
|
||||||
|
if (typeof MozWebSocket != "undefined") {
|
||||||
|
socket_lm = new MozWebSocket(get_appropriate_ws_url(),
|
||||||
|
"lws-mirror-protocol");
|
||||||
|
} else {
|
||||||
|
socket_lm = new WebSocket(get_appropriate_ws_url(),
|
||||||
|
"lws-mirror-protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
socket_lm.onopen = function() {
|
||||||
|
document.getElementById("wslm_statustd").style.backgroundColor = "#40ff40";
|
||||||
|
document.getElementById("wslm_status").textContent = " websocket connection opened ";
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_lm.onmessage =function got_packet(msg) {
|
||||||
|
j = msg.data.split(';');
|
||||||
|
f = 0;
|
||||||
|
while (f < j.length - 1) {
|
||||||
|
i = j[f].split(' ');
|
||||||
|
if (i[0] == 'd') {
|
||||||
|
ctx.strokeStyle = i[1];
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(+(i[2]), +(i[3]));
|
||||||
|
ctx.lineTo(+(i[4]), +(i[5]));
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
if (i[0] == 'c') {
|
||||||
|
ctx.strokeStyle = i[1];
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(+(i[2]), +(i[3]), +(i[4]), 0, Math.PI*2, true);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
f++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_lm.onclose = function(){
|
||||||
|
document.getElementById("wslm_statustd").style.backgroundColor = "#ff4040";
|
||||||
|
document.getElementById("wslm_status").textContent = " websocket connection CLOSED ";
|
||||||
|
}
|
||||||
|
} catch(exception) {
|
||||||
|
alert('<p>Error' + exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.height = 300;
|
||||||
|
canvas.width = 480;
|
||||||
|
ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
document.getElementById('wslm_drawing').appendChild(canvas);
|
||||||
|
|
||||||
|
canvas.addEventListener('mousemove', ev_mousemove, false);
|
||||||
|
canvas.addEventListener('mousedown', ev_mousedown, false);
|
||||||
|
canvas.addEventListener('mouseup', ev_mouseup, false);
|
||||||
|
|
||||||
|
offsetX = offsetY = 0;
|
||||||
|
element = canvas;
|
||||||
|
if (element.offsetParent) {
|
||||||
|
do {
|
||||||
|
offsetX += element.offsetLeft;
|
||||||
|
offsetY += element.offsetTop;
|
||||||
|
} while ((element = element.offsetParent));
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_color() {
|
||||||
|
color = document.getElementById("color").value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ev_mousedown (ev) {
|
||||||
|
down = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ev_mouseup(ev) {
|
||||||
|
down = 0;
|
||||||
|
no_last = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ev_mousemove (ev) {
|
||||||
|
var x, y;
|
||||||
|
|
||||||
|
if (ev.offsetX) {
|
||||||
|
x = ev.offsetX;
|
||||||
|
y = ev.offsetY;
|
||||||
|
} else {
|
||||||
|
x = ev.layerX - offsetX;
|
||||||
|
y = ev.layerY - offsetY;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!down)
|
||||||
|
return;
|
||||||
|
if (no_last) {
|
||||||
|
no_last = 0;
|
||||||
|
last_x = x;
|
||||||
|
last_y = y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket_lm.send("d " + color + " " + last_x + " " + last_y + " " + x + ' ' + y + ';');
|
||||||
|
|
||||||
|
last_x = x;
|
||||||
|
last_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
#include <zlib.h>
|
#include "deps/zlib/zlib.h"
|
||||||
|
|
||||||
#define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1
|
#define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1
|
||||||
#define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION
|
#define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
#include <zlib.h>
|
#include "deps/zlib/zlib.h"
|
||||||
|
|
||||||
#define DEFLATE_STREAM_CHUNK 128
|
#define DEFLATE_STREAM_CHUNK 128
|
||||||
#define DEFLATE_STREAM_COMPRESSION_LEVEL 1
|
#define DEFLATE_STREAM_COMPRESSION_LEVEL 1
|
||||||
|
|
|
@ -19,8 +19,13 @@
|
||||||
* MA 02110-1301 USA
|
* MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "private-libwebsockets.h"
|
#include "private-libwebsockets.h"
|
||||||
|
|
||||||
|
#if HOST_OS == OS_WINDOWS
|
||||||
|
#pragma comment(lib, "Ws2_32.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
|
int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
|
||||||
static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
|
static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "private-libwebsockets.h"
|
#include "private-libwebsockets.h"
|
||||||
|
|
||||||
|
#include "build.h"
|
||||||
|
|
||||||
|
#if HOST_OS != OS_WINDOWS
|
||||||
/*
|
/*
|
||||||
* included from libwebsockets.c for unix builds
|
* included from libwebsockets.c for unix builds
|
||||||
*/
|
*/
|
||||||
|
@ -387,4 +390,5 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
|
||||||
{
|
{
|
||||||
return inet_ntop(af, src, dst, cnt);
|
return inet_ntop(af, src, dst, cnt);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
|
@ -19,11 +19,20 @@
|
||||||
* MA 02110-1301 USA
|
* MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "build.h"
|
||||||
|
|
||||||
|
/* The Libwebsocket version */
|
||||||
|
#define LWS_LIBRARY_VERSION "1.3"
|
||||||
|
|
||||||
|
/* The current git commit hash that we're building from */
|
||||||
|
#define LWS_BUILD_HASH "c11b847"
|
||||||
|
|
||||||
|
|
||||||
/* System introspection configs */
|
/* System introspection configs */
|
||||||
#ifdef CMAKE_BUILD
|
#ifdef CMAKE_BUILD
|
||||||
#include "lws_config.h"
|
#include "lws_config.h"
|
||||||
#else
|
#else
|
||||||
#if defined(WIN32) || defined(_WIN32)
|
#if HOST_OS == OS_WINDOWS
|
||||||
#define inline __inline
|
#define inline __inline
|
||||||
#else /* not WIN32 */
|
#else /* not WIN32 */
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "hw/maple/maple_cfg.h"
|
#include "hw/maple/maple_cfg.h"
|
||||||
#include "hw/sh4/sh4_mem.h"
|
#include "hw/sh4/sh4_mem.h"
|
||||||
|
|
||||||
|
#include "webui/server.h"
|
||||||
|
|
||||||
settings_t settings;
|
settings_t settings;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -41,7 +43,7 @@ int GetFile(char *szFileName, char *szParse=0,u32 flags=0)
|
||||||
if (strcmp(szFileName,"null")==0)
|
if (strcmp(szFileName,"null")==0)
|
||||||
{
|
{
|
||||||
#if defined(OMAP4)
|
#if defined(OMAP4)
|
||||||
strcpy(szFileName,GetPath("gdimage/crazy_taxi.chd").c_str());
|
strcpy(szFileName,GetPath("/gdimage/crazy_taxi.chd").c_str());
|
||||||
#else
|
#else
|
||||||
#if HOST_OS==OS_WINDOWS
|
#if HOST_OS==OS_WINDOWS
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
|
@ -64,7 +66,7 @@ int GetFile(char *szFileName, char *szParse=0,u32 flags=0)
|
||||||
//strcpy(szFileName,ofn.lpstrFile);
|
//strcpy(szFileName,ofn.lpstrFile);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
strcpy(szFileName,GetPath("discs/game.gdi").c_str());
|
strcpy(szFileName,GetPath("/discs/game.gdi").c_str());
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -127,6 +129,17 @@ void plugins_Reset(bool Manual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* webui_th(void* p)
|
||||||
|
{
|
||||||
|
#if HOST_OS == OS_WINDOWS
|
||||||
|
webui_start();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cThread webui_thd(&webui_th,0);
|
||||||
|
|
||||||
int dc_init(int argc,wchar* argv[])
|
int dc_init(int argc,wchar* argv[])
|
||||||
{
|
{
|
||||||
setbuf(stdin,0);
|
setbuf(stdin,0);
|
||||||
|
@ -138,6 +151,8 @@ int dc_init(int argc,wchar* argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
webui_thd.Start();
|
||||||
|
|
||||||
if(ParseCommandLine(argc,argv))
|
if(ParseCommandLine(argc,argv))
|
||||||
{
|
{
|
||||||
return 69;
|
return 69;
|
||||||
|
|
|
@ -0,0 +1,873 @@
|
||||||
|
/*
|
||||||
|
* libwebsockets-test-server - libwebsockets test implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2011 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
|
||||||
|
*/
|
||||||
|
#ifdef CMAKE_BUILD
|
||||||
|
#include "lws_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#ifdef EXTERNAL_POLL
|
||||||
|
#define poll WSAPoll
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "deps/libwebsocket/libwebsockets.h"
|
||||||
|
#include "oslib/oslib.h"
|
||||||
|
|
||||||
|
static int close_testing;
|
||||||
|
int max_poll_elements;
|
||||||
|
|
||||||
|
struct pollfd *pollfds;
|
||||||
|
int *fd_lookup;
|
||||||
|
int count_pollfds;
|
||||||
|
static volatile int force_exit = 0;
|
||||||
|
static struct libwebsocket_context *context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This demo server shows how to use libwebsockets for one or more
|
||||||
|
* websocket protocols in the same server
|
||||||
|
*
|
||||||
|
* It defines the following websocket protocols:
|
||||||
|
*
|
||||||
|
* dumb-increment-protocol: once the socket is opened, an incrementing
|
||||||
|
* ascii string is sent down it every 50ms.
|
||||||
|
* If you send "reset\n" on the websocket, then
|
||||||
|
* the incrementing number is reset to 0.
|
||||||
|
*
|
||||||
|
* lws-mirror-protocol: copies any received packet to every connection also
|
||||||
|
* using this protocol, including the sender
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum demo_protocols {
|
||||||
|
/* always first */
|
||||||
|
PROTOCOL_HTTP = 0,
|
||||||
|
|
||||||
|
PROTOCOL_DUMB_INCREMENT,
|
||||||
|
PROTOCOL_LWS_MIRROR,
|
||||||
|
|
||||||
|
/* always last */
|
||||||
|
DEMO_PROTOCOL_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WEBUI_PATH GetPath("/webui")
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We take a strict whitelist approach to stop ../ attacks
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct serveable {
|
||||||
|
const char *urlpath;
|
||||||
|
const char *mimetype;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct per_session_data__http {
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this is just an example of parsing handshake headers, you don't need this
|
||||||
|
* in your code unless you will filter allowing connections by the header
|
||||||
|
* content
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
dump_handshake_info(struct libwebsocket *wsi)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
static const char *token_names[] = {
|
||||||
|
/*[WSI_TOKEN_GET_URI] =*/ "GET URI",
|
||||||
|
/*[WSI_TOKEN_POST_URI] =*/ "POST URI",
|
||||||
|
/*[WSI_TOKEN_HOST] =*/ "Host",
|
||||||
|
/*[WSI_TOKEN_CONNECTION] =*/ "Connection",
|
||||||
|
/*[WSI_TOKEN_KEY1] =*/ "key 1",
|
||||||
|
/*[WSI_TOKEN_KEY2] =*/ "key 2",
|
||||||
|
/*[WSI_TOKEN_PROTOCOL] =*/ "Protocol",
|
||||||
|
/*[WSI_TOKEN_UPGRADE] =*/ "Upgrade",
|
||||||
|
/*[WSI_TOKEN_ORIGIN] =*/ "Origin",
|
||||||
|
/*[WSI_TOKEN_DRAFT] =*/ "Draft",
|
||||||
|
/*[WSI_TOKEN_CHALLENGE] =*/ "Challenge",
|
||||||
|
|
||||||
|
/* new for 04 */
|
||||||
|
/*[WSI_TOKEN_KEY] =*/ "Key",
|
||||||
|
/*[WSI_TOKEN_VERSION] =*/ "Version",
|
||||||
|
/*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin",
|
||||||
|
|
||||||
|
/* new for 05 */
|
||||||
|
/*[WSI_TOKEN_EXTENSIONS] =*/ "Extensions",
|
||||||
|
|
||||||
|
/* client receives these */
|
||||||
|
/*[WSI_TOKEN_ACCEPT] =*/ "Accept",
|
||||||
|
/*[WSI_TOKEN_NONCE] =*/ "Nonce",
|
||||||
|
/*[WSI_TOKEN_HTTP] =*/ "Http",
|
||||||
|
|
||||||
|
"Accept:",
|
||||||
|
"If-Modified-Since:",
|
||||||
|
"Accept-Encoding:",
|
||||||
|
"Accept-Language:",
|
||||||
|
"Pragma:",
|
||||||
|
"Cache-Control:",
|
||||||
|
"Authorization:",
|
||||||
|
"Cookie:",
|
||||||
|
"Content-Length:",
|
||||||
|
"Content-Type:",
|
||||||
|
"Date:",
|
||||||
|
"Range:",
|
||||||
|
"Referer:",
|
||||||
|
"Uri-Args:",
|
||||||
|
|
||||||
|
/*[WSI_TOKEN_MUXURL] =*/ "MuxURL",
|
||||||
|
};
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
for (n = 0; n < sizeof(token_names) / sizeof(token_names[0]); n++) {
|
||||||
|
if (!lws_hdr_total_length(wsi, (lws_token_indexes)n))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lws_hdr_copy(wsi, buf, sizeof buf, (lws_token_indexes)n);
|
||||||
|
|
||||||
|
fprintf(stderr, " %s = %s\n", token_names[n], buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * get_mimetype(const char *file)
|
||||||
|
{
|
||||||
|
int n = strlen(file);
|
||||||
|
|
||||||
|
if (n < 5)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!strcmp(&file[n - 4], ".ico"))
|
||||||
|
return "image/x-icon";
|
||||||
|
|
||||||
|
if (!strcmp(&file[n - 4], ".png"))
|
||||||
|
return "image/png";
|
||||||
|
|
||||||
|
if (!strcmp(&file[n - 5], ".html"))
|
||||||
|
return "text/html";
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this protocol server (always the first one) just knows how to do HTTP */
|
||||||
|
|
||||||
|
static int callback_http(struct libwebsocket_context *context,
|
||||||
|
struct libwebsocket *wsi,
|
||||||
|
enum libwebsocket_callback_reasons reason, void *user,
|
||||||
|
void *in, size_t len)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
char client_name[128];
|
||||||
|
char client_ip[128];
|
||||||
|
#endif
|
||||||
|
char buf[256];
|
||||||
|
char leaf_path[1024];
|
||||||
|
char b64[64];
|
||||||
|
struct timeval tv;
|
||||||
|
int n, m;
|
||||||
|
unsigned char *p;
|
||||||
|
char *other_headers = 0;
|
||||||
|
static unsigned char buffer[4096];
|
||||||
|
struct stat stat_buf;
|
||||||
|
struct per_session_data__http *pss =
|
||||||
|
(struct per_session_data__http *)user;
|
||||||
|
const char *mimetype;
|
||||||
|
#ifdef EXTERNAL_POLL
|
||||||
|
struct libwebsocket_pollargs *pa = (struct libwebsocket_pollargs *)in;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const string path = WEBUI_PATH;
|
||||||
|
|
||||||
|
const char* resource_path = path.c_str();
|
||||||
|
|
||||||
|
switch (reason) {
|
||||||
|
case LWS_CALLBACK_HTTP:
|
||||||
|
|
||||||
|
dump_handshake_info(wsi);
|
||||||
|
|
||||||
|
if (len < 1) {
|
||||||
|
libwebsockets_return_http_status(context, wsi,
|
||||||
|
HTTP_STATUS_BAD_REQUEST, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this server has no concept of directories */
|
||||||
|
if (strchr((const char *)in + 1, '/')) {
|
||||||
|
libwebsockets_return_http_status(context, wsi,
|
||||||
|
HTTP_STATUS_FORBIDDEN, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if a legal POST URL, let it continue and accept data */
|
||||||
|
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* check for the "send a big file by hand" example case */
|
||||||
|
|
||||||
|
if (!strcmp((const char *)in, "/leaf.jpg")) {
|
||||||
|
if (strlen(resource_path) > sizeof(leaf_path) - 10)
|
||||||
|
return -1;
|
||||||
|
sprintf(leaf_path, "%s/leaf.jpg", resource_path);
|
||||||
|
|
||||||
|
/* well, let's demonstrate how to send the hard way */
|
||||||
|
|
||||||
|
p = buffer;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
pss->fd = open(leaf_path, O_RDONLY | _O_BINARY);
|
||||||
|
#else
|
||||||
|
pss->fd = open(leaf_path, O_RDONLY);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pss->fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fstat(pss->fd, &stat_buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we will send a big jpeg file, but it could be
|
||||||
|
* anything. Set the Content-Type: appropriately
|
||||||
|
* so the browser knows what to do with it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
p += sprintf((char *)p,
|
||||||
|
"HTTP/1.0 200 OK\x0d\x0a"
|
||||||
|
"Server: libwebsockets\x0d\x0a"
|
||||||
|
"Content-Type: image/jpeg\x0d\x0a"
|
||||||
|
"Content-Length: %u\x0d\x0a\x0d\x0a",
|
||||||
|
(unsigned int)stat_buf.st_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send the http headers...
|
||||||
|
* this won't block since it's the first payload sent
|
||||||
|
* on the connection since it was established
|
||||||
|
* (too small for partial)
|
||||||
|
*/
|
||||||
|
|
||||||
|
n = libwebsocket_write(wsi, buffer,
|
||||||
|
p - buffer, LWS_WRITE_HTTP);
|
||||||
|
|
||||||
|
if (n < 0) {
|
||||||
|
close(pss->fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* book us a LWS_CALLBACK_HTTP_WRITEABLE callback
|
||||||
|
*/
|
||||||
|
libwebsocket_callback_on_writable(context, wsi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if not, send a file the easy way */
|
||||||
|
strcpy(buf, resource_path);
|
||||||
|
if (strcmp((const char*)in, "/")) {
|
||||||
|
if (*((const char *)in) != '/')
|
||||||
|
strcat(buf, "/");
|
||||||
|
strncat(buf, (const char*)in, sizeof(buf) - strlen(resource_path));
|
||||||
|
} else /* default file to serve */
|
||||||
|
strcat(buf, "/debugger.html");
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
|
||||||
|
/* refuse to serve files we don't understand */
|
||||||
|
mimetype = get_mimetype(buf);
|
||||||
|
if (!mimetype) {
|
||||||
|
lwsl_err("Unknown mimetype for %s\n", buf);
|
||||||
|
libwebsockets_return_http_status(context, wsi,
|
||||||
|
HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libwebsockets_serve_http_file(context, wsi, buf,
|
||||||
|
mimetype, other_headers))
|
||||||
|
return -1; /* through completion or error, close the socket */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* notice that the sending of the file completes asynchronously,
|
||||||
|
* we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
|
||||||
|
* it's done
|
||||||
|
*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_HTTP_BODY:
|
||||||
|
strncpy(buf, (const char*)in, 20);
|
||||||
|
buf[20] = '\0';
|
||||||
|
if (len < 20)
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
lwsl_notice("LWS_CALLBACK_HTTP_BODY: %s... len %d\n",
|
||||||
|
(const char *)buf, (int)len);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
||||||
|
lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
|
||||||
|
/* the whole of the sent body arried, close the connection */
|
||||||
|
libwebsockets_return_http_status(context, wsi,
|
||||||
|
HTTP_STATUS_OK, NULL);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
||||||
|
// lwsl_info("LWS_CALLBACK_HTTP_FILE_COMPLETION seen\n");
|
||||||
|
/* kill the connection after we sent one file */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||||
|
/*
|
||||||
|
* we can send more of whatever it is we were sending
|
||||||
|
*/
|
||||||
|
|
||||||
|
do {
|
||||||
|
n = read(pss->fd, buffer, sizeof buffer);
|
||||||
|
/* problem reading, close conn */
|
||||||
|
if (n < 0)
|
||||||
|
goto bail;
|
||||||
|
/* sent it all, close conn */
|
||||||
|
if (n == 0)
|
||||||
|
goto flush_bail;
|
||||||
|
/*
|
||||||
|
* because it's HTTP and not websocket, don't need to take
|
||||||
|
* care about pre and postamble
|
||||||
|
*/
|
||||||
|
m = libwebsocket_write(wsi, buffer, n, LWS_WRITE_HTTP);
|
||||||
|
if (m < 0)
|
||||||
|
/* write failed, close conn */
|
||||||
|
goto bail;
|
||||||
|
if (m != n)
|
||||||
|
/* partial write, adjust */
|
||||||
|
lseek(pss->fd, m - n, SEEK_CUR);
|
||||||
|
|
||||||
|
if (m) /* while still active, extend timeout */
|
||||||
|
libwebsocket_set_timeout(wsi,
|
||||||
|
PENDING_TIMEOUT_HTTP_CONTENT, 5);
|
||||||
|
|
||||||
|
} while (!lws_send_pipe_choked(wsi));
|
||||||
|
libwebsocket_callback_on_writable(context, wsi);
|
||||||
|
break;
|
||||||
|
flush_bail:
|
||||||
|
/* true if still partial pending */
|
||||||
|
if (lws_send_pipe_choked(wsi)) {
|
||||||
|
libwebsocket_callback_on_writable(context, wsi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bail:
|
||||||
|
close(pss->fd);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* callback for confirming to continue with client IP appear in
|
||||||
|
* protocol 0 callback since no websocket protocol has been agreed
|
||||||
|
* yet. You can just ignore this if you won't filter on client IP
|
||||||
|
* since the default uhandled callback return is 0 meaning let the
|
||||||
|
* connection continue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
|
||||||
|
#if 0
|
||||||
|
libwebsockets_get_peer_addresses(context, wsi, (int)(long)in, client_name,
|
||||||
|
sizeof(client_name), client_ip, sizeof(client_ip));
|
||||||
|
|
||||||
|
fprintf(stderr, "Received network connect from %s (%s)\n",
|
||||||
|
client_name, client_ip);
|
||||||
|
#endif
|
||||||
|
/* if we returned non-zero from here, we kill the connection */
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef EXTERNAL_POLL
|
||||||
|
/*
|
||||||
|
* callbacks for managing the external poll() array appear in
|
||||||
|
* protocol 0 callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
case LWS_CALLBACK_LOCK_POLL:
|
||||||
|
/*
|
||||||
|
* lock mutex to protect pollfd state
|
||||||
|
* called before any other POLL related callback
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_UNLOCK_POLL:
|
||||||
|
/*
|
||||||
|
* unlock mutex to protect pollfd state when
|
||||||
|
* called after any other POLL related callback
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_ADD_POLL_FD:
|
||||||
|
|
||||||
|
if (count_pollfds >= max_poll_elements) {
|
||||||
|
lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_lookup[pa->fd] = count_pollfds;
|
||||||
|
pollfds[count_pollfds].fd = pa->fd;
|
||||||
|
pollfds[count_pollfds].events = pa->events;
|
||||||
|
pollfds[count_pollfds++].revents = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_DEL_POLL_FD:
|
||||||
|
if (!--count_pollfds)
|
||||||
|
break;
|
||||||
|
m = fd_lookup[pa->fd];
|
||||||
|
/* have the last guy take up the vacant slot */
|
||||||
|
pollfds[m] = pollfds[count_pollfds];
|
||||||
|
fd_lookup[pollfds[count_pollfds].fd] = m;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
|
||||||
|
pollfds[fd_lookup[pa->fd]].events = pa->events;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case LWS_CALLBACK_GET_THREAD_ID:
|
||||||
|
/*
|
||||||
|
* if you will call "libwebsocket_callback_on_writable"
|
||||||
|
* from a different thread, return the caller thread ID
|
||||||
|
* here so lws can use this information to work out if it
|
||||||
|
* should signal the poll() loop to exit and restart early
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* return pthread_getthreadid_np(); */
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* dumb_increment protocol */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* one of these is auto-created for each connection and a pointer to the
|
||||||
|
* appropriate instance is passed to the callback in the user parameter
|
||||||
|
*
|
||||||
|
* for this example protocol we use it to individualize the count for each
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct per_session_data__dumb_increment {
|
||||||
|
int number;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
callback_dumb_increment(struct libwebsocket_context *context,
|
||||||
|
struct libwebsocket *wsi,
|
||||||
|
enum libwebsocket_callback_reasons reason,
|
||||||
|
void *user, void *in, size_t len)
|
||||||
|
{
|
||||||
|
int n, m;
|
||||||
|
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
|
||||||
|
LWS_SEND_BUFFER_POST_PADDING];
|
||||||
|
unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
|
||||||
|
struct per_session_data__dumb_increment *pss = (struct per_session_data__dumb_increment *)user;
|
||||||
|
|
||||||
|
switch (reason) {
|
||||||
|
|
||||||
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
|
lwsl_info("callback_dumb_increment: "
|
||||||
|
"LWS_CALLBACK_ESTABLISHED\n");
|
||||||
|
pss->number = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||||
|
n = sprintf((char *)p, "%d", pss->number++);
|
||||||
|
m = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
|
||||||
|
if (m < n) {
|
||||||
|
lwsl_err("ERROR %d writing to di socket\n", n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (close_testing && pss->number == 50) {
|
||||||
|
lwsl_info("close tesing limit, closing\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_RECEIVE:
|
||||||
|
// fprintf(stderr, "rx %d\n", (int)len);
|
||||||
|
if (len < 6)
|
||||||
|
break;
|
||||||
|
if (strcmp((const char *)in, "reset\n") == 0)
|
||||||
|
pss->number = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* lws-mirror_protocol */
|
||||||
|
|
||||||
|
#define MAX_MESSAGE_QUEUE 32
|
||||||
|
|
||||||
|
struct per_session_data__lws_mirror {
|
||||||
|
struct libwebsocket *wsi;
|
||||||
|
int ringbuffer_tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct a_message {
|
||||||
|
void *payload;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
|
||||||
|
static int ringbuffer_head;
|
||||||
|
|
||||||
|
static int
|
||||||
|
callback_lws_mirror(struct libwebsocket_context *context,
|
||||||
|
struct libwebsocket *wsi,
|
||||||
|
enum libwebsocket_callback_reasons reason,
|
||||||
|
void *user, void *in, size_t len)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct per_session_data__lws_mirror *pss = (struct per_session_data__lws_mirror *)user;
|
||||||
|
|
||||||
|
switch (reason) {
|
||||||
|
|
||||||
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
|
lwsl_info("callback_lws_mirror: LWS_CALLBACK_ESTABLISHED\n");
|
||||||
|
pss->ringbuffer_tail = ringbuffer_head;
|
||||||
|
pss->wsi = wsi;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||||
|
lwsl_notice("mirror protocol cleaning up\n");
|
||||||
|
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) {
|
||||||
|
|
||||||
|
n = libwebsocket_write(wsi, (unsigned char *)
|
||||||
|
ringbuffer[pss->ringbuffer_tail].payload +
|
||||||
|
LWS_SEND_BUFFER_PRE_PADDING,
|
||||||
|
ringbuffer[pss->ringbuffer_tail].len,
|
||||||
|
LWS_WRITE_TEXT);
|
||||||
|
if (n < 0) {
|
||||||
|
lwsl_err("ERROR %d writing to mirror socket\n", n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (n < ringbuffer[pss->ringbuffer_tail].len)
|
||||||
|
lwsl_err("mirror partial write %d vs %d\n",
|
||||||
|
n, ringbuffer[pss->ringbuffer_tail].len);
|
||||||
|
|
||||||
|
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))
|
||||||
|
libwebsocket_rx_flow_allow_all_protocol(
|
||||||
|
libwebsockets_get_protocol(wsi));
|
||||||
|
|
||||||
|
// lwsl_debug("tx fifo %d\n", (ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1));
|
||||||
|
|
||||||
|
if (lws_send_pipe_choked(wsi)) {
|
||||||
|
libwebsocket_callback_on_writable(context, wsi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* for tests with chrome on same machine as client and
|
||||||
|
* server, this is needed to stop chrome choking
|
||||||
|
*/
|
||||||
|
#ifdef _WIN32
|
||||||
|
Sleep(1);
|
||||||
|
#else
|
||||||
|
usleep(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
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_SEND_BUFFER_PRE_PADDING + len +
|
||||||
|
LWS_SEND_BUFFER_POST_PADDING);
|
||||||
|
ringbuffer[ringbuffer_head].len = len;
|
||||||
|
memcpy((char *)ringbuffer[ringbuffer_head].payload +
|
||||||
|
LWS_SEND_BUFFER_PRE_PADDING, 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);
|
||||||
|
libwebsocket_rx_flow_control(wsi, 0);
|
||||||
|
|
||||||
|
// lwsl_debug("rx fifo %d\n", (ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1));
|
||||||
|
done:
|
||||||
|
libwebsocket_callback_on_writable_all_protocol(
|
||||||
|
libwebsockets_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* list of supported protocols and callbacks */
|
||||||
|
|
||||||
|
static struct libwebsocket_protocols protocols[] = {
|
||||||
|
/* first protocol must always be HTTP handler */
|
||||||
|
|
||||||
|
{
|
||||||
|
"http-only", /* name */
|
||||||
|
callback_http, /* callback */
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{ NULL, NULL, 0, 0 } /* terminator */
|
||||||
|
};
|
||||||
|
|
||||||
|
void sighandler(int sig)
|
||||||
|
{
|
||||||
|
force_exit = 1;
|
||||||
|
libwebsocket_cancel_service(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void webui_start()
|
||||||
|
{
|
||||||
|
char cert_path[1024];
|
||||||
|
char key_path[1024];
|
||||||
|
int n = 0;
|
||||||
|
int use_ssl = 0;
|
||||||
|
int opts = 0;
|
||||||
|
char interface_name[128] = "";
|
||||||
|
const char *iface = NULL;
|
||||||
|
#ifndef WIN32
|
||||||
|
int syslog_options = LOG_PID | LOG_PERROR;
|
||||||
|
#endif
|
||||||
|
struct lws_context_creation_info info;
|
||||||
|
|
||||||
|
int debug_level = 7;
|
||||||
|
#ifndef LWS_NO_DAEMONIZE
|
||||||
|
int daemonize = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof info);
|
||||||
|
info.port = 5678;
|
||||||
|
|
||||||
|
const string path = WEBUI_PATH;
|
||||||
|
|
||||||
|
const char* resource_path = path.c_str();
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
/* we will only try to log things according to our debug_level */
|
||||||
|
setlogmask(LOG_UPTO (LOG_DEBUG));
|
||||||
|
openlog("lwsts", syslog_options, LOG_DAEMON);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* tell the library what debug level to emit and to send it to syslog */
|
||||||
|
lws_set_log_level(debug_level, lwsl_emit_syslog);
|
||||||
|
|
||||||
|
lwsl_notice("libwebsockets test server - "
|
||||||
|
"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> - "
|
||||||
|
"licensed under LGPL2.1\n");
|
||||||
|
#ifdef EXTERNAL_POLL
|
||||||
|
max_poll_elements = getdtablesize();
|
||||||
|
pollfds = malloc(max_poll_elements * sizeof (struct pollfd));
|
||||||
|
fd_lookup = malloc(max_poll_elements * sizeof (int));
|
||||||
|
if (pollfds == NULL || fd_lookup == NULL) {
|
||||||
|
lwsl_err("Out of memory pollfds=%d\n", max_poll_elements);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
info.iface = iface;
|
||||||
|
info.protocols = protocols;
|
||||||
|
#ifndef LWS_NO_EXTENSIONS
|
||||||
|
info.extensions = libwebsocket_get_internal_extensions();
|
||||||
|
#endif
|
||||||
|
if (!use_ssl) {
|
||||||
|
info.ssl_cert_filepath = NULL;
|
||||||
|
info.ssl_private_key_filepath = NULL;
|
||||||
|
} else {
|
||||||
|
if (strlen(resource_path) > sizeof(cert_path) - 32) {
|
||||||
|
lwsl_err("resource path too long\n");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
sprintf(cert_path, "%s/libwebsockets-test-server.pem",
|
||||||
|
resource_path);
|
||||||
|
if (strlen(resource_path) > sizeof(key_path) - 32) {
|
||||||
|
lwsl_err("resource path too long\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sprintf(key_path, "%s/libwebsockets-test-server.key.pem",
|
||||||
|
resource_path);
|
||||||
|
|
||||||
|
info.ssl_cert_filepath = cert_path;
|
||||||
|
info.ssl_private_key_filepath = key_path;
|
||||||
|
}
|
||||||
|
info.gid = -1;
|
||||||
|
info.uid = -1;
|
||||||
|
info.options = opts;
|
||||||
|
|
||||||
|
context = libwebsocket_create_context(&info);
|
||||||
|
if (context == NULL) {
|
||||||
|
lwsl_err("libwebsocket init failed\n");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
double old_time = 0;
|
||||||
|
|
||||||
|
while (n >= 0 && !force_exit) {
|
||||||
|
|
||||||
|
double time = os_GetSeconds();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This provokes the LWS_CALLBACK_SERVER_WRITEABLE for every
|
||||||
|
* live websocket connection using the DUMB_INCREMENT protocol,
|
||||||
|
* as soon as it can take more packets (usually immediately)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((time - old_time ) > 0.050) {
|
||||||
|
libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_DUMB_INCREMENT]);
|
||||||
|
old_time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EXTERNAL_POLL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this represents an existing server's single poll action
|
||||||
|
* which also includes libwebsocket sockets
|
||||||
|
*/
|
||||||
|
|
||||||
|
n = poll(pollfds, count_pollfds, 50);
|
||||||
|
if (n < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
if (n)
|
||||||
|
for (n = 0; n < count_pollfds; n++)
|
||||||
|
if (pollfds[n].revents)
|
||||||
|
/*
|
||||||
|
* returns immediately if the fd does not
|
||||||
|
* match anything under libwebsockets
|
||||||
|
* control
|
||||||
|
*/
|
||||||
|
if (libwebsocket_service_fd(context,
|
||||||
|
&pollfds[n]) < 0)
|
||||||
|
goto done;
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* If libwebsockets sockets are all we care about,
|
||||||
|
* you can use this api which takes care of the poll()
|
||||||
|
* and looping through finding who needed service.
|
||||||
|
*
|
||||||
|
* If no socket needs service, it'll return anyway after
|
||||||
|
* the number of ms in the second argument.
|
||||||
|
*/
|
||||||
|
|
||||||
|
n = libwebsocket_service(context, 50);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EXTERNAL_POLL
|
||||||
|
done:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
libwebsocket_context_destroy(context);
|
||||||
|
|
||||||
|
lwsl_notice("libwebsockets-test-server exited cleanly\n");
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
closelog();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
void webui_start();
|
|
@ -43,6 +43,7 @@
|
||||||
<ClCompile Include="..\core\deps\libwebsocket\extension-deflate-frame.c" />
|
<ClCompile Include="..\core\deps\libwebsocket\extension-deflate-frame.c" />
|
||||||
<ClCompile Include="..\core\deps\libwebsocket\extension-deflate-stream.c" />
|
<ClCompile Include="..\core\deps\libwebsocket\extension-deflate-stream.c" />
|
||||||
<ClCompile Include="..\core\deps\libwebsocket\extension.c" />
|
<ClCompile Include="..\core\deps\libwebsocket\extension.c" />
|
||||||
|
<ClCompile Include="..\core\deps\libwebsocket\handshake.c" />
|
||||||
<ClCompile Include="..\core\deps\libwebsocket\libwebsockets.c" />
|
<ClCompile Include="..\core\deps\libwebsocket\libwebsockets.c" />
|
||||||
<ClCompile Include="..\core\deps\libwebsocket\lws-plat-unix.c" />
|
<ClCompile Include="..\core\deps\libwebsocket\lws-plat-unix.c" />
|
||||||
<ClCompile Include="..\core\deps\libwebsocket\lws-plat-win.c" />
|
<ClCompile Include="..\core\deps\libwebsocket\lws-plat-win.c" />
|
||||||
|
@ -147,6 +148,7 @@
|
||||||
<ClCompile Include="..\core\rend\gles\gltex.cpp" />
|
<ClCompile Include="..\core\rend\gles\gltex.cpp" />
|
||||||
<ClCompile Include="..\core\rend\TexCache.cpp" />
|
<ClCompile Include="..\core\rend\TexCache.cpp" />
|
||||||
<ClCompile Include="..\core\stdclass.cpp" />
|
<ClCompile Include="..\core\stdclass.cpp" />
|
||||||
|
<ClCompile Include="..\core\webui\server.cpp" />
|
||||||
<ClCompile Include="..\core\windows\win86_driver.cpp" />
|
<ClCompile Include="..\core\windows\win86_driver.cpp" />
|
||||||
<ClCompile Include="..\core\windows\win86_il.cpp" />
|
<ClCompile Include="..\core\windows\win86_il.cpp" />
|
||||||
<ClCompile Include="..\core\windows\win86_ngen.cpp" />
|
<ClCompile Include="..\core\windows\win86_ngen.cpp" />
|
||||||
|
@ -271,6 +273,7 @@
|
||||||
<ClInclude Include="..\core\rend\TexCache.h" />
|
<ClInclude Include="..\core\rend\TexCache.h" />
|
||||||
<ClInclude Include="..\core\stdclass.h" />
|
<ClInclude Include="..\core\stdclass.h" />
|
||||||
<ClInclude Include="..\core\types.h" />
|
<ClInclude Include="..\core\types.h" />
|
||||||
|
<ClInclude Include="..\core\webui\server.h" />
|
||||||
<ClInclude Include="..\core\windows\win86_ngen.h" />
|
<ClInclude Include="..\core\windows\win86_ngen.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -390,6 +390,12 @@
|
||||||
<ClCompile Include="..\core\deps\libwebsocket\sha-1.c">
|
<ClCompile Include="..\core\deps\libwebsocket\sha-1.c">
|
||||||
<Filter>deps\libwebsocket</Filter>
|
<Filter>deps\libwebsocket</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\core\deps\libwebsocket\handshake.c">
|
||||||
|
<Filter>deps\libwebsocket</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\core\webui\server.cpp">
|
||||||
|
<Filter>webui</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="hw">
|
<Filter Include="hw">
|
||||||
|
@ -503,6 +509,9 @@
|
||||||
<Filter Include="deps\libwebsocket">
|
<Filter Include="deps\libwebsocket">
|
||||||
<UniqueIdentifier>{3d3de3ff-9e79-4920-a95a-61d190e73004}</UniqueIdentifier>
|
<UniqueIdentifier>{3d3de3ff-9e79-4920-a95a-61d190e73004}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="webui">
|
||||||
|
<UniqueIdentifier>{81193efc-656a-4154-9adf-146856d4c7d3}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\core\hw\aica\aica.h">
|
<ClInclude Include="..\core\hw\aica\aica.h">
|
||||||
|
@ -847,6 +856,9 @@
|
||||||
<ClInclude Include="..\core\deps\libwebsocket\private-libwebsockets.h">
|
<ClInclude Include="..\core\deps\libwebsocket\private-libwebsockets.h">
|
||||||
<Filter>deps\libwebsocket</Filter>
|
<Filter>deps\libwebsocket</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\core\webui\server.h">
|
||||||
|
<Filter>webui</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\core\deps\zlib\Makefile">
|
<None Include="..\core\deps\zlib\Makefile">
|
||||||
|
|
Loading…
Reference in New Issue