commit
e42f1a6a21
@ -38,27 +38,27 @@
|
||||
"dependencies": {
|
||||
"axios": "^0.20.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"busboy": "^0.3.1",
|
||||
"circular-json": "^0.5.9",
|
||||
"express": "^4.17.1",
|
||||
"generic-type-guard": "^3.2.0",
|
||||
"google-protobuf": "^3.13.0",
|
||||
"http-status-codes": "^1.4.0",
|
||||
"iterall": "^1.3.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"prom-client": "^12.0.0",
|
||||
"socket.io": "^2.3.0",
|
||||
"query-string": "^6.13.3",
|
||||
"systeminformation": "^4.26.5",
|
||||
"ts-node-dev": "^1.0.0-pre.44",
|
||||
"typescript": "^3.8.3",
|
||||
"uWebSockets.js": "uNetworking/uWebSockets.js#v18.5.0",
|
||||
"uuidv4": "^6.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/circular-json": "^0.4.0",
|
||||
"@types/express": "^4.17.4",
|
||||
"@types/google-protobuf": "^3.7.3",
|
||||
"@types/http-status-codes": "^1.2.0",
|
||||
"@types/jasmine": "^3.5.10",
|
||||
"@types/jsonwebtoken": "^8.3.8",
|
||||
"@types/socket.io": "^2.1.4",
|
||||
"@types/uuidv4": "^5.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.26.0",
|
||||
"@typescript-eslint/parser": "^2.26.0",
|
||||
|
@ -1,3 +1,3 @@
|
||||
// lib/server.ts
|
||||
import App from "./src/App";
|
||||
App.listen(8080, () => console.log(`Example app listening on port 8080!`))
|
||||
App.listen(8080, () => console.log(`WorkAdventure starting on port 8080!`))
|
||||
|
@ -1,17 +1,13 @@
|
||||
// lib/app.ts
|
||||
import {IoSocketController} from "./Controller/IoSocketController"; //TODO fix import by "_Controller/..."
|
||||
import {AuthenticateController} from "./Controller/AuthenticateController"; //TODO fix import by "_Controller/..."
|
||||
import express from "express";
|
||||
import {Application, Request, Response} from 'express';
|
||||
import bodyParser = require('body-parser');
|
||||
import * as http from "http";
|
||||
import {MapController} from "./Controller/MapController";
|
||||
import {PrometheusController} from "./Controller/PrometheusController";
|
||||
import {DebugController} from "./Controller/DebugController";
|
||||
import {App as uwsApp} from "./Server/sifrr.server";
|
||||
|
||||
class App {
|
||||
public app: Application;
|
||||
public server: http.Server;
|
||||
public app: uwsApp;
|
||||
public ioSocketController: IoSocketController;
|
||||
public authenticateController: AuthenticateController;
|
||||
public mapController: MapController;
|
||||
@ -19,40 +15,15 @@ class App {
|
||||
private debugController: DebugController;
|
||||
|
||||
constructor() {
|
||||
this.app = express();
|
||||
|
||||
//config server http
|
||||
this.server = http.createServer(this.app);
|
||||
|
||||
this.config();
|
||||
this.crossOrigin();
|
||||
|
||||
//TODO add middleware with access token to secure api
|
||||
this.app = new uwsApp();
|
||||
|
||||
//create socket controllers
|
||||
this.ioSocketController = new IoSocketController(this.server);
|
||||
this.ioSocketController = new IoSocketController(this.app);
|
||||
this.authenticateController = new AuthenticateController(this.app);
|
||||
this.mapController = new MapController(this.app);
|
||||
this.prometheusController = new PrometheusController(this.app, this.ioSocketController);
|
||||
this.debugController = new DebugController(this.app, this.ioSocketController);
|
||||
}
|
||||
|
||||
// TODO add session user
|
||||
private config(): void {
|
||||
this.app.use(bodyParser.json());
|
||||
this.app.use(bodyParser.urlencoded({extended: false}));
|
||||
}
|
||||
|
||||
private crossOrigin(){
|
||||
this.app.use((req: Request, res: Response, next) => {
|
||||
res.setHeader("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
|
||||
// Request methods you wish to allow
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
|
||||
// Request headers you wish to allow
|
||||
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
||||
next();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new App().server;
|
||||
export default new App().app;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {Application, Request, Response} from "express";
|
||||
import Jwt from "jsonwebtoken";
|
||||
import {OK} from "http-status-codes";
|
||||
import {ADMIN_API_TOKEN, ADMIN_API_URL, SECRET_KEY, URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||
import { uuid } from 'uuidv4';
|
||||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||
import {BaseController} from "./BaseController";
|
||||
import Axios from "axios";
|
||||
|
||||
export interface TokenInterface {
|
||||
@ -17,20 +17,33 @@ interface AdminApiData {
|
||||
userUuid: string
|
||||
}
|
||||
|
||||
export class AuthenticateController {
|
||||
App : Application;
|
||||
export class AuthenticateController extends BaseController {
|
||||
|
||||
constructor(App : Application) {
|
||||
this.App = App;
|
||||
constructor(private App : TemplatedApp) {
|
||||
super();
|
||||
this.login();
|
||||
}
|
||||
|
||||
//permit to login on application. Return token to connect on Websocket IO.
|
||||
login(){
|
||||
// For now, let's completely forget the /login route.
|
||||
this.App.post("/login", async (req: Request, res: Response) => {
|
||||
this.App.options("/login", (res: HttpResponse, req: HttpRequest) => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
res.end();
|
||||
});
|
||||
|
||||
this.App.post("/login", (res: HttpResponse, req: HttpRequest) => {
|
||||
(async () => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
res.onAborted(() => {
|
||||
console.warn('Login request was aborted');
|
||||
})
|
||||
const host = req.getHeader('host');
|
||||
const param = await res.json();
|
||||
|
||||
//todo: what to do if the organizationMemberToken is already used?
|
||||
const organizationMemberToken:string|null = req.body.organizationMemberToken;
|
||||
const organizationMemberToken:string|null = param.organizationMemberToken;
|
||||
|
||||
try {
|
||||
let userUuid;
|
||||
@ -51,23 +64,25 @@ export class AuthenticateController {
|
||||
newUrl = this.getNewUrlOnAdminAuth(data)
|
||||
} else {
|
||||
userUuid = uuid();
|
||||
mapUrlStart = req.headers.host?.replace('api.', 'maps.') + URL_ROOM_STARTED;
|
||||
mapUrlStart = host.replace('api.', 'maps.') + URL_ROOM_STARTED;
|
||||
newUrl = null;
|
||||
}
|
||||
|
||||
const authToken = Jwt.sign({userUuid: userUuid}, SECRET_KEY, {expiresIn: '24h'});
|
||||
return res.status(OK).send({
|
||||
res.writeStatus("200 OK").end(JSON.stringify({
|
||||
authToken,
|
||||
userUuid,
|
||||
mapUrlStart,
|
||||
newUrl,
|
||||
});
|
||||
}));
|
||||
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
return res.status(e.status || 500).send('An error happened');
|
||||
console.log("An error happened", e)
|
||||
res.writeStatus(e.status || "500 Internal Server Error").end('An error happened');
|
||||
}
|
||||
|
||||
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
|
10
back/src/Controller/BaseController.ts
Normal file
10
back/src/Controller/BaseController.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import {HttpResponse} from "uWebSockets.js";
|
||||
|
||||
|
||||
export class BaseController {
|
||||
protected addCorsHeaders(res: HttpResponse): void {
|
||||
res.writeHeader('access-control-allow-headers', 'Origin, X-Requested-With, Content-Type, Accept');
|
||||
res.writeHeader('access-control-allow-methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
|
||||
res.writeHeader('access-control-allow-origin', '*');
|
||||
}
|
||||
}
|
@ -1,22 +1,25 @@
|
||||
import {Application, Request, Response} from "express";
|
||||
import {OK} from "http-status-codes";
|
||||
import {ADMIN_API_TOKEN} from "../Enum/EnvironmentVariable";
|
||||
import {IoSocketController} from "_Controller/IoSocketController";
|
||||
import {stringify} from "circular-json";
|
||||
import {HttpRequest, HttpResponse} from "uWebSockets.js";
|
||||
import { parse } from 'query-string';
|
||||
import {App} from "../Server/sifrr.server";
|
||||
|
||||
export class DebugController {
|
||||
constructor(private App : Application, private ioSocketController: IoSocketController) {
|
||||
constructor(private App : App, private ioSocketController: IoSocketController) {
|
||||
this.getDump();
|
||||
}
|
||||
|
||||
|
||||
getDump(){
|
||||
this.App.get("/dump", (req: Request, res: Response) => {
|
||||
if (req.query.token !== ADMIN_API_TOKEN) {
|
||||
this.App.get("/dump", (res: HttpResponse, req: HttpRequest) => {
|
||||
const query = parse(req.getQuery());
|
||||
|
||||
if (query.token !== ADMIN_API_TOKEN) {
|
||||
return res.status(401).send('Invalid token sent!');
|
||||
}
|
||||
|
||||
return res.status(OK).contentType('application/json').send(stringify(
|
||||
return res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(stringify(
|
||||
this.ioSocketController.getWorlds(),
|
||||
(key: unknown, value: unknown) => {
|
||||
if(value instanceof Map) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,30 +1,34 @@
|
||||
import express from "express";
|
||||
import {Application, Request, Response} from "express";
|
||||
import {OK} from "http-status-codes";
|
||||
import {URL_ROOM_STARTED} from "../Enum/EnvironmentVariable";
|
||||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||
import {BaseController} from "./BaseController";
|
||||
|
||||
//todo: delete this
|
||||
export class MapController {
|
||||
App: Application;
|
||||
export class MapController extends BaseController{
|
||||
|
||||
constructor(App: Application) {
|
||||
constructor(private App : TemplatedApp) {
|
||||
super();
|
||||
this.App = App;
|
||||
this.getStartMap();
|
||||
this.assetMaps();
|
||||
}
|
||||
|
||||
assetMaps() {
|
||||
this.App.use('/map/files', express.static('src/Assets/Maps'));
|
||||
}
|
||||
|
||||
// Returns a map mapping map name to file name of the map
|
||||
getStartMap() {
|
||||
this.App.get("/start-map", (req: Request, res: Response) => {
|
||||
const url = req.headers.host?.replace('api.', 'maps.') + URL_ROOM_STARTED;
|
||||
res.status(OK).send({
|
||||
this.App.options("/start-map", (res: HttpResponse, req: HttpRequest) => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
res.end();
|
||||
});
|
||||
|
||||
this.App.get("/start-map", (res: HttpResponse, req: HttpRequest) => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
const url = req.getHeader('host').replace('api.', 'maps.') + URL_ROOM_STARTED;
|
||||
res.writeStatus("200 OK").end(JSON.stringify({
|
||||
mapUrlStart: url,
|
||||
startInstance: "global"
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import {Application, Request, Response} from "express";
|
||||
import {App} from "../Server/sifrr.server";
|
||||
import {IoSocketController} from "_Controller/IoSocketController";
|
||||
import {HttpRequest, HttpResponse} from "uWebSockets.js";
|
||||
const register = require('prom-client').register;
|
||||
const collectDefaultMetrics = require('prom-client').collectDefaultMetrics;
|
||||
|
||||
export class PrometheusController {
|
||||
constructor(private App: Application, private ioSocketController: IoSocketController) {
|
||||
constructor(private App: App, private ioSocketController: IoSocketController) {
|
||||
collectDefaultMetrics({
|
||||
timeout: 10000,
|
||||
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5], // These are the default buckets.
|
||||
@ -13,8 +14,8 @@ export class PrometheusController {
|
||||
this.App.get("/metrics", this.metrics.bind(this));
|
||||
}
|
||||
|
||||
private metrics(req: Request, res: Response): void {
|
||||
res.set('Content-Type', register.contentType);
|
||||
private metrics(res: HttpResponse, req: HttpRequest): void {
|
||||
res.writeHeader('Content-Type', register.contentType);
|
||||
res.end(register.metrics());
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ const GROUP_RADIUS = process.env.GROUP_RADIUS ? Number(process.env.GROUP_RADIUS)
|
||||
const ALLOW_ARTILLERY = process.env.ALLOW_ARTILLERY ? process.env.ALLOW_ARTILLERY == 'true' : false;
|
||||
const ADMIN_API_URL = process.env.ADMIN_API_URL || null;
|
||||
const ADMIN_API_TOKEN = process.env.ADMIN_API_TOKEN || null;
|
||||
const CPU_OVERHEAT_THRESHOLD = Number(process.env.CPU_OVERHEAT_THRESHOLD) || 80;
|
||||
|
||||
export {
|
||||
SECRET_KEY,
|
||||
@ -14,4 +15,5 @@ export {
|
||||
ADMIN_API_TOKEN,
|
||||
GROUP_RADIUS,
|
||||
ALLOW_ARTILLERY,
|
||||
CPU_OVERHEAT_THRESHOLD,
|
||||
}
|
@ -87,7 +87,7 @@ export class Group implements Movable {
|
||||
join(user: User): void
|
||||
{
|
||||
// Broadcast on the right event
|
||||
this.connectCallback(user.id, this);
|
||||
this.connectCallback(user, this);
|
||||
this.users.add(user);
|
||||
user.group = this;
|
||||
}
|
||||
@ -105,7 +105,7 @@ export class Group implements Movable {
|
||||
}
|
||||
|
||||
// Broadcast on the right event
|
||||
this.disconnectCallback(user.id, this);
|
||||
this.disconnectCallback(user, this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,7 @@ import {Zone} from "_Model/Zone";
|
||||
import {Movable} from "_Model/Movable";
|
||||
import {PositionInterface} from "_Model/PositionInterface";
|
||||
import {PositionNotifier} from "_Model/PositionNotifier";
|
||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
||||
|
||||
export class User implements Movable {
|
||||
public listenedZones: Set<Zone>;
|
||||
@ -13,7 +14,8 @@ export class User implements Movable {
|
||||
public id: number,
|
||||
private position: PointInterface,
|
||||
public silent: boolean,
|
||||
private positionNotifier: PositionNotifier
|
||||
private positionNotifier: PositionNotifier,
|
||||
public readonly socket: ExSocketInterface
|
||||
) {
|
||||
this.listenedZones = new Set<Zone>();
|
||||
|
||||
|
@ -1,24 +1,23 @@
|
||||
import {Socket} from "socket.io";
|
||||
import {PointInterface} from "./PointInterface";
|
||||
import {Identificable} from "./Identificable";
|
||||
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
||||
import {BatchMessage, SubMessage} from "../../Messages/generated/messages_pb";
|
||||
import {WebSocket} from "uWebSockets.js"
|
||||
|
||||
export interface ExSocketInterface extends Socket, Identificable {
|
||||
export interface ExSocketInterface extends WebSocket, Identificable {
|
||||
token: string;
|
||||
roomId: string;
|
||||
webRtcRoomId: string|undefined;
|
||||
userId: number; // A temporary (autoincremented) identifier for this user
|
||||
userUuid: string; // A unique identifier for this user
|
||||
name: string;
|
||||
characterLayers: string[];
|
||||
position: PointInterface;
|
||||
viewport: ViewportInterface;
|
||||
isArtillery: boolean; // Whether this socket is opened by Artillery for load testing (hack)
|
||||
/**
|
||||
* Pushes an event that will be sent in the next batch of events
|
||||
*/
|
||||
emitInBatch: (event: string, payload: SubMessage) => void;
|
||||
emitInBatch: (payload: SubMessage) => void;
|
||||
batchedMessages: BatchMessage;
|
||||
batchTimeout: NodeJS.Timeout|null;
|
||||
disconnecting: boolean
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import {PointInterface} from "./PointInterface";
|
||||
import {ItemEventMessage, PositionMessage} from "../../Messages/generated/messages_pb";
|
||||
import {ItemEventMessage, PointMessage, PositionMessage} from "../../Messages/generated/messages_pb";
|
||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
||||
import Direction = PositionMessage.Direction;
|
||||
import {ItemEventMessageInterface} from "_Model/Websocket/ItemEventMessage";
|
||||
import {PositionInterface} from "_Model/PositionInterface";
|
||||
|
||||
export class ProtobufUtils {
|
||||
|
||||
@ -34,6 +35,42 @@ export class ProtobufUtils {
|
||||
return position;
|
||||
}
|
||||
|
||||
public static toPointInterface(position: PositionMessage): PointInterface {
|
||||
let direction: string;
|
||||
switch (position.getDirection()) {
|
||||
case Direction.UP:
|
||||
direction = 'up';
|
||||
break;
|
||||
case Direction.DOWN:
|
||||
direction = 'down';
|
||||
break;
|
||||
case Direction.LEFT:
|
||||
direction = 'left';
|
||||
break;
|
||||
case Direction.RIGHT:
|
||||
direction = 'right';
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unexpected direction");
|
||||
}
|
||||
|
||||
// sending to all clients in room except sender
|
||||
return {
|
||||
x: position.getX(),
|
||||
y: position.getY(),
|
||||
direction,
|
||||
moving: position.getMoving(),
|
||||
};
|
||||
}
|
||||
|
||||
public static toPointMessage(point: PositionInterface): PointMessage {
|
||||
const position = new PointMessage();
|
||||
position.setX(Math.floor(point.x));
|
||||
position.setY(Math.floor(point.y));
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
public static toItemEvent(itemEventMessage: ItemEventMessage): ItemEventMessageInterface {
|
||||
return {
|
||||
itemId: itemEventMessage.getItemid(),
|
||||
|
@ -11,8 +11,8 @@ import {PositionNotifier} from "./PositionNotifier";
|
||||
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
||||
import {Movable} from "_Model/Movable";
|
||||
|
||||
export type ConnectCallback = (user: number, group: Group) => void;
|
||||
export type DisconnectCallback = (user: number, group: Group) => void;
|
||||
export type ConnectCallback = (user: User, group: Group) => void;
|
||||
export type DisconnectCallback = (user: User, group: Group) => void;
|
||||
|
||||
export class World {
|
||||
private readonly minDistance: number;
|
||||
@ -55,8 +55,8 @@ export class World {
|
||||
return this.users;
|
||||
}
|
||||
|
||||
public join(socket : Identificable, userPosition: PointInterface): void {
|
||||
const user = new User(socket.userId, userPosition, false, this.positionNotifier);
|
||||
public join(socket : ExSocketInterface, userPosition: PointInterface): void {
|
||||
const user = new User(socket.userId, userPosition, false, this.positionNotifier, socket);
|
||||
this.users.set(socket.userId, user);
|
||||
// Let's call update position to trigger the join / leave room
|
||||
//this.updatePosition(socket, userPosition);
|
||||
@ -74,8 +74,8 @@ export class World {
|
||||
this.users.delete(user.userId);
|
||||
|
||||
if (userObj !== undefined) {
|
||||
this.positionNotifier.leave(userObj);
|
||||
this.positionNotifier.removeViewport(userObj);
|
||||
this.positionNotifier.leave(userObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
13
back/src/Server/server/app.ts
Normal file
13
back/src/Server/server/app.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { App as _App, AppOptions } from 'uWebSockets.js';
|
||||
import BaseApp from './baseapp';
|
||||
import { extend } from './utils';
|
||||
import { UwsApp } from './types';
|
||||
|
||||
class App extends (<UwsApp>_App) {
|
||||
constructor(options: AppOptions = {}) {
|
||||
super(options); // eslint-disable-line constructor-super
|
||||
extend(this, new BaseApp());
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
111
back/src/Server/server/baseapp.ts
Normal file
111
back/src/Server/server/baseapp.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import { Readable } from 'stream';
|
||||
import { us_listen_socket_close, TemplatedApp, HttpResponse, HttpRequest } from 'uWebSockets.js';
|
||||
|
||||
import { stob } from './utils';
|
||||
import { Handler } from './types';
|
||||
|
||||
const noOp = () => true;
|
||||
|
||||
const handleBody = (res: HttpResponse, req: HttpRequest) => {
|
||||
const contType = req.getHeader('content-type');
|
||||
|
||||
res.bodyStream = function() {
|
||||
const stream = new Readable();
|
||||
stream._read = noOp; // eslint-disable-line @typescript-eslint/unbound-method
|
||||
|
||||
this.onData((ab, isLast) => {
|
||||
// uint and then slicing is bit faster than slice and then uint
|
||||
stream.push(new Uint8Array(ab.slice((ab as any).byteOffset, ab.byteLength))); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
if (isLast) {
|
||||
stream.push(null);
|
||||
}
|
||||
});
|
||||
|
||||
return stream;
|
||||
};
|
||||
|
||||
res.body = () => stob(res.bodyStream());
|
||||
|
||||
if (contType.includes('application/json'))
|
||||
res.json = async () => JSON.parse(await res.body());
|
||||
};
|
||||
|
||||
class BaseApp {
|
||||
_sockets = new Map();
|
||||
ws!: TemplatedApp['ws'];
|
||||
get!: TemplatedApp['get'];
|
||||
_post!: TemplatedApp['post'];
|
||||
_put!: TemplatedApp['put'];
|
||||
_patch!: TemplatedApp['patch'];
|
||||
_listen!: TemplatedApp['listen'];
|
||||
|
||||
post(pattern: string, handler: Handler) {
|
||||
if (typeof handler !== 'function')
|
||||
throw Error(`handler should be a function, given ${typeof handler}.`);
|
||||
this._post(pattern, (res, req) => {
|
||||
handleBody(res, req);
|
||||
handler(res, req);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
put(pattern: string, handler: Handler) {
|
||||
if (typeof handler !== 'function')
|
||||
throw Error(`handler should be a function, given ${typeof handler}.`);
|
||||
this._put(pattern, (res, req) => {
|
||||
handleBody(res, req);
|
||||
|
||||
handler(res, req);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
patch(pattern: string, handler: Handler) {
|
||||
if (typeof handler !== 'function')
|
||||
throw Error(`handler should be a function, given ${typeof handler}.`);
|
||||
this._patch(pattern, (res, req) => {
|
||||
handleBody(res, req);
|
||||
|
||||
handler(res, req);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
listen(h: string | number, p: Function | number = noOp, cb?: Function) {
|
||||
if (typeof p === 'number' && typeof h === 'string') {
|
||||
this._listen(h, p, socket => {
|
||||
this._sockets.set(p, socket);
|
||||
if (cb === undefined) {
|
||||
throw new Error('cb undefined');
|
||||
}
|
||||
cb(socket);
|
||||
});
|
||||
} else if (typeof h === 'number' && typeof p === 'function') {
|
||||
this._listen(h, socket => {
|
||||
this._sockets.set(h, socket);
|
||||
p(socket);
|
||||
});
|
||||
} else {
|
||||
throw Error(
|
||||
'Argument types: (host: string, port: number, cb?: Function) | (port: number, cb?: Function)'
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
close(port: null | number = null) {
|
||||
if (port) {
|
||||
this._sockets.has(port) && us_listen_socket_close(this._sockets.get(port));
|
||||
this._sockets.delete(port);
|
||||
} else {
|
||||
this._sockets.forEach(app => {
|
||||
us_listen_socket_close(app);
|
||||
});
|
||||
this._sockets.clear();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseApp;
|
13
back/src/Server/server/sslapp.ts
Normal file
13
back/src/Server/server/sslapp.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { SSLApp as _SSLApp, AppOptions } from 'uWebSockets.js';
|
||||
import BaseApp from './baseapp';
|
||||
import { extend } from './utils';
|
||||
import { UwsApp } from './types';
|
||||
|
||||
class SSLApp extends (<UwsApp>_SSLApp) {
|
||||
constructor(options: AppOptions) {
|
||||
super(options); // eslint-disable-line constructor-super
|
||||
extend(this, new BaseApp());
|
||||
}
|
||||
}
|
||||
|
||||
export default SSLApp;
|
11
back/src/Server/server/types.ts
Normal file
11
back/src/Server/server/types.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { AppOptions, TemplatedApp, HttpResponse, HttpRequest } from 'uWebSockets.js';
|
||||
|
||||
export type UwsApp = {
|
||||
(options: AppOptions): TemplatedApp;
|
||||
new (options: AppOptions): TemplatedApp;
|
||||
prototype: TemplatedApp;
|
||||
};
|
||||
|
||||
export type Handler = (res: HttpResponse, req: HttpRequest) => void;
|
||||
|
||||
export {};
|
37
back/src/Server/server/utils.ts
Normal file
37
back/src/Server/server/utils.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { ReadStream } from 'fs';
|
||||
|
||||
function extend(who: any, from: any, overwrite = true) { // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
const ownProps = Object.getOwnPropertyNames(Object.getPrototypeOf(from)).concat(
|
||||
Object.keys(from)
|
||||
);
|
||||
ownProps.forEach(prop => {
|
||||
if (prop === 'constructor' || from[prop] === undefined) return;
|
||||
if (who[prop] && overwrite) {
|
||||
who[`_${prop}`] = who[prop];
|
||||
}
|
||||
if (typeof from[prop] === 'function') who[prop] = from[prop].bind(who);
|
||||
else who[prop] = from[prop];
|
||||
});
|
||||
}
|
||||
|
||||
function stob(stream: ReadStream): Promise<Buffer> {
|
||||
return new Promise(resolve => {
|
||||
const buffers: Buffer[] = [];
|
||||
stream.on('data', buffers.push.bind(buffers));
|
||||
|
||||
stream.on('end', () => {
|
||||
switch (buffers.length) {
|
||||
case 0:
|
||||
resolve(Buffer.allocUnsafe(0));
|
||||
break;
|
||||
case 1:
|
||||
resolve(buffers[0]);
|
||||
break;
|
||||
default:
|
||||
resolve(Buffer.concat(buffers));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export { extend, stob };
|
19
back/src/Server/sifrr.server.ts
Normal file
19
back/src/Server/sifrr.server.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { parse } from 'query-string';
|
||||
import { HttpRequest } from 'uWebSockets.js';
|
||||
import App from './server/app';
|
||||
import SSLApp from './server/sslapp';
|
||||
import * as types from './server/types';
|
||||
|
||||
const getQuery = (req: HttpRequest) => {
|
||||
return parse(req.getQuery());
|
||||
};
|
||||
|
||||
export { App, SSLApp, getQuery };
|
||||
export * from './server/types';
|
||||
|
||||
export default {
|
||||
App,
|
||||
SSLApp,
|
||||
getQuery,
|
||||
...types
|
||||
};
|
55
back/src/Services/CpuTracker.ts
Normal file
55
back/src/Services/CpuTracker.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import {CPU_OVERHEAT_THRESHOLD} from "../Enum/EnvironmentVariable";
|
||||
|
||||
function secNSec2ms(secNSec: Array<number>|number) {
|
||||
if (Array.isArray(secNSec)) {
|
||||
return secNSec[0] * 1000 + secNSec[1] / 1000000;
|
||||
}
|
||||
return secNSec / 1000;
|
||||
}
|
||||
|
||||
class CpuTracker {
|
||||
private cpuPercent: number = 0;
|
||||
private overHeating: boolean = false;
|
||||
|
||||
constructor() {
|
||||
let time = process.hrtime.bigint()
|
||||
let usage = process.cpuUsage()
|
||||
setInterval(() => {
|
||||
const elapTime = process.hrtime.bigint();
|
||||
const elapUsage = process.cpuUsage(usage)
|
||||
usage = process.cpuUsage()
|
||||
|
||||
const elapTimeMS = elapTime - time;
|
||||
const elapUserMS = secNSec2ms(elapUsage.user)
|
||||
const elapSystMS = secNSec2ms(elapUsage.system)
|
||||
this.cpuPercent = Math.round(100 * (elapUserMS + elapSystMS) / Number(elapTimeMS) * 1000000)
|
||||
|
||||
time = elapTime;
|
||||
|
||||
if (!this.overHeating && this.cpuPercent > CPU_OVERHEAT_THRESHOLD) {
|
||||
this.overHeating = true;
|
||||
console.warn('CPU high threshold alert. Going in "overheat" mode');
|
||||
} else if (this.overHeating && this.cpuPercent <= CPU_OVERHEAT_THRESHOLD) {
|
||||
this.overHeating = false;
|
||||
console.log('CPU is back to normal. Canceling "overheat" mode');
|
||||
}
|
||||
|
||||
/*console.log('elapsed time ms: ', elapTimeMS)
|
||||
console.log('elapsed user ms: ', elapUserMS)
|
||||
console.log('elapsed system ms:', elapSystMS)
|
||||
console.log('cpu percent: ', this.cpuPercent)*/
|
||||
}, 100);
|
||||
}
|
||||
|
||||
public getCpuPercent(): number {
|
||||
return this.cpuPercent;
|
||||
}
|
||||
|
||||
public isOverHeating(): boolean {
|
||||
return this.overHeating;
|
||||
}
|
||||
}
|
||||
|
||||
const cpuTracker = new CpuTracker();
|
||||
|
||||
export { cpuTracker };
|
@ -8,6 +8,7 @@ import {PointInterface} from "../src/Model/Websocket/PointInterface";
|
||||
import {Zone} from "_Model/Zone";
|
||||
import {Movable} from "_Model/Movable";
|
||||
import {PositionInterface} from "_Model/PositionInterface";
|
||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
||||
|
||||
|
||||
describe("PositionNotifier", () => {
|
||||
@ -29,14 +30,14 @@ describe("PositionNotifier", () => {
|
||||
y: 500,
|
||||
moving: false,
|
||||
direction: 'down'
|
||||
}, false, positionNotifier);
|
||||
}, false, positionNotifier, {} as ExSocketInterface);
|
||||
|
||||
const user2 = new User(2, {
|
||||
x: -9999,
|
||||
y: -9999,
|
||||
moving: false,
|
||||
direction: 'down'
|
||||
}, false, positionNotifier);
|
||||
}, false, positionNotifier, {} as ExSocketInterface);
|
||||
|
||||
positionNotifier.setViewport(user1, {
|
||||
left: 200,
|
||||
@ -107,14 +108,14 @@ describe("PositionNotifier", () => {
|
||||
y: 500,
|
||||
moving: false,
|
||||
direction: 'down'
|
||||
}, false, positionNotifier);
|
||||
}, false, positionNotifier, {} as ExSocketInterface);
|
||||
|
||||
const user2 = new User(2, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
moving: false,
|
||||
direction: 'down'
|
||||
}, false, positionNotifier);
|
||||
}, false, positionNotifier, {} as ExSocketInterface);
|
||||
|
||||
let newUsers = positionNotifier.setViewport(user1, {
|
||||
left: 200,
|
||||
|
@ -2,22 +2,30 @@ import "jasmine";
|
||||
import {World, ConnectCallback, DisconnectCallback } from "../src/Model/World";
|
||||
import {Point} from "../src/Model/Websocket/MessageUserPosition";
|
||||
import { Group } from "../src/Model/Group";
|
||||
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
|
||||
import {User} from "_Model/User";
|
||||
|
||||
function createMockUser(userId: number): ExSocketInterface {
|
||||
return {
|
||||
userId
|
||||
} as ExSocketInterface;
|
||||
}
|
||||
|
||||
describe("World", () => {
|
||||
it("should connect user1 and user2", () => {
|
||||
let connectCalledNumber: number = 0;
|
||||
const connect: ConnectCallback = (user: number, group: Group): void => {
|
||||
const connect: ConnectCallback = (user: User, group: Group): void => {
|
||||
connectCalledNumber++;
|
||||
}
|
||||
const disconnect: DisconnectCallback = (user: number, group: Group): void => {
|
||||
const disconnect: DisconnectCallback = (user: User, group: Group): void => {
|
||||
|
||||
}
|
||||
|
||||
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
||||
|
||||
world.join({ userId: 1 }, new Point(100, 100));
|
||||
world.join(createMockUser(1), new Point(100, 100));
|
||||
|
||||
world.join({ userId: 2 }, new Point(500, 100));
|
||||
world.join(createMockUser(2), new Point(500, 100));
|
||||
|
||||
world.updatePosition({ userId: 2 }, new Point(261, 100));
|
||||
|
||||
@ -33,24 +41,24 @@ describe("World", () => {
|
||||
|
||||
it("should connect 3 users", () => {
|
||||
let connectCalled: boolean = false;
|
||||
const connect: ConnectCallback = (user: number, group: Group): void => {
|
||||
const connect: ConnectCallback = (user: User, group: Group): void => {
|
||||
connectCalled = true;
|
||||
}
|
||||
const disconnect: DisconnectCallback = (user: number, group: Group): void => {
|
||||
const disconnect: DisconnectCallback = (user: User, group: Group): void => {
|
||||
|
||||
}
|
||||
|
||||
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
||||
|
||||
world.join({ userId: 1 }, new Point(100, 100));
|
||||
world.join(createMockUser(1), new Point(100, 100));
|
||||
|
||||
world.join({ userId: 2 }, new Point(200, 100));
|
||||
world.join(createMockUser(2), new Point(200, 100));
|
||||
|
||||
expect(connectCalled).toBe(true);
|
||||
connectCalled = false;
|
||||
|
||||
// baz joins at the outer limit of the group
|
||||
world.join({ userId: 3 }, new Point(311, 100));
|
||||
world.join(createMockUser(3), new Point(311, 100));
|
||||
|
||||
expect(connectCalled).toBe(false);
|
||||
|
||||
@ -62,18 +70,18 @@ describe("World", () => {
|
||||
it("should disconnect user1 and user2", () => {
|
||||
let connectCalled: boolean = false;
|
||||
let disconnectCallNumber: number = 0;
|
||||
const connect: ConnectCallback = (user: number, group: Group): void => {
|
||||
const connect: ConnectCallback = (user: User, group: Group): void => {
|
||||
connectCalled = true;
|
||||
}
|
||||
const disconnect: DisconnectCallback = (user: number, group: Group): void => {
|
||||
const disconnect: DisconnectCallback = (user: User, group: Group): void => {
|
||||
disconnectCallNumber++;
|
||||
}
|
||||
|
||||
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
||||
|
||||
world.join({ userId: 1 }, new Point(100, 100));
|
||||
world.join(createMockUser(1), new Point(100, 100));
|
||||
|
||||
world.join({ userId: 2 }, new Point(259, 100));
|
||||
world.join(createMockUser(2), new Point(259, 100));
|
||||
|
||||
expect(connectCalled).toBe(true);
|
||||
expect(disconnectCallNumber).toBe(0);
|
||||
|
505
back/yarn.lock
505
back/yarn.lock
@ -20,13 +20,6 @@
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@types/body-parser@*":
|
||||
version "1.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
|
||||
dependencies:
|
||||
"@types/connect" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/circular-json@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/circular-json/-/circular-json-0.4.0.tgz#7401f7e218cfe87ad4c43690da5658b9acaf51be"
|
||||
@ -36,32 +29,10 @@
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
|
||||
|
||||
"@types/connect@*":
|
||||
version "3.4.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/eslint-visitor-keys@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||
|
||||
"@types/express-serve-static-core@*":
|
||||
version "4.17.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.3.tgz#dc8068ee3e354d7fba69feb86b3dfeee49b10f09"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/range-parser" "*"
|
||||
|
||||
"@types/express@^4.17.4":
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.4.tgz#e78bf09f3f530889575f4da8a94cd45384520aac"
|
||||
dependencies:
|
||||
"@types/body-parser" "*"
|
||||
"@types/express-serve-static-core" "*"
|
||||
"@types/qs" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/google-protobuf@^3.7.3":
|
||||
version "3.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.7.3.tgz#429512e541bbd777f2c867692e6335ee08d1f6d4"
|
||||
@ -87,35 +58,10 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/mime@*":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
|
||||
|
||||
"@types/node@*":
|
||||
version "13.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
|
||||
|
||||
"@types/qs@*":
|
||||
version "6.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.1.tgz#937fab3194766256ee09fcd40b781740758617e7"
|
||||
|
||||
"@types/range-parser@*":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||
|
||||
"@types/serve-static@*":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
|
||||
dependencies:
|
||||
"@types/express-serve-static-core" "*"
|
||||
"@types/mime" "*"
|
||||
|
||||
"@types/socket.io@^2.1.4":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/socket.io/-/socket.io-2.1.4.tgz#674e7bc193c5ccdadd4433f79f3660d31759e9ac"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/strip-bom@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2"
|
||||
@ -169,13 +115,6 @@
|
||||
semver "^6.3.0"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
accepts@~1.3.4, accepts@~1.3.7:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||
dependencies:
|
||||
mime-types "~2.1.24"
|
||||
negotiator "0.6.2"
|
||||
|
||||
acorn-jsx@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
|
||||
@ -184,10 +123,6 @@ acorn@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
|
||||
|
||||
after@0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
|
||||
|
||||
ajv@^6.10.0, ajv@^6.10.2:
|
||||
version "6.12.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7"
|
||||
@ -238,22 +173,10 @@ array-find-index@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
|
||||
arraybuffer.slice@~0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
|
||||
|
||||
astral-regex@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
|
||||
|
||||
async-limiter@~1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
|
||||
|
||||
axios@^0.20.0:
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd"
|
||||
@ -261,38 +184,16 @@ axios@^0.20.0:
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
backo2@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
|
||||
base64-arraybuffer@0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
||||
|
||||
base64id@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
|
||||
|
||||
better-assert@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
|
||||
dependencies:
|
||||
callsite "1.0.0"
|
||||
|
||||
bintrees@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524"
|
||||
integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=
|
||||
|
||||
blob@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
|
||||
|
||||
body-parser@1.19.0, body-parser@^1.19.0:
|
||||
body-parser@^1.19.0:
|
||||
version "1.19.0"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||
dependencies:
|
||||
@ -322,14 +223,17 @@ buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
|
||||
busboy@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
||||
integrity sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==
|
||||
dependencies:
|
||||
dicer "0.3.0"
|
||||
|
||||
bytes@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||
|
||||
callsite@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
@ -399,44 +303,14 @@ color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
|
||||
component-bind@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
|
||||
|
||||
component-emitter@1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
|
||||
|
||||
component-inherit@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
|
||||
content-disposition@0.5.3:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
|
||||
dependencies:
|
||||
safe-buffer "5.1.2"
|
||||
|
||||
content-type@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
|
||||
cookie-signature@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
|
||||
cookie@0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
|
||||
|
||||
cookie@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
|
||||
|
||||
cross-spawn@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
@ -470,22 +344,21 @@ debug@2.6.9:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^4.0.1, debug@^4.1.1, debug@~4.1.0:
|
||||
debug@^4.0.1, debug@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@~3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
decamelize@^1.1.2:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
|
||||
decode-uri-component@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
||||
|
||||
deep-is@~0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
@ -494,9 +367,12 @@ depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
|
||||
destroy@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
dicer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
|
||||
integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==
|
||||
dependencies:
|
||||
streamsearch "0.1.2"
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
@ -532,57 +408,12 @@ emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
|
||||
engine.io-client@~3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.0.tgz#82a642b42862a9b3f7a188f41776b2deab643700"
|
||||
dependencies:
|
||||
component-emitter "1.2.1"
|
||||
component-inherit "0.0.3"
|
||||
debug "~4.1.0"
|
||||
engine.io-parser "~2.2.0"
|
||||
has-cors "1.1.0"
|
||||
indexof "0.0.1"
|
||||
parseqs "0.0.5"
|
||||
parseuri "0.0.5"
|
||||
ws "~6.1.0"
|
||||
xmlhttprequest-ssl "~1.5.4"
|
||||
yeast "0.1.2"
|
||||
|
||||
engine.io-parser@~2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.0.tgz#312c4894f57d52a02b420868da7b5c1c84af80ed"
|
||||
dependencies:
|
||||
after "0.8.2"
|
||||
arraybuffer.slice "~0.0.7"
|
||||
base64-arraybuffer "0.1.5"
|
||||
blob "0.0.5"
|
||||
has-binary2 "~1.0.2"
|
||||
|
||||
engine.io@~3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.4.0.tgz#3a962cc4535928c252759a00f98519cb46c53ff3"
|
||||
dependencies:
|
||||
accepts "~1.3.4"
|
||||
base64id "2.0.0"
|
||||
cookie "0.3.1"
|
||||
debug "~4.1.0"
|
||||
engine.io-parser "~2.2.0"
|
||||
ws "^7.1.2"
|
||||
|
||||
error-ex@^1.2.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
@ -688,45 +519,6 @@ esutils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
|
||||
express@^4.17.1:
|
||||
version "4.17.1"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
||||
dependencies:
|
||||
accepts "~1.3.7"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.19.0"
|
||||
content-disposition "0.5.3"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.4.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "~1.1.2"
|
||||
fresh "0.5.2"
|
||||
merge-descriptors "1.0.1"
|
||||
methods "~1.1.2"
|
||||
on-finished "~2.3.0"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~2.0.5"
|
||||
qs "6.7.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.1.2"
|
||||
send "0.17.1"
|
||||
serve-static "1.14.1"
|
||||
setprototypeof "1.1.1"
|
||||
statuses "~1.5.0"
|
||||
type-is "~1.6.18"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
external-editor@^3.0.3:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
|
||||
@ -765,18 +557,6 @@ filewatcher@~3.0.0:
|
||||
dependencies:
|
||||
debounce "^1.0.0"
|
||||
|
||||
finalhandler@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "~2.3.0"
|
||||
parseurl "~1.3.3"
|
||||
statuses "~1.5.0"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
find-up@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
|
||||
@ -801,14 +581,6 @@ follow-redirects@^1.10.0:
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
|
||||
integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
|
||||
|
||||
forwarded@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@ -862,16 +634,6 @@ growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
|
||||
has-binary2@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d"
|
||||
dependencies:
|
||||
isarray "2.0.1"
|
||||
|
||||
has-cors@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
@ -894,16 +656,6 @@ http-errors@1.7.2:
|
||||
statuses ">= 1.5.0 < 2"
|
||||
toidentifier "1.0.0"
|
||||
|
||||
http-errors@~1.7.2:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
|
||||
dependencies:
|
||||
depd "~1.1.2"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.1.1"
|
||||
statuses ">= 1.5.0 < 2"
|
||||
toidentifier "1.0.0"
|
||||
|
||||
http-status-codes@*, http-status-codes@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-1.4.0.tgz#6e4c15d16ff3a9e2df03b89f3a55e1aae05fb477"
|
||||
@ -935,10 +687,6 @@ indent-string@^2.1.0:
|
||||
dependencies:
|
||||
repeating "^2.0.0"
|
||||
|
||||
indexof@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
@ -946,7 +694,7 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@2.0.4:
|
||||
inherits@2:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
|
||||
@ -972,10 +720,6 @@ inquirer@^7.0.0:
|
||||
strip-ansi "^6.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
@ -1014,14 +758,15 @@ is-wsl@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
|
||||
|
||||
isarray@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
|
||||
iterall@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
|
||||
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
|
||||
|
||||
jasmine-core@~3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.5.0.tgz#132c23e645af96d85c8bca13c8758b18429fc1e4"
|
||||
@ -1165,14 +910,6 @@ meow@^3.3.0:
|
||||
redent "^1.0.0"
|
||||
trim-newlines "^1.0.0"
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
|
||||
mime-db@1.43.0:
|
||||
version "1.43.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
|
||||
@ -1183,10 +920,6 @@ mime-types@~2.1.24:
|
||||
dependencies:
|
||||
mime-db "1.43.0"
|
||||
|
||||
mime@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
|
||||
mimic-fn@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
@ -1211,10 +944,6 @@ ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
|
||||
ms@2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||
|
||||
ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
@ -1227,10 +956,6 @@ natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
|
||||
negotiator@0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
|
||||
nice-try@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
@ -1258,10 +983,6 @@ object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
||||
object-component@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
|
||||
|
||||
on-finished@~2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||
@ -1307,22 +1028,6 @@ parse-json@^2.2.0:
|
||||
dependencies:
|
||||
error-ex "^1.2.0"
|
||||
|
||||
parseqs@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
|
||||
dependencies:
|
||||
better-assert "~1.0.0"
|
||||
|
||||
parseuri@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
|
||||
dependencies:
|
||||
better-assert "~1.0.0"
|
||||
|
||||
parseurl@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
||||
|
||||
path-exists@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
|
||||
@ -1341,10 +1046,6 @@ path-parse@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
|
||||
path-type@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
|
||||
@ -1382,13 +1083,6 @@ prom-client@^12.0.0:
|
||||
dependencies:
|
||||
tdigest "^0.1.1"
|
||||
|
||||
proxy-addr@~2.0.5:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
|
||||
dependencies:
|
||||
forwarded "~0.1.2"
|
||||
ipaddr.js "1.9.1"
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
@ -1397,9 +1091,14 @@ qs@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
|
||||
range-parser@~1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
query-string@^6.13.3:
|
||||
version "6.13.3"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.3.tgz#57d1c20e828b0e562d66b7f71a4998bd57f84112"
|
||||
integrity sha512-dldo2oHe3sg03iPshlHw/64nkaRUJKdS0FW85kmWQkmCkqUbNdNdgkgtAufJcEpjzrx6Q9EW9Y3xqx/rM9pGhw==
|
||||
dependencies:
|
||||
decode-uri-component "^0.2.0"
|
||||
split-on-first "^1.0.0"
|
||||
strict-uri-encode "^2.0.0"
|
||||
|
||||
raw-body@2.4.0:
|
||||
version "2.4.0"
|
||||
@ -1487,10 +1186,6 @@ rxjs@^6.5.3:
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
safe-buffer@5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
|
||||
safe-buffer@^5.0.1:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||
@ -1507,33 +1202,6 @@ semver@^6.1.2, semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
|
||||
send@0.17.1:
|
||||
version "0.17.1"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
destroy "~1.0.4"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "~1.7.2"
|
||||
mime "1.6.0"
|
||||
ms "2.1.1"
|
||||
on-finished "~2.3.0"
|
||||
range-parser "~1.2.1"
|
||||
statuses "~1.5.0"
|
||||
|
||||
serve-static@1.14.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
|
||||
dependencies:
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.3"
|
||||
send "0.17.1"
|
||||
|
||||
setprototypeof@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
|
||||
@ -1564,56 +1232,6 @@ slice-ansi@^2.1.0:
|
||||
astral-regex "^1.0.0"
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
|
||||
socket.io-adapter@~1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9"
|
||||
|
||||
socket.io-client@2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4"
|
||||
dependencies:
|
||||
backo2 "1.0.2"
|
||||
base64-arraybuffer "0.1.5"
|
||||
component-bind "1.0.0"
|
||||
component-emitter "1.2.1"
|
||||
debug "~4.1.0"
|
||||
engine.io-client "~3.4.0"
|
||||
has-binary2 "~1.0.2"
|
||||
has-cors "1.1.0"
|
||||
indexof "0.0.1"
|
||||
object-component "0.0.3"
|
||||
parseqs "0.0.5"
|
||||
parseuri "0.0.5"
|
||||
socket.io-parser "~3.3.0"
|
||||
to-array "0.1.4"
|
||||
|
||||
socket.io-parser@~3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f"
|
||||
dependencies:
|
||||
component-emitter "1.2.1"
|
||||
debug "~3.1.0"
|
||||
isarray "2.0.1"
|
||||
|
||||
socket.io-parser@~3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.4.0.tgz#370bb4a151df2f77ce3345ff55a7072cc6e9565a"
|
||||
dependencies:
|
||||
component-emitter "1.2.1"
|
||||
debug "~4.1.0"
|
||||
isarray "2.0.1"
|
||||
|
||||
socket.io@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.3.0.tgz#cd762ed6a4faeca59bc1f3e243c0969311eb73fb"
|
||||
dependencies:
|
||||
debug "~4.1.0"
|
||||
engine.io "~3.4.0"
|
||||
has-binary2 "~1.0.2"
|
||||
socket.io-adapter "~1.1.0"
|
||||
socket.io-client "2.3.0"
|
||||
socket.io-parser "~3.4.0"
|
||||
|
||||
source-map-support@^0.5.12, source-map-support@^0.5.6:
|
||||
version "0.5.16"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
|
||||
@ -1647,14 +1265,29 @@ spdx-license-ids@^3.0.0:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
|
||||
|
||||
split-on-first@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
|
||||
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
|
||||
"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
|
||||
"statuses@>= 1.5.0 < 2":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||
|
||||
streamsearch@0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
||||
|
||||
strict-uri-encode@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
|
||||
|
||||
string-width@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
||||
@ -1753,10 +1386,6 @@ tmp@^0.0.33:
|
||||
dependencies:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
to-array@0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
|
||||
|
||||
toidentifier@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||
@ -1829,7 +1458,7 @@ type-fest@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
|
||||
type-is@~1.6.17, type-is@~1.6.18:
|
||||
type-is@~1.6.17:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
dependencies:
|
||||
@ -1840,7 +1469,11 @@ typescript@^3.8.3:
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
uWebSockets.js@uNetworking/uWebSockets.js#v18.5.0:
|
||||
version "18.5.0"
|
||||
resolved "https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/9b1605d2db82981cafe69dbe356e10ce412f5805"
|
||||
|
||||
unpipe@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
|
||||
@ -1850,10 +1483,6 @@ uri-js@^4.2.2:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
utils-merge@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
|
||||
uuid@7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
|
||||
@ -1875,10 +1504,6 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
|
||||
which@^1.2.9, which@^1.3.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
@ -1899,28 +1524,10 @@ write@1.0.3:
|
||||
dependencies:
|
||||
mkdirp "^0.5.1"
|
||||
|
||||
ws@^7.1.2:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46"
|
||||
|
||||
ws@~6.1.0:
|
||||
version "6.1.4"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9"
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
xmlhttprequest-ssl@~1.5.4:
|
||||
version "1.5.5"
|
||||
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
|
||||
|
||||
xtend@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
|
||||
yeast@0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
|
||||
|
||||
yn@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||
|
@ -1,13 +1,20 @@
|
||||
import {RoomConnection} from "../front/src/Connexion/Connection";
|
||||
import {RoomConnection} from "../front/src/Connexion/RoomConnection";
|
||||
import {connectionManager} from "../front/src/Connexion/ConnectionManager";
|
||||
import * as WebSocket from "ws"
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function startOneUser(): Promise<void> {
|
||||
const connection = await RoomConnection.createConnection('foo', ['male3']);
|
||||
RoomConnection.setWebsocketFactory((url: string) => {
|
||||
return new WebSocket(url);
|
||||
});
|
||||
|
||||
await connection.joinARoom('global__maps.workadventure.localhost/Floor0/floor0', 783, 170, 'down', false, {
|
||||
async function startOneUser(): Promise<void> {
|
||||
const connection = await connectionManager.connectToRoomSocket();
|
||||
connection.emitPlayerDetailsMessage('foo', ['male3']);
|
||||
|
||||
await connection.joinARoom('global__maps.workadventure.localhost/Floor0/floor0', 783, 170, 'down', true, {
|
||||
top: 0,
|
||||
bottom: 200,
|
||||
left: 500,
|
||||
@ -38,6 +45,9 @@ async function startOneUser(): Promise<void> {
|
||||
}
|
||||
|
||||
(async () => {
|
||||
connectionManager.initBenchmark();
|
||||
|
||||
|
||||
for (let userNo = 0; userNo < 40; userNo++) {
|
||||
startOneUser();
|
||||
// Wait 0.5s between adding users
|
||||
|
@ -21,11 +21,10 @@
|
||||
],
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"dependencies": {
|
||||
"socket.io-client": "^2.3.0",
|
||||
"@types/ws": "^7.2.6",
|
||||
"ts-node-dev": "^1.0.0-pre.62",
|
||||
"typescript": "^4.0.2"
|
||||
"typescript": "^4.0.2",
|
||||
"ws": "^7.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/socket.io-client": "^1.4.33"
|
||||
}
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/socket.io-client@^1.4.33":
|
||||
version "1.4.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/socket.io-client/-/socket.io-client-1.4.33.tgz#8e705b9b3f7fba6cb329d27cd2eda222812adbf1"
|
||||
"@types/node@*":
|
||||
version "14.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256"
|
||||
|
||||
"@types/strip-bom@^3.0.0":
|
||||
version "3.0.0"
|
||||
@ -14,9 +14,11 @@
|
||||
version "0.0.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
|
||||
|
||||
after@0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
|
||||
"@types/ws@^7.2.6":
|
||||
version "7.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.2.6.tgz#516cbfb818310f87b43940460e065eb912a4178d"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
anymatch@~3.1.1:
|
||||
version "3.1.1"
|
||||
@ -33,40 +35,14 @@ array-find-index@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
|
||||
|
||||
arraybuffer.slice@~0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
|
||||
|
||||
async-limiter@~1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
|
||||
|
||||
backo2@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
|
||||
base64-arraybuffer@0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
||||
|
||||
better-assert@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
|
||||
dependencies:
|
||||
callsite "1.0.0"
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
|
||||
|
||||
blob@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@ -84,10 +60,6 @@ buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
|
||||
callsite@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
|
||||
|
||||
camelcase-keys@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
|
||||
@ -113,22 +85,6 @@ chokidar@^3.4.0:
|
||||
optionalDependencies:
|
||||
fsevents "~2.1.2"
|
||||
|
||||
component-bind@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
|
||||
|
||||
component-emitter@1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
|
||||
|
||||
component-emitter@~1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||
|
||||
component-inherit@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
@ -146,18 +102,6 @@ dateformat@~1.0.4-1.2.3:
|
||||
get-stdin "^4.0.1"
|
||||
meow "^3.3.0"
|
||||
|
||||
debug@~3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@~4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
decamelize@^1.1.2:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
@ -172,32 +116,6 @@ dynamic-dedupe@^0.3.0:
|
||||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
engine.io-client@~3.4.0:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.3.tgz#192d09865403e3097e3575ebfeb3861c4d01a66c"
|
||||
dependencies:
|
||||
component-emitter "~1.3.0"
|
||||
component-inherit "0.0.3"
|
||||
debug "~4.1.0"
|
||||
engine.io-parser "~2.2.0"
|
||||
has-cors "1.1.0"
|
||||
indexof "0.0.1"
|
||||
parseqs "0.0.5"
|
||||
parseuri "0.0.5"
|
||||
ws "~6.1.0"
|
||||
xmlhttprequest-ssl "~1.5.4"
|
||||
yeast "0.1.2"
|
||||
|
||||
engine.io-parser@~2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.0.tgz#312c4894f57d52a02b420868da7b5c1c84af80ed"
|
||||
dependencies:
|
||||
after "0.8.2"
|
||||
arraybuffer.slice "~0.0.7"
|
||||
base64-arraybuffer "0.1.5"
|
||||
blob "0.0.5"
|
||||
has-binary2 "~1.0.2"
|
||||
|
||||
error-ex@^1.2.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
@ -250,16 +168,6 @@ graceful-fs@^4.1.2:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
|
||||
has-binary2@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d"
|
||||
dependencies:
|
||||
isarray "2.0.1"
|
||||
|
||||
has-cors@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.8"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||
@ -270,10 +178,6 @@ indent-string@^2.1.0:
|
||||
dependencies:
|
||||
repeating "^2.0.0"
|
||||
|
||||
indexof@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
@ -317,10 +221,6 @@ is-utf8@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
|
||||
|
||||
isarray@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
|
||||
|
||||
load-json-file@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
|
||||
@ -375,14 +275,6 @@ mkdirp@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
|
||||
ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
|
||||
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
|
||||
@ -400,10 +292,6 @@ object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
||||
object-component@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@ -416,18 +304,6 @@ parse-json@^2.2.0:
|
||||
dependencies:
|
||||
error-ex "^1.2.0"
|
||||
|
||||
parseqs@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
|
||||
dependencies:
|
||||
better-assert "~1.0.0"
|
||||
|
||||
parseuri@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
|
||||
dependencies:
|
||||
better-assert "~1.0.0"
|
||||
|
||||
path-exists@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
|
||||
@ -522,33 +398,6 @@ signal-exit@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||
|
||||
socket.io-client@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4"
|
||||
dependencies:
|
||||
backo2 "1.0.2"
|
||||
base64-arraybuffer "0.1.5"
|
||||
component-bind "1.0.0"
|
||||
component-emitter "1.2.1"
|
||||
debug "~4.1.0"
|
||||
engine.io-client "~3.4.0"
|
||||
has-binary2 "~1.0.2"
|
||||
has-cors "1.1.0"
|
||||
indexof "0.0.1"
|
||||
object-component "0.0.3"
|
||||
parseqs "0.0.5"
|
||||
parseuri "0.0.5"
|
||||
socket.io-parser "~3.3.0"
|
||||
to-array "0.1.4"
|
||||
|
||||
socket.io-parser@~3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f"
|
||||
dependencies:
|
||||
component-emitter "1.2.1"
|
||||
debug "~3.1.0"
|
||||
isarray "2.0.1"
|
||||
|
||||
source-map-support@^0.5.12, source-map-support@^0.5.17:
|
||||
version "0.5.19"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||
@ -602,10 +451,6 @@ strip-json-comments@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
|
||||
to-array@0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
@ -670,24 +515,14 @@ wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
|
||||
ws@~6.1.0:
|
||||
version "6.1.4"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9"
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
xmlhttprequest-ssl@~1.5.4:
|
||||
version "1.5.5"
|
||||
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
|
||||
ws@^7.3.1:
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8"
|
||||
|
||||
xtend@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
|
||||
yeast@0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
|
||||
|
||||
yn@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||
|
@ -31,6 +31,10 @@ class ConnectionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public initBenchmark(): void {
|
||||
this.authToken = 'test';
|
||||
}
|
||||
|
||||
public connectToRoomSocket(): Promise<RoomConnection> {
|
||||
return new Promise<RoomConnection>((resolve, reject) => {
|
||||
const connection = new RoomConnection(this.authToken as string);
|
||||
@ -38,7 +42,9 @@ class ConnectionManager {
|
||||
console.log('An error occurred while connecting to socket server. Retrying');
|
||||
reject(error);
|
||||
});
|
||||
connection.onConnect(() => {
|
||||
resolve(connection);
|
||||
})
|
||||
}).catch((err) => {
|
||||
// Let's retry in 4-6 seconds
|
||||
return new Promise<RoomConnection>((resolve, reject) => {
|
||||
|
@ -1,14 +1,29 @@
|
||||
import {API_URL} from "../Enum/EnvironmentVariable";
|
||||
import {
|
||||
BatchMessage, GroupDeleteMessage, GroupUpdateMessage, ItemEventMessage,
|
||||
BatchMessage,
|
||||
ClientToServerMessage,
|
||||
GroupDeleteMessage,
|
||||
GroupUpdateMessage,
|
||||
ItemEventMessage,
|
||||
JoinRoomMessage,
|
||||
PositionMessage,
|
||||
SetPlayerDetailsMessage, UserJoinedMessage, UserLeftMessage, UserMovedMessage,
|
||||
RoomJoinedMessage,
|
||||
ServerToClientMessage,
|
||||
SetPlayerDetailsMessage,
|
||||
SetUserIdMessage,
|
||||
SilentMessage,
|
||||
UserJoinedMessage,
|
||||
UserLeftMessage,
|
||||
UserMovedMessage,
|
||||
UserMovesMessage,
|
||||
ViewportMessage
|
||||
ViewportMessage,
|
||||
WebRtcDisconnectMessage,
|
||||
WebRtcSignalToClientMessage,
|
||||
WebRtcSignalToServerMessage,
|
||||
WebRtcStartMessage
|
||||
} from "../Messages/generated/messages_pb"
|
||||
|
||||
const SocketIo = require('socket.io-client');
|
||||
import Socket = SocketIOClient.Socket;
|
||||
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||
import Direction = PositionMessage.Direction;
|
||||
import {ProtobufClientUtils} from "../Network/ProtobufClientUtils";
|
||||
import {
|
||||
@ -24,96 +39,146 @@ import {
|
||||
|
||||
|
||||
export class RoomConnection implements RoomConnection {
|
||||
private readonly socket: Socket;
|
||||
private readonly socket: WebSocket;
|
||||
private userId: number|null = null;
|
||||
private batchCallbacks: Map<string, Function[]> = new Map<string, Function[]>();
|
||||
private listeners: Map<string, Function[]> = new Map<string, Function[]>();
|
||||
private static websocketFactory: null|((url: string)=>any) = null; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
public static setWebsocketFactory(websocketFactory: (url: string)=>any): void { // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
RoomConnection.websocketFactory = websocketFactory;
|
||||
}
|
||||
|
||||
public constructor(token: string) {
|
||||
let url = API_URL.replace('http://', 'ws://').replace('https://', 'wss://');
|
||||
url += '?token='+token;
|
||||
|
||||
this.socket = SocketIo(`${API_URL}`, {
|
||||
query: {
|
||||
token: token
|
||||
},
|
||||
reconnection: false // Reconnection is handled by the application itself
|
||||
});
|
||||
if (RoomConnection.websocketFactory) {
|
||||
this.socket = RoomConnection.websocketFactory(url);
|
||||
} else {
|
||||
this.socket = new WebSocket(url);
|
||||
}
|
||||
|
||||
this.socket.on(EventMessage.MESSAGE_ERROR, (message: string) => {
|
||||
console.error(EventMessage.MESSAGE_ERROR, message);
|
||||
})
|
||||
this.socket.binaryType = 'arraybuffer';
|
||||
|
||||
/**
|
||||
* Messages inside batched messages are extracted and sent to listeners directly.
|
||||
*/
|
||||
this.socket.on(EventMessage.BATCH, (batchedMessagesBinary: ArrayBuffer) => {
|
||||
const batchMessage = BatchMessage.deserializeBinary(new Uint8Array(batchedMessagesBinary));
|
||||
this.socket.onopen = (ev) => {
|
||||
//console.log('WS connected');
|
||||
};
|
||||
|
||||
for (const message of batchMessage.getPayloadList()) {
|
||||
this.socket.onmessage = (messageEvent) => {
|
||||
const arrayBuffer: ArrayBuffer = messageEvent.data;
|
||||
const message = ServerToClientMessage.deserializeBinary(new Uint8Array(arrayBuffer));
|
||||
|
||||
if (message.hasBatchmessage()) {
|
||||
for (const subMessage of (message.getBatchmessage() as BatchMessage).getPayloadList()) {
|
||||
let event: string;
|
||||
let payload;
|
||||
if (message.hasUsermovedmessage()) {
|
||||
if (subMessage.hasUsermovedmessage()) {
|
||||
event = EventMessage.USER_MOVED;
|
||||
payload = message.getUsermovedmessage();
|
||||
} else if (message.hasGroupupdatemessage()) {
|
||||
payload = subMessage.getUsermovedmessage();
|
||||
} else if (subMessage.hasGroupupdatemessage()) {
|
||||
event = EventMessage.GROUP_CREATE_UPDATE;
|
||||
payload = message.getGroupupdatemessage();
|
||||
} else if (message.hasGroupdeletemessage()) {
|
||||
payload = subMessage.getGroupupdatemessage();
|
||||
} else if (subMessage.hasGroupdeletemessage()) {
|
||||
event = EventMessage.GROUP_DELETE;
|
||||
payload = message.getGroupdeletemessage();
|
||||
} else if (message.hasUserjoinedmessage()) {
|
||||
payload = subMessage.getGroupdeletemessage();
|
||||
} else if (subMessage.hasUserjoinedmessage()) {
|
||||
event = EventMessage.JOIN_ROOM;
|
||||
payload = message.getUserjoinedmessage();
|
||||
} else if (message.hasUserleftmessage()) {
|
||||
payload = subMessage.getUserjoinedmessage();
|
||||
} else if (subMessage.hasUserleftmessage()) {
|
||||
event = EventMessage.USER_LEFT;
|
||||
payload = message.getUserleftmessage();
|
||||
} else if (message.hasItemeventmessage()) {
|
||||
payload = subMessage.getUserleftmessage();
|
||||
} else if (subMessage.hasItemeventmessage()) {
|
||||
event = EventMessage.ITEM_EVENT;
|
||||
payload = message.getItemeventmessage();
|
||||
payload = subMessage.getItemeventmessage();
|
||||
} else {
|
||||
throw new Error('Unexpected batch message type');
|
||||
}
|
||||
|
||||
const listeners = this.batchCallbacks.get(event);
|
||||
this.dispatch(event, payload);
|
||||
}
|
||||
} else if (message.hasRoomjoinedmessage()) {
|
||||
const roomJoinedMessage = message.getRoomjoinedmessage() as RoomJoinedMessage;
|
||||
|
||||
const users: Array<MessageUserJoined> = roomJoinedMessage.getUserList().map(this.toMessageUserJoined.bind(this));
|
||||
const groups: Array<GroupCreatedUpdatedMessageInterface> = roomJoinedMessage.getGroupList().map(this.toGroupCreatedUpdatedMessage.bind(this));
|
||||
const items: { [itemId: number] : unknown } = {};
|
||||
for (const item of roomJoinedMessage.getItemList()) {
|
||||
items[item.getItemid()] = JSON.parse(item.getStatejson());
|
||||
}
|
||||
|
||||
this.resolveJoinRoom({
|
||||
users,
|
||||
groups,
|
||||
items
|
||||
})
|
||||
} else if (message.hasSetuseridmessage()) {
|
||||
this.userId = (message.getSetuseridmessage() as SetUserIdMessage).getUserid();
|
||||
} else if (message.hasErrormessage()) {
|
||||
console.error(EventMessage.MESSAGE_ERROR, message.getErrormessage()?.getMessage());
|
||||
} else if (message.hasWebrtcsignaltoclientmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_SIGNAL, message.getWebrtcsignaltoclientmessage());
|
||||
} else if (message.hasWebrtcscreensharingsignaltoclientmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_SCREEN_SHARING_SIGNAL, message.getWebrtcscreensharingsignaltoclientmessage());
|
||||
} else if (message.hasWebrtcstartmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_START, message.getWebrtcstartmessage());
|
||||
} else if (message.hasWebrtcdisconnectmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_DISCONNECT, message.getWebrtcdisconnectmessage());
|
||||
} else {
|
||||
throw new Error('Unknown message received');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private dispatch(event: string, payload: unknown): void {
|
||||
const listeners = this.listeners.get(event);
|
||||
if (listeners === undefined) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
for (const listener of listeners) {
|
||||
listener(payload);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public emitPlayerDetailsMessage(userName: string, characterLayersSelected: string[]) {
|
||||
const message = new SetPlayerDetailsMessage();
|
||||
message.setName(userName);
|
||||
message.setCharacterlayersList(characterLayersSelected);
|
||||
this.socket.emit(EventMessage.SET_PLAYER_DETAILS, message.serializeBinary().buffer, (id: number) => {
|
||||
this.userId = id;
|
||||
});
|
||||
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setSetplayerdetailsmessage(message);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
public closeConnection(): void {
|
||||
this.socket?.close();
|
||||
}
|
||||
|
||||
private resolveJoinRoom!: (value?: (RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface> | undefined)) => void;
|
||||
|
||||
public joinARoom(roomId: string, startX: number, startY: number, direction: string, moving: boolean, viewport: ViewportInterface): Promise<RoomJoinedMessageInterface> {
|
||||
const promise = new Promise<RoomJoinedMessageInterface>((resolve, reject) => {
|
||||
this.socket.emit(EventMessage.JOIN_ROOM, {
|
||||
roomId,
|
||||
position: {x: startX, y: startY, direction, moving },
|
||||
viewport,
|
||||
}, (roomJoinedMessage: RoomJoinedMessageInterface) => {
|
||||
resolve(roomJoinedMessage);
|
||||
});
|
||||
this.resolveJoinRoom = resolve;
|
||||
|
||||
const positionMessage = this.toPositionMessage(startX, startY, direction, moving);
|
||||
const viewportMessage = this.toViewportMessage(viewport);
|
||||
|
||||
const joinRoomMessage = new JoinRoomMessage();
|
||||
joinRoomMessage.setRoomid(roomId);
|
||||
joinRoomMessage.setPosition(positionMessage);
|
||||
joinRoomMessage.setViewport(viewportMessage);
|
||||
|
||||
//console.log('Sending position ', positionMessage.getX(), positionMessage.getY());
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setJoinroommessage(joinRoomMessage);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
})
|
||||
return promise;
|
||||
}
|
||||
|
||||
public sharePosition(x : number, y : number, direction : string, moving: boolean, viewport: ViewportInterface) : void{
|
||||
if(!this.socket){
|
||||
return;
|
||||
}
|
||||
private toPositionMessage(x : number, y : number, direction : string, moving: boolean): PositionMessage {
|
||||
const positionMessage = new PositionMessage();
|
||||
positionMessage.setX(Math.floor(x));
|
||||
positionMessage.setY(Math.floor(y));
|
||||
@ -137,23 +202,47 @@ export class RoomConnection implements RoomConnection {
|
||||
positionMessage.setDirection(directionEnum);
|
||||
positionMessage.setMoving(moving);
|
||||
|
||||
return positionMessage;
|
||||
}
|
||||
|
||||
private toViewportMessage(viewport: ViewportInterface): ViewportMessage {
|
||||
const viewportMessage = new ViewportMessage();
|
||||
viewportMessage.setLeft(Math.floor(viewport.left));
|
||||
viewportMessage.setRight(Math.floor(viewport.right));
|
||||
viewportMessage.setTop(Math.floor(viewport.top));
|
||||
viewportMessage.setBottom(Math.floor(viewport.bottom));
|
||||
|
||||
return viewportMessage;
|
||||
}
|
||||
|
||||
public sharePosition(x : number, y : number, direction : string, moving: boolean, viewport: ViewportInterface) : void{
|
||||
if(!this.socket){
|
||||
return;
|
||||
}
|
||||
|
||||
const positionMessage = this.toPositionMessage(x, y, direction, moving);
|
||||
|
||||
const viewportMessage = this.toViewportMessage(viewport);
|
||||
|
||||
const userMovesMessage = new UserMovesMessage();
|
||||
userMovesMessage.setPosition(positionMessage);
|
||||
userMovesMessage.setViewport(viewportMessage);
|
||||
|
||||
//console.log('Sending position ', positionMessage.getX(), positionMessage.getY());
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setUsermovesmessage(userMovesMessage);
|
||||
|
||||
this.socket.emit(EventMessage.USER_POSITION, userMovesMessage.serializeBinary().buffer);
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
public setSilent(silent: boolean): void {
|
||||
this.socket.emit(EventMessage.SET_SILENT, silent);
|
||||
const silentMessage = new SilentMessage();
|
||||
silentMessage.setSilent(silent);
|
||||
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setSilentmessage(silentMessage);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
public setViewport(viewport: ViewportInterface): void {
|
||||
@ -163,108 +252,145 @@ export class RoomConnection implements RoomConnection {
|
||||
viewportMessage.setLeft(Math.round(viewport.left));
|
||||
viewportMessage.setRight(Math.round(viewport.right));
|
||||
|
||||
this.socket.emit(EventMessage.SET_VIEWPORT, viewportMessage.serializeBinary().buffer);
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setViewportmessage(viewportMessage);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
public onUserJoins(callback: (message: MessageUserJoined) => void): void {
|
||||
this.onBatchMessage(EventMessage.JOIN_ROOM, (message: UserJoinedMessage) => {
|
||||
this.onMessage(EventMessage.JOIN_ROOM, (message: UserJoinedMessage) => {
|
||||
callback(this.toMessageUserJoined(message));
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: move this to protobuf utils
|
||||
private toMessageUserJoined(message: UserJoinedMessage): MessageUserJoined {
|
||||
const position = message.getPosition();
|
||||
if (position === undefined) {
|
||||
throw new Error('Invalid JOIN_ROOM message');
|
||||
}
|
||||
const messageUserJoined: MessageUserJoined = {
|
||||
return {
|
||||
userId: message.getUserid(),
|
||||
name: message.getName(),
|
||||
characterLayers: message.getCharacterlayersList(),
|
||||
position: ProtobufClientUtils.toPointInterface(position)
|
||||
}
|
||||
callback(messageUserJoined);
|
||||
});
|
||||
}
|
||||
|
||||
public onUserMoved(callback: (message: UserMovedMessage) => void): void {
|
||||
this.onBatchMessage(EventMessage.USER_MOVED, callback);
|
||||
this.onMessage(EventMessage.USER_MOVED, callback);
|
||||
//this.socket.on(EventMessage.USER_MOVED, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener on a message that is part of a batch
|
||||
*/
|
||||
private onBatchMessage(eventName: string, callback: Function): void {
|
||||
let callbacks = this.batchCallbacks.get(eventName);
|
||||
private onMessage(eventName: string, callback: Function): void {
|
||||
let callbacks = this.listeners.get(eventName);
|
||||
if (callbacks === undefined) {
|
||||
callbacks = new Array<Function>();
|
||||
this.batchCallbacks.set(eventName, callbacks);
|
||||
this.listeners.set(eventName, callbacks);
|
||||
}
|
||||
callbacks.push(callback);
|
||||
}
|
||||
|
||||
public onUserLeft(callback: (userId: number) => void): void {
|
||||
this.onBatchMessage(EventMessage.USER_LEFT, (message: UserLeftMessage) => {
|
||||
this.onMessage(EventMessage.USER_LEFT, (message: UserLeftMessage) => {
|
||||
callback(message.getUserid());
|
||||
});
|
||||
}
|
||||
|
||||
public onGroupUpdatedOrCreated(callback: (groupCreateUpdateMessage: GroupCreatedUpdatedMessageInterface) => void): void {
|
||||
this.onBatchMessage(EventMessage.GROUP_CREATE_UPDATE, (message: GroupUpdateMessage) => {
|
||||
this.onMessage(EventMessage.GROUP_CREATE_UPDATE, (message: GroupUpdateMessage) => {
|
||||
callback(this.toGroupCreatedUpdatedMessage(message));
|
||||
});
|
||||
}
|
||||
|
||||
private toGroupCreatedUpdatedMessage(message: GroupUpdateMessage): GroupCreatedUpdatedMessageInterface {
|
||||
const position = message.getPosition();
|
||||
if (position === undefined) {
|
||||
throw new Error('Missing position in GROUP_CREATE_UPDATE');
|
||||
}
|
||||
|
||||
const groupCreateUpdateMessage: GroupCreatedUpdatedMessageInterface = {
|
||||
return {
|
||||
groupId: message.getGroupid(),
|
||||
position: position.toObject()
|
||||
}
|
||||
|
||||
//console.log('Group position: ', position.toObject());
|
||||
callback(groupCreateUpdateMessage);
|
||||
});
|
||||
}
|
||||
|
||||
public onGroupDeleted(callback: (groupId: number) => void): void {
|
||||
this.onBatchMessage(EventMessage.GROUP_DELETE, (message: GroupDeleteMessage) => {
|
||||
this.onMessage(EventMessage.GROUP_DELETE, (message: GroupDeleteMessage) => {
|
||||
callback(message.getGroupid());
|
||||
});
|
||||
}
|
||||
|
||||
public onConnectError(callback: (error: object) => void): void {
|
||||
this.socket.on(EventMessage.CONNECT_ERROR, callback)
|
||||
public onConnectError(callback: (error: Event) => void): void {
|
||||
this.socket.addEventListener('error', callback)
|
||||
}
|
||||
|
||||
public onConnect(callback: (event: Event) => void): void {
|
||||
this.socket.addEventListener('open', callback)
|
||||
}
|
||||
|
||||
public sendWebrtcSignal(signal: unknown, receiverId: number) {
|
||||
return this.socket.emit(EventMessage.WEBRTC_SIGNAL, {
|
||||
receiverId: receiverId,
|
||||
signal: signal
|
||||
} as WebRtcSignalSentMessageInterface);
|
||||
const webRtcSignal = new WebRtcSignalToServerMessage();
|
||||
webRtcSignal.setReceiverid(receiverId);
|
||||
webRtcSignal.setSignal(JSON.stringify(signal));
|
||||
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setWebrtcsignaltoservermessage(webRtcSignal);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
public sendWebrtcScreenSharingSignal(signal: unknown, receiverId: number) {
|
||||
return this.socket.emit(EventMessage.WEBRTC_SCREEN_SHARING_SIGNAL, {
|
||||
receiverId: receiverId,
|
||||
signal: signal
|
||||
} as WebRtcSignalSentMessageInterface);
|
||||
const webRtcSignal = new WebRtcSignalToServerMessage();
|
||||
webRtcSignal.setReceiverid(receiverId);
|
||||
webRtcSignal.setSignal(JSON.stringify(signal));
|
||||
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setWebrtcscreensharingsignaltoservermessage(webRtcSignal);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
public receiveWebrtcStart(callback: (message: WebRtcStartMessageInterface) => void) {
|
||||
this.socket.on(EventMessage.WEBRTC_START, callback);
|
||||
public receiveWebrtcStart(callback: (message: UserSimplePeerInterface) => void) {
|
||||
this.onMessage(EventMessage.WEBRTC_START, (message: WebRtcStartMessage) => {
|
||||
callback({
|
||||
userId: message.getUserid(),
|
||||
name: message.getName(),
|
||||
initiator: message.getInitiator()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public receiveWebrtcSignal(callback: (message: WebRtcSignalReceivedMessageInterface) => void) {
|
||||
return this.socket.on(EventMessage.WEBRTC_SIGNAL, callback);
|
||||
this.onMessage(EventMessage.WEBRTC_SIGNAL, (message: WebRtcSignalToClientMessage) => {
|
||||
callback({
|
||||
userId: message.getUserid(),
|
||||
signal: JSON.parse(message.getSignal())
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public receiveWebrtcScreenSharingSignal(callback: (message: WebRtcSignalReceivedMessageInterface) => void) {
|
||||
return this.socket.on(EventMessage.WEBRTC_SCREEN_SHARING_SIGNAL, callback);
|
||||
this.onMessage(EventMessage.WEBRTC_SCREEN_SHARING_SIGNAL, (message: WebRtcSignalToClientMessage) => {
|
||||
callback({
|
||||
userId: message.getUserid(),
|
||||
signal: JSON.parse(message.getSignal())
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public onServerDisconnected(callback: (reason: string) => void): void {
|
||||
this.socket.on('disconnect', (reason: string) => {
|
||||
if (reason === 'io client disconnect') {
|
||||
// The client asks for disconnect, let's not trigger any event.
|
||||
public onServerDisconnected(callback: (event: CloseEvent) => void): void {
|
||||
this.socket.addEventListener('close', (event) => {
|
||||
console.log('Socket closed with code '+event.code+". Reason: "+event.reason);
|
||||
if (event.code === 1000) {
|
||||
// Normal closure case
|
||||
return;
|
||||
}
|
||||
callback(reason);
|
||||
callback(event);
|
||||
});
|
||||
|
||||
}
|
||||
@ -274,7 +400,11 @@ export class RoomConnection implements RoomConnection {
|
||||
}
|
||||
|
||||
disconnectMessage(callback: (message: WebRtcDisconnectMessageInterface) => void): void {
|
||||
this.socket.on(EventMessage.WEBRTC_DISCONNECT, callback);
|
||||
this.onMessage(EventMessage.WEBRTC_DISCONNECT, (message: WebRtcDisconnectMessage) => {
|
||||
callback({
|
||||
userId: message.getUserid()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
emitActionableEvent(itemId: number, event: string, state: unknown, parameters: unknown): void {
|
||||
@ -284,11 +414,14 @@ export class RoomConnection implements RoomConnection {
|
||||
itemEventMessage.setStatejson(JSON.stringify(state));
|
||||
itemEventMessage.setParametersjson(JSON.stringify(parameters));
|
||||
|
||||
this.socket.emit(EventMessage.ITEM_EVENT, itemEventMessage.serializeBinary().buffer);
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setItemeventmessage(itemEventMessage);
|
||||
|
||||
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||
}
|
||||
|
||||
onActionableEvent(callback: (message: ItemEventMessageInterface) => void): void {
|
||||
this.onBatchMessage(EventMessage.ITEM_EVENT, (message: ItemEventMessage) => {
|
||||
this.onMessage(EventMessage.ITEM_EVENT, (message: ItemEventMessage) => {
|
||||
callback({
|
||||
itemId: message.getItemid(),
|
||||
event: message.getEvent(),
|
||||
|
@ -7,7 +7,7 @@ const JITSI_URL : string|undefined = (process.env.JITSI_URL === '') ? undefined
|
||||
const RESOLUTION = 3;
|
||||
const ZOOM_LEVEL = 1/*3/4*/;
|
||||
const POSITION_DELAY = 200; // Wait 200ms between sending position events
|
||||
const MAX_EXTRAPOLATION_TIME = 250; // Extrapolate a maximum of 250ms if no new movement is sent by the player
|
||||
const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new movement is sent by the player
|
||||
|
||||
export {
|
||||
DEBUG_MODE,
|
||||
|
@ -82,7 +82,7 @@ export class SimplePeer {
|
||||
mediaManager.getCamera().then(() => {
|
||||
|
||||
//receive message start
|
||||
this.Connection.receiveWebrtcStart((message: WebRtcStartMessageInterface) => {
|
||||
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
|
||||
this.receiveWebrtcStart(message);
|
||||
});
|
||||
|
||||
@ -95,17 +95,22 @@ export class SimplePeer {
|
||||
});
|
||||
}
|
||||
|
||||
private receiveWebrtcStart(data: WebRtcStartMessageInterface) {
|
||||
this.WebRtcRoomId = data.roomId;
|
||||
this.Users = data.clients;
|
||||
private receiveWebrtcStart(user: UserSimplePeerInterface) {
|
||||
//this.WebRtcRoomId = data.roomId;
|
||||
this.Users.push(user);
|
||||
// Note: the clients array contain the list of all clients (even the ones we are already connected to in case a user joints a group)
|
||||
// So we can receive a request we already had before. (which will abort at the first line of createPeerConnection)
|
||||
// TODO: refactor this to only send a message to connect to one user (rather than several users).
|
||||
// TODO: refactor this to only send a message to connect to one user (rather than several users). => DONE
|
||||
// This would be symmetrical to the way we handle disconnection.
|
||||
//console.log('Start message', data);
|
||||
|
||||
//start connection
|
||||
this.startWebRtc();
|
||||
//this.startWebRtc();
|
||||
console.log('receiveWebrtcStart. Initiator: ', user.initiator)
|
||||
if(!user.initiator){
|
||||
return;
|
||||
}
|
||||
this.createPeerConnection(user);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,6 +134,7 @@ export class SimplePeer {
|
||||
if(
|
||||
this.PeerConnectionArray.has(user.userId)
|
||||
){
|
||||
console.log('Peer connection already exists to user '+user.userId)
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,10 @@ message ViewportMessage {
|
||||
int32 bottom = 4;
|
||||
}
|
||||
|
||||
message SilentMessage {
|
||||
bool silent = 1;
|
||||
}
|
||||
|
||||
/*********** CLIENT TO SERVER MESSAGES *************/
|
||||
|
||||
message SetPlayerDetailsMessage {
|
||||
@ -34,11 +38,36 @@ message SetPlayerDetailsMessage {
|
||||
repeated string characterLayers = 2;
|
||||
}
|
||||
|
||||
message JoinRoomMessage {
|
||||
string roomId = 1;
|
||||
PositionMessage position = 2;
|
||||
ViewportMessage viewport = 3;
|
||||
}
|
||||
|
||||
message UserMovesMessage {
|
||||
PositionMessage position = 1;
|
||||
ViewportMessage viewport = 2;
|
||||
}
|
||||
|
||||
message WebRtcSignalToServerMessage {
|
||||
int32 receiverId = 1;
|
||||
string signal = 2;
|
||||
}
|
||||
|
||||
message ClientToServerMessage {
|
||||
oneof message {
|
||||
JoinRoomMessage joinRoomMessage = 1;
|
||||
UserMovesMessage userMovesMessage = 2;
|
||||
SilentMessage silentMessage = 3;
|
||||
ViewportMessage viewportMessage = 4;
|
||||
ItemEventMessage itemEventMessage = 5;
|
||||
SetPlayerDetailsMessage setPlayerDetailsMessage = 6;
|
||||
WebRtcSignalToServerMessage webRtcSignalToServerMessage = 7;
|
||||
WebRtcSignalToServerMessage webRtcScreenSharingSignalToServerMessage = 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************ BI-DIRECTIONAL MESSAGES **************/
|
||||
|
||||
message ItemEventMessage {
|
||||
@ -90,3 +119,50 @@ message UserJoinedMessage {
|
||||
message UserLeftMessage {
|
||||
int32 userId = 1;
|
||||
}
|
||||
|
||||
message ErrorMessage {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message SetUserIdMessage {
|
||||
int32 userId = 1;
|
||||
}
|
||||
|
||||
message ItemStateMessage {
|
||||
int32 itemId = 1;
|
||||
string stateJson = 2;
|
||||
}
|
||||
|
||||
message RoomJoinedMessage {
|
||||
repeated UserJoinedMessage user = 1;
|
||||
repeated GroupUpdateMessage group = 2;
|
||||
repeated ItemStateMessage item = 3;
|
||||
}
|
||||
|
||||
message WebRtcStartMessage {
|
||||
int32 userId = 1;
|
||||
string name = 2;
|
||||
bool initiator = 3;
|
||||
}
|
||||
|
||||
message WebRtcDisconnectMessage {
|
||||
int32 userId = 1;
|
||||
}
|
||||
|
||||
message WebRtcSignalToClientMessage {
|
||||
int32 userId = 1;
|
||||
string signal = 2;
|
||||
}
|
||||
|
||||
message ServerToClientMessage {
|
||||
oneof message {
|
||||
BatchMessage batchMessage = 1;
|
||||
ErrorMessage errorMessage = 2;
|
||||
RoomJoinedMessage roomJoinedMessage = 3;
|
||||
SetUserIdMessage setUserIdMessage = 4; // TODO: merge this with RoomJoinedMessage ?
|
||||
WebRtcStartMessage webRtcStartMessage = 5;
|
||||
WebRtcSignalToClientMessage webRtcSignalToClientMessage = 6;
|
||||
WebRtcSignalToClientMessage webRtcScreenSharingSignalToClientMessage = 7;
|
||||
WebRtcDisconnectMessage webRtcDisconnectMessage = 8;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user