some stuff
parent
c9f97b3285
commit
afae75e41f
@ -0,0 +1,93 @@
|
||||
var stderrBuffer = ""
|
||||
var messageBuffer = []
|
||||
var initialized = false;
|
||||
var flushing = false;
|
||||
|
||||
var headerMode = true;
|
||||
var header="";
|
||||
var re = /Content-Length: (\d+)\r\n/i;
|
||||
var contentLength = 0;
|
||||
var content = []
|
||||
var utf8decoder = new TextDecoder();
|
||||
|
||||
|
||||
function flushMessageBuffer(){
|
||||
if (initialized && !flushing) {
|
||||
while(messageBuffer.length > 0) {
|
||||
flushing = true;
|
||||
var msg = messageBuffer.shift();
|
||||
console.log(`Send message: ${msg}`);
|
||||
Module.ccall('send_message', 'void', ['string'], [msg]);
|
||||
console.log(`Message done: ${msg}`);
|
||||
}
|
||||
flushing = false;
|
||||
}
|
||||
}
|
||||
|
||||
var Module = {
|
||||
"arguments": ["--worker"],
|
||||
"preRun": [function() {
|
||||
function stdin() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function stdout(asciiCode) {
|
||||
if (headerMode) {
|
||||
header += String.fromCharCode(asciiCode)
|
||||
if (header.endsWith('\r\n\r\n')) {
|
||||
const found = header.match(re)
|
||||
if (found == null) { console.error(`Invalid header: ${header}`) }
|
||||
contentLength = parseInt(found[1])
|
||||
content = []
|
||||
headerMode = false
|
||||
}
|
||||
} else {
|
||||
content.push(asciiCode)
|
||||
if (content.length == contentLength) {
|
||||
const message = utf8decoder.decode(new Uint8Array(content))
|
||||
console.log(`Server: ${message}`)
|
||||
postMessage(message);
|
||||
headerMode = true
|
||||
header = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stderr(asciiCode) {
|
||||
stderrBuffer += String.fromCharCode(asciiCode)
|
||||
}
|
||||
|
||||
FS.init(stdin, stdout, stderr);
|
||||
}],
|
||||
"noInitialRun": true,
|
||||
"onRuntimeInitialized": () => {
|
||||
Module.ccall('main', 'void', [], []);
|
||||
initialized = true;
|
||||
if (stderrBuffer !== "") {
|
||||
console.log(stderrBuffer);
|
||||
stderrBuffer = ""
|
||||
}
|
||||
flushMessageBuffer();
|
||||
}
|
||||
};
|
||||
|
||||
importScripts("server.js")
|
||||
|
||||
|
||||
|
||||
onmessage = (ev) => {
|
||||
console.log(`Client: ${ev.data}`)
|
||||
messageBuffer.push(ev.data);
|
||||
flushMessageBuffer();
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
if (stderrBuffer !== "") {
|
||||
console.log(stderrBuffer);
|
||||
stderrBuffer = ""
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
setTimeout(() =>{
|
||||
|
||||
},2000)
|
||||
@ -0,0 +1,339 @@
|
||||
import { DataCallback, AbstractMessageReader, MessageReader } from 'vscode-jsonrpc/lib/common/messageReader.js';
|
||||
|
||||
import { Message } from 'vscode-jsonrpc/lib/common/messages.js';
|
||||
import { AbstractMessageWriter, MessageWriter } from 'vscode-jsonrpc/lib/common/messageWriter.js';
|
||||
import { Emitter } from 'vscode-jsonrpc/lib/common/events.js';
|
||||
import { Disposable, IWebSocket } from 'vscode-ws-jsonrpc/.';
|
||||
|
||||
declare var IO: any;
|
||||
|
||||
export class WasmWriter implements MessageWriter {
|
||||
protected errorCount = 0;
|
||||
errorEmitter
|
||||
closeEmitter
|
||||
constructor(private worker: Worker) {
|
||||
this.errorEmitter = new Emitter()
|
||||
this.closeEmitter = new Emitter()
|
||||
}
|
||||
dispose() {
|
||||
this.errorEmitter.dispose();
|
||||
this.closeEmitter.dispose();
|
||||
}
|
||||
get onError() {
|
||||
return this.errorEmitter.event;
|
||||
}
|
||||
fireError(error, message, count) {
|
||||
this.errorEmitter.fire([this.asError(error), message, count]);
|
||||
}
|
||||
get onClose() {
|
||||
return this.closeEmitter.event;
|
||||
}
|
||||
fireClose() {
|
||||
this.closeEmitter.fire(undefined);
|
||||
}
|
||||
asError(error) {
|
||||
if (error instanceof Error) {
|
||||
return error;
|
||||
}
|
||||
else {
|
||||
return new Error(`Writer received error. Reason: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
end(): void {
|
||||
}
|
||||
|
||||
async write(msg: Message): Promise<void> {
|
||||
try {
|
||||
const content = JSON.stringify(msg);
|
||||
this.worker.postMessage(content)
|
||||
} catch (e) {
|
||||
this.errorCount++;
|
||||
this.fireError(e, msg, this.errorCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class WasmReader implements MessageReader {
|
||||
protected state: 'initial' | 'listening' | 'closed' = 'initial';
|
||||
protected callback: DataCallback | undefined;
|
||||
protected readonly events: { message?: any, error?: any }[] = [];
|
||||
|
||||
constructor(private worker: Worker) {
|
||||
this.worker.onmessage = (ev) => {
|
||||
this.readMessage(ev.data)
|
||||
}
|
||||
// this.socket.onMessage(message =>
|
||||
// this.readMessage(message)
|
||||
// );
|
||||
// this.socket.onError(error =>
|
||||
// this.fireError(error)
|
||||
// );
|
||||
// this.socket.onClose((code, reason) => {
|
||||
// if (code !== 1000) {
|
||||
// const error: Error = {
|
||||
// name: '' + code,
|
||||
// message: `Error during socket reconnect: code = ${code}, reason = ${reason}`
|
||||
// };
|
||||
// this.fireError(error);
|
||||
// }
|
||||
// this.fireClose();
|
||||
// });
|
||||
this.errorEmitter = new Emitter()
|
||||
this.closeEmitter = new Emitter()
|
||||
this.partialMessageEmitter = new Emitter()
|
||||
}
|
||||
|
||||
protected errorCount = 0;
|
||||
errorEmitter
|
||||
closeEmitter
|
||||
partialMessageEmitter
|
||||
|
||||
dispose() {
|
||||
this.errorEmitter.dispose();
|
||||
this.closeEmitter.dispose();
|
||||
}
|
||||
get onError() {
|
||||
return this.errorEmitter.event;
|
||||
}
|
||||
get onClose() {
|
||||
return this.closeEmitter.event;
|
||||
}
|
||||
get onPartialMessage() {
|
||||
return this.partialMessageEmitter.event;
|
||||
}
|
||||
firePartialMessage(info) {
|
||||
this.partialMessageEmitter.fire(info);
|
||||
}
|
||||
asError(error) {
|
||||
if (error instanceof Error) {
|
||||
return error;
|
||||
}
|
||||
else {
|
||||
return new Error(`Reader received error. Reason: ${error.message ? error.message : 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
listen(callback: DataCallback): Disposable {
|
||||
if (this.state === 'initial') {
|
||||
this.state = 'listening';
|
||||
this.callback = callback;
|
||||
while (this.events.length !== 0) {
|
||||
const event = this.events.pop()!;
|
||||
if (event.message) {
|
||||
this.readMessage(event.message);
|
||||
} else if (event.error) {
|
||||
this.fireError(event.error);
|
||||
} else {
|
||||
this.fireClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
dispose: () => {
|
||||
if (this.callback === callback) {
|
||||
this.callback = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected readMessage(message: any): void {
|
||||
if (this.state === 'initial') {
|
||||
this.events.splice(0, 0, { message });
|
||||
} else if (this.state === 'listening') {
|
||||
try {
|
||||
const data = JSON.parse(message);
|
||||
this.callback!(data);
|
||||
} catch (err) {
|
||||
const error: Error = {
|
||||
name: '' + 400,
|
||||
message: `Error during message parsing, reason = ${typeof err === 'object' ? (err as any).message : 'unknown'}`
|
||||
};
|
||||
this.fireError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fireError(error: any): void {
|
||||
if (this.state === 'initial') {
|
||||
this.events.splice(0, 0, { error });
|
||||
} else if (this.state === 'listening') {
|
||||
|
||||
this.errorEmitter.fire(this.asError(error));
|
||||
}
|
||||
}
|
||||
|
||||
protected fireClose(): void {
|
||||
if (this.state === 'initial') {
|
||||
this.events.splice(0, 0, {});
|
||||
} else if (this.state === 'listening') {
|
||||
this.closeEmitter.fire(undefined);
|
||||
}
|
||||
this.state = 'closed';
|
||||
}
|
||||
}
|
||||
export class WebSocketMessageWriter implements MessageWriter {
|
||||
protected errorCount = 0;
|
||||
errorEmitter
|
||||
closeEmitter
|
||||
|
||||
constructor(protected readonly socket: IWebSocket) {
|
||||
this.errorEmitter = new Emitter();
|
||||
this.closeEmitter = new Emitter();
|
||||
}
|
||||
dispose() {
|
||||
this.errorEmitter.dispose();
|
||||
this.closeEmitter.dispose();
|
||||
}
|
||||
get onError() {
|
||||
return this.errorEmitter.event;
|
||||
}
|
||||
fireError(error, message, count) {
|
||||
this.errorEmitter.fire([this.asError(error), message, count]);
|
||||
}
|
||||
get onClose() {
|
||||
return this.closeEmitter.event;
|
||||
}
|
||||
fireClose() {
|
||||
this.closeEmitter.fire(undefined);
|
||||
}
|
||||
asError(error) {
|
||||
if (error instanceof Error) {
|
||||
return error;
|
||||
}
|
||||
else {
|
||||
return new Error(`Writer received error. Reason: ${(error.message) ? error.message : 'unknown'}`);
|
||||
}
|
||||
}
|
||||
end(): void {
|
||||
}
|
||||
|
||||
async write(msg: Message): Promise<void> {
|
||||
console.log("WRITE",msg)
|
||||
try {
|
||||
const content = JSON.stringify(msg);
|
||||
this.socket.send(content);
|
||||
} catch (e) {
|
||||
this.errorCount++;
|
||||
this.fireError(e, msg, this.errorCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class WebSocketMessageReader implements MessageReader {
|
||||
protected state: 'initial' | 'listening' | 'closed' = 'initial';
|
||||
protected callback: DataCallback | undefined;
|
||||
protected readonly events: { message?: any, error?: any }[] = [];
|
||||
errorEmitter
|
||||
closeEmitter
|
||||
partialMessageEmitter
|
||||
|
||||
constructor(protected readonly socket: IWebSocket) {
|
||||
this.errorEmitter = new Emitter();
|
||||
this.closeEmitter = new Emitter();
|
||||
this.partialMessageEmitter = new Emitter();
|
||||
this.socket.onMessage(message =>{
|
||||
console.log("READ", message)
|
||||
this.readMessage(message)
|
||||
});
|
||||
this.socket.onError(error =>
|
||||
this.fireError(error)
|
||||
);
|
||||
this.socket.onClose((code, reason) => {
|
||||
if (code !== 1000) {
|
||||
const error: Error = {
|
||||
name: '' + code,
|
||||
message: `Error during socket reconnect: code = ${code}, reason = ${reason}`
|
||||
};
|
||||
this.fireError(error);
|
||||
}
|
||||
this.fireClose();
|
||||
});
|
||||
}
|
||||
dispose() {
|
||||
this.errorEmitter.dispose();
|
||||
this.closeEmitter.dispose();
|
||||
}
|
||||
get onError() {
|
||||
return this.errorEmitter.event;
|
||||
}
|
||||
get onClose() {
|
||||
return this.closeEmitter.event;
|
||||
}
|
||||
get onPartialMessage() {
|
||||
return this.partialMessageEmitter.event;
|
||||
}
|
||||
firePartialMessage(info) {
|
||||
this.partialMessageEmitter.fire(info);
|
||||
}
|
||||
asError(error) {
|
||||
if (error instanceof Error) {
|
||||
return error;
|
||||
}
|
||||
else {
|
||||
return new Error(`Reader received error. Reason: ${(error.message) ? error.message : 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
listen(callback: DataCallback): Disposable {
|
||||
if (this.state === 'initial') {
|
||||
this.state = 'listening';
|
||||
this.callback = callback;
|
||||
while (this.events.length !== 0) {
|
||||
const event = this.events.pop()!;
|
||||
if (event.message) {
|
||||
this.readMessage(event.message);
|
||||
} else if (event.error) {
|
||||
this.fireError(event.error);
|
||||
} else {
|
||||
this.fireClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
dispose: () => {
|
||||
if (this.callback === callback) {
|
||||
this.callback = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected readMessage(message: any): void {
|
||||
if (this.state === 'initial') {
|
||||
this.events.splice(0, 0, { message });
|
||||
} else if (this.state === 'listening') {
|
||||
try {
|
||||
const data = JSON.parse(message);
|
||||
this.callback!(data);
|
||||
} catch (err) {
|
||||
const error: Error = {
|
||||
name: '' + 400,
|
||||
message: `Error during message parsing, reason = ${typeof err === 'object' ? (err as any).message : 'unknown'}`
|
||||
};
|
||||
this.fireError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fireError(error: any): void {
|
||||
if (this.state === 'initial') {
|
||||
this.events.splice(0, 0, { error });
|
||||
} else if (this.state === 'listening') {
|
||||
this.errorEmitter.fire(this.asError(error));
|
||||
}
|
||||
}
|
||||
|
||||
protected fireClose(): void {
|
||||
if (this.state === 'initial') {
|
||||
this.events.splice(0, 0, {});
|
||||
} else if (this.state === 'listening') {
|
||||
this.closeEmitter.fire(undefined);
|
||||
}
|
||||
this.state = 'closed';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd server
|
||||
|
||||
mkdir -p .lake/toolchains
|
||||
if [ ! -f .lake/toolchains/lean-4.3.0-rc2-linux_wasm32.tar.zst ]
|
||||
then
|
||||
wget -P .lake/toolchains https://github.com/leanprover/lean4/releases/download/v4.3.0-rc2/lean-4.3.0-rc2-linux_wasm32.tar.zst
|
||||
tar --use-compress-program=unzstd -xvf .lake/toolchains/lean-4.3.0-rc2-linux_wasm32.tar.zst -C .lake/toolchains
|
||||
fi
|
||||
if [ ! -f .lake/toolchains/lean-4.3.0-rc2-linux_x86.tar.zst ]
|
||||
then
|
||||
wget -P .lake/toolchains https://github.com/leanprover/lean4/releases/download/v4.3.0-rc2/lean-4.3.0-rc2-linux_x86.tar.zst
|
||||
tar --use-compress-program=unzstd -xvf .lake/toolchains/lean-4.3.0-rc2-linux_x86.tar.zst -C .lake/toolchains
|
||||
fi
|
||||
|
||||
# Linking will fail, but that's ok. We only need the c files.
|
||||
.lake/toolchains/lean-4.3.0-rc2-linux_x86/bin/lake build -f=lakefile32.lean
|
||||
|
||||
|
||||
lake build
|
||||
|
||||
|
||||
OUT_DIR=../client/public
|
||||
LEAN_SYSROOT=.lake/toolchains/lean-4.3.0-rc2-linux_wasm32
|
||||
LEAN_LIBDIR=$LEAN_SYSROOT/lib/lean
|
||||
|
||||
emcc -o $OUT_DIR/server.js main.c -I $LEAN_SYSROOT/include -L $LEAN_LIBDIR .lake/build/ir/GameServer/*.c -lInit -lLean -lleancpp -lleanrt \
|
||||
-sFORCE_FILESYSTEM -lnodefs.js -s EXIT_RUNTIME=0 -s MAIN_MODULE=1 -s LINKABLE=1 -s EXPORT_ALL=1 -s ALLOW_MEMORY_GROWTH=1 -fwasm-exceptions -pthread -flto \
|
||||
-sPTHREAD_POOL_SIZE_STRICT=2 \
|
||||
--preload-file "${LEAN_SYSROOT}/lib/lean/Init"@/lib/Init \
|
||||
--preload-file "${LEAN_SYSROOT}/lib/lean/Init.olean"@/lib/Init.olean \
|
||||
--preload-file "${LEAN_SYSROOT}/lib/lean/Init.ilean"@/lib/Init.ilean \
|
||||
--preload-file "${LEAN_SYSROOT}/lib/lean/Lean"@/lib/Lean \
|
||||
--preload-file "${LEAN_SYSROOT}/lib/lean/Lean.olean"@/lib/Lean.olean \
|
||||
--preload-file "${LEAN_SYSROOT}/lib/lean/Lean.ilean"@/lib/Lean.ilean \
|
||||
--preload-file "./.lake/build32/lib"@/gamelib
|
||||
Loading…
Reference in New Issue