0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 09:50:43 -05:00
server/project/src/servers/WebSocketServer.ts

129 lines
4.8 KiB
TypeScript
Raw Normal View History

import http, { IncomingMessage } from "node:http";
2023-03-03 15:23:46 +00:00
import { inject, injectable } from "tsyringe";
import WebSocket from "ws";
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
import { INotification, NotificationType } from "@spt-aki/models/eft/notifier/INotifier";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { IHttpConfig } from "@spt-aki/models/spt/config/IHttpConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
2023-03-03 15:23:46 +00:00
@injectable()
export class WebSocketServer
2023-03-03 15:23:46 +00:00
{
constructor(
@inject("WinstonLogger") protected logger: ILogger,
@inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("ConfigServer") protected configServer: ConfigServer,
@inject("LocalisationService") protected localisationService: LocalisationService,
@inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper,
)
2023-03-03 15:23:46 +00:00
{
this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP);
}
protected httpConfig: IHttpConfig;
protected defaultNotification: INotification = { type: NotificationType.PING, eventId: "ping" };
2023-03-03 15:23:46 +00:00
protected webSockets: Record<string, WebSocket.WebSocket> = {};
protected websocketPingHandler = null;
public setupWebSocket(httpServer: http.Server): void
2023-03-03 15:23:46 +00:00
{
const webSocketServer = new WebSocket.Server({ server: httpServer });
2023-03-03 15:23:46 +00:00
webSocketServer.addListener("listening", () =>
2023-03-03 15:23:46 +00:00
{
this.logger.success(
this.localisationService.getText("websocket-started", this.httpServerHelper.getWebsocketUrl()),
);
this.logger.success(
`${this.localisationService.getText("server_running")}, ${this.getRandomisedMessage()}!`,
);
2023-03-03 15:23:46 +00:00
});
webSocketServer.addListener("connection", this.wsOnConnection.bind(this));
}
public sendMessage(sessionID: string, output: INotification): void
{
try
{
if (this.isConnectionWebSocket(sessionID))
{
this.webSockets[sessionID].send(this.jsonUtil.serialize(output));
2023-03-03 15:23:46 +00:00
this.logger.debug(this.localisationService.getText("websocket-message_sent"));
}
else
{
this.logger.debug(this.localisationService.getText("websocket-not_ready_message_not_sent", sessionID));
}
}
catch (err)
{
this.logger.error(this.localisationService.getText("websocket-message_send_failed_with_error", err));
}
}
protected getRandomisedMessage(): string
2023-03-03 15:23:46 +00:00
{
if (this.randomUtil.getInt(1, 1000) > 999)
2023-03-03 15:23:46 +00:00
{
2023-08-09 12:07:31 +01:00
return this.localisationService.getRandomTextThatMatchesPartialKey("server_start_meme_");
2023-03-03 15:23:46 +00:00
}
return (globalThis.G_RELEASE_CONFIGURATION)
? `${this.localisationService.getText("server_start_success")}!`
: this.localisationService.getText("server_start_success");
}
public isConnectionWebSocket(sessionID: string): boolean
2023-03-03 15:23:46 +00:00
{
return this.webSockets[sessionID] !== undefined && this.webSockets[sessionID].readyState === WebSocket.OPEN;
}
protected wsOnConnection(ws: WebSocket.WebSocket, req: IncomingMessage): void
2023-03-03 15:23:46 +00:00
{
// Strip request and break it into sections
const splitUrl = req.url.substring(0, req.url.indexOf("?")).split("/");
const sessionID = splitUrl.pop();
this.logger.info(this.localisationService.getText("websocket-player_connected", sessionID));
const logger = this.logger;
const msgToLog = this.localisationService.getText("websocket-received_message", sessionID);
ws.on("message", function message(msg)
2023-03-03 15:23:46 +00:00
{
logger.info(`${msgToLog} ${msg}`);
});
this.webSockets[sessionID] = ws;
if (this.websocketPingHandler)
2023-03-03 15:23:46 +00:00
{
clearInterval(this.websocketPingHandler);
}
this.websocketPingHandler = setInterval(() =>
2023-03-03 15:23:46 +00:00
{
this.logger.debug(this.localisationService.getText("websocket-pinging_player", sessionID));
if (ws.readyState === WebSocket.OPEN)
2023-03-03 15:23:46 +00:00
{
ws.send(this.jsonUtil.serialize(this.defaultNotification));
2023-03-03 15:23:46 +00:00
}
else
2023-03-03 15:23:46 +00:00
{
this.logger.debug(this.localisationService.getText("websocket-socket_lost_deleting_handle"));
clearInterval(this.websocketPingHandler);
delete this.webSockets[sessionID];
}
}, this.httpConfig.webSocketPingDelayMs);
}
}