mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-08-28 17:01:04 +00:00
13759b1db6
- reduce ASAR IO overhead with streamed archive reads, buffered copies, faster relative-path handling and placeholder integrity records - fix in-place app.asar.unpacked packing/extraction self-copy cases that caused locked-file failures - tighten JS patch discovery with candidate bundle filters and search hints - require prebuilt remote-panel dist artifacts and clean up embedded bridge/script packaging - add unified build entrypoints for PowerShell, cmd and bash and move native CMake output under .tmp - add release metadata validation, changelog section extraction, pre-commit hook and GitHub Actions validation/release pipelines - make CHANGELOG the source of truth for release notes and document the tag-driven release flow - add updater release notes UI with latest/full changelog loading and localize the new update strings - modularize bridge renderer scripts, add installed apps and game status sync, and support remote launch/stop commands - centralize bridge protocol, IPC and WebSocket constants and improve LAN IP selection for QR pairing - refactor remote panel controls/state enums, persist accent color, polish library/session UI and refresh assets
140 lines
3.4 KiB
JavaScript
140 lines
3.4 KiB
JavaScript
const crypto = require('node:crypto');
|
|
|
|
const { BRIDGE_PROTOCOL_VERSION, WS_OPCODE } = require('./constants.cjs');
|
|
|
|
const WS_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
|
|
|
|
function jsonMessage(type, payload, requestId = null) {
|
|
return JSON.stringify({
|
|
type,
|
|
version: BRIDGE_PROTOCOL_VERSION,
|
|
requestId,
|
|
payload,
|
|
});
|
|
}
|
|
|
|
function makeFrame(opcode, payload) {
|
|
const source = Buffer.isBuffer(payload) ? payload : Buffer.from(payload);
|
|
const header = [];
|
|
header.push(0x80 | (opcode & 0x0f));
|
|
|
|
if (source.length < 126) {
|
|
header.push(source.length);
|
|
return Buffer.concat([Buffer.from(header), source]);
|
|
}
|
|
|
|
if (source.length < 65536) {
|
|
const prefix = Buffer.from([header[0], 126, (source.length >> 8) & 0xff, source.length & 0xff]);
|
|
return Buffer.concat([prefix, source]);
|
|
}
|
|
|
|
const prefix = Buffer.alloc(10);
|
|
prefix[0] = header[0];
|
|
prefix[1] = 127;
|
|
prefix.writeUInt32BE(0, 2);
|
|
prefix.writeUInt32BE(source.length, 6);
|
|
return Buffer.concat([prefix, source]);
|
|
}
|
|
|
|
function sendText(client, text) {
|
|
if (!client.closed) {
|
|
client.socket.write(makeFrame(WS_OPCODE.TEXT, Buffer.from(text, 'utf8')));
|
|
}
|
|
}
|
|
|
|
function sendJson(client, type, payload, requestId = null) {
|
|
sendText(client, jsonMessage(type, payload, requestId));
|
|
}
|
|
|
|
function closeClient(client, code = 1000, reason = 'Closing') {
|
|
if (client.closed) {
|
|
return;
|
|
}
|
|
|
|
client.closed = true;
|
|
const reasonBuffer = Buffer.from(reason, 'utf8');
|
|
const payload = Buffer.alloc(2 + reasonBuffer.length);
|
|
payload.writeUInt16BE(code, 0);
|
|
reasonBuffer.copy(payload, 2);
|
|
client.socket.write(makeFrame(WS_OPCODE.CLOSE, payload));
|
|
client.socket.end();
|
|
}
|
|
|
|
function parseFrame(buffer) {
|
|
if (buffer.length < 2) {
|
|
return null;
|
|
}
|
|
|
|
const first = buffer[0];
|
|
const second = buffer[1];
|
|
const fin = (first & 0x80) !== 0;
|
|
const opcode = first & 0x0f;
|
|
const masked = (second & 0x80) !== 0;
|
|
let length = second & 0x7f;
|
|
let offset = 2;
|
|
|
|
if (length === 126) {
|
|
if (buffer.length < offset + 2) {
|
|
return null;
|
|
}
|
|
|
|
length = buffer.readUInt16BE(offset);
|
|
offset += 2;
|
|
} else if (length === 127) {
|
|
if (buffer.length < offset + 8) {
|
|
return null;
|
|
}
|
|
|
|
const high = buffer.readUInt32BE(offset);
|
|
const low = buffer.readUInt32BE(offset + 4);
|
|
if (high !== 0) {
|
|
throw new Error('Large websocket frames are not supported.');
|
|
}
|
|
|
|
length = low;
|
|
offset += 8;
|
|
}
|
|
|
|
let mask = null;
|
|
if (masked) {
|
|
if (buffer.length < offset + 4) {
|
|
return null;
|
|
}
|
|
|
|
mask = buffer.subarray(offset, offset + 4);
|
|
offset += 4;
|
|
}
|
|
|
|
if (buffer.length < offset + length) {
|
|
return null;
|
|
}
|
|
|
|
const payload = Buffer.from(buffer.subarray(offset, offset + length));
|
|
if (masked && mask) {
|
|
for (let index = 0; index < payload.length; index += 1) {
|
|
payload[index] ^= mask[index % 4];
|
|
}
|
|
}
|
|
|
|
return {
|
|
bytesConsumed: offset + length,
|
|
fin,
|
|
opcode,
|
|
payload,
|
|
};
|
|
}
|
|
|
|
function createAcceptKey(key) {
|
|
return crypto.createHash('sha1').update(key + WS_GUID).digest('base64');
|
|
}
|
|
|
|
module.exports = {
|
|
closeClient,
|
|
createAcceptKey,
|
|
jsonMessage,
|
|
makeFrame,
|
|
parseFrame,
|
|
sendJson,
|
|
sendText,
|
|
};
|