@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,264 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SFUConnection = void 0;
37
+ const lib_pixelstreamingcommon_ue5_8_1 = require("@epicgames-ps/lib-pixelstreamingcommon-ue5.8");
38
+ const Logger_1 = require("./Logger");
39
+ const LogUtils = __importStar(require("./LoggingUtils"));
40
+ /**
41
+ * A SFU connection to the signalling server.
42
+ * An SFU can act as both a streamer and a player. It can subscribe to
43
+ * streamers like a player, and other players can subscribe to the sfu.
44
+ * Therefore the SFU will have a streamer id and a player id and be
45
+ * registered in both streamer registries and player registries.
46
+ *
47
+ * Interesting internals:
48
+ * playerId: The player id of this connectiom.
49
+ * streamerId: The streamer id of this connection.
50
+ * transport: The ITransport where transport events can be subscribed to
51
+ * protocol: The SignallingProtocol where signalling messages can be
52
+ * subscribed to.
53
+ * streaming: True when the streamer is ready to accept subscriptions.
54
+ */
55
+ class SFUConnection extends lib_pixelstreamingcommon_ue5_8_1.EventEmitter {
56
+ /**
57
+ * Construct a new SFU connection.
58
+ * @param server - The signalling server object that spawned this sfu.
59
+ * @param ws - The websocket coupled to this sfu connection.
60
+ * @param remoteAddress - The remote address of this connection. Only used as display.
61
+ * @param request - The HTTP upgrade request that opened this connection, if available.
62
+ */
63
+ constructor(server, ws, remoteAddress, request) {
64
+ super();
65
+ this.server = server;
66
+ this.transport = new lib_pixelstreamingcommon_ue5_8_1.WebSocketTransportNJS(ws);
67
+ this.protocol = new lib_pixelstreamingcommon_ue5_8_1.SignallingProtocol(this.transport);
68
+ this.playerId = '';
69
+ this.streamerId = '';
70
+ this.streaming = false;
71
+ this.remoteAddress = remoteAddress;
72
+ this.request = request;
73
+ this.subscribedStreamer = null;
74
+ this.maxSubscribers = 0;
75
+ this.subscribers = new Set();
76
+ this.transport.on('error', this.onTransportError.bind(this));
77
+ this.transport.on('close', this.onTransportClose.bind(this));
78
+ this.layerPreferenceListener = this.onLayerPreference.bind(this);
79
+ this.streamerIdChangeListener = this.onStreamerIdChanged.bind(this);
80
+ this.streamerDisconnectedListener = this.onStreamerDisconnected.bind(this);
81
+ this.registerMessageHandlers();
82
+ }
83
+ /**
84
+ * Returns an identifier that is displayed in logs.
85
+ * @returns A string describing this connection.
86
+ */
87
+ getReadableIdentifier() {
88
+ return `(${this.streamerId}:${this.playerId})`;
89
+ }
90
+ /**
91
+ * Sends a signalling message to the SFU.
92
+ * @param message - The message to send.
93
+ */
94
+ sendMessage(message) {
95
+ LogUtils.logOutgoing(this, message);
96
+ this.protocol.sendMessage(message);
97
+ }
98
+ /**
99
+ * Returns a descriptive object for the REST API inspection operations.
100
+ * @returns An IStreamerInfo object containing viewable information about this connection.
101
+ */
102
+ getStreamerInfo() {
103
+ return {
104
+ streamerId: this.streamerId,
105
+ type: 'SFU',
106
+ streaming: this.streaming,
107
+ remoteAddress: this.remoteAddress,
108
+ subscribers: this.server.playerRegistry
109
+ .listPlayers()
110
+ .filter((player) => player.subscribedStreamer == this)
111
+ .map((player) => player.getPlayerInfo())
112
+ };
113
+ }
114
+ /**
115
+ * Returns a descriptive object for the REST API inspection operations.
116
+ * @returns An IPlayerInfo object containing viewable information about this connection.
117
+ */
118
+ getPlayerInfo() {
119
+ var _a;
120
+ return {
121
+ playerId: this.playerId,
122
+ type: 'SFU',
123
+ remoteAddress: this.remoteAddress,
124
+ subscribedTo: (_a = this.subscribedStreamer) === null || _a === void 0 ? void 0 : _a.streamerId
125
+ };
126
+ }
127
+ registerMessageHandlers() {
128
+ /* eslint-disable @typescript-eslint/unbound-method */
129
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.subscribe.typeName, LogUtils.createHandlerListener(this, this.onSubscribeMessage));
130
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.unsubscribe.typeName, LogUtils.createHandlerListener(this, this.onUnsubscribeMessage));
131
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.listStreamers.typeName, LogUtils.createHandlerListener(this, this.onListStreamers));
132
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.endpointId.typeName, LogUtils.createHandlerListener(this, this.onEndpointId));
133
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.streamerDataChannels.typeName, LogUtils.createHandlerListener(this, this.onStreamerDataChannels));
134
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.startStreaming.typeName, LogUtils.createHandlerListener(this, this.onStartStreaming));
135
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.stopStreaming.typeName, LogUtils.createHandlerListener(this, this.onStopStreaming));
136
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.ping.typeName, LogUtils.createHandlerListener(this, this.onPingMessage));
137
+ /* eslint-enable @typescript-eslint/unbound-method */
138
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.offer.typeName, this.sendToPlayer.bind(this));
139
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.answer.typeName, this.sendToStreamer.bind(this));
140
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.peerDataChannels.typeName, this.sendToPlayer.bind(this));
141
+ }
142
+ subscribe(streamerId) {
143
+ const streamer = this.server.streamerRegistry.find(streamerId);
144
+ if (!streamer) {
145
+ Logger_1.Logger.error(`subscribe: SFU ${this.playerId} tried to subscribe to a non-existent streamer ${streamerId}`);
146
+ return;
147
+ }
148
+ this.subscribedStreamer = streamer;
149
+ // Register as a subscriber of the upstream streamer so it will forward signalling messages
150
+ // back to this SFU (the streamer's forwardMessage only sends to subscribed players).
151
+ this.subscribedStreamer.subscribers.add(this.playerId);
152
+ this.subscribedStreamer.on('layer_preference', this.layerPreferenceListener);
153
+ this.subscribedStreamer.on('id_changed', this.streamerIdChangeListener);
154
+ this.subscribedStreamer.on('disconnect', this.streamerDisconnectedListener);
155
+ const connectedMessage = lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.playerConnected, {
156
+ playerId: this.playerId,
157
+ dataChannel: true,
158
+ sfu: true
159
+ });
160
+ this.sendToStreamer(connectedMessage);
161
+ }
162
+ unsubscribe() {
163
+ if (!this.subscribedStreamer) {
164
+ return;
165
+ }
166
+ const disconnectedMessage = lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.playerDisconnected, {
167
+ playerId: this.playerId
168
+ });
169
+ this.sendToStreamer(disconnectedMessage);
170
+ this.subscribedStreamer.subscribers.delete(this.playerId);
171
+ this.subscribedStreamer.off('layer_preference', this.layerPreferenceListener);
172
+ this.subscribedStreamer.off('id_changed', this.streamerIdChangeListener);
173
+ this.subscribedStreamer.off('disconnect', this.streamerDisconnectedListener);
174
+ this.subscribedStreamer = null;
175
+ }
176
+ sendToStreamer(message) {
177
+ if (!this.subscribedStreamer) {
178
+ Logger_1.Logger.error(`SFU ${this.playerId} tried to send to a streamer but they're not subscribed to any.`);
179
+ return;
180
+ }
181
+ LogUtils.logForward(this, this.subscribedStreamer, message);
182
+ // normally we want to indicate what player this message came from
183
+ // but in some instances we might already have set this (streamerDataChannels) due to poor choices
184
+ message.playerId = message.playerId || this.playerId;
185
+ this.subscribedStreamer.protocol.sendMessage(message);
186
+ }
187
+ sendToPlayer(message) {
188
+ if (!message.playerId) {
189
+ Logger_1.Logger.error(`SFU ${this.streamerId} trying to send a message to a player with no playerId. Ignored.`);
190
+ return;
191
+ }
192
+ if (!this.subscribers.has(message.playerId)) {
193
+ // Only send to players subscribed to this SFU, otherwise the SFU could target any player
194
+ // on the server via the global player registry (cross-tenant signalling).
195
+ Logger_1.Logger.error(`SFU ${this.streamerId} tried to send a message to player ${message.playerId} which is not subscribed to it. Ignored.`);
196
+ return;
197
+ }
198
+ const player = this.server.playerRegistry.get(message.playerId);
199
+ if (player) {
200
+ delete message.playerId;
201
+ LogUtils.logForward(this, player, message);
202
+ player.protocol.sendMessage(message);
203
+ }
204
+ else {
205
+ Logger_1.Logger.error(`SFU attempted to forward to player ${message.playerId} which does not exist.`);
206
+ }
207
+ }
208
+ disconnect() {
209
+ this.unsubscribe();
210
+ this.protocol.disconnect();
211
+ this.emit('disconnect');
212
+ }
213
+ onLayerPreference(message) {
214
+ this.sendMessage(message);
215
+ }
216
+ onStreamerIdChanged(newId) {
217
+ const renameMessage = lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.streamerIdChanged, { newID: newId });
218
+ this.sendMessage(renameMessage);
219
+ }
220
+ onStreamerDisconnected() {
221
+ this.unsubscribe();
222
+ this.sendMessage(lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.streamerDisconnected));
223
+ this.streaming = false;
224
+ this.emit('disconnect');
225
+ }
226
+ onTransportError(error) {
227
+ Logger_1.Logger.error(`SFU (${this.playerId}) transport error ${error.message}`);
228
+ }
229
+ onTransportClose(_event) {
230
+ Logger_1.Logger.debug('SFUConnection transport close.');
231
+ this.disconnect();
232
+ }
233
+ onSubscribeMessage(message) {
234
+ this.subscribe(message.streamerId);
235
+ }
236
+ onUnsubscribeMessage(_message) {
237
+ this.unsubscribe();
238
+ }
239
+ onListStreamers(_message) {
240
+ const listMessage = lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.streamerList, {
241
+ ids: this.server.streamerRegistry.streamers.map((streamer) => streamer.streamerId)
242
+ });
243
+ this.sendMessage(listMessage);
244
+ }
245
+ onStreamerDataChannels(message) {
246
+ message.sfuId = this.playerId;
247
+ this.sendToStreamer(message);
248
+ }
249
+ onEndpointId(_message) {
250
+ this.streaming = true;
251
+ }
252
+ onStartStreaming(_message) {
253
+ this.streaming = true;
254
+ }
255
+ onStopStreaming(_message) {
256
+ this.streaming = false;
257
+ this.emit('disconnect');
258
+ }
259
+ onPingMessage(message) {
260
+ this.sendMessage(lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.pong, { time: message.time }));
261
+ }
262
+ }
263
+ exports.SFUConnection = SFUConnection;
264
+ //# sourceMappingURL=SFUConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SFUConnection.js","sourceRoot":"","sources":["../../src/SFUConnection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SignallingServer = void 0;
37
+ const wslib = __importStar(require("ws"));
38
+ const StreamerConnection_1 = require("./StreamerConnection");
39
+ const PlayerConnection_1 = require("./PlayerConnection");
40
+ const SFUConnection_1 = require("./SFUConnection");
41
+ const Logger_1 = require("./Logger");
42
+ const StreamerRegistry_1 = require("./StreamerRegistry");
43
+ const PlayerRegistry_1 = require("./PlayerRegistry");
44
+ const lib_pixelstreamingcommon_ue5_8_1 = require("@epicgames-ps/lib-pixelstreamingcommon-ue5.8");
45
+ const Utils_1 = require("./Utils");
46
+ /**
47
+ * The main signalling server object.
48
+ * Contains a streamer and player registry and handles setting up of websockets
49
+ * to listen for incoming connections.
50
+ */
51
+ class SignallingServer {
52
+ /**
53
+ * Initializes the server object and sets up listening sockets for streamers
54
+ * players and optionally SFU connections.
55
+ * @param config - A collection of options for this server.
56
+ */
57
+ constructor(config) {
58
+ Logger_1.Logger.debug('Started SignallingServer with config: %s', (0, Utils_1.stringify)(config));
59
+ this.config = config;
60
+ this.streamerRegistry = new StreamerRegistry_1.StreamerRegistry(config.authorizeStreamerId);
61
+ this.playerRegistry = new PlayerRegistry_1.PlayerRegistry();
62
+ this.protocolConfig = {
63
+ protocolVersion: lib_pixelstreamingcommon_ue5_8_1.SignallingProtocol.SIGNALLING_VERSION,
64
+ peerConnectionOptions: this.config.peerOptions || {}
65
+ };
66
+ this.startTime = new Date();
67
+ if (!config.playerPort && !config.httpServer && !config.httpsServer) {
68
+ Logger_1.Logger.error('No player port, http server or https server supplied to SignallingServer.');
69
+ return;
70
+ }
71
+ // Streamer connections
72
+ const streamerServer = new wslib.WebSocketServer(Object.assign({ port: config.streamerPort, backlog: 1 }, config.streamerWsOptions));
73
+ streamerServer.on('connection', this.onStreamerConnected.bind(this));
74
+ Logger_1.Logger.info(`Listening for streamer connections on port ${config.streamerPort}`);
75
+ // Player connections
76
+ const server = config.httpsServer || config.httpServer;
77
+ const playerServer = new wslib.WebSocketServer(Object.assign({ server: server, port: server ? undefined : config.playerPort }, config.playerWsOptions));
78
+ playerServer.on('connection', this.onPlayerConnected.bind(this));
79
+ if (!config.httpServer && !config.httpsServer) {
80
+ Logger_1.Logger.info(`Listening for player connections on port ${config.playerPort}`);
81
+ }
82
+ // Optional SFU connections
83
+ if (config.sfuPort) {
84
+ const sfuServer = new wslib.WebSocketServer(Object.assign({ port: config.sfuPort, backlog: 1 }, config.sfuWsOptions));
85
+ sfuServer.on('connection', this.onSFUConnected.bind(this));
86
+ Logger_1.Logger.info(`Listening for SFU connections on port ${config.sfuPort}`);
87
+ }
88
+ }
89
+ sendConfigMessage(connection) {
90
+ // peer connection options is a general field with all optional fields;
91
+ // it doesnt play nice with mergePartial so we just add it verbatim
92
+ const message = lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.config, this.protocolConfig);
93
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
94
+ message.peerConnectionOptions = this.protocolConfig['peerConnectionOptions'];
95
+ connection.sendMessage(message);
96
+ }
97
+ onStreamerConnected(ws, request) {
98
+ Logger_1.Logger.info(`New streamer connection: %s`, request.socket.remoteAddress);
99
+ const newStreamer = new StreamerConnection_1.StreamerConnection(this, ws, request.socket.remoteAddress, request);
100
+ newStreamer.maxSubscribers = this.config.maxSubscribers || 0;
101
+ // add it to the registry and when the transport closes, remove it.
102
+ this.streamerRegistry.add(newStreamer);
103
+ newStreamer.transport.on('close', () => {
104
+ this.streamerRegistry.remove(newStreamer);
105
+ Logger_1.Logger.info(`Streamer %s (%s) disconnected.`, newStreamer.streamerId, request.socket.remoteAddress);
106
+ });
107
+ this.sendConfigMessage(newStreamer);
108
+ }
109
+ onPlayerConnected(ws, request) {
110
+ Logger_1.Logger.info(`New player connection: %s (%s)`, request.socket.remoteAddress, request.url);
111
+ const newPlayer = new PlayerConnection_1.PlayerConnection(this, ws, request.socket.remoteAddress, request);
112
+ // add it to the registry and when the transport closes, remove it
113
+ this.playerRegistry.add(newPlayer);
114
+ newPlayer.transport.on('close', () => {
115
+ this.playerRegistry.remove(newPlayer);
116
+ Logger_1.Logger.info(`Player %s (%s) disconnected.`, newPlayer.playerId, request.socket.remoteAddress);
117
+ });
118
+ // Optionally monitor the player connection for liveness. A player whose socket dies without
119
+ // a clean close frame (sleeping laptop, dropped Wi-Fi, killed tab) is otherwise only removed
120
+ // once the OS TCP keepalive eventually reaps it, leaving it subscribed in the meantime. When
121
+ // maxSubscribers is set this can hold a slot that no live player is using. We use
122
+ // ws.terminate() rather than a graceful close because a dead peer never completes the close
123
+ // handshake. The monitor stops itself on transport 'close', so no manual teardown is needed.
124
+ const keepaliveTimeout = this.config.playerKeepaliveTimeout || 0;
125
+ if (keepaliveTimeout > 0) {
126
+ const keepalive = new lib_pixelstreamingcommon_ue5_8_1.KeepaliveMonitor(newPlayer.protocol, keepaliveTimeout);
127
+ keepalive.onTimeout = () => {
128
+ Logger_1.Logger.info(`Player %s (%s) failed keepalive - terminating dead connection.`, newPlayer.playerId, request.socket.remoteAddress);
129
+ ws.terminate();
130
+ };
131
+ }
132
+ this.sendConfigMessage(newPlayer);
133
+ }
134
+ onSFUConnected(ws, request) {
135
+ Logger_1.Logger.info(`New SFU connection: %s`, request.socket.remoteAddress);
136
+ const newSFU = new SFUConnection_1.SFUConnection(this, ws, request.socket.remoteAddress, request);
137
+ // SFU acts as both a streamer and player
138
+ this.streamerRegistry.add(newSFU);
139
+ this.playerRegistry.add(newSFU);
140
+ newSFU.transport.on('close', () => {
141
+ this.streamerRegistry.remove(newSFU);
142
+ this.playerRegistry.remove(newSFU);
143
+ Logger_1.Logger.info(`SFU %s (%s) disconnected.`, newSFU.streamerId, request.socket.remoteAddress);
144
+ });
145
+ this.sendConfigMessage(newSFU);
146
+ }
147
+ }
148
+ exports.SignallingServer = SignallingServer;
149
+ //# sourceMappingURL=SignallingServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignallingServer.js","sourceRoot":"","sources":["../../src/SignallingServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.StreamerConnection = void 0;
37
+ const lib_pixelstreamingcommon_ue5_8_1 = require("@epicgames-ps/lib-pixelstreamingcommon-ue5.8");
38
+ const Utils_1 = require("./Utils");
39
+ const Logger_1 = require("./Logger");
40
+ const LogUtils = __importStar(require("./LoggingUtils"));
41
+ /**
42
+ * A connection between the signalling server and a streamer connection.
43
+ * This is where messages expected to be handled by the streamer come in
44
+ * and where messages are sent to the streamer.
45
+ *
46
+ * Interesting internals:
47
+ * streamerId: The unique id string of this streamer.
48
+ * transport: The ITransport where transport events can be subscribed to
49
+ * protocol: The SignallingProtocol where signalling messages can be
50
+ * subscribed to.
51
+ * streaming: True when the streamer is ready to accept subscriptions.
52
+ */
53
+ class StreamerConnection extends lib_pixelstreamingcommon_ue5_8_1.EventEmitter {
54
+ /**
55
+ * Initializes a new connection with given and sane values. Adds listeners for the
56
+ * websocket close and error and will emit a disconnected event when disconneted.
57
+ * @param server - The signalling server object that spawned this streamer.
58
+ * @param ws - The websocket coupled to this streamer connection.
59
+ * @param remoteAddress - The remote address of this connection. Only used as display.
60
+ * @param request - The HTTP upgrade request that opened this connection, if available.
61
+ */
62
+ constructor(server, ws, remoteAddress, request) {
63
+ super();
64
+ this.server = server;
65
+ this.streamerId = '';
66
+ this.transport = new lib_pixelstreamingcommon_ue5_8_1.WebSocketTransportNJS(ws);
67
+ this.protocol = new lib_pixelstreamingcommon_ue5_8_1.SignallingProtocol(this.transport);
68
+ this.streaming = false;
69
+ this.remoteAddress = remoteAddress;
70
+ this.request = request;
71
+ this.maxSubscribers = 0;
72
+ this.subscribers = new Set();
73
+ this.transport.on('error', this.onTransportError.bind(this));
74
+ this.transport.on('close', this.onTransportClose.bind(this));
75
+ this.registerMessageHandlers();
76
+ this.protocol.on('unhandled', (message) => {
77
+ Logger_1.Logger.warn(`Unhandled streamer protocol message: ${JSON.stringify(message)}`);
78
+ });
79
+ }
80
+ /**
81
+ * Returns an identifier that is displayed in logs.
82
+ * @returns A string describing this connection.
83
+ */
84
+ getReadableIdentifier() {
85
+ return this.streamerId;
86
+ }
87
+ /**
88
+ * Sends a signalling message to the player.
89
+ * @param message - The message to send.
90
+ */
91
+ sendMessage(message) {
92
+ LogUtils.logOutgoing(this, message);
93
+ this.protocol.sendMessage(message);
94
+ }
95
+ /**
96
+ * Returns a descriptive object for the REST API inspection operations.
97
+ * @returns An IStreamerInfo object containing viewable information about this connection.
98
+ */
99
+ getStreamerInfo() {
100
+ return {
101
+ streamerId: this.streamerId,
102
+ type: 'Streamer',
103
+ streaming: this.streaming,
104
+ remoteAddress: this.remoteAddress,
105
+ subscribers: this.server.playerRegistry
106
+ .listPlayers()
107
+ .filter((player) => player.subscribedStreamer == this)
108
+ .map((player) => player.getPlayerInfo())
109
+ };
110
+ }
111
+ registerMessageHandlers() {
112
+ /* eslint-disable @typescript-eslint/unbound-method */
113
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.endpointId.typeName, LogUtils.createHandlerListener(this, this.onEndpointId));
114
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.disconnectPlayer.typeName, LogUtils.createHandlerListener(this, this.onDisconnectPlayerRequest));
115
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.layerPreference.typeName, LogUtils.createHandlerListener(this, this.onLayerPreference));
116
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.ping.typeName, LogUtils.createHandlerListener(this, this.onPingMessage));
117
+ /* eslint-enable @typescript-eslint/unbound-method */
118
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.offer.typeName, this.forwardMessage.bind(this));
119
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.answer.typeName, this.forwardMessage.bind(this));
120
+ this.protocol.on(lib_pixelstreamingcommon_ue5_8_1.Messages.iceCandidate.typeName, this.forwardMessage.bind(this));
121
+ }
122
+ forwardMessage(message) {
123
+ if (!message.playerId) {
124
+ Logger_1.Logger.warn(`No playerId specified, cannot forward message: ${(0, Utils_1.stringify)(message)}`);
125
+ }
126
+ else if (!this.subscribers.has(message.playerId)) {
127
+ // Only forward to players that are actually subscribed to this streamer. Without this
128
+ // check a streamer could target any player on the server (resolved via the global player
129
+ // registry), allowing cross-tenant signalling on a shared signalling server.
130
+ Logger_1.Logger.warn(`Streamer ${this.streamerId} tried to forward a message to player ${message.playerId} which is not subscribed to it. Ignoring.`);
131
+ }
132
+ else {
133
+ const player = this.server.playerRegistry.get(message.playerId);
134
+ if (player) {
135
+ LogUtils.logForward(this, player, message);
136
+ player.protocol.sendMessage(message);
137
+ }
138
+ }
139
+ }
140
+ onTransportError(error) {
141
+ Logger_1.Logger.error(`Streamer (${this.streamerId}) transport error ${error.message}`);
142
+ }
143
+ onTransportClose() {
144
+ Logger_1.Logger.info(`Streamer '${this.streamerId}' - websocket disconnected.`);
145
+ this.emit('disconnect');
146
+ }
147
+ onEndpointId(_message) {
148
+ this.streaming = true; // we're ready to stream when we id ourselves
149
+ }
150
+ onDisconnectPlayerRequest(message) {
151
+ if (message.playerId) {
152
+ if (!this.subscribers.has(message.playerId)) {
153
+ // A streamer may only disconnect its own subscribed players. Otherwise any streamer
154
+ // could forcibly close arbitrary player connections on a shared signalling server.
155
+ Logger_1.Logger.warn(`Streamer ${this.streamerId} tried to disconnect player ${message.playerId} which is not subscribed to it. Ignoring.`);
156
+ return;
157
+ }
158
+ const player = this.server.playerRegistry.get(message.playerId);
159
+ if (player) {
160
+ player.protocol.disconnect(1011, message.reason);
161
+ }
162
+ }
163
+ }
164
+ onLayerPreference(message) {
165
+ this.emit('layer_preference', message);
166
+ }
167
+ onPingMessage(message) {
168
+ this.sendMessage(lib_pixelstreamingcommon_ue5_8_1.MessageHelpers.createMessage(lib_pixelstreamingcommon_ue5_8_1.Messages.pong, { time: message.time }));
169
+ }
170
+ }
171
+ exports.StreamerConnection = StreamerConnection;
172
+ //# sourceMappingURL=StreamerConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamerConnection.js","sourceRoot":"","sources":["../../src/StreamerConnection.ts"],"names":[],"mappings":"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"}