diff --git a/plugins/cloud/package-lock.json b/plugins/cloud/package-lock.json index fd38701b9..fcec5f01c 100644 --- a/plugins/cloud/package-lock.json +++ b/plugins/cloud/package-lock.json @@ -1,15 +1,16 @@ { "name": "@scrypted/cloud", - "version": "0.0.22", + "version": "0.0.23", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/cloud", - "version": "0.0.22", + "version": "0.0.23", "dependencies": { "@koush/wrtc": "^0.5.2", "axios": "^0.21.1", + "bpmux": "^8.1.3", "debug": "^4.3.1", "http-proxy": "^1.18.1", "push-receiver": "^2.1.1", @@ -23,7 +24,7 @@ }, "../../sdk": { "name": "@scrypted/sdk", - "version": "0.0.134", + "version": "0.0.139", "dev": true, "license": "ISC", "dependencies": { @@ -498,6 +499,17 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "node_modules/bpmux": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/bpmux/-/bpmux-8.1.3.tgz", + "integrity": "sha512-GPcaXF/V5vQk6GjpYLAuaMZtm+sHN6RGq04dBzzZIMlfWwgI8e2iyjfZAoGHBEKpSywR/rStniaITLwkrC9FdQ==", + "dependencies": { + "frame-stream": "^2.0.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -737,9 +749,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", - "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==", + "version": "1.14.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", + "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", "funding": [ { "type": "individual", @@ -776,6 +788,14 @@ "node": ">= 0.12" } }, + "node_modules/frame-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/frame-stream/-/frame-stream-2.1.0.tgz", + "integrity": "sha512-EFeq3xo+oXi2zmpwzK3cN84iIPp7gR8dZS8VZXd4kcBtjct1Br8VDsfib235pWo4VrBO/LxT5lGHbxvX+XgSUQ==", + "engines": { + "node": ">=5" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2277,6 +2297,14 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "bpmux": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/bpmux/-/bpmux-8.1.3.tgz", + "integrity": "sha512-GPcaXF/V5vQk6GjpYLAuaMZtm+sHN6RGq04dBzzZIMlfWwgI8e2iyjfZAoGHBEKpSywR/rStniaITLwkrC9FdQ==", + "requires": { + "frame-stream": "^2.0.3" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2468,9 +2496,9 @@ } }, "follow-redirects": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", - "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==" + "version": "1.14.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", + "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" }, "forever-agent": { "version": "0.6.1", @@ -2487,6 +2515,11 @@ "mime-types": "^2.1.12" } }, + "frame-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/frame-stream/-/frame-stream-2.1.0.tgz", + "integrity": "sha512-EFeq3xo+oXi2zmpwzK3cN84iIPp7gR8dZS8VZXd4kcBtjct1Br8VDsfib235pWo4VrBO/LxT5lGHbxvX+XgSUQ==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", diff --git a/plugins/cloud/package.json b/plugins/cloud/package.json index 38c3fff93..6f8b2e9a8 100644 --- a/plugins/cloud/package.json +++ b/plugins/cloud/package.json @@ -34,6 +34,7 @@ "dependencies": { "@koush/wrtc": "^0.5.2", "axios": "^0.21.1", + "bpmux": "^8.1.3", "debug": "^4.3.1", "http-proxy": "^1.18.1", "push-receiver": "^2.1.1", @@ -44,5 +45,5 @@ "@types/debug": "^4.1.5", "@types/http-proxy": "^1.17.5" }, - "version": "0.0.22" + "version": "0.0.23" } diff --git a/plugins/cloud/src/legacy.ts b/plugins/cloud/src/legacy.ts index 1b36ad122..cc08b36b5 100644 --- a/plugins/cloud/src/legacy.ts +++ b/plugins/cloud/src/legacy.ts @@ -469,11 +469,8 @@ export class GcmRtcManager extends EventEmitter { conn.manager.incoming(senderId, src, srcPort, dst, dstPort, message); return; } - else if (GcmRtcManager.onUnknownMessage) { - GcmRtcManager.onUnknownMessage(data); - } else { - debug('unknown message ' + type); + throw new Error("unhandled message"); } } @@ -881,10 +878,6 @@ export class GcmRtcManager extends EventEmitter { } return sdp; }; - - static onUnknownMessage(data: any) { - - } } diff --git a/plugins/cloud/src/main.ts b/plugins/cloud/src/main.ts index 5840bdec8..55a974d0f 100644 --- a/plugins/cloud/src/main.ts +++ b/plugins/cloud/src/main.ts @@ -11,10 +11,12 @@ import Url from 'url'; import sdk from "@scrypted/sdk"; import { once } from 'events'; import path from 'path'; +import bpmux from 'bpmux'; const { deviceManager, endpointManager } = sdk; export const DEFAULT_SENDER_ID = '827888101440'; +const SCRYPTED_SERVER = 'home.scrypted.app'; export async function createDefaultRtcManager(): Promise { const manager = await GcmRtcManager.start({ @@ -23,11 +25,6 @@ export async function createDefaultRtcManager(): Promise { }, { iceServers: [ - { - urls: ["turn:turn0.clockworkmod.com", "turn:n0.clockworkmod.com", "turn:n1.clockworkmod.com"], - username: "foo", - credential: "bar", - }, ], }); @@ -132,7 +129,7 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, } getHostname() { - const hostname = this.storage.getItem('hostname') || 'home.scrypted.app'; + const hostname = this.storage.getItem('hostname') || SCRYPTED_SERVER; return hostname; } @@ -178,7 +175,7 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, registration_id: this.manager.registrationId, sender_id: DEFAULT_SENDER_ID, }) - return `https://home.scrypted.app/_punch/login?${args}`; + return `https://home.koushikdutta.com/_punch/login?${args}`; // this is disabled because we can't assume that custom domains will implement this oauth endpoint. // return `https://${this.getHostname()}/_punch/login?${args}` } @@ -244,20 +241,39 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings, this.manager = await createDefaultRtcManager(); this.manager.on('unhandled', message => { - if (message.type !== 'cloudmessage') - return; - try { - const payload = JSON.parse(message.request) as HttpRequest; - if (!payload.rootPath?.startsWith('/push/')) - return; - const endpoint = payload.rootPath.replace('/push/', ''); - payload.rootPath = '/'; - endpointManager.deliverPush(endpoint, payload) + if (message.type === 'cloudmessage') { + try { + const payload = JSON.parse(message.request) as HttpRequest; + if (!payload.rootPath?.startsWith('/push/')) + return; + const endpoint = payload.rootPath.replace('/push/', ''); + payload.rootPath = '/'; + endpointManager.deliverPush(endpoint, payload) + } + catch (e) { + this.console.error('cloudmessage error', e); + } } - catch (e) { - this.console.error('cloudmessage error', e); + else if (message.type === 'callback') { + const client = net.connect(4000, 'home.scrypted.app'); + client.write(this.manager.registrationId + '\n'); + const mux: any = new bpmux.BPMux(client as any); + mux.on('handshake', async (socket: Duplex) => { + let local: any; + + await new Promise(resolve => process.nextTick(resolve)); + + local = net.connect({ + port, + host: '127.0.0.1', + }); + await new Promise(resolve => process.nextTick(resolve)); + + socket.pipe(local).pipe(socket); + }) } }); + // legacy this.manager.listen("http://localhost", (conn: GcmRtcConnection) => { conn.on('socket', async (command: string, socket: Duplex) => { let local: any;