diff --git a/Common/package-lock.json b/Common/package-lock.json index 817764fe9..43cc2413e 100644 --- a/Common/package-lock.json +++ b/Common/package-lock.json @@ -1,15 +1,17 @@ { "name": "@epicgames-ps/lib-pixelstreamingcommon-ue5.5", - "version": "0.0.6", + "version": "0.0.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@epicgames-ps/lib-pixelstreamingcommon-ue5.5", - "version": "0.0.6", + "version": "0.0.8", "license": "MIT", "dependencies": { - "@protobuf-ts/plugin": "^2.9.3" + "@protobuf-ts/plugin": "^2.9.3", + "@types/ws": "^8.5.10", + "ws": "^8.16.0" }, "devDependencies": { "@types/jest": "27.5.1", @@ -1751,7 +1753,6 @@ "version": "20.10.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -1780,6 +1781,14 @@ "integrity": "sha512-n3u5sqXQJhf1CS68mw3Wf16FQ4cRPNBBwdYLFzq3UddiADOim1Pn3Y6PBdDilz1vOJF3ybLxJ8ZEDlLIzrOQZg==", "dev": true }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "16.0.9", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", @@ -4921,6 +4930,27 @@ } } }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -6571,8 +6601,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unique-string": { "version": "2.0.0", @@ -6907,16 +6936,15 @@ } }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -8396,7 +8424,6 @@ "version": "20.10.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", - "dev": true, "requires": { "undici-types": "~5.26.4" } @@ -8425,6 +8452,14 @@ "integrity": "sha512-n3u5sqXQJhf1CS68mw3Wf16FQ4cRPNBBwdYLFzq3UddiADOim1Pn3Y6PBdDilz1vOJF3ybLxJ8ZEDlLIzrOQZg==", "dev": true }, + "@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "16.0.9", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", @@ -10801,6 +10836,15 @@ "whatwg-url": "^8.5.0", "ws": "^7.4.6", "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "requires": {} + } } }, "jsesc": { @@ -11990,8 +12034,7 @@ "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "unique-string": { "version": "2.0.0", @@ -12245,10 +12288,9 @@ } }, "ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "requires": {} }, "xdg-basedir": { diff --git a/Common/package.json b/Common/package.json index 5fb7ed2cc..a2954dca8 100644 --- a/Common/package.json +++ b/Common/package.json @@ -3,12 +3,12 @@ "version": "0.0.8", "description": "Common utilities library for Unreal Engine 5.5 Pixel Streaming", "main": "build/commonjs/pixelstreamingcommon.js", - "module": "build/es2015/pixelstreamingcommon.js", + "module": "build/esm/pixelstreamingcommon.js", "types": "build/types/pixelstreamingcommon.d.ts", "sideEffects": false, "scripts": { "build_proto": "npx protoc --ts_out src/Messages --proto_path protobuf protobuf/signalling_messages.proto", - "compile": "rimraf ./build && tsc --module es2015 --outDir build/es2015 && tsc --module commonjs --outDir build/commonjs --declaration --declarationDir build/types", + "compile": "rimraf ./build && tsc --project tsconfig.esm.json && tsc --project tsconfig.cjs.json", "build": "npm run build_proto && npm run compile", "test": "echo \"Error: no test specified\" && exit 1", "lint": "eslint . --ext .js,.jsx,.ts,.tsx" @@ -35,6 +35,8 @@ "access": "public" }, "dependencies": { - "@protobuf-ts/plugin": "^2.9.3" + "@protobuf-ts/plugin": "^2.9.3", + "@types/ws": "^8.5.10", + "ws": "^8.16.0" } } diff --git a/Common/src/WebSockets/SignallingProtocol.ts b/Common/src/Protocol/SignallingProtocol.ts similarity index 82% rename from Common/src/WebSockets/SignallingProtocol.ts rename to Common/src/Protocol/SignallingProtocol.ts index cade880ef..4f526dd4f 100644 --- a/Common/src/WebSockets/SignallingProtocol.ts +++ b/Common/src/Protocol/SignallingProtocol.ts @@ -14,12 +14,31 @@ export class SignallingProtocol { private transport: ITransport; /** - * Listen on this emitter for transport events, open, close, error. + * Listen on this emitter for transport events. + * + * Events emitted: + * open: + * Emitted when the transport connection opens and is ready to handle messages. + * + * error: + * Emitted when there is an error on the transport has an error and must close. + * + * close: + * Emitted when the transport connection closes and can no longer send or + * receive messages. Will also be emitted after an error. + * + * message: + * Emitted any time a message is received by the transport. Listen on this if + * you wish to capture all messages, rather than specific messages on + * 'messageHandlers'. */ transportEvents: EventEmitter; /** * Listen on this emitter for messages. Message type is the name of the event to listen for. + * + * Example: + * messageHandlers.addListener('config', (message: Messages.config) => console.log(`Got a config message: ${message}`))); */ messageHandlers: EventEmitter; diff --git a/SS_Test/src/WebSocketTransportCJS.ts b/Common/src/Transport/WebSocketTransportNJS.ts similarity index 85% rename from SS_Test/src/WebSocketTransportCJS.ts rename to Common/src/Transport/WebSocketTransportNJS.ts index 4ee5348f8..8fa6fb4b5 100644 --- a/SS_Test/src/WebSocketTransportCJS.ts +++ b/Common/src/Transport/WebSocketTransportNJS.ts @@ -1,13 +1,17 @@ // Copyright Epic Games, Inc. All Rights Reserved. -import { ITransport, BaseMessage } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5'; +import { ITransport } from './ITransport'; +import { BaseMessage } from '../Messages/base_message'; import WebSocket from 'ws'; import { EventEmitter } from 'events'; /** - * An implementation of WebSocketTransport from pixelstreamingcommon that supports commonjs websockets + * An implementation of WebSocketTransport from pixelstreamingcommon that supports node.js websockets + * This is needed because of the slight differences between the 'ws' node.js package and the websockets + * supported in the browsers. + * If you are using this code in a browser use 'WebSocketTransport' instead. */ -export class WebSocketTransportCJS implements ITransport { +export class WebSocketTransportNJS implements ITransport { WS_OPEN_STATE = 1; webSocket: WebSocket; events: EventEmitter; diff --git a/Common/src/pixelstreamingcommon.ts b/Common/src/pixelstreamingcommon.ts index 1dbe090c9..dcfda7dfc 100644 --- a/Common/src/pixelstreamingcommon.ts +++ b/Common/src/pixelstreamingcommon.ts @@ -1,7 +1,8 @@ export { Logger } from './Logger/Logger'; export { ITransport } from './Transport/ITransport'; export { WebSocketTransport } from './Transport/WebSocketTransport'; -export { SignallingProtocol } from './WebSockets/SignallingProtocol'; +export { WebSocketTransportNJS } from './Transport/WebSocketTransportNJS'; +export { SignallingProtocol } from './Protocol/SignallingProtocol'; export { IMessageType } from "@protobuf-ts/runtime"; export { BaseMessage } from './Messages/base_message'; export { MessageRegistry } from './Messages/message_registry'; diff --git a/Common/tsconfig.base.json b/Common/tsconfig.base.json new file mode 100644 index 000000000..be58135d6 --- /dev/null +++ b/Common/tsconfig.base.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "noImplicitAny": true, + "esModuleInterop": true, + "target": "ES6", + "moduleResolution": "node", + "sourceMap": true, + "allowJs": true + }, + "include": ["./src/*.ts"], +} diff --git a/Common/tsconfig.cjs.json b/Common/tsconfig.cjs.json new file mode 100644 index 000000000..ccee4d619 --- /dev/null +++ b/Common/tsconfig.cjs.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "outDir": "./build/commonjs", + "module": "commonjs", + "declaration": true, + "declarationDir": "./build/types" + } +} diff --git a/Common/tsconfig.esm.json b/Common/tsconfig.esm.json new file mode 100644 index 000000000..184e0dcdb --- /dev/null +++ b/Common/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "outDir": "./build/esm", + "module": "es2015" + } +} diff --git a/Common/tsconfig.json b/Common/tsconfig.json deleted file mode 100644 index 2384467b6..000000000 --- a/Common/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./types", - "noImplicitAny": true, - "module": "es6", - "esModuleInterop": true, - "target": "ES6", - "moduleResolution": "node", - "sourceMap": true, - "allowJs": true, - "declaration": true - }, - "lib": ["es2015"], - "include": ["./src/*.ts"], - "exclude": ["./src/**/*.test.ts"], - "typedocOptions": { - "exclude": "src/index.*", - "entryPoints": ["src/pixelstreamingcommon.ts"], - "sort": ["enum-value-ascending", "required-first", "source-order"], - "out": "docs", - "theme": "default", - "hideGenerator": "true" - } -} - diff --git a/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts b/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts index 845318f84..c41bf824b 100644 --- a/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts +++ b/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts @@ -1610,7 +1610,7 @@ export class WebRtcPlayerController { maxBitrateBps: 1000 * this.config.getNumericSettingValue(NumericParameters.WebRTCMaxBitrate) }; - this.protocol.sendWebRtcOffer(MessageHelpers.createMessage(Messages.offer, extraParams)); + this.protocol.sendWebRtcOffer(extraParams); } /** @@ -1630,7 +1630,7 @@ export class WebRtcPlayerController { maxBitrateBps: 1000 * this.config.getNumericSettingValue(NumericParameters.WebRTCMaxBitrate) }; - this.protocol.sendWebRtcOffer(MessageHelpers.createMessage(Messages.answer, extraParams)); + this.protocol.sendWebRtcAnswer(extraParams); if (this.isUsingSFU) { this.protocol.sendWebRtcDatachannelRequest(); diff --git a/SS_Test/Dockerfile b/SS_Test/Dockerfile index b48ef73e8..78fdae2ba 100644 --- a/SS_Test/Dockerfile +++ b/SS_Test/Dockerfile @@ -1,14 +1,19 @@ FROM node:18.17.0 as builder -COPY SS_Test/package*.json /SignallingTester/SS_Test/ -COPY Common/protobuf/signalling_messages.proto /SignallingTester/Common/protobuf/signalling_messages.proto +WORKDIR /SignallingTester -WORKDIR /SignallingTester/SS_Test +COPY Common/ Common +COPY SS_Test/ SS_Test + +WORKDIR /SignallingTester/Common RUN npm ci +RUN npm run build -COPY SS_Test/. . +WORKDIR /SignallingTester/SS_Test +RUN npm ci +RUN npm link ../Common RUN npm run build USER node diff --git a/SS_Test/src/signalling_tester.ts b/SS_Test/src/signalling_tester.ts index 19ed927f7..b09ee8625 100644 --- a/SS_Test/src/signalling_tester.ts +++ b/SS_Test/src/signalling_tester.ts @@ -2,8 +2,8 @@ import { IMessageType, BaseMessage, MessageRegistry, MessageHelpers, + WebSocketTransportNJS, SignallingProtocol } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5'; -import { WebSocketTransportCJS } from './WebSocketTransportCJS'; import WebSocket from 'ws'; export interface ExpectedMessage { @@ -157,7 +157,7 @@ export class SignallingConnection { this.failedCallback = (connection, unsatisfiedExpects, unhandledEvents) => {}; this.processTimer = null; - this.protocol = new SignallingProtocol(new WebSocketTransportCJS()); + this.protocol = new SignallingProtocol(new WebSocketTransportNJS()); this.protocol.transportEvents.addListener("open", event => this.onConnectionOpen(event)); this.protocol.transportEvents.addListener("error", event => this.onConnectionError(event)); this.protocol.transportEvents.addListener("close", event => this.onConnectionClose(event));