websocket mode

This commit is contained in:
d07riv
2019-08-15 06:02:31 +03:00
parent 916bbd90cb
commit 30fe33639e
5 changed files with 55 additions and 37 deletions

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "diabloweb", "name": "diabloweb",
"version": "1.0.29", "version": "1.0.30",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "diabloweb", "name": "diabloweb",
"version": "1.0.29", "version": "1.0.30",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@babel/core": "7.4.3", "@babel/core": "7.4.3",

View File

@@ -40,7 +40,7 @@ export class buffer_reader {
this.pos += length; this.pos += length;
return result; return result;
} }
rest() { read_buf() {
const size = this.read32(); const size = this.read32();
const result = this.buffer.subarray(this.pos, this.pos + size); const result = this.buffer.subarray(this.pos, this.pos + size);
this.pos += size; this.pos += size;
@@ -86,11 +86,15 @@ export class buffer_writer {
return this; return this;
} }
rest(value) { rest(value) {
this.write32(value.byteLength);
this.buffer.set(value, this.pos); this.buffer.set(value, this.pos);
this.pos += value.byteLength; this.pos += value.byteLength;
return this; return this;
} }
write_buf(value) {
this.write32(value.byteLength);
this.rest(value);
return this;
}
} }
export const RejectionReason = { export const RejectionReason = {
@@ -194,9 +198,9 @@ export const server_packet = {
}, },
message: { message: {
code: 0x01, code: 0x01,
read: reader => ({id: reader.read8(), payload: reader.rest()}), read: reader => ({id: reader.read8(), payload: reader.read_buf()}),
size: ({payload}) => 5 + payload.byteLength, 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: { turn: {
code: 0x02, code: 0x02,
@@ -246,9 +250,9 @@ export const client_packet = {
}, },
message: { message: {
code: 0x01, code: 0x01,
read: reader => ({id: reader.read8(), payload: reader.rest()}), read: reader => ({id: reader.read8(), payload: reader.read_buf()}),
size: ({payload}) => 5 + payload.byteLength, 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: { turn: {
code: 0x02, code: 0x02,

View File

@@ -31,7 +31,7 @@ class webrtc_server {
this.seed = Math.floor(Math.random() * Math.pow(2, 32)); this.seed = Math.floor(Math.random() * Math.pow(2, 32));
const onError = () => { 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(); onClose();
this.peer.off('error', onError); this.peer.off('error', onError);
this.peer.off('open', onOpen); this.peer.off('open', onOpen);
@@ -39,8 +39,8 @@ class webrtc_server {
const onOpen = () => { const onOpen = () => {
//console.log('peer open'); //console.log('peer open');
setTimeout(() => { setTimeout(() => {
onMessage(server_packet.join_accept.write({cookie, index: 0, seed: this.seed, difficulty})); onMessage(write_packet(server_packet.join_accept, {cookie, index: 0, seed: this.seed, difficulty}));
onMessage(server_packet.connect.write({id: 0})); onMessage(write_packet(server_packet.connect, {id: 0}));
}, 0); }, 0);
this.peer.off('error', onError); this.peer.off('error', onError);
this.peer.off('open', onOpen); this.peer.off('open', onOpen);
@@ -64,23 +64,23 @@ class webrtc_server {
break; break;
case client_packet.join_game.code: case client_packet.join_game.code:
if (peer.version !== this.version) { 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) { } 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) { } 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 { } else {
let i = 1; let i = 1;
while (i < MAX_PLRS && this.players[i]) { while (i < MAX_PLRS && this.players[i]) {
++i; ++i;
} }
if (i >= MAX_PLRS) { 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 { } else {
this.players[i] = peer; this.players[i] = peer;
peer.id = i; peer.id = i;
conn.send(server_packet.join_accept.write({cookie: pkt.cookie, index: i, seed: this.seed, difficulty: this.difficulty})); conn.send(write_packet(server_packet.join_accept, {cookie: pkt.cookie, index: i, seed: this.seed, difficulty: this.difficulty}));
this.send(0xFF, server_packet.connect.write({id: i})); this.send(0xFF, write_packet(server_packet.connect, {id: i}));
} }
} }
break; break;
@@ -122,11 +122,11 @@ class webrtc_server {
for (let i = 1; i < MAX_PLRS; ++i) { for (let i = 1; i < MAX_PLRS; ++i) {
this.drop(i, 0x40000006); 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.peer.destroy();
this.onClose(); this.onClose();
} else if (this.players[id]) { } 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; this.players[id].id = null;
if (this.players[id].conn) { if (this.players[id].conn) {
this.players[id].conn.close(); this.players[id].conn.close();
@@ -144,10 +144,10 @@ class webrtc_server {
this.drop(pkt.id, pkt.reason); this.drop(pkt.id, pkt.reason);
break; break;
case client_packet.message.code: 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; break;
case client_packet.turn.code: 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; break;
default: default:
throw Error(`invalid packet ${code}`); throw Error(`invalid packet ${code}`);
@@ -174,13 +174,13 @@ class webrtc_client {
clearTimeout(timeout); clearTimeout(timeout);
}; };
const onError = () => { 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(); onClose();
unreg(); unreg();
}; };
const onOpen = () => { const onOpen = () => {
this.conn.send(client_packet.info.write({version})); this.conn.send(write_packet(client_packet.info, {version}));
this.conn.send(client_packet.join_game.write({cookie, name, password})); this.conn.send(write_packet(client_packet.join_game, {cookie, name, password}));
for (let pkt of this.pending) { for (let pkt of this.pending) {
this.conn.send(pkt); this.conn.send(pkt);
} }
@@ -251,14 +251,14 @@ export default function webrtc_open(onMessage) {
break; break;
case client_packet.create_game.code: case client_packet.create_game.code:
if (server || client) { 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 { } else {
server = new webrtc_server(version, pkt, onMessage, () => server = null); server = new webrtc_server(version, pkt, onMessage, () => server = null);
} }
break; break;
case client_packet.join_game.code: case client_packet.join_game.code:
if (server || client) { 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 { } else {
client = new webrtc_client(version, pkt, onMessage, () => client = null); client = new webrtc_client(version, pkt, onMessage, () => client = null);
} }

View File

@@ -48,32 +48,46 @@ async function do_websocket_open(url, handler) {
} }
export default function websocket_open(url, handler, finisher) { export default function websocket_open(url, handler, finisher) {
let ws = null, pending = []; let ws = null, batch = [], intr = null;
const proxy = { const proxy = {
get readyState() { get readyState() {
return ws ? ws.readyState : 0; return ws ? ws.readyState : 0;
}, },
send(msg) { send(msg) {
if (ws) { batch.push(msg.slice());
ws.send(msg);
} else {
pending.push(msg.slice());
}
}, },
close() { close() {
if (intr) {
clearInterval(intr);
intr = null;
}
if (ws) { if (ws) {
ws.close(); ws.close();
} else { } else {
pending = null; batch = null;
} }
}, },
}; };
do_websocket_open(url, handler).then(sock => { do_websocket_open(url, handler).then(sock => {
ws = sock; ws = sock;
if (pending) { if (batch) {
for (let msg of pending) { intr = setInterval(() => {
ws.send(msg); 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 { } else {
ws.close(); ws.close();
} }