monkeeShark/src/client/app/common/scripts/streaming/stream.ts

138 lines
3.2 KiB
TypeScript
Raw Normal View History

2017-11-16 16:24:44 +00:00
import { EventEmitter } from 'eventemitter3';
2018-03-15 10:53:46 +00:00
import * as uuid from 'uuid';
2017-11-09 16:11:46 +00:00
import * as ReconnectingWebsocket from 'reconnecting-websocket';
import { wsUrl } from '../../../config';
2018-03-15 10:53:46 +00:00
import MiOS from '../../mios';
2017-03-18 11:05:11 +00:00
2017-05-10 20:08:12 +00:00
/**
2017-06-08 16:03:54 +00:00
* Misskey stream connection
2017-05-10 20:08:12 +00:00
*/
2017-11-16 16:24:44 +00:00
export default class Connection extends EventEmitter {
2018-02-26 10:23:53 +00:00
public state: string;
2017-11-13 09:05:35 +00:00
private buffer: any[];
2018-03-15 10:53:46 +00:00
public socket: ReconnectingWebsocket;
public name: string;
public connectedAt: Date;
public user: string = null;
public in: number = 0;
public out: number = 0;
public inout: Array<{
type: 'in' | 'out',
at: Date,
data: string
}> = [];
public id: string;
2018-03-15 21:05:39 +00:00
public isSuspended = false;
2018-03-15 10:53:46 +00:00
private os: MiOS;
2017-11-13 09:05:35 +00:00
2018-03-15 10:53:46 +00:00
constructor(os: MiOS, endpoint, params?) {
2017-11-16 16:24:44 +00:00
super();
//#region BIND
2017-03-18 11:05:11 +00:00
this.onOpen = this.onOpen.bind(this);
this.onClose = this.onClose.bind(this);
this.onMessage = this.onMessage.bind(this);
2017-03-20 05:49:24 +00:00
this.send = this.send.bind(this);
2017-03-18 11:05:11 +00:00
this.close = this.close.bind(this);
2017-11-16 16:24:44 +00:00
//#endregion
2017-03-20 05:49:24 +00:00
2018-03-15 10:53:46 +00:00
this.id = uuid();
this.os = os;
this.name = endpoint;
2017-03-18 11:05:11 +00:00
this.state = 'initializing';
2017-03-21 09:14:59 +00:00
this.buffer = [];
2017-03-18 11:05:11 +00:00
2017-06-08 16:03:54 +00:00
const query = params
? Object.keys(params)
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
.join('&')
: null;
this.socket = new ReconnectingWebsocket(`${wsUrl}/${endpoint}${query ? '?' + query : ''}`);
2017-03-18 11:05:11 +00:00
this.socket.addEventListener('open', this.onOpen);
this.socket.addEventListener('close', this.onClose);
this.socket.addEventListener('message', this.onMessage);
2018-03-15 10:53:46 +00:00
// Register this connection for debugging
this.os.registerStreamConnection(this);
2017-03-18 11:05:11 +00:00
}
2017-05-10 20:08:12 +00:00
/**
* Callback of when open connection
*/
2017-11-13 09:05:35 +00:00
private onOpen() {
2017-03-18 11:05:11 +00:00
this.state = 'connected';
2017-11-16 16:24:44 +00:00
this.emit('_connected_');
2017-03-21 09:14:59 +00:00
2018-03-15 10:53:46 +00:00
this.connectedAt = new Date();
2017-03-21 09:14:59 +00:00
// バッファーを処理
const _buffer = [].concat(this.buffer); // Shallow copy
this.buffer = []; // Clear buffer
2018-03-15 10:53:46 +00:00
_buffer.forEach(data => {
this.send(data); // Resend each buffered messages
if (this.os.debug) {
this.out++;
this.inout.push({ type: 'out', at: new Date(), data });
}
2017-03-21 09:14:59 +00:00
});
2017-03-18 11:05:11 +00:00
}
2017-05-10 20:08:12 +00:00
/**
* Callback of when close connection
*/
2017-11-13 09:05:35 +00:00
private onClose() {
2017-03-18 11:05:11 +00:00
this.state = 'reconnecting';
2018-02-26 10:23:53 +00:00
this.emit('_disconnected_');
2017-03-18 11:05:11 +00:00
}
2017-05-10 20:08:12 +00:00
/**
* Callback of when received a message from connection
*/
2017-11-13 09:05:35 +00:00
private onMessage(message) {
2018-03-15 21:05:39 +00:00
if (this.isSuspended) return;
2018-03-15 10:53:46 +00:00
if (this.os.debug) {
this.in++;
this.inout.push({ type: 'in', at: new Date(), data: message.data });
}
2017-02-18 04:18:59 +00:00
try {
2017-02-18 23:02:59 +00:00
const msg = JSON.parse(message.data);
2017-11-16 16:24:44 +00:00
if (msg.type) this.emit(msg.type, msg.body);
2017-11-13 09:05:35 +00:00
} catch (e) {
2017-02-18 04:18:59 +00:00
// noop
}
2017-03-18 11:05:11 +00:00
}
2017-02-18 04:18:59 +00:00
2017-05-10 20:08:12 +00:00
/**
* Send a message to connection
*/
2018-03-15 10:53:46 +00:00
public send(data) {
2018-03-15 21:05:39 +00:00
if (this.isSuspended) return;
2017-03-21 09:14:59 +00:00
// まだ接続が確立されていなかったらバッファリングして次に接続した時に送信する
if (this.state != 'connected') {
2018-03-15 10:53:46 +00:00
this.buffer.push(data);
2017-03-21 09:14:59 +00:00
return;
2017-11-13 09:05:35 +00:00
}
2017-03-21 09:14:59 +00:00
2018-03-15 10:53:46 +00:00
if (this.os.debug) {
this.out++;
this.inout.push({ type: 'out', at: new Date(), data });
}
this.socket.send(JSON.stringify(data));
2017-03-20 04:54:59 +00:00
}
2017-05-10 20:08:12 +00:00
/**
* Close this connection
*/
2017-11-13 09:05:35 +00:00
public close() {
2018-03-15 10:53:46 +00:00
this.os.unregisterStreamConnection(this);
2017-03-18 11:05:11 +00:00
this.socket.removeEventListener('open', this.onOpen);
this.socket.removeEventListener('message', this.onMessage);
}
}