@scrypted/server 0.123.1 → 0.123.3

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 (98) hide show
  1. package/dist/ip.d.ts +2 -0
  2. package/dist/ip.js +5 -4
  3. package/dist/ip.js.map +1 -1
  4. package/dist/listen-zero.d.ts +5 -2
  5. package/dist/listen-zero.js +2 -1
  6. package/dist/listen-zero.js.map +1 -1
  7. package/dist/plugin/plugin-api.d.ts +9 -3
  8. package/dist/plugin/plugin-api.js +10 -1
  9. package/dist/plugin/plugin-api.js.map +1 -1
  10. package/dist/plugin/plugin-console.d.ts +2 -1
  11. package/dist/plugin/plugin-console.js +27 -6
  12. package/dist/plugin/plugin-console.js.map +1 -1
  13. package/dist/plugin/plugin-host-api.js +1 -1
  14. package/dist/plugin/plugin-host-api.js.map +1 -1
  15. package/dist/plugin/plugin-host.d.ts +4 -7
  16. package/dist/plugin/plugin-host.js +76 -62
  17. package/dist/plugin/plugin-host.js.map +1 -1
  18. package/dist/plugin/plugin-lazy-remote.d.ts +3 -3
  19. package/dist/plugin/plugin-lazy-remote.js +2 -2
  20. package/dist/plugin/plugin-lazy-remote.js.map +1 -1
  21. package/dist/plugin/plugin-remote-stats.d.ts +2 -2
  22. package/dist/plugin/plugin-remote-stats.js +4 -2
  23. package/dist/plugin/plugin-remote-stats.js.map +1 -1
  24. package/dist/plugin/plugin-remote-worker.d.ts +0 -1
  25. package/dist/plugin/plugin-remote-worker.js +77 -335
  26. package/dist/plugin/plugin-remote-worker.js.map +1 -1
  27. package/dist/plugin/plugin-remote.d.ts +3 -3
  28. package/dist/plugin/plugin-remote.js +2 -2
  29. package/dist/plugin/plugin-remote.js.map +1 -1
  30. package/dist/plugin/plugin-repl.js +2 -1
  31. package/dist/plugin/plugin-repl.js.map +1 -1
  32. package/dist/plugin/runtime/cluster-fork.worker.d.ts +9 -0
  33. package/dist/plugin/runtime/cluster-fork.worker.js +73 -0
  34. package/dist/plugin/runtime/cluster-fork.worker.js.map +1 -0
  35. package/dist/plugin/runtime/custom-worker.js +2 -2
  36. package/dist/plugin/runtime/custom-worker.js.map +1 -1
  37. package/dist/plugin/runtime/node-fork-worker.js +5 -3
  38. package/dist/plugin/runtime/node-fork-worker.js.map +1 -1
  39. package/dist/plugin/runtime/python-worker.js +2 -2
  40. package/dist/plugin/runtime/python-worker.js.map +1 -1
  41. package/dist/rpc.d.ts +1 -0
  42. package/dist/rpc.js +3 -2
  43. package/dist/rpc.js.map +1 -1
  44. package/dist/runtime.d.ts +4 -0
  45. package/dist/runtime.js +16 -2
  46. package/dist/runtime.js.map +1 -1
  47. package/dist/scrypted-cluster-common.d.ts +22 -0
  48. package/dist/scrypted-cluster-common.js +332 -0
  49. package/dist/scrypted-cluster-common.js.map +1 -0
  50. package/dist/scrypted-cluster-main.d.ts +2 -0
  51. package/dist/scrypted-cluster-main.js +12 -0
  52. package/dist/scrypted-cluster-main.js.map +1 -0
  53. package/dist/scrypted-cluster.d.ts +38 -0
  54. package/dist/scrypted-cluster.js +277 -0
  55. package/dist/scrypted-cluster.js.map +1 -0
  56. package/dist/scrypted-main-exports.js +20 -14
  57. package/dist/scrypted-main-exports.js.map +1 -1
  58. package/dist/scrypted-server-main.js +8 -15
  59. package/dist/scrypted-server-main.js.map +1 -1
  60. package/dist/server-settings.d.ts +1 -0
  61. package/dist/server-settings.js +2 -1
  62. package/dist/server-settings.js.map +1 -1
  63. package/dist/services/backup.js.map +1 -1
  64. package/dist/services/cluster-fork.d.ts +7 -0
  65. package/dist/services/cluster-fork.js +25 -0
  66. package/dist/services/cluster-fork.js.map +1 -0
  67. package/dist/services/plugin.d.ts +2 -7
  68. package/dist/services/plugin.js +2 -17
  69. package/dist/services/plugin.js.map +1 -1
  70. package/package.json +2 -2
  71. package/python/plugin_remote.py +150 -135
  72. package/python/rpc_reader.py +3 -19
  73. package/src/ip.ts +5 -4
  74. package/src/listen-zero.ts +3 -2
  75. package/src/plugin/plugin-api.ts +11 -3
  76. package/src/plugin/plugin-console.ts +29 -7
  77. package/src/plugin/plugin-host-api.ts +1 -1
  78. package/src/plugin/plugin-host.ts +92 -77
  79. package/src/plugin/plugin-lazy-remote.ts +4 -4
  80. package/src/plugin/plugin-remote-stats.ts +6 -4
  81. package/src/plugin/plugin-remote-worker.ts +91 -376
  82. package/src/plugin/plugin-remote.ts +5 -5
  83. package/src/plugin/plugin-repl.ts +2 -1
  84. package/src/plugin/runtime/cluster-fork.worker.ts +92 -0
  85. package/src/plugin/runtime/custom-worker.ts +2 -2
  86. package/src/plugin/runtime/node-fork-worker.ts +6 -3
  87. package/src/plugin/runtime/python-worker.ts +2 -2
  88. package/src/rpc.ts +3 -2
  89. package/src/runtime.ts +17 -2
  90. package/src/scrypted-cluster-common.ts +374 -0
  91. package/src/scrypted-cluster-main.ts +12 -0
  92. package/src/scrypted-cluster.ts +329 -0
  93. package/src/scrypted-main-exports.ts +22 -16
  94. package/src/scrypted-server-main.ts +15 -23
  95. package/src/server-settings.ts +1 -0
  96. package/src/services/backup.ts +0 -1
  97. package/src/services/cluster-fork.ts +22 -0
  98. package/src/services/plugin.ts +3 -21
@@ -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.1",
3
+ "version": "0.123.3",
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.64",
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",
@@ -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, peer: rpc.RpcPeer, api, pluginId: str, hostInfo, loop: AbstractEventLoop
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, getZip: Any, options: dict):
635
- sdk = ScryptedStatic()
755
+ async def loadZipWrapped(self, packageJson, zipAPI: Any, options: dict):
756
+ await self.clusterSetup.initializeCluster(options)
636
757
 
637
- clusterId = options["clusterId"]
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 resolveObject(
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
- peer, api, pluginId, hostInfo, loop
1194
+ clusterSetup, api, pluginId, hostInfo, loop
1180
1195
  )
1181
1196
 
1182
1197
  try:
@@ -12,23 +12,7 @@ import multiprocessing.connection
12
12
  import rpc
13
13
  import concurrent.futures
14
14
  import json
15
- import math
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(json_dumps_clean(j), 'utf8'), reject)
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(json_dumps_clean(j), 'utf8'), reject)
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;
@@ -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;
@@ -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, getZip: () => Promise<Buffer>, options: PluginRemoteLoadZipOptions): Promise<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 {