mirror of
https://github.com/d07RiV/diabloweb.git
synced 2026-06-03 21:41:38 +00:00
server stuff
This commit is contained in:
2212
src/api/Diablo.jscc
2212
src/api/Diablo.jscc
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -4,6 +4,8 @@ import SpawnBinary from './DiabloSpawn.wasm';
|
||||
import SpawnModule from './DiabloSpawn.jscc';
|
||||
import axios from 'axios';
|
||||
|
||||
import websocket_open from './websocket';
|
||||
|
||||
const DiabloSize = 1466809;
|
||||
const SpawnSize = 1337416;
|
||||
|
||||
@@ -16,6 +18,7 @@ let files = null;
|
||||
let renderBatch = null;
|
||||
let drawBelt = null;
|
||||
let is_spawn = false;
|
||||
let websocket = null;
|
||||
|
||||
const ChunkSize = 1 << 20;
|
||||
class RemoteFile {
|
||||
@@ -116,8 +119,35 @@ const DApi = {
|
||||
worker.postMessage({action: "keyboard", rect: null});
|
||||
},
|
||||
|
||||
use_websocket(flag) {
|
||||
if (flag) {
|
||||
if (!websocket || websocket.readyState !== 1) {
|
||||
const sock = websocket = websocket_open('ws://diablo.rivsoft.net/', data => {
|
||||
if (websocket === sock) {
|
||||
try_api(() => {
|
||||
const ptr = wasm._DApi_AllocPacket(data.byteLength);
|
||||
wasm.HEAPU8.set(new Uint8Array(data), ptr);
|
||||
});
|
||||
}
|
||||
}, code => {
|
||||
if (typeof code !== "number") {
|
||||
worker.postMessage({action: "error", error: code.toString(), stack: code.stack});
|
||||
code = 3;
|
||||
}
|
||||
call_api("SNet_WebsocketStatus", code);
|
||||
});
|
||||
} else {
|
||||
call_api("SNet_WebsocketStatus", 0);
|
||||
}
|
||||
} else {
|
||||
if (websocket) {
|
||||
websocket.close();
|
||||
}
|
||||
websocket = null;
|
||||
}
|
||||
},
|
||||
websocket_closed() {
|
||||
return false;
|
||||
return websocket ? websocket.readyState !== 1 : false;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -234,7 +264,9 @@ let maxSoundId = 0, maxBatchId = 0;
|
||||
|
||||
let packetBatch = null;
|
||||
DApi.websocket_send = function(data) {
|
||||
if (packetBatch) {
|
||||
if (websocket) {
|
||||
websocket.send(data);
|
||||
} else if (packetBatch) {
|
||||
packetBatch.push(data.slice().buffer);
|
||||
} else {
|
||||
worker.postMessage({action: "packet", buffer: data});
|
||||
@@ -249,9 +281,6 @@ function try_api(func) {
|
||||
try {
|
||||
func();
|
||||
} catch (e) {
|
||||
if (typeof e === "string") {
|
||||
worker.postMessage({action: ""})
|
||||
}
|
||||
worker.postMessage({action: "error", error: e.toString(), stack: e.stack});
|
||||
}
|
||||
}
|
||||
|
||||
260
src/api/packet.js
Normal file
260
src/api/packet.js
Normal file
@@ -0,0 +1,260 @@
|
||||
export class buffer_reader {
|
||||
constructor(buffer) {
|
||||
this.buffer = (buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer));
|
||||
this.pos = 0;
|
||||
}
|
||||
done() {
|
||||
return this.pos === this.buffer.byteLength;
|
||||
}
|
||||
read8() {
|
||||
if (this.pos >= this.buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
return this.buffer[this.pos++];
|
||||
}
|
||||
read16() {
|
||||
const {pos, buffer} = this;
|
||||
if (pos + 2 > buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
const result = buffer[pos] | (buffer[pos + 1] << 8);
|
||||
this.pos += 2;
|
||||
return result;
|
||||
}
|
||||
read32() {
|
||||
const {pos, buffer} = this;
|
||||
if (pos + 4 > buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
const result = buffer[pos] | (buffer[pos + 1] << 8) | (buffer[pos + 2] << 16) | (buffer[pos + 3] << 24);
|
||||
this.pos += 4;
|
||||
return result;
|
||||
}
|
||||
read_str() {
|
||||
const length = this.read8();
|
||||
const {pos, buffer} = this;
|
||||
if (pos + length > buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
const result = String.fromCharCode(...buffer.subarray(pos, pos + length));
|
||||
this.pos += length;
|
||||
return result;
|
||||
}
|
||||
rest() {
|
||||
const size = this.read32();
|
||||
const result = this.buffer.subarray(this.pos, this.pos + size);
|
||||
this.pos += size;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
export class buffer_writer {
|
||||
constructor(length) {
|
||||
this.buffer = new Uint8Array(length);
|
||||
this.pos = 0;
|
||||
}
|
||||
get result() {
|
||||
return this.buffer.buffer;
|
||||
}
|
||||
write8(value) {
|
||||
this.buffer[this.pos++] = value;
|
||||
return this;
|
||||
}
|
||||
write16(value) {
|
||||
const {pos, buffer} = this;
|
||||
buffer[pos] = value;
|
||||
buffer[pos + 1] = value >> 8;
|
||||
this.pos += 2;
|
||||
return this;
|
||||
}
|
||||
write32(value) {
|
||||
const {pos, buffer} = this;
|
||||
buffer[pos] = value;
|
||||
buffer[pos + 1] = value >> 8;
|
||||
buffer[pos + 2] = value >> 16;
|
||||
buffer[pos + 3] = value >> 24;
|
||||
this.pos += 4;
|
||||
return this;
|
||||
}
|
||||
write_str(value) {
|
||||
const length = value.length;
|
||||
this.write8(length);
|
||||
const {pos, buffer} = this;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
buffer[pos + i] = value.charCodeAt(i);
|
||||
}
|
||||
this.pos += length;
|
||||
return this;
|
||||
}
|
||||
rest(value) {
|
||||
this.write32(value.byteLength);
|
||||
this.buffer.set(value, this.pos);
|
||||
this.pos += value.byteLength;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export const RejectionReason = {
|
||||
JOIN_SUCCESS: 0x00,
|
||||
JOIN_ALREADY_IN_GAME: 0x01,
|
||||
JOIN_GAME_NOT_FOUND: 0x02,
|
||||
JOIN_INCORRECT_PASSWORD: 0x03,
|
||||
JOIN_VERSION_MISMATCH: 0x04,
|
||||
JOIN_GAME_FULL: 0x05,
|
||||
CREATE_GAME_EXISTS: 0x06,
|
||||
};
|
||||
|
||||
export function read_packet(reader, types) {
|
||||
const code = reader.read8();
|
||||
const cls = Object.values(types).find(cls => cls.code === code);
|
||||
if (!cls) {
|
||||
throw Error('invalid packet code');
|
||||
}
|
||||
return {type: cls, packet: cls.read(reader)};
|
||||
}
|
||||
export function packet_size(type, packet) {
|
||||
return (typeof type.size === "function" ? type.size(packet) : type.size) + 1;
|
||||
}
|
||||
export function write_packet(type, packet) {
|
||||
const size = packet_size(type, packet);
|
||||
return type.write(new buffer_writer(size).write8(type.code), packet).result;
|
||||
}
|
||||
|
||||
export function make_batch(types) {
|
||||
return {
|
||||
code: 0x00,
|
||||
read: reader => {
|
||||
const count = reader.read16();
|
||||
const packets = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
packets.push(read_packet(reader, types()));
|
||||
}
|
||||
return packets;
|
||||
},
|
||||
size: packets => packets.reduce((sum, {type, packet}) => sum + packet_size(type, packet), 2),
|
||||
write: (writer, packets) => {
|
||||
writer.write16(packets.length);
|
||||
for (let {type, packet} of packets) {
|
||||
type.write(writer.write8(type.code), packet);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const server_packet = {
|
||||
info: {
|
||||
code: 0x32,
|
||||
read: reader => ({version: reader.read32()}),
|
||||
size: 4,
|
||||
write: (writer, {version}) => writer.write32(version),
|
||||
},
|
||||
game_list: {
|
||||
code: 0x21,
|
||||
read: reader => {
|
||||
const count = reader.read16();
|
||||
const games = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
games.push({type: reader.read32(), name: reader.read_str()});
|
||||
}
|
||||
return {games};
|
||||
},
|
||||
size: ({games}) => games.reduce((sum, {name}) => sum + 5 + name.length, 2),
|
||||
write: (writer, {games}) => {
|
||||
writer.write16(games.length);
|
||||
for (let {type, name} of games) {
|
||||
writer.write32(type);
|
||||
writer.write_str(name);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
},
|
||||
join_accept: {
|
||||
code: 0x12,
|
||||
read: reader => ({cookie: reader.read32(), index: reader.read8(), seed: reader.read32(), difficulty: reader.read32()}),
|
||||
size: 13,
|
||||
write: (writer, {cookie, index, seed, difficulty}) => writer.write32(cookie).write8(index).write32(seed).write32(difficulty),
|
||||
},
|
||||
join_reject: {
|
||||
code: 0x15,
|
||||
read: reader => ({cookie: reader.read32(), reason: reader.read8()}),
|
||||
size: 5,
|
||||
write: (writer, {cookie, reason}) => writer.write32(cookie).write8(reason),
|
||||
},
|
||||
connect: {
|
||||
code: 0x13,
|
||||
read: reader => ({id: reader.read8()}),
|
||||
size: 1,
|
||||
write: (writer, {id}) => writer.write8(id),
|
||||
},
|
||||
disconnect: {
|
||||
code: 0x14,
|
||||
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
||||
size: 5,
|
||||
write: (writer, {id, reason}) => writer.write8(id).write32(reason),
|
||||
},
|
||||
message: {
|
||||
code: 0x01,
|
||||
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
||||
size: ({payload}) => 5 + payload.byteLength,
|
||||
write: (writer, {id, payload}) => writer.write8(id).rest(payload),
|
||||
},
|
||||
turn: {
|
||||
code: 0x02,
|
||||
read: reader => ({id: reader.read8(), turn: reader.read32()}),
|
||||
size: 5,
|
||||
write: (writer, {id, turn}) => writer.write8(id).write32(turn),
|
||||
},
|
||||
batch: make_batch(() => server_packet),
|
||||
};
|
||||
|
||||
export const client_packet = {
|
||||
info: {
|
||||
code: 0x31,
|
||||
read: reader => ({version: reader.read32()}),
|
||||
size: 4,
|
||||
write: (writer, {version}) => writer.write32(version),
|
||||
},
|
||||
game_list: {
|
||||
code: 0x21,
|
||||
read: () => ({}),
|
||||
size: 0,
|
||||
write: writer => writer,
|
||||
},
|
||||
create_game: {
|
||||
code: 0x22,
|
||||
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str(), difficulty: reader.read32()}),
|
||||
size: ({name, password}) => 10 + name.length + password.length,
|
||||
write: (writer, {cookie, name, password, difficulty}) => writer.write32(cookie).write_str(name).write_str(password).write32(difficulty),
|
||||
},
|
||||
join_game: {
|
||||
code: 0x23,
|
||||
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str()}),
|
||||
size: ({name, password}) => 6 + name.length + password.length,
|
||||
write: (writer, {cookie, name, password}) => writer.write32(cookie).write_str(name).write_str(password),
|
||||
},
|
||||
leave_game: {
|
||||
code: 0x24,
|
||||
read: () => ({}),
|
||||
size: 0,
|
||||
write: writer => writer,
|
||||
},
|
||||
drop_player: {
|
||||
code: 0x03,
|
||||
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
||||
size: 5,
|
||||
write: (writer, {id, reason}) => writer.write8(id).write32(reason),
|
||||
},
|
||||
message: {
|
||||
code: 0x01,
|
||||
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
||||
size: ({payload}) => 5 + payload.byteLength,
|
||||
write: (writer, {id, payload}) => writer.write8(id).rest(payload),
|
||||
},
|
||||
turn: {
|
||||
code: 0x02,
|
||||
read: reader => ({turn: reader.read32()}),
|
||||
size: 4,
|
||||
write: (writer, {turn}) => writer.write32(turn),
|
||||
},
|
||||
batch: make_batch(() => server_packet),
|
||||
};
|
||||
@@ -1,210 +1,5 @@
|
||||
import Peer from 'peerjs';
|
||||
|
||||
class buffer_reader {
|
||||
constructor(buffer) {
|
||||
this.buffer = (buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer));
|
||||
this.pos = 0;
|
||||
}
|
||||
done() {
|
||||
return this.pos === this.buffer.byteLength;
|
||||
}
|
||||
read8() {
|
||||
if (this.pos >= this.buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
return this.buffer[this.pos++];
|
||||
}
|
||||
read16() {
|
||||
const {pos, buffer} = this;
|
||||
if (pos + 2 > buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
const result = buffer[pos] | (buffer[pos + 1] << 8);
|
||||
this.pos += 2;
|
||||
return result;
|
||||
}
|
||||
read32() {
|
||||
const {pos, buffer} = this;
|
||||
if (pos + 4 > buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
const result = buffer[pos] | (buffer[pos + 1] << 8) | (buffer[pos + 2] << 16) | (buffer[pos + 3] << 24);
|
||||
this.pos += 4;
|
||||
return result;
|
||||
}
|
||||
read_str() {
|
||||
const length = this.read8();
|
||||
const {pos, buffer} = this;
|
||||
if (pos + length > buffer.byteLength) {
|
||||
throw Error('packet too small');
|
||||
}
|
||||
const result = String.fromCharCode(...buffer.subarray(pos, pos + length));
|
||||
this.pos += length;
|
||||
return result;
|
||||
}
|
||||
rest() {
|
||||
const result = this.buffer.subarray(this.pos);
|
||||
this.pos = this.buffer.length;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
class buffer_writer {
|
||||
constructor(length) {
|
||||
this.buffer = new Uint8Array(length);
|
||||
this.pos = 0;
|
||||
}
|
||||
get result() {
|
||||
return this.buffer.buffer;
|
||||
}
|
||||
write8(value) {
|
||||
this.buffer[this.pos++] = value;
|
||||
return this;
|
||||
}
|
||||
write16(value) {
|
||||
const {pos, buffer} = this;
|
||||
buffer[pos] = value;
|
||||
buffer[pos + 1] = value >> 8;
|
||||
this.pos += 2;
|
||||
return this;
|
||||
}
|
||||
write32(value) {
|
||||
const {pos, buffer} = this;
|
||||
buffer[pos] = value;
|
||||
buffer[pos + 1] = value >> 8;
|
||||
buffer[pos + 2] = value >> 16;
|
||||
buffer[pos + 3] = value >> 24;
|
||||
this.pos += 4;
|
||||
return this;
|
||||
}
|
||||
write_str(value) {
|
||||
const length = value.length;
|
||||
this.write8(length);
|
||||
const {pos, buffer} = this;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
buffer[pos + i] = value.charCodeAt(i);
|
||||
}
|
||||
this.pos += length;
|
||||
return this;
|
||||
}
|
||||
rest(value) {
|
||||
this.buffer.set(value, this.pos);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
const RejectionReason = {
|
||||
JOIN_SUCCESS: 0x00,
|
||||
JOIN_ALREADY_IN_GAME: 0x01,
|
||||
JOIN_GAME_NOT_FOUND: 0x02,
|
||||
JOIN_INCORRECT_PASSWORD: 0x03,
|
||||
JOIN_VERSION_MISMATCH: 0x04,
|
||||
JOIN_GAME_FULL: 0x05,
|
||||
CREATE_GAME_EXISTS: 0x06,
|
||||
};
|
||||
|
||||
const server_packet = {
|
||||
info: {
|
||||
code: 0x32,
|
||||
read: reader => ({version: reader.read32()}),
|
||||
write: ({version}) => new buffer_writer(5).write8(server_packet.info.code).write32(version).result,
|
||||
},
|
||||
game_list: {
|
||||
code: 0x21,
|
||||
read: reader => {
|
||||
const count = reader.read8();
|
||||
const games = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
games.push({type: reader.read32(), name: reader.read_str()});
|
||||
}
|
||||
return {games};
|
||||
},
|
||||
write: ({games}) => {
|
||||
const writer = new buffer_writer(games.reduce((sum, {name}) => sum + 5 + name.length, 2));
|
||||
writer.write8(server_packet.game_list.code);
|
||||
writer.write8(games.length);
|
||||
for (let {code, name} of games) {
|
||||
writer.write32(code);
|
||||
writer.write_str(name);
|
||||
}
|
||||
return writer.result;
|
||||
},
|
||||
},
|
||||
join_accept: {
|
||||
code: 0x12,
|
||||
read: reader => ({cookie: reader.read32(), index: reader.read8(), seed: reader.read32(), difficulty: reader.read32()}),
|
||||
write: ({cookie, index, seed, difficulty}) => new buffer_writer(14).write8(server_packet.join_accept.code).write32(cookie).write8(index).write32(seed).write32(difficulty).result,
|
||||
},
|
||||
join_reject: {
|
||||
code: 0x15,
|
||||
read: reader => ({cookie: reader.read32(), reason: reader.read8()}),
|
||||
write: ({cookie, reason}) => new buffer_writer(6).write8(server_packet.join_reject.code).write32(cookie).write8(reason).result,
|
||||
},
|
||||
connect: {
|
||||
code: 0x13,
|
||||
read: reader => ({id: reader.read8()}),
|
||||
write: ({id}) => new buffer_writer(2).write8(server_packet.connect.code).write8(id).result,
|
||||
},
|
||||
disconnect: {
|
||||
code: 0x14,
|
||||
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
||||
write: ({id, reason}) => new buffer_writer(6).write8(server_packet.disconnect.code).write8(id).write32(reason).result,
|
||||
},
|
||||
message: {
|
||||
code: 0x01,
|
||||
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
||||
write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(server_packet.message.code).write8(id).rest(payload).result,
|
||||
},
|
||||
turn: {
|
||||
code: 0x02,
|
||||
read: reader => ({id: reader.read8(), turn: reader.read32()}),
|
||||
write: ({id, turn}) => new buffer_writer(6).write8(server_packet.turn.code).write8(id).write32(turn).result,
|
||||
},
|
||||
};
|
||||
|
||||
const client_packet = {
|
||||
info: {
|
||||
code: 0x31,
|
||||
read: reader => ({version: reader.read32()}),
|
||||
write: ({version}) => new buffer_writer(5).write8(client_packet.info.code).write32(version).result,
|
||||
},
|
||||
game_list: {
|
||||
code: 0x21,
|
||||
read: () => ({}),
|
||||
write: () => new buffer_writer(1).write8(client_packet.game_list.code).result,
|
||||
},
|
||||
create_game: {
|
||||
code: 0x22,
|
||||
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str(), difficulty: reader.read32()}),
|
||||
write: ({cookie, name, password, difficulty}) => new buffer_writer(11 + name.length + password.length)
|
||||
.write8(client_packet.create_game.code).write32(cookie).write_str(name).write_str(password).write32(difficulty).result,
|
||||
},
|
||||
join_game: {
|
||||
code: 0x23,
|
||||
read: reader => ({cookie: reader.read32(), name: reader.read_str(), password: reader.read_str()}),
|
||||
write: ({cookie, name, password}) => new buffer_writer(7 + name.length + password.length)
|
||||
.write8(client_packet.join_game.code).write32(cookie).write_str(name).write_str(password).result,
|
||||
},
|
||||
leave_game: {
|
||||
code: 0x24,
|
||||
read: () => ({}),
|
||||
write: () => new buffer_writer(1).write8(client_packet.leave_game.code).result,
|
||||
},
|
||||
drop_player: {
|
||||
code: 0x03,
|
||||
read: reader => ({id: reader.read8(), reason: reader.read32()}),
|
||||
write: ({id, reason}) => new buffer_writer(6).write8(client_packet.drop_player.code).write8(id).write32(reason).result,
|
||||
},
|
||||
message: {
|
||||
code: 0x01,
|
||||
read: reader => ({id: reader.read8(), payload: reader.rest()}),
|
||||
write: ({id, payload}) => new buffer_writer(2 + payload.byteLength).write8(client_packet.message.code).write8(id).rest(payload).result,
|
||||
},
|
||||
turn: {
|
||||
code: 0x02,
|
||||
read: reader => ({turn: reader.read32()}),
|
||||
write: ({turn}) => new buffer_writer(5).write8(client_packet.turn.code).write32(turn).result,
|
||||
},
|
||||
};
|
||||
import { buffer_reader, read_packet, write_packet, client_packet, server_packet, RejectionReason } from './packet';
|
||||
|
||||
/*function log_packet(data, type) {
|
||||
const reader = new buffer_reader(data);
|
||||
@@ -262,15 +57,12 @@ class webrtc_server {
|
||||
const peer = {conn};
|
||||
conn.on('data', packet => {
|
||||
const reader = new buffer_reader(packet);
|
||||
const code = reader.read8();
|
||||
let pkt;
|
||||
switch (code) {
|
||||
const {type, packet: pkt} = read_packet(reader, client_packet);
|
||||
switch (type.code) {
|
||||
case client_packet.info.code:
|
||||
pkt = client_packet.info.read(reader);
|
||||
peer.version = pkt.version;
|
||||
break;
|
||||
case client_packet.join_game.code:
|
||||
pkt = client_packet.join_game.read(reader);
|
||||
if (peer.version !== this.version) {
|
||||
conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_VERSION_MISMATCH}));
|
||||
} else if (pkt.name !== this.name) {
|
||||
@@ -294,7 +86,7 @@ class webrtc_server {
|
||||
break;
|
||||
default:
|
||||
if (peer.id != null) {
|
||||
this.handle(peer.id, code, reader);
|
||||
this.handle(peer.id, type.code, pkt);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@@ -343,23 +135,18 @@ class webrtc_server {
|
||||
}
|
||||
}
|
||||
|
||||
handle(id, code, reader) {
|
||||
let pkt;
|
||||
handle(id, code, pkt) {
|
||||
switch (code) {
|
||||
case client_packet.leave_game.code:
|
||||
pkt = client_packet.leave_game.read(reader);
|
||||
this.drop(id, 3);
|
||||
break;
|
||||
case client_packet.drop_player.code:
|
||||
pkt = client_packet.drop_player.read(reader);
|
||||
this.drop(pkt.id, pkt.reason);
|
||||
break;
|
||||
case client_packet.message.code:
|
||||
pkt = client_packet.message.read(reader);
|
||||
this.send(pkt.id === 0xFF ? ~(1 << id) : (1 << pkt.id), server_packet.message.write({id, payload: pkt.payload}));
|
||||
break;
|
||||
case client_packet.turn.code:
|
||||
pkt = client_packet.turn.read(reader);
|
||||
this.send(~(1 << id), server_packet.turn.write({id, turn: pkt.turn}));
|
||||
break;
|
||||
default:
|
||||
@@ -411,18 +198,15 @@ class webrtc_client {
|
||||
this.conn.on('data', data => {
|
||||
unreg();
|
||||
const reader = new buffer_reader(data);
|
||||
const code = reader.read8();
|
||||
let pkt;
|
||||
switch (code) {
|
||||
const {type, packet: pkt} = read_packet(reader, server_packet);
|
||||
switch (type.code) {
|
||||
case server_packet.join_accept.code:
|
||||
pkt = server_packet.join_accept.read(reader);
|
||||
this.myplr = pkt.index;
|
||||
break;
|
||||
case server_packet.join_reject.code:
|
||||
onClose();
|
||||
break;
|
||||
case server_packet.disconnect.code:
|
||||
pkt = server_packet.disconnect.read(reader);
|
||||
if (pkt.id === 'myplr') {
|
||||
onClose();
|
||||
}
|
||||
@@ -460,15 +244,12 @@ export default function webrtc_open(onMessage) {
|
||||
send: function(packet) {
|
||||
//log_packet(packet, client_packet);
|
||||
const reader = new buffer_reader(packet);
|
||||
const code = reader.read8();
|
||||
let pkt;
|
||||
switch (code) {
|
||||
const {type, packet: pkt} = read_packet(reader, client_packet);
|
||||
switch (type.code) {
|
||||
case client_packet.info.code:
|
||||
pkt = client_packet.info.read(reader);
|
||||
version = pkt.version;
|
||||
break;
|
||||
case client_packet.create_game.code:
|
||||
pkt = client_packet.create_game.read(reader);
|
||||
if (server || client) {
|
||||
onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME}));
|
||||
} else {
|
||||
@@ -476,7 +257,6 @@ export default function webrtc_open(onMessage) {
|
||||
}
|
||||
break;
|
||||
case client_packet.join_game.code:
|
||||
pkt = client_packet.join_game.read(reader);
|
||||
if (server || client) {
|
||||
onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME}));
|
||||
} else {
|
||||
@@ -485,18 +265,18 @@ export default function webrtc_open(onMessage) {
|
||||
break;
|
||||
default:
|
||||
if (server) {
|
||||
server.handle(0, code, reader);
|
||||
if (code === client_packet.leave_game.code) {
|
||||
server.handle(0, type.code, pkt);
|
||||
if (type.code === client_packet.leave_game.code) {
|
||||
server = null;
|
||||
}
|
||||
} else if (client) {
|
||||
client.send(packet);
|
||||
if (code === client_packet.leave_game.code) {
|
||||
if (type.code === client_packet.leave_game.code) {
|
||||
client = null;
|
||||
}
|
||||
return;
|
||||
} else if (code !== client_packet.leave_game.code) {
|
||||
throw Error(`invalid packet ${code}`);
|
||||
} else if (type.code !== client_packet.leave_game.code) {
|
||||
throw Error(`invalid packet ${type.code}`);
|
||||
}
|
||||
}
|
||||
if (!reader.done()) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default async function websocket_open(url, handler) {
|
||||
async function do_websocket_open(url, handler) {
|
||||
const socket = new WebSocket(url);
|
||||
socket.binaryType = "arraybuffer";
|
||||
let versionCbk = null;
|
||||
@@ -9,7 +9,7 @@ export default async function websocket_open(url, handler) {
|
||||
handler(data);
|
||||
});
|
||||
await new Promise((resolve, reject) => {
|
||||
const onError = err => reject(err);
|
||||
const onError = err => reject(1);
|
||||
socket.addEventListener("error", onError);
|
||||
socket.addEventListener("open", () => {
|
||||
socket.removeEventListener("error", onError);
|
||||
@@ -19,7 +19,7 @@ export default async function websocket_open(url, handler) {
|
||||
await new Promise((resolve, reject) => {
|
||||
const to = setTimeout(() => {
|
||||
versionCbk = null;
|
||||
reject(Error("connection timed out"));
|
||||
reject(1);
|
||||
}, 5000);
|
||||
versionCbk = data => {
|
||||
clearTimeout(to);
|
||||
@@ -30,7 +30,7 @@ export default async function websocket_open(url, handler) {
|
||||
if (version === 1) {
|
||||
resolve();
|
||||
} else {
|
||||
reject("server version mismatch");
|
||||
reject(2);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -46,3 +46,40 @@ export default async function websocket_open(url, handler) {
|
||||
socket.send(clientInfo);
|
||||
return socket;
|
||||
}
|
||||
|
||||
export default function websocket_open(url, handler, finisher) {
|
||||
let ws = null, pending = [];
|
||||
const proxy = {
|
||||
get readyState() {
|
||||
return ws ? ws.readyState : 0;
|
||||
},
|
||||
send(msg) {
|
||||
if (ws) {
|
||||
ws.send(msg);
|
||||
} else {
|
||||
pending.push(msg.slice());
|
||||
}
|
||||
},
|
||||
close() {
|
||||
if (ws) {
|
||||
ws.close();
|
||||
} else {
|
||||
pending = null;
|
||||
}
|
||||
},
|
||||
};
|
||||
do_websocket_open(url, handler).then(sock => {
|
||||
ws = sock;
|
||||
if (pending) {
|
||||
for (let msg of pending) {
|
||||
ws.send(msg);
|
||||
}
|
||||
} else {
|
||||
ws.close();
|
||||
}
|
||||
finisher(0);
|
||||
}, err => {
|
||||
finisher(err);
|
||||
});
|
||||
return proxy;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user