@epicgames-ps/lib-pixelstreamingsignalling-ue5.8 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.lintstagedrc.mjs +7 -0
  2. package/.prettierignore +0 -0
  3. package/CHANGELOG.md +21 -0
  4. package/README.md +32 -0
  5. package/dist/cjs/Logger.js +148 -0
  6. package/dist/cjs/Logger.js.map +1 -0
  7. package/dist/cjs/LoggingUtils.js +64 -0
  8. package/dist/cjs/LoggingUtils.js.map +1 -0
  9. package/dist/cjs/PlayerConnection.js +220 -0
  10. package/dist/cjs/PlayerConnection.js.map +1 -0
  11. package/dist/cjs/PlayerRegistry.js +77 -0
  12. package/dist/cjs/PlayerRegistry.js.map +1 -0
  13. package/dist/cjs/SFUConnection.js +264 -0
  14. package/dist/cjs/SFUConnection.js.map +1 -0
  15. package/dist/cjs/SignallingServer.js +149 -0
  16. package/dist/cjs/SignallingServer.js.map +1 -0
  17. package/dist/cjs/StreamerConnection.js +172 -0
  18. package/dist/cjs/StreamerConnection.js.map +1 -0
  19. package/dist/cjs/StreamerRegistry.js +149 -0
  20. package/dist/cjs/StreamerRegistry.js.map +1 -0
  21. package/dist/cjs/Utils.js +19 -0
  22. package/dist/cjs/Utils.js.map +1 -0
  23. package/dist/cjs/WebServer.js +124 -0
  24. package/dist/cjs/WebServer.js.map +1 -0
  25. package/dist/cjs/pixelstreamingsignalling.js +28 -0
  26. package/dist/cjs/pixelstreamingsignalling.js.map +1 -0
  27. package/dist/esm/Logger.js +141 -0
  28. package/dist/esm/Logger.js.map +1 -0
  29. package/dist/esm/LoggingUtils.js +58 -0
  30. package/dist/esm/LoggingUtils.js.map +1 -0
  31. package/dist/esm/PlayerConnection.js +183 -0
  32. package/dist/esm/PlayerConnection.js.map +1 -0
  33. package/dist/esm/PlayerRegistry.js +73 -0
  34. package/dist/esm/PlayerRegistry.js.map +1 -0
  35. package/dist/esm/SFUConnection.js +227 -0
  36. package/dist/esm/SFUConnection.js.map +1 -0
  37. package/dist/esm/SignallingServer.js +112 -0
  38. package/dist/esm/SignallingServer.js.map +1 -0
  39. package/dist/esm/StreamerConnection.js +135 -0
  40. package/dist/esm/StreamerConnection.js.map +1 -0
  41. package/dist/esm/StreamerRegistry.js +145 -0
  42. package/dist/esm/StreamerRegistry.js.map +1 -0
  43. package/dist/esm/Utils.js +15 -0
  44. package/dist/esm/Utils.js.map +1 -0
  45. package/dist/esm/WebServer.js +117 -0
  46. package/dist/esm/WebServer.js.map +1 -0
  47. package/dist/esm/pixelstreamingsignalling.js +12 -0
  48. package/dist/esm/pixelstreamingsignalling.js.map +1 -0
  49. package/dist/types/Logger.d.ts +20 -0
  50. package/dist/types/LoggingUtils.d.ts +44 -0
  51. package/dist/types/PlayerConnection.d.ts +66 -0
  52. package/dist/types/PlayerRegistry.d.ts +66 -0
  53. package/dist/types/SFUConnection.d.ts +85 -0
  54. package/dist/types/SignallingServer.d.ts +48 -0
  55. package/dist/types/StreamerConnection.d.ts +61 -0
  56. package/dist/types/StreamerRegistry.d.ts +96 -0
  57. package/dist/types/Utils.d.ts +8 -0
  58. package/dist/types/WebServer.d.ts +42 -0
  59. package/dist/types/pixelstreamingsignalling.d.ts +9 -0
  60. package/docs/Logger/README.md +19 -0
  61. package/docs/Logger/functions/InitLogging.md +26 -0
  62. package/docs/Logger/interfaces/IConfig.md +41 -0
  63. package/docs/Logger/variables/Logger.md +15 -0
  64. package/docs/LoggingUtils/README.md +19 -0
  65. package/docs/LoggingUtils/functions/createHandlerListener.md +42 -0
  66. package/docs/LoggingUtils/functions/logForward.md +36 -0
  67. package/docs/LoggingUtils/functions/logIncoming.md +30 -0
  68. package/docs/LoggingUtils/functions/logOutgoing.md +30 -0
  69. package/docs/LoggingUtils/interfaces/IMessageLogger.md +29 -0
  70. package/docs/LoggingUtils/interfaces/IProtoLogObj.md +57 -0
  71. package/docs/PlayerConnection/README.md +11 -0
  72. package/docs/PlayerConnection/classes/PlayerConnection.md +177 -0
  73. package/docs/PlayerRegistry/README.md +16 -0
  74. package/docs/PlayerRegistry/classes/PlayerRegistry.md +423 -0
  75. package/docs/PlayerRegistry/interfaces/IPlayer.md +86 -0
  76. package/docs/PlayerRegistry/interfaces/IPlayerInfo.md +43 -0
  77. package/docs/README.md +19 -0
  78. package/docs/SFUConnection/README.md +11 -0
  79. package/docs/SFUConnection/classes/SFUConnection.md +554 -0
  80. package/docs/SignallingServer/README.md +19 -0
  81. package/docs/SignallingServer/classes/SignallingServer.md +76 -0
  82. package/docs/SignallingServer/interfaces/IServerConfig.md +92 -0
  83. package/docs/SignallingServer/type-aliases/ProtocolConfig.md +15 -0
  84. package/docs/StreamerConnection/README.md +11 -0
  85. package/docs/StreamerConnection/classes/StreamerConnection.md +507 -0
  86. package/docs/StreamerRegistry/README.md +16 -0
  87. package/docs/StreamerRegistry/classes/StreamerRegistry.md +431 -0
  88. package/docs/StreamerRegistry/interfaces/IStreamer.md +375 -0
  89. package/docs/StreamerRegistry/interfaces/IStreamerInfo.md +51 -0
  90. package/docs/Utils/README.md +12 -0
  91. package/docs/Utils/functions/beautify.md +23 -0
  92. package/docs/Utils/functions/stringify.md +23 -0
  93. package/docs/WebServer/README.md +15 -0
  94. package/docs/WebServer/classes/WebServer.md +50 -0
  95. package/docs/WebServer/interfaces/IWebServerConfig.md +76 -0
  96. package/docs/pixelstreamingsignalling/README.md +145 -0
  97. package/eslint.config.mjs +39 -0
  98. package/package.json +58 -0
  99. package/src/Logger.ts +189 -0
  100. package/src/LoggingUtils.ts +80 -0
  101. package/src/PlayerConnection.ts +257 -0
  102. package/src/PlayerRegistry.ts +116 -0
  103. package/src/SFUConnection.ts +329 -0
  104. package/src/SignallingServer.ts +214 -0
  105. package/src/StreamerConnection.ts +194 -0
  106. package/src/StreamerRegistry.ts +252 -0
  107. package/src/Utils.ts +16 -0
  108. package/src/WebServer.ts +213 -0
  109. package/src/pixelstreamingsignalling.ts +11 -0
  110. package/tsconfig.cjs.json +8 -0
  111. package/tsconfig.esm.json +8 -0
  112. package/tsconfig.json +29 -0
@@ -0,0 +1,135 @@
1
+ import { SignallingProtocol, WebSocketTransportNJS, Messages, EventEmitter, MessageHelpers } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.8';
2
+ import { stringify } from './Utils';
3
+ import { Logger } from './Logger';
4
+ import * as LogUtils from './LoggingUtils';
5
+ /**
6
+ * A connection between the signalling server and a streamer connection.
7
+ * This is where messages expected to be handled by the streamer come in
8
+ * and where messages are sent to the streamer.
9
+ *
10
+ * Interesting internals:
11
+ * streamerId: The unique id string of this streamer.
12
+ * transport: The ITransport where transport events can be subscribed to
13
+ * protocol: The SignallingProtocol where signalling messages can be
14
+ * subscribed to.
15
+ * streaming: True when the streamer is ready to accept subscriptions.
16
+ */
17
+ export class StreamerConnection extends EventEmitter {
18
+ /**
19
+ * Initializes a new connection with given and sane values. Adds listeners for the
20
+ * websocket close and error and will emit a disconnected event when disconneted.
21
+ * @param server - The signalling server object that spawned this streamer.
22
+ * @param ws - The websocket coupled to this streamer connection.
23
+ * @param remoteAddress - The remote address of this connection. Only used as display.
24
+ * @param request - The HTTP upgrade request that opened this connection, if available.
25
+ */
26
+ constructor(server, ws, remoteAddress, request) {
27
+ super();
28
+ this.server = server;
29
+ this.streamerId = '';
30
+ this.transport = new WebSocketTransportNJS(ws);
31
+ this.protocol = new SignallingProtocol(this.transport);
32
+ this.streaming = false;
33
+ this.remoteAddress = remoteAddress;
34
+ this.request = request;
35
+ this.maxSubscribers = 0;
36
+ this.subscribers = new Set();
37
+ this.transport.on('error', this.onTransportError.bind(this));
38
+ this.transport.on('close', this.onTransportClose.bind(this));
39
+ this.registerMessageHandlers();
40
+ this.protocol.on('unhandled', (message) => {
41
+ Logger.warn(`Unhandled streamer protocol message: ${JSON.stringify(message)}`);
42
+ });
43
+ }
44
+ /**
45
+ * Returns an identifier that is displayed in logs.
46
+ * @returns A string describing this connection.
47
+ */
48
+ getReadableIdentifier() {
49
+ return this.streamerId;
50
+ }
51
+ /**
52
+ * Sends a signalling message to the player.
53
+ * @param message - The message to send.
54
+ */
55
+ sendMessage(message) {
56
+ LogUtils.logOutgoing(this, message);
57
+ this.protocol.sendMessage(message);
58
+ }
59
+ /**
60
+ * Returns a descriptive object for the REST API inspection operations.
61
+ * @returns An IStreamerInfo object containing viewable information about this connection.
62
+ */
63
+ getStreamerInfo() {
64
+ return {
65
+ streamerId: this.streamerId,
66
+ type: 'Streamer',
67
+ streaming: this.streaming,
68
+ remoteAddress: this.remoteAddress,
69
+ subscribers: this.server.playerRegistry
70
+ .listPlayers()
71
+ .filter((player) => player.subscribedStreamer == this)
72
+ .map((player) => player.getPlayerInfo())
73
+ };
74
+ }
75
+ registerMessageHandlers() {
76
+ /* eslint-disable @typescript-eslint/unbound-method */
77
+ this.protocol.on(Messages.endpointId.typeName, LogUtils.createHandlerListener(this, this.onEndpointId));
78
+ this.protocol.on(Messages.disconnectPlayer.typeName, LogUtils.createHandlerListener(this, this.onDisconnectPlayerRequest));
79
+ this.protocol.on(Messages.layerPreference.typeName, LogUtils.createHandlerListener(this, this.onLayerPreference));
80
+ this.protocol.on(Messages.ping.typeName, LogUtils.createHandlerListener(this, this.onPingMessage));
81
+ /* eslint-enable @typescript-eslint/unbound-method */
82
+ this.protocol.on(Messages.offer.typeName, this.forwardMessage.bind(this));
83
+ this.protocol.on(Messages.answer.typeName, this.forwardMessage.bind(this));
84
+ this.protocol.on(Messages.iceCandidate.typeName, this.forwardMessage.bind(this));
85
+ }
86
+ forwardMessage(message) {
87
+ if (!message.playerId) {
88
+ Logger.warn(`No playerId specified, cannot forward message: ${stringify(message)}`);
89
+ }
90
+ else if (!this.subscribers.has(message.playerId)) {
91
+ // Only forward to players that are actually subscribed to this streamer. Without this
92
+ // check a streamer could target any player on the server (resolved via the global player
93
+ // registry), allowing cross-tenant signalling on a shared signalling server.
94
+ Logger.warn(`Streamer ${this.streamerId} tried to forward a message to player ${message.playerId} which is not subscribed to it. Ignoring.`);
95
+ }
96
+ else {
97
+ const player = this.server.playerRegistry.get(message.playerId);
98
+ if (player) {
99
+ LogUtils.logForward(this, player, message);
100
+ player.protocol.sendMessage(message);
101
+ }
102
+ }
103
+ }
104
+ onTransportError(error) {
105
+ Logger.error(`Streamer (${this.streamerId}) transport error ${error.message}`);
106
+ }
107
+ onTransportClose() {
108
+ Logger.info(`Streamer '${this.streamerId}' - websocket disconnected.`);
109
+ this.emit('disconnect');
110
+ }
111
+ onEndpointId(_message) {
112
+ this.streaming = true; // we're ready to stream when we id ourselves
113
+ }
114
+ onDisconnectPlayerRequest(message) {
115
+ if (message.playerId) {
116
+ if (!this.subscribers.has(message.playerId)) {
117
+ // A streamer may only disconnect its own subscribed players. Otherwise any streamer
118
+ // could forcibly close arbitrary player connections on a shared signalling server.
119
+ Logger.warn(`Streamer ${this.streamerId} tried to disconnect player ${message.playerId} which is not subscribed to it. Ignoring.`);
120
+ return;
121
+ }
122
+ const player = this.server.playerRegistry.get(message.playerId);
123
+ if (player) {
124
+ player.protocol.disconnect(1011, message.reason);
125
+ }
126
+ }
127
+ }
128
+ onLayerPreference(message) {
129
+ this.emit('layer_preference', message);
130
+ }
131
+ onPingMessage(message) {
132
+ this.sendMessage(MessageHelpers.createMessage(Messages.pong, { time: message.time }));
133
+ }
134
+ }
135
+ //# sourceMappingURL=StreamerConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamerConnection.js","sourceRoot":"","sources":["../../src/StreamerConnection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+ import { Messages, MessageHelpers, EventEmitter } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.8';
3
+ import { Logger } from './Logger';
4
+ /**
5
+ * Handles all the streamer connections of a signalling server and
6
+ * can be used to lookup connections by id etc.
7
+ * Fires events when streamers are added or removed.
8
+ * Events:
9
+ * 'added': (playerId: string) Player was added.
10
+ * 'removed': (playerId: string) Player was removed.
11
+ */
12
+ export class StreamerRegistry extends EventEmitter {
13
+ constructor(authorizeStreamerId) {
14
+ super();
15
+ this.defaultStreamerIdPrefix = 'UnknownStreamer';
16
+ this.streamers = [];
17
+ this.authorizeStreamerId = authorizeStreamerId;
18
+ }
19
+ /**
20
+ * Adds a streamer to the registry. If the streamer already has an id
21
+ * it will be sanitized (checked against existing ids and altered if
22
+ * there are collisions), or if it has no id it will be assigned a
23
+ * default unique id.
24
+ * @returns True if the add was successful.
25
+ */
26
+ add(streamer) {
27
+ streamer.streamerId = this.sanitizeStreamerId(streamer.streamerId);
28
+ if (this.find(streamer.streamerId)) {
29
+ Logger.error(`StreamerRegistry: Tried to register streamer ${streamer.streamerId} but that id already exists.`);
30
+ return false;
31
+ }
32
+ this.streamers.push(streamer);
33
+ // request that the new streamer id itself.
34
+ streamer.protocol.on(Messages.endpointId.typeName, this.onEndpointId.bind(this, streamer));
35
+ streamer.sendMessage(MessageHelpers.createMessage(Messages.identify));
36
+ this.emit('added', streamer.streamerId);
37
+ return true;
38
+ }
39
+ /**
40
+ * Removes a streamer from the registry. If the streamer isn't found
41
+ * it does nothing.
42
+ * @returns True if the streamer was removed.
43
+ */
44
+ remove(streamer) {
45
+ const index = this.streamers.indexOf(streamer);
46
+ if (index === -1) {
47
+ Logger.debug(`StreamerRegistry: Tried to remove streamer ${streamer.streamerId} but it doesn't exist`);
48
+ return false;
49
+ }
50
+ this.streamers.splice(index, 1);
51
+ this.emit('removed', streamer.streamerId);
52
+ return true;
53
+ }
54
+ /**
55
+ * Attempts to find the given streamer id in the registry.
56
+ */
57
+ find(streamerId) {
58
+ return this.streamers.find((streamer) => streamer.streamerId === streamerId);
59
+ }
60
+ /**
61
+ * Used by players who haven't subscribed but try to send a message.
62
+ * This is to cover legacy connections that do not know how to subscribe.
63
+ * The player will be assigned the first streamer in the list.
64
+ * @returns The first streamerId in the registry or null if there are none.
65
+ */
66
+ getFirstStreamerId() {
67
+ if (this.empty()) {
68
+ return null;
69
+ }
70
+ return this.streamers[0].streamerId;
71
+ }
72
+ /**
73
+ * Returns true when the registry is empty.
74
+ */
75
+ empty() {
76
+ return this.streamers.length === 0;
77
+ }
78
+ /**
79
+ * Returns the total number of connected streamers.
80
+ */
81
+ count() {
82
+ return this.streamers.length;
83
+ }
84
+ onEndpointId(streamer, message) {
85
+ const oldId = streamer.streamerId;
86
+ // id might conflict or be invalid so here we sanitize it
87
+ const sanitizedId = this.sanitizeStreamerId(message.id);
88
+ let committedId = sanitizedId;
89
+ if (this.authorizeStreamerId) {
90
+ // Let the consumer accept the default id, override it (e.g. namespace per tenant), or
91
+ // reject the registration entirely. This is where anti-squatting policy lives.
92
+ committedId = this.authorizeStreamerId({
93
+ streamer,
94
+ requestedId: message.id,
95
+ sanitizedId,
96
+ collided: !!message.id && sanitizedId !== message.id
97
+ });
98
+ if (committedId === null) {
99
+ Logger.warn(`StreamerRegistry: streamer id '${message.id}' (was ${oldId}) rejected by authorizer. Disconnecting.`);
100
+ this.remove(streamer);
101
+ streamer.protocol.disconnect(1008, 'streamer id not authorized');
102
+ return;
103
+ }
104
+ // An override must remain unique or it would corrupt id-based lookups. If the consumer
105
+ // hands back an id already held by a different streamer we reject rather than clobber.
106
+ const existing = this.find(committedId);
107
+ if (existing && existing !== streamer) {
108
+ Logger.error(`StreamerRegistry: authorizer returned id '${committedId}' which is already in use. Disconnecting.`);
109
+ this.remove(streamer);
110
+ streamer.protocol.disconnect(1008, 'streamer id not authorized');
111
+ return;
112
+ }
113
+ }
114
+ streamer.streamerId = committedId;
115
+ Logger.debug(`StreamerRegistry: Streamer id change. ${oldId} -> ${streamer.streamerId}`);
116
+ streamer.emit('id_changed', streamer.streamerId);
117
+ // because we might have sanitized the id, we confirm the id back to the streamer
118
+ streamer.sendMessage(MessageHelpers.createMessage(Messages.endpointIdConfirm, { committedId: streamer.streamerId }));
119
+ }
120
+ sanitizeStreamerId(id) {
121
+ // create a default id if none supplied
122
+ if (!id) {
123
+ id = this.defaultStreamerIdPrefix;
124
+ }
125
+ // search for existing streamerId and optionally append a numeric value
126
+ let maxPostfix = -1;
127
+ for (const streamer of this.streamers) {
128
+ const idMatchRegex = /^(.*?)(\d*)$/;
129
+ const [, baseId, postfix] = streamer.streamerId.match(idMatchRegex);
130
+ // if the id is numeric then base id will be empty and we need to compare with the postfix
131
+ if ((baseId !== '' && baseId !== id) || (baseId === '' && postfix !== id)) {
132
+ continue;
133
+ }
134
+ const numPostfix = Number(postfix);
135
+ if (numPostfix > maxPostfix) {
136
+ maxPostfix = numPostfix;
137
+ }
138
+ }
139
+ if (maxPostfix >= 0) {
140
+ return id + (maxPostfix + 1);
141
+ }
142
+ return id;
143
+ }
144
+ }
145
+ //# sourceMappingURL=StreamerRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamerRegistry.js","sourceRoot":"","sources":["../../src/StreamerRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+ import { jsonc } from 'jsonc';
3
+ /**
4
+ * Cirular reference safe version of JSON.stringify
5
+ */
6
+ export function stringify(obj) {
7
+ return jsonc.stringify(obj);
8
+ }
9
+ /**
10
+ * Circular reference save version of JSON.stringify with extra formatting.
11
+ */
12
+ export function beautify(obj) {
13
+ return jsonc.stringify(obj, undefined, '\t');
14
+ }
15
+ //# sourceMappingURL=Utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../src/Utils.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,GAAQ;IAC9B,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAQ;IAC7B,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,117 @@
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+ import express from 'express';
3
+ import path from 'path';
4
+ import fs from 'fs';
5
+ import http from 'http';
6
+ import https from 'https';
7
+ import helmet from 'helmet';
8
+ import cors from 'cors';
9
+ import { Logger } from './Logger';
10
+ import RateLimit from 'express-rate-limit';
11
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
12
+ const hsts = require('hsts');
13
+ /**
14
+ * An object to manage the initialization of a web server. Used to serve the
15
+ * pixel streaming frontend.
16
+ */
17
+ export class WebServer {
18
+ constructor(app, config) {
19
+ var _a;
20
+ Logger.debug('Starting WebServer with config: %s', config);
21
+ // only listen on the http port if we're not using https or if we want to redirect
22
+ if (!config.httpsPort || config.https_redirect) {
23
+ this.httpServer = http.createServer(app);
24
+ this.httpServer.listen(config.httpPort, () => {
25
+ Logger.info(`Http server listening on port ${config.httpPort}`);
26
+ });
27
+ }
28
+ /* eslint-disable @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access */
29
+ // if using https listen on the given ports and setup some details
30
+ if (config.httpsPort) {
31
+ const options = { key: config.ssl_key, cert: config.ssl_cert };
32
+ this.httpsServer = https.createServer(options, app);
33
+ this.httpsServer.listen(config.httpsPort, () => {
34
+ Logger.info(`Https server listening on port ${config.httpsPort}`);
35
+ });
36
+ app.use(helmet({
37
+ contentSecurityPolicy: {
38
+ directives: {
39
+ 'connect-src': ['*', "'self'"]
40
+ }
41
+ }
42
+ }));
43
+ app.use(hsts({
44
+ maxAge: 15552000 // 180 days in seconds
45
+ }));
46
+ // Setup http -> https redirect if requested
47
+ if (config.https_redirect) {
48
+ app.use((req, res, next) => {
49
+ if (!req.secure) {
50
+ if (req.get('Host')) {
51
+ const hostAddressParts = req.get('Host').split(':');
52
+ let hostAddress = hostAddressParts[0];
53
+ if (config.httpsPort != 443) {
54
+ hostAddress = `${hostAddress}:${config.httpsPort}`;
55
+ }
56
+ return res.redirect(['https://', hostAddress, req.originalUrl].join(''));
57
+ }
58
+ else {
59
+ Logger.error(`Unable to get host name from header. Requestor ${req.ip}, url path: '${req.originalUrl}', available headers ${JSON.stringify(req.headers)}`);
60
+ return res.status(400).send('Bad Request');
61
+ }
62
+ }
63
+ next();
64
+ });
65
+ }
66
+ }
67
+ if ((_a = config.cors) === null || _a === void 0 ? void 0 : _a.enabled) {
68
+ const corsOptions = {};
69
+ if (config.cors.allowedOrigins && config.cors.allowedOrigins.length > 0) {
70
+ corsOptions.origin = config.cors.allowedOrigins;
71
+ }
72
+ if (config.cors.allowedMethods && config.cors.allowedMethods.length > 0) {
73
+ corsOptions.methods = config.cors.allowedMethods;
74
+ }
75
+ if (config.cors.allowedHeaders && config.cors.allowedHeaders.length > 0) {
76
+ corsOptions.allowedHeaders = config.cors.allowedHeaders;
77
+ }
78
+ if (config.cors.credentials) {
79
+ corsOptions.credentials = true;
80
+ }
81
+ // Register cors before the rate limiter so that preflight (OPTIONS)
82
+ // requests are answered with CORS headers even when an origin is
83
+ // close to the rate limit, and before any route handlers so the
84
+ // homepage, static files, and the REST API all respond uniformly.
85
+ app.use(cors(corsOptions));
86
+ Logger.info(`CORS enabled. Allowed origins: ${corsOptions.origin ? JSON.stringify(corsOptions.origin) : '*'}`);
87
+ }
88
+ const limiter = RateLimit({
89
+ windowMs: 60 * 1000, // 1 minute
90
+ max: config.perMinuteRateLimit ? config.perMinuteRateLimit : 3000
91
+ });
92
+ // apply rate limiter to all requests. Registered before any route
93
+ // handler so that static files, the homepage route, and any routes
94
+ // registered on `app` by downstream code are all subject to it.
95
+ app.use(limiter);
96
+ if (config.serveStatic) {
97
+ app.use(express.static(config.root));
98
+ // Request has been sent to site root, send the homepage file
99
+ app.get('/', function (req, res) {
100
+ // Try a few paths, see if any resolve to a homepage file the user has set
101
+ const p = path.resolve(path.join(config.root, config.homepageFile));
102
+ if (fs.existsSync(p)) {
103
+ // Send the file for browser to display it
104
+ res.sendFile(p);
105
+ return;
106
+ }
107
+ // Catch file doesn't exist, and send back 404 if not
108
+ const error = 'Unable to locate file ' + config.homepageFile;
109
+ Logger.error(error);
110
+ res.status(404).send(error);
111
+ return;
112
+ });
113
+ }
114
+ /* eslint-enable @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access */
115
+ }
116
+ }
117
+ //# sourceMappingURL=WebServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebServer.js","sourceRoot":"","sources":["../../src/WebServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ // Copyright Epic Games, Inc. All Rights Reserved.
2
+ export * from './Logger';
3
+ export * from './LoggingUtils';
4
+ export * from './PlayerConnection';
5
+ export * from './PlayerRegistry';
6
+ export * from './SFUConnection';
7
+ export * from './SignallingServer';
8
+ export * from './StreamerConnection';
9
+ export * from './StreamerRegistry';
10
+ export * from './WebServer';
11
+ // keep Utils internal for now
12
+ //# sourceMappingURL=pixelstreamingsignalling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pixelstreamingsignalling.js","sourceRoot":"","sources":["../../src/pixelstreamingsignalling.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,8BAA8B"}
@@ -0,0 +1,20 @@
1
+ import winston from 'winston';
2
+ import 'winston-daily-rotate-file';
3
+ /**
4
+ * The actual logger object. This is just a winston logger.
5
+ * You can use InitLogging to get a decent result, or you can
6
+ * completely create your own winston logger and assign it.
7
+ */
8
+ export declare let Logger: winston.Logger;
9
+ export interface IConfig {
10
+ logDir?: string;
11
+ logMessagesToConsole?: string;
12
+ logLevelConsole?: string;
13
+ logLevelFile?: string;
14
+ }
15
+ /**
16
+ * Call this as early as possible to setup the logging module with your
17
+ * preferred settings.
18
+ * @param config - The settings to init the logger with. See IConfig interface
19
+ */
20
+ export declare function InitLogging(config: IConfig): void;
@@ -0,0 +1,44 @@
1
+ import { BaseMessage } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.8';
2
+ export interface IProtoLogObj {
3
+ event: string;
4
+ direction: string;
5
+ sender?: string;
6
+ receiver?: string;
7
+ target?: string;
8
+ protoMessage: BaseMessage;
9
+ }
10
+ /**
11
+ * Most methods in here rely on connections implementing this interface so we can identify
12
+ * who is sending or receiving etc.
13
+ */
14
+ export interface IMessageLogger {
15
+ getReadableIdentifier(): string;
16
+ }
17
+ /**
18
+ * Call to log messages received on a connection that we will handle here at the server.
19
+ * Do not call this for messages being forwarded to another connection.
20
+ * @param recvr - IMessageLogger The connection the message was received on.
21
+ */
22
+ export declare function logIncoming(recvr: IMessageLogger, message: BaseMessage): void;
23
+ /**
24
+ * Call to log messages created here at the server and being sent to the connection.
25
+ * Do not call this for messages being forwarded to this connection.
26
+ * @param sender - IMessageLogger The connection the message is being sent to.
27
+ */
28
+ export declare function logOutgoing(sender: IMessageLogger, message: BaseMessage): void;
29
+ /**
30
+ * Call this for messages being forwarded to this connection. That is messages received on
31
+ * one connection and being sent to another with only minor changes being made.
32
+ * @param recvr - The connection the message was received on.
33
+ * @param target - The connection the message is being sent to.
34
+ */
35
+ export declare function logForward(recvr: IMessageLogger, target: IMessageLogger, message: BaseMessage): void;
36
+ /**
37
+ * We don't want to log every incoming and outgoing messages. This is because some messages are simply
38
+ * forwarded to other connections. This results in duplicated spam. So we only want to log incoming
39
+ * messages that we handle internally, and any messages that we forward we only log once for the recv
40
+ * and send events.
41
+ * This creation method allows a simple way to enforce this. Any events we handle directly will
42
+ * be preceded by the logging call.
43
+ */
44
+ export declare function createHandlerListener(obj: IMessageLogger, handler: (message: any) => void): (message: BaseMessage) => void;
@@ -0,0 +1,66 @@
1
+ import type { IncomingMessage } from 'http';
2
+ import WebSocket from 'ws';
3
+ import { ITransport, SignallingProtocol, BaseMessage } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.8';
4
+ import { IPlayer, IPlayerInfo } from './PlayerRegistry';
5
+ import { IStreamer } from './StreamerRegistry';
6
+ import * as LogUtils from './LoggingUtils';
7
+ import { SignallingServer } from './SignallingServer';
8
+ /**
9
+ * A connection between the signalling server and a player connection.
10
+ * This is where messages expected to be handled by the player come in
11
+ * and where messages are sent to the player.
12
+ *
13
+ * Interesting internals:
14
+ * playerId: The unique id string of this player.
15
+ * transport: The ITransport where transport events can be subscribed to
16
+ * protocol: The SignallingProtocol where signalling messages can be
17
+ * subscribed to.
18
+ */
19
+ export declare class PlayerConnection implements IPlayer, LogUtils.IMessageLogger {
20
+ playerId: string;
21
+ transport: ITransport;
22
+ protocol: SignallingProtocol;
23
+ subscribedStreamer: IStreamer | null;
24
+ remoteAddress?: string;
25
+ request?: IncomingMessage;
26
+ private server;
27
+ private streamerIdChangeListener;
28
+ private streamerDisconnectedListener;
29
+ /**
30
+ * Initializes a new connection with given and sane values. Adds listeners for the
31
+ * websocket close and error so it can react by unsubscribing and resetting itself.
32
+ * @param server - The signalling server object that spawned this player.
33
+ * @param ws - The websocket coupled to this player connection.
34
+ * @param remoteAddress - The remote address of this connection. Only used as display.
35
+ * @param request - The HTTP upgrade request that opened this connection, if available.
36
+ */
37
+ constructor(server: SignallingServer, ws: WebSocket, remoteAddress?: string, request?: IncomingMessage);
38
+ /**
39
+ * Returns an identifier that is displayed in logs.
40
+ * @returns A string describing this connection.
41
+ */
42
+ getReadableIdentifier(): string;
43
+ /**
44
+ * Sends a signalling message to the player.
45
+ * @param message - The message to send.
46
+ */
47
+ sendMessage(message: BaseMessage): void;
48
+ /**
49
+ * Returns a descriptive object for the REST API inspection operations.
50
+ * @returns An IPlayerInfo object containing viewable information about this connection.
51
+ */
52
+ getPlayerInfo(): IPlayerInfo;
53
+ private registerMessageHandlers;
54
+ private sendToStreamer;
55
+ private subscribe;
56
+ private unsubscribe;
57
+ private disconnect;
58
+ private onStreamerDisconnected;
59
+ private onTransportError;
60
+ private onTransportClose;
61
+ private onSubscribeMessage;
62
+ private onUnsubscribeMessage;
63
+ private onListStreamers;
64
+ private onStreamerIdChanged;
65
+ private onPingMessage;
66
+ }