Merge pull request #293 from peers/290-rangeerror-invalid-websocket-frame-rsv2-and-rsv3-must-be-clear
fix: the server could crash if a client sends invalid frames
This commit is contained in:
commit
ae4f6fd8c6
@ -1,13 +1,13 @@
|
|||||||
import { MyWebSocket } from "../services/webSocketServer/webSocket";
|
import type WebSocket from "ws";
|
||||||
|
|
||||||
export interface IClient {
|
export interface IClient {
|
||||||
getId(): string;
|
getId(): string;
|
||||||
|
|
||||||
getToken(): string;
|
getToken(): string;
|
||||||
|
|
||||||
getSocket(): MyWebSocket | null;
|
getSocket(): WebSocket | null;
|
||||||
|
|
||||||
setSocket(socket: MyWebSocket | null): void;
|
setSocket(socket: WebSocket | null): void;
|
||||||
|
|
||||||
getLastPing(): number;
|
getLastPing(): number;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export interface IClient {
|
|||||||
export class Client implements IClient {
|
export class Client implements IClient {
|
||||||
private readonly id: string;
|
private readonly id: string;
|
||||||
private readonly token: string;
|
private readonly token: string;
|
||||||
private socket: MyWebSocket | null = null;
|
private socket: WebSocket | null = null;
|
||||||
private lastPing: number = new Date().getTime();
|
private lastPing: number = new Date().getTime();
|
||||||
|
|
||||||
constructor({ id, token }: { id: string; token: string; }) {
|
constructor({ id, token }: { id: string; token: string; }) {
|
||||||
@ -35,11 +35,11 @@ export class Client implements IClient {
|
|||||||
return this.token;
|
return this.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSocket(): MyWebSocket | null {
|
public getSocket(): WebSocket | null {
|
||||||
return this.socket;
|
return this.socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSocket(socket: MyWebSocket | null): void {
|
public setSocket(socket: WebSocket | null): void {
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import { IConfig } from "../../config";
|
|||||||
import { Errors, MessageType } from "../../enums";
|
import { Errors, MessageType } from "../../enums";
|
||||||
import { Client, IClient } from "../../models/client";
|
import { Client, IClient } from "../../models/client";
|
||||||
import { IRealm } from "../../models/realm";
|
import { IRealm } from "../../models/realm";
|
||||||
import { MyWebSocket } from "./webSocket";
|
import type WebSocket from "ws";
|
||||||
|
|
||||||
export interface IWebSocketServer extends EventEmitter {
|
export interface IWebSocketServer extends EventEmitter {
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
@ -42,11 +42,14 @@ export class WebSocketServer extends EventEmitter implements IWebSocketServer {
|
|||||||
|
|
||||||
this.socketServer = new WebSocketLib.Server({ path: this.path, server });
|
this.socketServer = new WebSocketLib.Server({ path: this.path, server });
|
||||||
|
|
||||||
this.socketServer.on("connection", (socket: MyWebSocket, req) => this._onSocketConnection(socket, req));
|
this.socketServer.on("connection", (socket, req) => this._onSocketConnection(socket, req));
|
||||||
this.socketServer.on("error", (error: Error) => this._onSocketError(error));
|
this.socketServer.on("error", (error: Error) => this._onSocketError(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onSocketConnection(socket: MyWebSocket, req: IncomingMessage): void {
|
private _onSocketConnection(socket: WebSocket, req: IncomingMessage): void {
|
||||||
|
// An unhandled socket error might crash the server. Handle it first.
|
||||||
|
socket.on("error", error => this._onSocketError(error))
|
||||||
|
|
||||||
const { query = {} } = url.parse(req.url ?? '', true);
|
const { query = {} } = url.parse(req.url ?? '', true);
|
||||||
|
|
||||||
const { id, token, key }: IAuthParams = query;
|
const { id, token, key }: IAuthParams = query;
|
||||||
@ -85,7 +88,7 @@ export class WebSocketServer extends EventEmitter implements IWebSocketServer {
|
|||||||
|
|
||||||
private _registerClient({ socket, id, token }:
|
private _registerClient({ socket, id, token }:
|
||||||
{
|
{
|
||||||
socket: MyWebSocket;
|
socket: WebSocket;
|
||||||
id: string;
|
id: string;
|
||||||
token: string;
|
token: string;
|
||||||
}): void {
|
}): void {
|
||||||
@ -103,7 +106,7 @@ export class WebSocketServer extends EventEmitter implements IWebSocketServer {
|
|||||||
this._configureWS(socket, newClient);
|
this._configureWS(socket, newClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _configureWS(socket: MyWebSocket, client: IClient): void {
|
private _configureWS(socket: WebSocket, client: IClient): void {
|
||||||
client.setSocket(socket);
|
client.setSocket(socket);
|
||||||
|
|
||||||
// Cleanup after a socket closes.
|
// Cleanup after a socket closes.
|
||||||
@ -130,7 +133,7 @@ export class WebSocketServer extends EventEmitter implements IWebSocketServer {
|
|||||||
this.emit("connection", client);
|
this.emit("connection", client);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _sendErrorAndClose(socket: MyWebSocket, msg: Errors): void {
|
private _sendErrorAndClose(socket: WebSocket, msg: Errors): void {
|
||||||
socket.send(
|
socket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: MessageType.ERROR,
|
type: MessageType.ERROR,
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
import EventEmitter from "events";
|
|
||||||
import WebSocketLib from "ws";
|
|
||||||
|
|
||||||
export type MyWebSocket = WebSocketLib & EventEmitter;
|
|
@ -3,9 +3,9 @@ import { Client } from '../../../../src/models/client';
|
|||||||
import { TransmissionHandler } from '../../../../src/messageHandler/handlers';
|
import { TransmissionHandler } from '../../../../src/messageHandler/handlers';
|
||||||
import { Realm } from '../../../../src/models/realm';
|
import { Realm } from '../../../../src/models/realm';
|
||||||
import { MessageType } from '../../../../src/enums';
|
import { MessageType } from '../../../../src/enums';
|
||||||
import { MyWebSocket } from '../../../../src/services/webSocketServer/webSocket';
|
import type WebSocket from "ws";
|
||||||
|
|
||||||
const createFakeSocket = (): MyWebSocket => {
|
const createFakeSocket = (): WebSocket => {
|
||||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||||
const sock = {
|
const sock = {
|
||||||
send: (): void => { },
|
send: (): void => { },
|
||||||
@ -14,7 +14,7 @@ const createFakeSocket = (): MyWebSocket => {
|
|||||||
};
|
};
|
||||||
/* eslint-enable @typescript-eslint/no-empty-function */
|
/* eslint-enable @typescript-eslint/no-empty-function */
|
||||||
|
|
||||||
return (sock as unknown as MyWebSocket);
|
return (sock as unknown as WebSocket);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Transmission handler', () => {
|
describe('Transmission handler', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user