From 30fe33639e6c86a42f9c9b543f31a21be5de00d4 Mon Sep 17 00:00:00 2001 From: d07riv Date: Thu, 15 Aug 2019 06:02:31 +0300 Subject: [PATCH] websocket mode --- package-lock.json | 2 +- package.json | 2 +- src/api/packet.js | 16 ++++++++++------ src/api/webrtc.js | 36 ++++++++++++++++++------------------ src/api/websocket.js | 36 +++++++++++++++++++++++++----------- 5 files changed, 55 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index affaed0..db3ddf3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "diabloweb", - "version": "1.0.29", + "version": "1.0.30", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a941582..d4fe373 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "diabloweb", - "version": "1.0.29", + "version": "1.0.30", "private": true, "dependencies": { "@babel/core": "7.4.3", diff --git a/src/api/packet.js b/src/api/packet.js index 7b1214f..5492142 100644 --- a/src/api/packet.js +++ b/src/api/packet.js @@ -40,7 +40,7 @@ export class buffer_reader { this.pos += length; return result; } - rest() { + read_buf() { const size = this.read32(); const result = this.buffer.subarray(this.pos, this.pos + size); this.pos += size; @@ -86,11 +86,15 @@ export class buffer_writer { return this; } rest(value) { - this.write32(value.byteLength); this.buffer.set(value, this.pos); this.pos += value.byteLength; return this; } + write_buf(value) { + this.write32(value.byteLength); + this.rest(value); + return this; + } } export const RejectionReason = { @@ -194,9 +198,9 @@ export const server_packet = { }, message: { code: 0x01, - read: reader => ({id: reader.read8(), payload: reader.rest()}), + read: reader => ({id: reader.read8(), payload: reader.read_buf()}), size: ({payload}) => 5 + payload.byteLength, - write: (writer, {id, payload}) => writer.write8(id).rest(payload), + write: (writer, {id, payload}) => writer.write8(id).write_buf(payload), }, turn: { code: 0x02, @@ -246,9 +250,9 @@ export const client_packet = { }, message: { code: 0x01, - read: reader => ({id: reader.read8(), payload: reader.rest()}), + read: reader => ({id: reader.read8(), payload: reader.read_buf()}), size: ({payload}) => 5 + payload.byteLength, - write: (writer, {id, payload}) => writer.write8(id).rest(payload), + write: (writer, {id, payload}) => writer.write8(id).write_buf(payload), }, turn: { code: 0x02, diff --git a/src/api/webrtc.js b/src/api/webrtc.js index 36b5270..eb3e9fa 100644 --- a/src/api/webrtc.js +++ b/src/api/webrtc.js @@ -31,7 +31,7 @@ class webrtc_server { this.seed = Math.floor(Math.random() * Math.pow(2, 32)); const onError = () => { - onMessage(server_packet.join_reject.write({cookie, reason: RejectionReason.CREATE_GAME_EXISTS})); + onMessage(write_packet(server_packet.join_reject, {cookie, reason: RejectionReason.CREATE_GAME_EXISTS})); onClose(); this.peer.off('error', onError); this.peer.off('open', onOpen); @@ -39,8 +39,8 @@ class webrtc_server { const onOpen = () => { //console.log('peer open'); setTimeout(() => { - onMessage(server_packet.join_accept.write({cookie, index: 0, seed: this.seed, difficulty})); - onMessage(server_packet.connect.write({id: 0})); + onMessage(write_packet(server_packet.join_accept, {cookie, index: 0, seed: this.seed, difficulty})); + onMessage(write_packet(server_packet.connect, {id: 0})); }, 0); this.peer.off('error', onError); this.peer.off('open', onOpen); @@ -64,23 +64,23 @@ class webrtc_server { break; case client_packet.join_game.code: if (peer.version !== this.version) { - conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_VERSION_MISMATCH})); + conn.send(write_packet(server_packet.join_reject, {cookie: pkt.cookie, reason: RejectionReason.JOIN_VERSION_MISMATCH})); } else if (pkt.name !== this.name) { - conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND})); + conn.send(write_packet(server_packet.join_reject, {cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND})); } else if (pkt.password !== this.password) { - conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_INCORRECT_PASSWORD})); + conn.send(write_packet(server_packet.join_reject, {cookie: pkt.cookie, reason: RejectionReason.JOIN_INCORRECT_PASSWORD})); } else { let i = 1; while (i < MAX_PLRS && this.players[i]) { ++i; } if (i >= MAX_PLRS) { - conn.send(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_FULL})); + conn.send(write_packet(server_packet.join_reject, {cookie: pkt.cookie, reason: RejectionReason.JOIN_GAME_FULL})); } else { this.players[i] = peer; peer.id = i; - conn.send(server_packet.join_accept.write({cookie: pkt.cookie, index: i, seed: this.seed, difficulty: this.difficulty})); - this.send(0xFF, server_packet.connect.write({id: i})); + conn.send(write_packet(server_packet.join_accept, {cookie: pkt.cookie, index: i, seed: this.seed, difficulty: this.difficulty})); + this.send(0xFF, write_packet(server_packet.connect, {id: i})); } } break; @@ -122,11 +122,11 @@ class webrtc_server { for (let i = 1; i < MAX_PLRS; ++i) { this.drop(i, 0x40000006); } - this.onMessage(server_packet.disconnect.write({id, reason})); + this.onMessage(write_packet(server_packet.disconnect, {id, reason})); this.peer.destroy(); this.onClose(); } else if (this.players[id]) { - this.send(0xFF, server_packet.disconnect.write({id, reason})); + this.send(0xFF, write_packet(server_packet.disconnect, {id, reason})); this.players[id].id = null; if (this.players[id].conn) { this.players[id].conn.close(); @@ -144,10 +144,10 @@ class webrtc_server { this.drop(pkt.id, pkt.reason); break; case client_packet.message.code: - this.send(pkt.id === 0xFF ? ~(1 << id) : (1 << pkt.id), server_packet.message.write({id, payload: pkt.payload})); + this.send(pkt.id === 0xFF ? ~(1 << id) : (1 << pkt.id), write_packet(server_packet.message, {id, payload: pkt.payload})); break; case client_packet.turn.code: - this.send(~(1 << id), server_packet.turn.write({id, turn: pkt.turn})); + this.send(~(1 << id), write_packet(server_packet.turn, {id, turn: pkt.turn})); break; default: throw Error(`invalid packet ${code}`); @@ -174,13 +174,13 @@ class webrtc_client { clearTimeout(timeout); }; const onError = () => { - onMessage(server_packet.join_reject.write({cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND})); + onMessage(write_packet(server_packet.join_reject, {cookie, reason: RejectionReason.JOIN_GAME_NOT_FOUND})); onClose(); unreg(); }; const onOpen = () => { - this.conn.send(client_packet.info.write({version})); - this.conn.send(client_packet.join_game.write({cookie, name, password})); + this.conn.send(write_packet(client_packet.info, {version})); + this.conn.send(write_packet(client_packet.join_game, {cookie, name, password})); for (let pkt of this.pending) { this.conn.send(pkt); } @@ -251,14 +251,14 @@ export default function webrtc_open(onMessage) { break; case client_packet.create_game.code: if (server || client) { - onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME})); + onMessage(write_packet(server_packet.join_reject, {cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME})); } else { server = new webrtc_server(version, pkt, onMessage, () => server = null); } break; case client_packet.join_game.code: if (server || client) { - onMessage(server_packet.join_reject.write({cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME})); + onMessage(write_packet(server_packet.join_reject, {cookie: pkt.cookie, reason: RejectionReason.JOIN_ALREADY_IN_GAME})); } else { client = new webrtc_client(version, pkt, onMessage, () => client = null); } diff --git a/src/api/websocket.js b/src/api/websocket.js index 8e8898f..7563cec 100644 --- a/src/api/websocket.js +++ b/src/api/websocket.js @@ -48,32 +48,46 @@ async function do_websocket_open(url, handler) { } export default function websocket_open(url, handler, finisher) { - let ws = null, pending = []; + let ws = null, batch = [], intr = null; const proxy = { get readyState() { return ws ? ws.readyState : 0; }, send(msg) { - if (ws) { - ws.send(msg); - } else { - pending.push(msg.slice()); - } + batch.push(msg.slice()); }, close() { + if (intr) { + clearInterval(intr); + intr = null; + } if (ws) { ws.close(); } else { - pending = null; + batch = null; } }, }; do_websocket_open(url, handler).then(sock => { ws = sock; - if (pending) { - for (let msg of pending) { - ws.send(msg); - } + if (batch) { + intr = setInterval(() => { + if (!batch.length) { + return; + } + const size = batch.reduce((sum, msg) => sum + msg.byteLength, 3); + const buffer = new Uint8Array(size); + buffer[0] = 0; + buffer[1] = (batch.length & 0xFF); + buffer[2] = batch.length >> 8; + let pos = 3; + for (let msg of batch) { + buffer.set(msg, pos); + pos += msg.byteLength; + } + ws.send(buffer); + batch.length = 0; + }, 100); } else { ws.close(); }