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",
"version": "1.0.29",
"version": "1.0.30",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

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

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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();
}