cleanup and unit tests (#4434)

* put socket.updateHistory behind SessionCommand

* rename /websocket files from .tsx to .ts

* add unit tests to websocket commands

* complete unit tests for webClient commands

* secure wss

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Jeremy Letto 2021-10-17 15:15:09 -05:00 committed by GitHub
parent e9ba195d7d
commit f75ff2a7c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 611 additions and 48 deletions

View file

@ -0,0 +1,101 @@
import { Subject } from 'rxjs';
import { ServerStatus, StatusEnum } from "types";
import { KeepAliveService } from "./KeepAliveService";
import { WebClient } from '../WebClient';
export interface WebSocketOptions {
host: string;
port: string;
user: string;
pass: string;
autojoinrooms: boolean;
keepalive: number;
}
export class WebSocketService {
private socket: WebSocket;
private webClient: WebClient;
public keepAliveService: KeepAliveService;
public message$: Subject<MessageEvent> = new Subject();
public statusChange$: Subject<ServerStatus> = new Subject();
private status: StatusEnum = StatusEnum.DISCONNECTED;
private keepalive: number;
constructor(webClient: WebClient) {
this.webClient = webClient;
this.keepAliveService = new KeepAliveService(this);
this.keepAliveService.disconnected$.subscribe(() => {
this.disconnect();
this.updateStatus(StatusEnum.DISCONNECTED, "Connection timeout");
});
}
public connect(options: WebSocketOptions, protocol: string = 'wss'): void {
const { host, port, keepalive } = options;
this.keepalive = keepalive;
this.socket = this.createWebSocket(`${protocol}://${host}:${port}`);
}
public disconnect(): void {
if (this.socket) {
this.socket.close();
}
}
public checkReadyState(state: number): boolean {
return this.socket.readyState === state;
}
public send(message): void {
this.socket.send(message);
}
public updateStatus(status: StatusEnum, description: string): void {
this.status = status;
this.statusChange$.next({status, description});
}
private createWebSocket(url: string): WebSocket {
const socket = new WebSocket(url);
socket.binaryType = "arraybuffer"; // We are talking binary
socket.onopen = () => {
this.updateStatus(StatusEnum.CONNECTED, "Connected");
this.keepAliveService.startPingLoop(this.keepalive, (pingReceived: Function) => {
const command = this.webClient.protobuf.controller.SessionCommand.create({
".Command_Ping.ext" : this.webClient.protobuf.controller.Command_Ping.create()
});
this.webClient.protobuf.sendSessionCommand(command, () => {
pingReceived();
});
});
};
socket.onclose = () => {
// dont overwrite failure messages
if (this.status !== StatusEnum.DISCONNECTED) {
this.updateStatus(StatusEnum.DISCONNECTED, "Connection Closed");
}
this.keepAliveService.endPingLoop();
};
socket.onerror = () => {
this.updateStatus(StatusEnum.DISCONNECTED, "Connection Failed");
};
socket.onmessage = (event: MessageEvent) => {
this.message$.next(event);
}
return socket;
}
}