avocado-old/packages/net/client/socket.js

124 lines
2.9 KiB
JavaScript
Raw Permalink Normal View History

import D from 'debug';
2019-03-17 23:45:48 -05:00
import io from 'socket.io-client';
2019-04-28 23:45:03 -05:00
import {compose, EventEmitter} from '@avocado/core';
2019-04-24 18:01:17 -05:00
2020-06-27 00:45:40 -05:00
import * as SocketIoParser from '../packet/socket.io-parser';
2019-03-17 23:45:48 -05:00
2020-05-22 08:43:12 -05:00
const debug = D('@avocado/net:socket');
const decorate = compose(
EventEmitter,
);
2019-04-24 18:01:17 -05:00
export class SocketClient extends decorate(class {}) {
2019-03-17 23:45:48 -05:00
2019-04-12 12:09:05 -05:00
constructor(address, options = {}) {
2019-03-17 23:45:48 -05:00
super();
2019-04-20 14:13:15 -05:00
this.address = address;
this.isConnected = false;
this.isReconnecting = false;
2019-04-20 14:13:15 -05:00
this.options = {
2019-04-11 15:26:13 -05:00
parser: SocketIoParser,
2019-03-17 23:45:48 -05:00
path: '/avocado',
2019-04-12 00:09:25 -05:00
perMessageDeflate: false,
2019-04-20 14:13:15 -05:00
reconnection: false,
...options
};
this.socket = null;
this.connect();
}
connect() {
if (this.socket) {
this.socket.destroy();
}
this.socket = io(this.address, {
...this.options,
2019-03-17 23:45:48 -05:00
});
this.socket.on('connect', () => {
debug('connect');
this.isConnected = true;
2019-03-17 23:45:48 -05:00
this.emit('connect');
});
this.socket.on('connect_error', () => {
debug('connect_error');
this.tryReconnect();
});
this.socket.on('connect_timeout', () => {
debug('connect_timeout');
this.tryReconnect();
});
this.socket.on('disconnect', () => {
this.isConnected = false;
this.emit('disconnect');
debug('disconnect');
this.tryReconnect();
});
2020-06-17 04:35:59 -05:00
const {all, idFrom} = require('../packet/packets.scwp');
const entries = Object.entries(all());
for (let i = 0; i < entries.length; i++) {
const [, M] = entries[i];
const {default: Packet} = M;
const id = idFrom(M);
2020-06-27 01:35:11 -05:00
this.socket.on(id, (data, fn) => {
2020-05-22 08:43:12 -05:00
const packet = new Packet(data);
debug('recieved packet %o', packet);
2020-06-27 01:35:11 -05:00
this.emit('packet', packet, fn);
2019-04-11 15:26:13 -05:00
});
2019-03-17 23:45:48 -05:00
}
}
2019-04-20 14:13:15 -05:00
disconnect() {
this.socket.disconnect();
}
2020-05-21 08:57:01 -05:00
get id() {
return this.socket ? this.socket.id : undefined;
}
2020-06-27 01:35:11 -05:00
send(packet, fn) {
2020-05-22 08:43:12 -05:00
debug('sending packet %o', packet);
2020-06-17 04:35:59 -05:00
const {idFrom} = require('../packet/registrar');
const id = idFrom(packet.constructor);
2020-06-27 01:35:11 -05:00
this.socket.binary(true).emit(id, packet.data, fn);
2019-03-17 23:45:48 -05:00
}
2020-05-21 08:57:01 -05:00
get session() {
return this.socket.handshake.session;
}
to(channel) {
return {
send: (packet) => {
2020-06-17 04:35:59 -05:00
const {idFrom} = require('../packet/registrar');
const id = idFrom(packet.constructor);
2020-05-21 08:57:01 -05:00
this.socket.binary(true).to(channel).emit(id, packet.data);
},
};
}
tryReconnect() {
if (this.isReconnecting) {
return;
}
this.isReconnecting = true;
let backoff = 100;
const tryToReconnect = () => {
debug('try to reconnect');
if (this.isConnected) {
2020-05-26 06:21:09 -05:00
debug('reconnected');
this.emit('reconnect');
this.isReconnecting = false;
return;
}
this.connect();
backoff = Math.min(2000, backoff * 1.5);
debug('backoff', backoff);
setTimeout(tryToReconnect, backoff);
}
setTimeout(tryToReconnect, 0);
}
2019-03-17 23:45:48 -05:00
}