@scrypted/server 0.123.1 → 0.123.2
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.
- package/dist/ip.d.ts +2 -0
- package/dist/ip.js +5 -4
- package/dist/ip.js.map +1 -1
- package/dist/listen-zero.d.ts +5 -2
- package/dist/listen-zero.js +2 -1
- package/dist/listen-zero.js.map +1 -1
- package/dist/plugin/plugin-api.d.ts +9 -3
- package/dist/plugin/plugin-api.js +10 -1
- package/dist/plugin/plugin-api.js.map +1 -1
- package/dist/plugin/plugin-console.d.ts +2 -1
- package/dist/plugin/plugin-console.js +27 -6
- package/dist/plugin/plugin-console.js.map +1 -1
- package/dist/plugin/plugin-host-api.js +1 -1
- package/dist/plugin/plugin-host-api.js.map +1 -1
- package/dist/plugin/plugin-host.d.ts +4 -7
- package/dist/plugin/plugin-host.js +76 -62
- package/dist/plugin/plugin-host.js.map +1 -1
- package/dist/plugin/plugin-lazy-remote.d.ts +3 -3
- package/dist/plugin/plugin-lazy-remote.js +2 -2
- package/dist/plugin/plugin-lazy-remote.js.map +1 -1
- package/dist/plugin/plugin-remote-stats.d.ts +2 -2
- package/dist/plugin/plugin-remote-stats.js +4 -2
- package/dist/plugin/plugin-remote-stats.js.map +1 -1
- package/dist/plugin/plugin-remote-worker.d.ts +0 -1
- package/dist/plugin/plugin-remote-worker.js +77 -335
- package/dist/plugin/plugin-remote-worker.js.map +1 -1
- package/dist/plugin/plugin-remote.d.ts +3 -3
- package/dist/plugin/plugin-remote.js +2 -2
- package/dist/plugin/plugin-remote.js.map +1 -1
- package/dist/plugin/plugin-repl.js +2 -1
- package/dist/plugin/plugin-repl.js.map +1 -1
- package/dist/plugin/runtime/cluster-fork.worker.d.ts +9 -0
- package/dist/plugin/runtime/cluster-fork.worker.js +73 -0
- package/dist/plugin/runtime/cluster-fork.worker.js.map +1 -0
- package/dist/plugin/runtime/custom-worker.js +2 -2
- package/dist/plugin/runtime/custom-worker.js.map +1 -1
- package/dist/plugin/runtime/node-fork-worker.js +5 -3
- package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
- package/dist/plugin/runtime/python-worker.js +2 -2
- package/dist/plugin/runtime/python-worker.js.map +1 -1
- package/dist/rpc.d.ts +1 -0
- package/dist/rpc.js +3 -2
- package/dist/rpc.js.map +1 -1
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.js +16 -2
- package/dist/runtime.js.map +1 -1
- package/dist/scrypted-cluster-common.d.ts +22 -0
- package/dist/scrypted-cluster-common.js +332 -0
- package/dist/scrypted-cluster-common.js.map +1 -0
- package/dist/scrypted-cluster-main.d.ts +2 -0
- package/dist/scrypted-cluster-main.js +12 -0
- package/dist/scrypted-cluster-main.js.map +1 -0
- package/dist/scrypted-cluster.d.ts +38 -0
- package/dist/scrypted-cluster.js +277 -0
- package/dist/scrypted-cluster.js.map +1 -0
- package/dist/scrypted-main-exports.js +20 -14
- package/dist/scrypted-main-exports.js.map +1 -1
- package/dist/scrypted-server-main.js +8 -15
- package/dist/scrypted-server-main.js.map +1 -1
- package/dist/server-settings.d.ts +1 -0
- package/dist/server-settings.js +2 -1
- package/dist/server-settings.js.map +1 -1
- package/dist/services/backup.js.map +1 -1
- package/dist/services/cluster-fork.d.ts +7 -0
- package/dist/services/cluster-fork.js +25 -0
- package/dist/services/cluster-fork.js.map +1 -0
- package/dist/services/plugin.d.ts +2 -7
- package/dist/services/plugin.js +2 -17
- package/dist/services/plugin.js.map +1 -1
- package/package.json +2 -2
- package/python/plugin_remote.py +150 -135
- package/python/rpc_reader.py +3 -19
- package/src/ip.ts +5 -4
- package/src/listen-zero.ts +3 -2
- package/src/plugin/plugin-api.ts +11 -3
- package/src/plugin/plugin-console.ts +29 -7
- package/src/plugin/plugin-host-api.ts +1 -1
- package/src/plugin/plugin-host.ts +92 -77
- package/src/plugin/plugin-lazy-remote.ts +4 -4
- package/src/plugin/plugin-remote-stats.ts +6 -4
- package/src/plugin/plugin-remote-worker.ts +91 -376
- package/src/plugin/plugin-remote.ts +5 -5
- package/src/plugin/plugin-repl.ts +2 -1
- package/src/plugin/runtime/cluster-fork.worker.ts +92 -0
- package/src/plugin/runtime/custom-worker.ts +2 -2
- package/src/plugin/runtime/node-fork-worker.ts +6 -3
- package/src/plugin/runtime/python-worker.ts +2 -2
- package/src/rpc.ts +3 -2
- package/src/runtime.ts +17 -2
- package/src/scrypted-cluster-common.ts +374 -0
- package/src/scrypted-cluster-main.ts +12 -0
- package/src/scrypted-cluster.ts +326 -0
- package/src/scrypted-main-exports.ts +22 -16
- package/src/scrypted-server-main.ts +15 -23
- package/src/server-settings.ts +1 -0
- package/src/services/backup.ts +0 -1
- package/src/services/cluster-fork.ts +22 -0
- package/src/services/plugin.ts +3 -21
package/dist/services/plugin.js
CHANGED
@@ -168,29 +168,14 @@ class PluginComponent {
|
|
168
168
|
async getRemoteServicePort(pluginId, name, ...args) {
|
169
169
|
if (name === 'console') {
|
170
170
|
const consoleServer = await this.scrypted.plugins[pluginId].consoleServer;
|
171
|
-
return consoleServer.readPort;
|
171
|
+
return [consoleServer.readPort, process.env.SCRYPTED_CLUSTER_ADDRESS];
|
172
172
|
}
|
173
173
|
if (name === 'console-writer') {
|
174
174
|
const consoleServer = await this.scrypted.plugins[pluginId].consoleServer;
|
175
|
-
return consoleServer.writePort;
|
175
|
+
return [consoleServer.writePort, process.env.SCRYPTED_CLUSTER_ADDRESS];
|
176
176
|
}
|
177
177
|
return this.scrypted.plugins[pluginId].remote.getServicePort(name, ...args);
|
178
178
|
}
|
179
|
-
async setHostParam(pluginId, name, param) {
|
180
|
-
const host = this.scrypted.plugins[pluginId];
|
181
|
-
if (!host)
|
182
|
-
return;
|
183
|
-
const key = `oob-param-${name}`;
|
184
|
-
if (param === undefined)
|
185
|
-
delete host.peer.params[key];
|
186
|
-
else
|
187
|
-
host.peer.params[key] = param;
|
188
|
-
}
|
189
|
-
async getHostParam(pluginId, name) {
|
190
|
-
const host = this.scrypted.plugins[pluginId];
|
191
|
-
const key = `oob-param-${name}`;
|
192
|
-
return host?.peer?.params?.[key];
|
193
|
-
}
|
194
179
|
}
|
195
180
|
exports.PluginComponent = PluginComponent;
|
196
181
|
//# sourceMappingURL=plugin.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/services/plugin.ts"],"names":[],"mappings":"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
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/services/plugin.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "@scrypted/server",
|
3
|
-
"version": "0.123.
|
3
|
+
"version": "0.123.2",
|
4
4
|
"description": "",
|
5
5
|
"dependencies": {
|
6
6
|
"@scrypted/ffmpeg-static": "^6.1.0-build3",
|
7
7
|
"@scrypted/node-pty": "^1.0.18",
|
8
|
-
"@scrypted/types": "^0.3.
|
8
|
+
"@scrypted/types": "^0.3.66",
|
9
9
|
"adm-zip": "^0.5.16",
|
10
10
|
"body-parser": "^1.20.3",
|
11
11
|
"cookie-parser": "^1.4.7",
|
package/python/plugin_remote.py
CHANGED
@@ -555,9 +555,129 @@ class DeviceManager(scrypted_python.scrypted_sdk.types.DeviceManager):
|
|
555
555
|
return self.nativeIds.get(nativeId, None)
|
556
556
|
|
557
557
|
|
558
|
+
def isClusterAddress(address: str):
|
559
|
+
return not address or address == os.environ.get("SCRYPTED_CLUSTER_ADDRESS", None)
|
560
|
+
|
561
|
+
def getClusterPeerKey(address: str, port: int):
|
562
|
+
return f"{address}:{port}"
|
563
|
+
|
564
|
+
class ClusterSetup():
|
565
|
+
def __init__(self, loop: AbstractEventLoop, peer: rpc.RpcPeer):
|
566
|
+
self.loop = loop
|
567
|
+
self.peer = peer
|
568
|
+
self.clusterId: str = None
|
569
|
+
self.clusterSecret: str = None
|
570
|
+
self.clusterAddress: str = None
|
571
|
+
self.clusterPort: int = None
|
572
|
+
self.SCRYPTED_CLUSTER_ADDRESS: str = None
|
573
|
+
self.clusterPeers: Mapping[str, asyncio.Future[rpc.RpcPeer]] = {}
|
574
|
+
|
575
|
+
async def resolveObject(self, id: str, sourceKey: str):
|
576
|
+
sourcePeer: rpc.RpcPeer = (
|
577
|
+
self.peer
|
578
|
+
if not sourceKey
|
579
|
+
else await rpc.maybe_await(self.clusterPeers.get(sourceKey, None))
|
580
|
+
)
|
581
|
+
if not sourcePeer:
|
582
|
+
return
|
583
|
+
return sourcePeer.localProxyMap.get(id, None)
|
584
|
+
|
585
|
+
async def connectRPCObject(self, o: ClusterObject):
|
586
|
+
sha256 = self.computeClusterObjectHash(o)
|
587
|
+
if sha256 != o["sha256"]:
|
588
|
+
raise Exception("secret incorrect")
|
589
|
+
return await self.resolveObject(o.get('proxyId', None), o.get('sourceKey', None))
|
590
|
+
|
591
|
+
def onProxySerialization(self, peer: rpc.RpcPeer, value: Any, sourceKey: str = None):
|
592
|
+
properties: dict = rpc.RpcPeer.prepareProxyProperties(value) or {}
|
593
|
+
clusterEntry = properties.get("__cluster", None)
|
594
|
+
proxyId: str
|
595
|
+
existing = peer.localProxied.get(value, None)
|
596
|
+
if existing:
|
597
|
+
proxyId = existing["id"]
|
598
|
+
else:
|
599
|
+
proxyId = (
|
600
|
+
clusterEntry and clusterEntry.get("proxyId", None)
|
601
|
+
) or rpc.RpcPeer.generateId()
|
602
|
+
|
603
|
+
if clusterEntry:
|
604
|
+
if (
|
605
|
+
isClusterAddress(clusterEntry.get("address", None))
|
606
|
+
and self.clusterPort == clusterEntry["port"]
|
607
|
+
and sourceKey != clusterEntry.get("sourceKey", None)
|
608
|
+
):
|
609
|
+
clusterEntry = None
|
610
|
+
|
611
|
+
if not clusterEntry:
|
612
|
+
clusterEntry: ClusterObject = {
|
613
|
+
"id": self.clusterId,
|
614
|
+
"proxyId": proxyId,
|
615
|
+
"address": self.SCRYPTED_CLUSTER_ADDRESS,
|
616
|
+
"port": self.clusterPort,
|
617
|
+
"sourceKey": sourceKey,
|
618
|
+
}
|
619
|
+
clusterEntry["sha256"] = self.computeClusterObjectHash(clusterEntry)
|
620
|
+
properties["__cluster"] = clusterEntry
|
621
|
+
|
622
|
+
return proxyId, properties
|
623
|
+
|
624
|
+
async def initializeCluster(self, options: dict):
|
625
|
+
if self.clusterPort:
|
626
|
+
return
|
627
|
+
self.clusterId = options["clusterId"]
|
628
|
+
self.clusterSecret = options["clusterSecret"]
|
629
|
+
self.SCRYPTED_CLUSTER_ADDRESS = os.environ.get("SCRYPTED_CLUSTER_ADDRESS", None)
|
630
|
+
|
631
|
+
async def handleClusterClient(
|
632
|
+
reader: asyncio.StreamReader, writer: asyncio.StreamWriter
|
633
|
+
):
|
634
|
+
clusterPeerAddress, clusterPeerPort = writer.get_extra_info("peername")
|
635
|
+
clusterPeerKey = getClusterPeerKey(clusterPeerAddress, clusterPeerPort)
|
636
|
+
rpcTransport = rpc_reader.RpcStreamTransport(reader, writer)
|
637
|
+
peer: rpc.RpcPeer
|
638
|
+
peer, peerReadLoop = await rpc_reader.prepare_peer_readloop(
|
639
|
+
self.loop, rpcTransport
|
640
|
+
)
|
641
|
+
# set all params from self.peer
|
642
|
+
for key, value in self.peer.params.items():
|
643
|
+
peer.params[key] = value
|
644
|
+
peer.onProxySerialization = lambda value: self.onProxySerialization(
|
645
|
+
peer, value, clusterPeerKey
|
646
|
+
)
|
647
|
+
future: asyncio.Future[rpc.RpcPeer] = asyncio.Future()
|
648
|
+
future.set_result(peer)
|
649
|
+
self.clusterPeers[clusterPeerKey] = future
|
650
|
+
peer.params["connectRPCObject"] = lambda o: self.connectRPCObject(o)
|
651
|
+
try:
|
652
|
+
await peerReadLoop()
|
653
|
+
except:
|
654
|
+
pass
|
655
|
+
finally:
|
656
|
+
self.clusterPeers.pop(clusterPeerKey)
|
657
|
+
peer.kill("cluster client killed")
|
658
|
+
writer.close()
|
659
|
+
|
660
|
+
listenAddress = "0.0.0.0" if self.SCRYPTED_CLUSTER_ADDRESS else "127.0.0.1"
|
661
|
+
clusterRpcServer = await asyncio.start_server(
|
662
|
+
handleClusterClient, listenAddress, 0
|
663
|
+
)
|
664
|
+
self.clusterPort = clusterRpcServer.sockets[0].getsockname()[1]
|
665
|
+
self.peer.onProxySerialization = lambda value: self.onProxySerialization(self.peer, value, None)
|
666
|
+
del self.peer.params["initializeCluster"]
|
667
|
+
|
668
|
+
def computeClusterObjectHash(self, o: ClusterObject) -> str:
|
669
|
+
m = hashlib.sha256()
|
670
|
+
m.update(
|
671
|
+
bytes(
|
672
|
+
f"{o['id']}{o.get('address') or ''}{o['port']}{o.get('sourceKey', None) or ''}{o['proxyId']}{self.clusterSecret}",
|
673
|
+
"utf8",
|
674
|
+
)
|
675
|
+
)
|
676
|
+
return base64.b64encode(m.digest()).decode("utf-8")
|
677
|
+
|
558
678
|
class PluginRemote:
|
559
679
|
def __init__(
|
560
|
-
self,
|
680
|
+
self, clusterSetup: ClusterSetup, api, pluginId: str, hostInfo, loop: AbstractEventLoop
|
561
681
|
):
|
562
682
|
self.systemState: Mapping[str, Mapping[str, SystemDeviceState]] = {}
|
563
683
|
self.nativeIds: Mapping[str, DeviceStorage] = {}
|
@@ -565,7 +685,8 @@ class PluginRemote:
|
|
565
685
|
self.consoles: Mapping[str, Future[Tuple[StreamReader, StreamWriter]]] = {}
|
566
686
|
self.ptimeSum = 0
|
567
687
|
self.allMemoryStats = {}
|
568
|
-
self.peer = peer
|
688
|
+
self.peer = clusterSetup.peer
|
689
|
+
self.clusterSetup = clusterSetup
|
569
690
|
self.api = api
|
570
691
|
self.pluginId = pluginId
|
571
692
|
self.hostInfo = hostInfo
|
@@ -593,8 +714,8 @@ class PluginRemote:
|
|
593
714
|
consoleFuture = Future()
|
594
715
|
self.consoles[nativeId] = consoleFuture
|
595
716
|
plugins = await self.api.getComponent("plugins")
|
596
|
-
port = await plugins.getRemoteServicePort(self.pluginId, "console-writer")
|
597
|
-
connection = await asyncio.open_connection(port=port)
|
717
|
+
port, hostname = await plugins.getRemoteServicePort(self.pluginId, "console-writer")
|
718
|
+
connection = await asyncio.open_connection(host=hostname, port=port)
|
598
719
|
_, writer = connection
|
599
720
|
if not nativeId:
|
600
721
|
nid = "undefined"
|
@@ -631,122 +752,16 @@ class PluginRemote:
|
|
631
752
|
traceback.print_exc()
|
632
753
|
raise
|
633
754
|
|
634
|
-
async def loadZipWrapped(self, packageJson,
|
635
|
-
|
755
|
+
async def loadZipWrapped(self, packageJson, zipAPI: Any, options: dict):
|
756
|
+
await self.clusterSetup.initializeCluster(options)
|
636
757
|
|
637
|
-
|
638
|
-
clusterSecret = options["clusterSecret"]
|
639
|
-
SCRYPTED_CLUSTER_ADDRESS = os.environ.get("SCRYPTED_CLUSTER_ADDRESS", None)
|
640
|
-
|
641
|
-
def computeClusterObjectHash(o: ClusterObject) -> str:
|
642
|
-
m = hashlib.sha256()
|
643
|
-
m.update(
|
644
|
-
bytes(
|
645
|
-
f"{o['id']}{o.get('address') or ''}{o['port']}{o.get('sourceKey', None) or ''}{o['proxyId']}{clusterSecret}",
|
646
|
-
"utf8",
|
647
|
-
)
|
648
|
-
)
|
649
|
-
return base64.b64encode(m.digest()).decode("utf-8")
|
650
|
-
|
651
|
-
def isClusterAddress(address: str):
|
652
|
-
return not address or address == SCRYPTED_CLUSTER_ADDRESS
|
653
|
-
|
654
|
-
def onProxySerialization(peer: rpc.RpcPeer, value: Any, sourceKey: str = None):
|
655
|
-
properties: dict = rpc.RpcPeer.prepareProxyProperties(value) or {}
|
656
|
-
clusterEntry = properties.get("__cluster", None)
|
657
|
-
proxyId: str
|
658
|
-
existing = peer.localProxied.get(value, None)
|
659
|
-
if existing:
|
660
|
-
proxyId = existing["id"]
|
661
|
-
else:
|
662
|
-
proxyId = (
|
663
|
-
clusterEntry and clusterEntry.get("proxyId", None)
|
664
|
-
) or rpc.RpcPeer.generateId()
|
665
|
-
|
666
|
-
if clusterEntry:
|
667
|
-
if (
|
668
|
-
isClusterAddress(clusterEntry.get("address", None))
|
669
|
-
and clusterPort == clusterEntry["port"]
|
670
|
-
and sourceKey != clusterEntry.get("sourceKey", None)
|
671
|
-
):
|
672
|
-
clusterEntry = None
|
673
|
-
|
674
|
-
if not clusterEntry:
|
675
|
-
clusterEntry: ClusterObject = {
|
676
|
-
"id": clusterId,
|
677
|
-
"proxyId": proxyId,
|
678
|
-
"address": SCRYPTED_CLUSTER_ADDRESS,
|
679
|
-
"port": clusterPort,
|
680
|
-
"sourceKey": sourceKey,
|
681
|
-
}
|
682
|
-
clusterEntry["sha256"] = computeClusterObjectHash(clusterEntry)
|
683
|
-
properties["__cluster"] = clusterEntry
|
684
|
-
|
685
|
-
return proxyId, properties
|
686
|
-
|
687
|
-
self.peer.onProxySerialization = lambda value: onProxySerialization(
|
688
|
-
self.peer, value, None
|
689
|
-
)
|
690
|
-
|
691
|
-
async def resolveObject(id: str, sourceKey: str):
|
692
|
-
sourcePeer: rpc.RpcPeer = (
|
693
|
-
self.peer
|
694
|
-
if not sourceKey
|
695
|
-
else await rpc.maybe_await(clusterPeers.get(sourceKey, None))
|
696
|
-
)
|
697
|
-
if not sourcePeer:
|
698
|
-
return
|
699
|
-
return sourcePeer.localProxyMap.get(id, None)
|
700
|
-
|
701
|
-
clusterPeers: Mapping[str, asyncio.Future[rpc.RpcPeer]] = {}
|
702
|
-
|
703
|
-
def getClusterPeerKey(address: str, port: int):
|
704
|
-
return f"{address}:{port}"
|
705
|
-
|
706
|
-
async def handleClusterClient(
|
707
|
-
reader: asyncio.StreamReader, writer: asyncio.StreamWriter
|
708
|
-
):
|
709
|
-
clusterPeerAddress, clusterPeerPort = writer.get_extra_info("peername")
|
710
|
-
clusterPeerKey = getClusterPeerKey(clusterPeerAddress, clusterPeerPort)
|
711
|
-
rpcTransport = rpc_reader.RpcStreamTransport(reader, writer)
|
712
|
-
peer: rpc.RpcPeer
|
713
|
-
peer, peerReadLoop = await rpc_reader.prepare_peer_readloop(
|
714
|
-
self.loop, rpcTransport
|
715
|
-
)
|
716
|
-
peer.onProxySerialization = lambda value: onProxySerialization(
|
717
|
-
peer, value, clusterPeerKey
|
718
|
-
)
|
719
|
-
future: asyncio.Future[rpc.RpcPeer] = asyncio.Future()
|
720
|
-
future.set_result(peer)
|
721
|
-
clusterPeers[clusterPeerKey] = future
|
722
|
-
|
723
|
-
async def connectRPCObject(o: ClusterObject):
|
724
|
-
sha256 = computeClusterObjectHash(o)
|
725
|
-
if sha256 != o["sha256"]:
|
726
|
-
raise Exception("secret incorrect")
|
727
|
-
return await resolveObject(o["proxyId"], o.get("sourceKey", None))
|
728
|
-
|
729
|
-
peer.params["connectRPCObject"] = connectRPCObject
|
730
|
-
try:
|
731
|
-
await peerReadLoop()
|
732
|
-
except:
|
733
|
-
pass
|
734
|
-
finally:
|
735
|
-
clusterPeers.pop(clusterPeerKey)
|
736
|
-
peer.kill("cluster client killed")
|
737
|
-
writer.close()
|
738
|
-
|
739
|
-
listenAddress = "0.0.0.0" if SCRYPTED_CLUSTER_ADDRESS else "127.0.0.1"
|
740
|
-
clusterRpcServer = await asyncio.start_server(
|
741
|
-
handleClusterClient, listenAddress, 0
|
742
|
-
)
|
743
|
-
clusterPort = clusterRpcServer.sockets[0].getsockname()[1]
|
758
|
+
sdk = ScryptedStatic()
|
744
759
|
|
745
760
|
def ensureClusterPeer(address: str, port: int):
|
746
761
|
if isClusterAddress(address):
|
747
762
|
address = "127.0.0.1"
|
748
763
|
clusterPeerKey = getClusterPeerKey(address, port)
|
749
|
-
clusterPeerPromise = clusterPeers.get(clusterPeerKey)
|
764
|
+
clusterPeerPromise = self.clusterSetup.clusterPeers.get(clusterPeerKey)
|
750
765
|
if clusterPeerPromise:
|
751
766
|
return clusterPeerPromise
|
752
767
|
|
@@ -755,7 +770,7 @@ class PluginRemote:
|
|
755
770
|
reader, writer = await asyncio.open_connection(address, port)
|
756
771
|
sourceAddress, sourcePort = writer.get_extra_info("sockname")
|
757
772
|
if (
|
758
|
-
sourceAddress != SCRYPTED_CLUSTER_ADDRESS
|
773
|
+
sourceAddress != self.clusterSetup.SCRYPTED_CLUSTER_ADDRESS
|
759
774
|
and sourceAddress != "127.0.0.1"
|
760
775
|
):
|
761
776
|
print("source address mismatch", sourceAddress)
|
@@ -763,13 +778,16 @@ class PluginRemote:
|
|
763
778
|
clusterPeer, peerReadLoop = await rpc_reader.prepare_peer_readloop(
|
764
779
|
self.loop, rpcTransport
|
765
780
|
)
|
781
|
+
# set all params from self.peer
|
782
|
+
for key, value in self.peer.params.items():
|
783
|
+
clusterPeer.params[key] = value
|
766
784
|
clusterPeer.onProxySerialization = (
|
767
|
-
lambda value: onProxySerialization(
|
785
|
+
lambda value: self.clusterSetup.onProxySerialization(
|
768
786
|
clusterPeer, value, clusterPeerKey
|
769
787
|
)
|
770
788
|
)
|
771
789
|
except:
|
772
|
-
clusterPeers.pop(clusterPeerKey)
|
790
|
+
self.clusterSetup.clusterPeers.pop(clusterPeerKey)
|
773
791
|
raise
|
774
792
|
|
775
793
|
async def run_loop():
|
@@ -778,14 +796,14 @@ class PluginRemote:
|
|
778
796
|
except:
|
779
797
|
pass
|
780
798
|
finally:
|
781
|
-
clusterPeers.pop(clusterPeerKey)
|
799
|
+
self.clusterSetup.clusterPeers.pop(clusterPeerKey)
|
782
800
|
|
783
801
|
asyncio.run_coroutine_threadsafe(run_loop(), self.loop)
|
784
802
|
return clusterPeer
|
785
803
|
|
786
804
|
clusterPeerPromise = self.loop.create_task(connectClusterPeer())
|
787
805
|
|
788
|
-
clusterPeers[clusterPeerKey] = clusterPeerPromise
|
806
|
+
self.clusterSetup.clusterPeers[clusterPeerKey] = clusterPeerPromise
|
789
807
|
return clusterPeerPromise
|
790
808
|
|
791
809
|
async def connectRPCObject(value):
|
@@ -795,16 +813,14 @@ class PluginRemote:
|
|
795
813
|
|
796
814
|
clusterObject: ClusterObject = __cluster
|
797
815
|
|
798
|
-
if clusterObject.get("id", None) != clusterId:
|
816
|
+
if clusterObject.get("id", None) != self.clusterSetup.clusterId:
|
799
817
|
return value
|
800
818
|
|
801
819
|
address = clusterObject.get("address", None)
|
802
820
|
port = clusterObject["port"]
|
803
821
|
proxyId = clusterObject["proxyId"]
|
804
|
-
if port == clusterPort:
|
805
|
-
return await
|
806
|
-
proxyId, clusterObject.get("sourceKey", None)
|
807
|
-
)
|
822
|
+
if port == self.clusterSetup.clusterPort:
|
823
|
+
return await self.clusterSetup.connectRPCObject(clusterObject)
|
808
824
|
|
809
825
|
clusterPeerPromise = ensureClusterPeer(address, port)
|
810
826
|
|
@@ -846,7 +862,7 @@ class PluginRemote:
|
|
846
862
|
|
847
863
|
if not os.path.exists(zipPath) or debug:
|
848
864
|
os.makedirs(os.path.dirname(zipPath), exist_ok=True)
|
849
|
-
zipData = await getZip()
|
865
|
+
zipData = await zipAPI.getZip()
|
850
866
|
zipPathTmp = zipPath + ".tmp"
|
851
867
|
with open(zipPathTmp, "wb") as f:
|
852
868
|
f.write(zipData)
|
@@ -962,7 +978,7 @@ class PluginRemote:
|
|
962
978
|
self.deviceManager = DeviceManager(self.nativeIds, self.systemManager)
|
963
979
|
self.mediaManager = MediaManager(await self.api.getMediaManager())
|
964
980
|
|
965
|
-
await self.start_stats_runner()
|
981
|
+
await self.start_stats_runner(zipAPI.updateState)
|
966
982
|
|
967
983
|
try:
|
968
984
|
from scrypted_sdk import sdk_init2 # type: ignore
|
@@ -1030,7 +1046,7 @@ class PluginRemote:
|
|
1030
1046
|
forkOptions = options.copy()
|
1031
1047
|
forkOptions["fork"] = True
|
1032
1048
|
forkOptions["debug"] = debug
|
1033
|
-
return await remote.loadZip(packageJson, getZip, forkOptions)
|
1049
|
+
return await remote.loadZip(packageJson, zipAPI.getZip, forkOptions)
|
1034
1050
|
|
1035
1051
|
pluginFork.result = asyncio.create_task(getFork())
|
1036
1052
|
return pluginFork
|
@@ -1119,10 +1135,10 @@ class PluginRemote:
|
|
1119
1135
|
raise Exception("REPL unavailable: Plugin not loaded.")
|
1120
1136
|
if self.replPort == 0:
|
1121
1137
|
raise Exception("REPL unavailable: Python REPL not available.")
|
1122
|
-
return self.replPort
|
1138
|
+
return [self.replPort, os.getenv("SCRYPTED_CLUSTER_ADDRESS", None)]
|
1123
1139
|
raise Exception(f"unknown service {name}")
|
1124
1140
|
|
1125
|
-
async def start_stats_runner(self):
|
1141
|
+
async def start_stats_runner(self, update_stats):
|
1126
1142
|
pong = None
|
1127
1143
|
|
1128
1144
|
async def ping(time: int):
|
@@ -1132,11 +1148,6 @@ class PluginRemote:
|
|
1132
1148
|
|
1133
1149
|
self.peer.params["ping"] = ping
|
1134
1150
|
|
1135
|
-
update_stats = await self.peer.getParam("updateStats")
|
1136
|
-
if not update_stats:
|
1137
|
-
print("host did not provide update_stats")
|
1138
|
-
return
|
1139
|
-
|
1140
1151
|
def stats_runner():
|
1141
1152
|
ptime = round(time.process_time() * 1000000) + self.ptimeSum
|
1142
1153
|
try:
|
@@ -1175,8 +1186,12 @@ async def plugin_async_main(
|
|
1175
1186
|
):
|
1176
1187
|
peer, readLoop = await rpc_reader.prepare_peer_readloop(loop, rpcTransport)
|
1177
1188
|
peer.params["print"] = print
|
1189
|
+
|
1190
|
+
clusterSetup = ClusterSetup(loop, peer)
|
1191
|
+
peer.params["initializeCluster"] = lambda options: clusterSetup.initializeCluster(options)
|
1192
|
+
|
1178
1193
|
peer.params["getRemote"] = lambda api, pluginId, hostInfo: PluginRemote(
|
1179
|
-
|
1194
|
+
clusterSetup, api, pluginId, hostInfo, loop
|
1180
1195
|
)
|
1181
1196
|
|
1182
1197
|
try:
|
package/python/rpc_reader.py
CHANGED
@@ -12,23 +12,7 @@ import multiprocessing.connection
|
|
12
12
|
import rpc
|
13
13
|
import concurrent.futures
|
14
14
|
import json
|
15
|
-
|
16
|
-
|
17
|
-
def convert_nan_inf_to_none(obj):
|
18
|
-
if isinstance(obj, dict):
|
19
|
-
return {key: convert_nan_inf_to_none(value) for key, value in obj.items()}
|
20
|
-
elif isinstance(obj, list):
|
21
|
-
return [convert_nan_inf_to_none(item) for item in obj]
|
22
|
-
elif isinstance(obj, float):
|
23
|
-
if math.isnan(obj):
|
24
|
-
return None
|
25
|
-
if math.isinf(obj):
|
26
|
-
return None
|
27
|
-
return obj
|
28
|
-
|
29
|
-
def json_dumps_clean(obj, **kwargs):
|
30
|
-
cleaned_obj = convert_nan_inf_to_none(obj)
|
31
|
-
return json.dumps(cleaned_obj, **kwargs)
|
15
|
+
|
32
16
|
|
33
17
|
class BufferSerializer(rpc.RpcSerializer):
|
34
18
|
def serialize(self, value, serializationContext):
|
@@ -110,7 +94,7 @@ class RpcFileTransport(RpcTransport):
|
|
110
94
|
reject(e)
|
111
95
|
|
112
96
|
def writeJSON(self, j, reject):
|
113
|
-
return self.writeMessage(0, bytes(
|
97
|
+
return self.writeMessage(0, bytes(json.dumps(j, allow_nan=False), 'utf8'), reject)
|
114
98
|
|
115
99
|
def writeBuffer(self, buffer, reject):
|
116
100
|
return self.writeMessage(1, buffer, reject)
|
@@ -144,7 +128,7 @@ class RpcStreamTransport(RpcTransport):
|
|
144
128
|
reject(e)
|
145
129
|
|
146
130
|
def writeJSON(self, j, reject):
|
147
|
-
return self.writeMessage(0, bytes(
|
131
|
+
return self.writeMessage(0, bytes(json.dumps(j, allow_nan=False), 'utf8'), reject)
|
148
132
|
|
149
133
|
def writeBuffer(self, buffer, reject):
|
150
134
|
return self.writeMessage(1, buffer, reject)
|
package/src/ip.ts
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
import os from 'os';
|
2
2
|
import net from 'net';
|
3
3
|
|
4
|
+
export const loopbackList = new net.BlockList();
|
5
|
+
loopbackList.addSubnet('127.0.0.0', 8);
|
6
|
+
loopbackList.addAddress('::1', 'ipv6');
|
7
|
+
|
4
8
|
const unusableList = new net.BlockList();
|
5
|
-
// loopback
|
6
|
-
unusableList.addSubnet('127.0.0.0', 8);
|
7
|
-
unusableList.addAddress('::1', 'ipv6');
|
8
9
|
|
9
10
|
// link local
|
10
11
|
unusableList.addSubnet('169.254.0.0', 16);
|
@@ -56,7 +57,7 @@ function isUsableNetworkAddress(address: string) {
|
|
56
57
|
if (type === 'ipv6' && privateList.check(address, type))
|
57
58
|
return false;
|
58
59
|
|
59
|
-
return !unusableList.check(address, type);
|
60
|
+
return !unusableList.check(address, type) && !loopbackList.check(address, type);
|
60
61
|
}
|
61
62
|
catch (e) {
|
62
63
|
return false;
|
package/src/listen-zero.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { once } from 'events';
|
2
2
|
import net from 'net';
|
3
|
+
import tls from 'tls';
|
3
4
|
|
4
5
|
export class ListenZeroSingleClientTimeoutError extends Error {
|
5
6
|
constructor() {
|
@@ -13,8 +14,8 @@ export async function listenZero(server: net.Server, hostname: string) {
|
|
13
14
|
return (server.address() as net.AddressInfo).port;
|
14
15
|
}
|
15
16
|
|
16
|
-
export async function listenZeroSingleClient(hostname: string, options?: net.ServerOpts, listenTimeout = 30000) {
|
17
|
-
const server = new net.Server(options);
|
17
|
+
export async function listenZeroSingleClient(hostname: string, options?: net.ServerOpts & { tls?: boolean }, listenTimeout = 30000) {
|
18
|
+
const server = options?.tls ? new tls.Server(options) : new net.Server(options);
|
18
19
|
const port = await listenZero(server, hostname);
|
19
20
|
|
20
21
|
let cancel: () => void;
|
package/src/plugin/plugin-api.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import type { Device, DeviceManifest, EventDetails, EventListenerOptions, EventListenerRegister, MediaManager, MediaObject, ScryptedDevice, ScryptedInterfaceDescriptor, ScryptedInterfaceProperty, ScryptedNativeId, SystemDeviceState } from '@scrypted/types';
|
2
|
-
import { AccessControls } from './acl';
|
2
|
+
import type { AccessControls } from './acl';
|
3
|
+
import type { PluginStats } from './plugin-remote-stats';
|
3
4
|
|
4
5
|
export interface PluginLogger {
|
5
6
|
log(level: string, message: string): Promise<void>;
|
@@ -167,8 +168,15 @@ export interface PluginRemoteLoadZipOptions {
|
|
167
168
|
clusterSecret: string;
|
168
169
|
}
|
169
170
|
|
171
|
+
export class PluginZipAPI {
|
172
|
+
constructor(
|
173
|
+
public getZip: () => Promise<Buffer>,
|
174
|
+
public updateStats: (stats: PluginStats) => Promise<void>) {
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
170
178
|
export interface PluginRemote {
|
171
|
-
loadZip(packageJson: any,
|
179
|
+
loadZip(packageJson: any, zipAPI: PluginZipAPI, options: PluginRemoteLoadZipOptions): Promise<any>;
|
172
180
|
setSystemState(state: { [id: string]: { [property: string]: SystemDeviceState } }): Promise<void>;
|
173
181
|
setNativeId(nativeId: ScryptedNativeId, id: string, storage: { [key: string]: any }): Promise<void>;
|
174
182
|
updateDeviceState(id: string, state: { [property: string]: SystemDeviceState }): Promise<void>;
|
@@ -182,7 +190,7 @@ export interface PluginRemote {
|
|
182
190
|
|
183
191
|
createDeviceState(id: string, setState: (property: string, value: any) => Promise<any>): Promise<any>;
|
184
192
|
|
185
|
-
getServicePort(name: string, ...args: any[]): Promise<number>;
|
193
|
+
getServicePort(name: string, ...args: any[]): Promise<[number, string]>;
|
186
194
|
}
|
187
195
|
|
188
196
|
export interface MediaObjectRemote extends MediaObject {
|