@scrypted/server 0.123.21 → 0.123.22

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.
@@ -7,6 +7,7 @@ exports.ClusterForkResult = exports.PeerLiveness = void 0;
7
7
  exports.startClusterClient = startClusterClient;
8
8
  exports.createClusterServer = createClusterServer;
9
9
  const events_1 = require("events");
10
+ const net_1 = __importDefault(require("net"));
10
11
  const source_map_support_1 = require("source-map-support");
11
12
  const tls_1 = __importDefault(require("tls"));
12
13
  const cluster_hash_1 = require("./cluster/cluster-hash");
@@ -86,9 +87,20 @@ function startClusterClient(mainFilename) {
86
87
  // for local network, and having the immediate socket connection seems
87
88
  // to hang the app since no window is created yet.
88
89
  await (0, sleep_1.sleep)(1000);
89
- const socket = tls_1.default.connect({
90
+ const rawSocket = net_1.default.connect({
90
91
  host,
91
92
  port,
93
+ // require ipv4 to normalize cluster address.
94
+ family: 4,
95
+ });
96
+ try {
97
+ await (0, events_1.once)(rawSocket, 'connect');
98
+ }
99
+ catch (e) {
100
+ continue;
101
+ }
102
+ const socket = tls_1.default.connect({
103
+ socket: rawSocket,
92
104
  rejectUnauthorized: false,
93
105
  });
94
106
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"scrypted-cluster-main.js","sourceRoot":"","sources":["../src/scrypted-cluster-main.ts"],"names":[],"mappings":";;;;;;AAgGA,gDAuJC;AAED,kDAiDC;AAzSD,mCAA8B;AAC9B,2DAAwE;AAExE,8CAAsB;AAEtB,yDAAkE;AAClE,6DAA4D;AAC5D,2DAAkG;AAElG,0DAA4E;AAC5E,4EAAiE;AACjE,gEAAuE;AAEvE,+BAAgC;AAChC,qDAA6D;AAE7D,mCAAgC;AAEhC,IAAA,4BAAuB,EAAC;IACpB,WAAW,EAAE,MAAM;CACtB,CAAC,CAAC;AAEH,KAAK,UAAU,KAAK,CAAC,YAAoB;IACrC,kBAAkB,CAAC,YAAY,CAAC,CAAC;AACrC,CAAC;AAED,kBAAe,KAAK,CAAC;AAErB,SAAS,aAAa,CAAC,UAAwD,EAAE,IAAa,EAAE,MAAqB,EAAE,IAAyB;IAC5I,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAE9B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAEnD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;QACnB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACpB,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QAClB,MAAM,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,WAAW,CAAC,MAAqB,EAAE,IAAyB;IACjE,MAAM,UAAU,GAAG,IAAA,0CAAyB,EAAC,MAAM,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,aAAO,CAAC,kBAAkB,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE;QAC9I,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAE9C,OAAO,IAAI,CAAC;AAChB,CAAC;AAiBD,MAAa,YAAY;IAED;IADpB,sBAAsB,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,YAAoB,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;IACxC,CAAC;IACD,KAAK,CAAC,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;CACJ;AAPD,oCAOC;AAED,MAAa,iBAAkB,SAAQ,YAAY;IAC3B;IAA6C;IAAjE,YAAoB,IAAa,EAAE,MAAoB,EAAU,MAAW;QACxE,KAAK,CAAC,MAAM,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAS;QAAgC,WAAM,GAAN,MAAM,CAAK;IAE5E,CAAC;IAED,KAAK,CAAC,IAAI;QACN,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,SAAS;QACX,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;CACJ;AAZD,8CAYC;AAID,SAAgB,kBAAkB,CAAC,YAAoB;IACnD,MAAM,sBAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IACpE,MAAM,MAAM,GAAG,IAAA,iCAAgB,GAAE,CAAC;IAElC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAC1D,MAAM,WAAW,GAAG,IAAA,sCAAsB,GAAE,CAAC;IAC7C,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC;IACnC,CAAC,KAAK,IAAI,EAAE;QACR,OAAO,IAAI,EAAE,CAAC;YACV,oEAAoE;YACpE,kEAAkE;YAClE,sEAAsE;YACtE,kDAAkD;YAClD,MAAM,IAAA,aAAK,EAAC,IAAI,CAAC,CAAC;YAElB,MAAM,MAAM,GAAG,aAAG,CAAC,OAAO,CAAC;gBACvB,IAAI;gBACJ,IAAI;gBACJ,kBAAkB,EAAE,KAAK;aAC5B,CAAC,CAAC;YAEH,IAAI,CAAC;gBACD,MAAM,IAAA,aAAI,EAAC,MAAM,EAAE,eAAe,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,CAAC,EAAE,CAAC;gBACP,SAAS;YACb,CAAC;YAED,IAAI,sBAAsB,IAAI,sBAAsB,KAAK,MAAM,CAAC,YAAY;gBACxE,OAAO,CAAC,IAAI,CAAC,yGAAyG,EAAE,sBAAsB,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;;gBAErK,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,MAAM,CAAC,YAAY,CAAC;YAE/D,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC3C,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YAClE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACpB,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACzE,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC;gBAED,MAAM,iBAAiB,GAAsB,MAAM,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;gBACtF,MAAM,IAAI,GAAkB;oBACxB,OAAO,EAAE,MAAM,CAAC,YAAY;oBAC5B,IAAI,EAAE,MAAM,CAAC,SAAS;oBACtB,EAAE,EAAE,SAAS;oBACb,OAAO,EAAE,SAAS;oBAClB,SAAS,EAAE,SAAS;oBACpB,MAAM,EAAE,SAAS;iBACpB,CAAC;gBACF,IAAI,CAAC,MAAM,GAAG,IAAA,uCAAwB,EAAC,IAAI,EAAE,aAAa,CAAC,CAAC;gBAE5D,MAAM,UAAU,GAA4B;oBACxC,MAAM;iBACT,CAAC;gBAEF,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBAChE,MAAM,gBAAgB,GAAG,IAAA,4BAAY,EAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;gBAEvE,MAAM,gBAAgB,GAAqB,KAAK,EAC5C,YAA0B,EAC1B,OAAe,EACf,WAAgB,EAChB,OAAe,EACf,MAA6B,EAAE,EAAE;oBACjC,IAAI,aAA4B,CAAC;oBAEjC,MAAM,QAAQ,GAAG,IAAA,qCAAsB,GAAE,CAAC;oBAC1C,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACjC,IAAI,CAAC,EAAE;wBACH,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,OAAO,CAAC,CAAC;oBAElD,MAAM,QAAQ,GAAW,WAAW,CAAC,IAAI,CAAC;oBAC1C,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,IAAA,+BAAU,EAAC,IAAA,+BAAe,EAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;oBAE/F,MAAM,MAAM,GAAG,IAAA,iCAAiB,GAAE,CAAC;oBACnC,MAAM,YAAY,GAAG,IAAA,+BAAe,EAAC,QAAQ,CAAC,CAAC;oBAE/C,aAAa,GAAG,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE;wBACvC,WAAW;wBACX,GAAG,EAAE;4BACD,eAAe,EAAE,MAAM;4BACvB,sBAAsB,EAAE,YAAY;yBACvC;wBACD,WAAW,EAAE,SAAS;wBACtB,OAAO;wBACP,YAAY;wBACZ,OAAO;qBACV,EAAE,SAAS,CAAC,CAAC;oBAEd,MAAM,UAAU,GAAG,IAAI,aAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;oBACvJ,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;oBACvC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;wBAC1B,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;oBACrC,CAAC,CAAC,CAAC;oBACH,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;wBAC1B,UAAU,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;oBACzC,CAAC,CAAC,CAAC;oBACH,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;wBAC5C,aAAa,CAAC,IAAI,EAAE,CAAC;oBACzB,CAAC,CAAC,CAAC;oBACH,YAAY,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;wBACpD,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;oBACnC,CAAC,CAAC,CAAC;oBACH,IAAI,SAAc,CAAC;oBACnB,IAAI,CAAC;wBACD,MAAM,iBAAiB,GAAsB,MAAM,UAAU,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;wBAC5F,MAAM,iBAAiB,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;wBACtD,SAAS,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;oBACvD,CAAC;oBACD,OAAO,CAAC,EAAE,CAAC;wBACP,UAAU,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;wBACvC,MAAM,CAAC,CAAC;oBACZ,CAAC;oBAED,MAAM,UAAU,GAAG,KAAK,SAAS,CAAC,EAAE,MAAgB;wBAChD,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC;4BAChC,MAAM,MAAM,CAAC;wBACjB,CAAC;oBACL,CAAC,CAAA;oBAED,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;wBAC5B,UAAU,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;oBAC5C,CAAC,EAAE,KAAK,CAAC,CAAC;oBACV,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAW,EAAE,EAAE;wBACxC,YAAY,CAAC,OAAO,CAAC,CAAC;wBACtB,OAAO;4BACH,CAAC,aAAO,CAAC,qCAAqC,CAAC,EAAE,IAAI;4BACrD,MAAM,EAAE,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC;4BACxC,MAAM,EAAE,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC;4BACxC,SAAS;yBACZ,CAAC;oBACN,CAAC,CAAC;oBAEF,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;oBACtF,OAAO,MAAM,CAAC;gBAClB,CAAC,CAAC;gBAEF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,gBAAgB,CAAC;gBAEvC,MAAM,IAAI,CAAC,MAAM,CAAC;YACtB,CAAC;YACD,OAAO,CAAC,EAAE,CAAC;gBACP,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gBACrB,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,uBAAuB,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YACtE,CAAC;QACL,CAAC;IACL,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAwB,EAAE,WAA2D;IACrH,MAAM,MAAM,GAAG,aAAG,CAAC,YAAY,CAAC;QAC5B,GAAG,EAAE,WAAW,CAAC,UAAU;QAC3B,IAAI,EAAE,WAAW,CAAC,WAAW;KAChC,EAAE,CAAC,MAAM,EAAE,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAClF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAE3C,MAAM,iBAAiB,GAAsB,KAAK,EAAE,IAAmB,EAAE,UAAmC,EAAE,EAAE;YAC5G,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,IAAA,uCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;gBACrE,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM;oBACtB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;gBACpD,gEAAgE;gBAChE,0BAA0B;gBAC1B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,CAAC;oBACrD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;wBAC/E,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBAC3D,CAAC;gBACD,MAAM,MAAM,GAAkB;oBAC1B,GAAG,UAAU;oBACb,IAAI;iBACP,CAAC;gBACF,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACnC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;oBAClB,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC1C,CAAC,CAAC,CAAC;gBACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;oBACpB,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC1C,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YACtG,CAAC;YACD,OAAO,CAAC,EAAE,CAAC;gBACP,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACb,MAAM,CAAC,OAAO,EAAE,CAAC;YACrB,CAAC;YAED,OAAO;gBACH,SAAS,EAAE,OAAO,CAAC,SAAS;aAC/B,CAAA;QACL,CAAC,CAAA;QACD,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,iBAAiB,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"scrypted-cluster-main.js","sourceRoot":"","sources":["../src/scrypted-cluster-main.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrypted/server",
3
- "version": "0.123.21",
3
+ "version": "0.123.22",
4
4
  "description": "",
5
5
  "dependencies": {
6
6
  "@scrypted/ffmpeg-static": "^6.1.0-build3",
@@ -0,0 +1,227 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import base64
5
+ import hashlib
6
+ import os
7
+ from asyncio.events import AbstractEventLoop
8
+ from collections.abc import Mapping
9
+ from typing import Any
10
+
11
+ import rpc
12
+ import rpc_reader
13
+ from typing import TypedDict
14
+
15
+ class ClusterObject(TypedDict):
16
+ id: str
17
+ address: str
18
+ port: int
19
+ proxyId: str
20
+ sourceKey: str
21
+ sha256: str
22
+
23
+ def isClusterAddress(address: str):
24
+ return not address or address == os.environ.get("SCRYPTED_CLUSTER_ADDRESS", None)
25
+
26
+ def getClusterPeerKey(address: str, port: int):
27
+ return f"{address}:{port}"
28
+ class ClusterSetup():
29
+ def __init__(self, loop: AbstractEventLoop, peer: rpc.RpcPeer):
30
+ self.loop = loop
31
+ self.peer = peer
32
+ self.clusterId: str = None
33
+ self.clusterSecret: str = None
34
+ self.clusterAddress: str = None
35
+ self.clusterPort: int = None
36
+ self.SCRYPTED_CLUSTER_ADDRESS: str = None
37
+ self.clusterPeers: Mapping[str, asyncio.Future[rpc.RpcPeer]] = {}
38
+
39
+ async def resolveObject(self, id: str, sourceKey: str):
40
+ sourcePeer: rpc.RpcPeer = (
41
+ self.peer
42
+ if not sourceKey
43
+ else await rpc.maybe_await(self.clusterPeers.get(sourceKey, None))
44
+ )
45
+ if not sourcePeer:
46
+ return
47
+ return sourcePeer.localProxyMap.get(id, None)
48
+
49
+ async def connectClusterObject(self, o: ClusterObject):
50
+ sha256 = self.computeClusterObjectHash(o)
51
+ if sha256 != o["sha256"]:
52
+ raise Exception("secret incorrect")
53
+ return await self.resolveObject(o.get('proxyId', None), o.get('sourceKey', None))
54
+
55
+ def onProxySerialization(self, peer: rpc.RpcPeer, value: Any, sourceKey: str = None):
56
+ properties: dict = rpc.RpcPeer.prepareProxyProperties(value) or {}
57
+ clusterEntry = properties.get("__cluster", None)
58
+ proxyId: str
59
+ existing = peer.localProxied.get(value, None)
60
+ if existing:
61
+ proxyId = existing["id"]
62
+ else:
63
+ proxyId = (
64
+ clusterEntry and clusterEntry.get("proxyId", None)
65
+ ) or rpc.RpcPeer.generateId()
66
+
67
+ if clusterEntry:
68
+ if (
69
+ isClusterAddress(clusterEntry.get("address", None))
70
+ and self.clusterPort == clusterEntry["port"]
71
+ and sourceKey != clusterEntry.get("sourceKey", None)
72
+ ):
73
+ clusterEntry = None
74
+
75
+ if not clusterEntry:
76
+ clusterEntry: ClusterObject = {
77
+ "id": self.clusterId,
78
+ "proxyId": proxyId,
79
+ "address": self.SCRYPTED_CLUSTER_ADDRESS,
80
+ "port": self.clusterPort,
81
+ "sourceKey": sourceKey,
82
+ }
83
+ clusterEntry["sha256"] = self.computeClusterObjectHash(clusterEntry)
84
+ properties["__cluster"] = clusterEntry
85
+
86
+ return proxyId, properties
87
+
88
+ async def initializeCluster(self, options: dict):
89
+ if self.clusterPort:
90
+ return
91
+ self.clusterId = options["clusterId"]
92
+ self.clusterSecret = options["clusterSecret"]
93
+ self.SCRYPTED_CLUSTER_ADDRESS = os.environ.get("SCRYPTED_CLUSTER_ADDRESS", None)
94
+
95
+ async def handleClusterClient(
96
+ reader: asyncio.StreamReader, writer: asyncio.StreamWriter
97
+ ):
98
+ clusterPeerAddress, clusterPeerPort = writer.get_extra_info("peername")
99
+ clusterPeerKey = getClusterPeerKey(clusterPeerAddress, clusterPeerPort)
100
+ rpcTransport = rpc_reader.RpcStreamTransport(reader, writer)
101
+ peer: rpc.RpcPeer
102
+ peer, peerReadLoop = await rpc_reader.prepare_peer_readloop(
103
+ self.loop, rpcTransport
104
+ )
105
+ # set all params from self.peer
106
+ for key, value in self.peer.params.items():
107
+ peer.params[key] = value
108
+ peer.onProxySerialization = lambda value: self.onProxySerialization(
109
+ peer, value, clusterPeerKey
110
+ )
111
+ future: asyncio.Future[rpc.RpcPeer] = asyncio.Future()
112
+ future.set_result(peer)
113
+ self.clusterPeers[clusterPeerKey] = future
114
+ peer.params["connectRPCObject"] = lambda o: self.connectClusterObject(o)
115
+ try:
116
+ await peerReadLoop()
117
+ except:
118
+ pass
119
+ finally:
120
+ self.clusterPeers.pop(clusterPeerKey)
121
+ peer.kill("cluster client killed")
122
+ writer.close()
123
+
124
+ listenAddress = "0.0.0.0" if self.SCRYPTED_CLUSTER_ADDRESS else "127.0.0.1"
125
+ clusterRpcServer = await asyncio.start_server(
126
+ handleClusterClient, listenAddress, 0
127
+ )
128
+ self.clusterPort = clusterRpcServer.sockets[0].getsockname()[1]
129
+ self.peer.onProxySerialization = lambda value: self.onProxySerialization(self.peer, value, None)
130
+ del self.peer.params["initializeCluster"]
131
+
132
+ def computeClusterObjectHash(self, o: ClusterObject) -> str:
133
+ m = hashlib.sha256()
134
+ m.update(
135
+ bytes(
136
+ f"{o['id']}{o.get('address') or ''}{o['port']}{o.get('sourceKey', None) or ''}{o['proxyId']}{self.clusterSecret}",
137
+ "utf8",
138
+ )
139
+ )
140
+ return base64.b64encode(m.digest()).decode("utf-8")
141
+
142
+ def ensureClusterPeer(self, address: str, port: int):
143
+ if isClusterAddress(address):
144
+ address = "127.0.0.1"
145
+ clusterPeerKey = getClusterPeerKey(address, port)
146
+ clusterPeerPromise = self.clusterPeers.get(clusterPeerKey)
147
+ if clusterPeerPromise:
148
+ return clusterPeerPromise
149
+
150
+ async def connectClusterPeer():
151
+ try:
152
+ reader, writer = await asyncio.open_connection(address, port)
153
+ sourceAddress, sourcePort = writer.get_extra_info("sockname")
154
+ if (
155
+ sourceAddress != self.SCRYPTED_CLUSTER_ADDRESS
156
+ and sourceAddress != "127.0.0.1"
157
+ ):
158
+ print("source address mismatch", sourceAddress)
159
+ rpcTransport = rpc_reader.RpcStreamTransport(reader, writer)
160
+ clusterPeer, peerReadLoop = await rpc_reader.prepare_peer_readloop(
161
+ self.loop, rpcTransport
162
+ )
163
+ # set all params from self.peer
164
+ for key, value in self.peer.params.items():
165
+ clusterPeer.params[key] = value
166
+ clusterPeer.onProxySerialization = (
167
+ lambda value: self.clusterSetup.onProxySerialization(
168
+ clusterPeer, value, clusterPeerKey
169
+ )
170
+ )
171
+ except:
172
+ self.clusterPeers.pop(clusterPeerKey)
173
+ raise
174
+
175
+ async def run_loop():
176
+ try:
177
+ await peerReadLoop()
178
+ except:
179
+ pass
180
+ finally:
181
+ self.clusterPeers.pop(clusterPeerKey)
182
+
183
+ asyncio.run_coroutine_threadsafe(run_loop(), self.loop)
184
+ return clusterPeer
185
+
186
+ clusterPeerPromise = self.loop.create_task(connectClusterPeer())
187
+
188
+ self.clusterPeers[clusterPeerKey] = clusterPeerPromise
189
+ return clusterPeerPromise
190
+
191
+ async def connectRPCObject(self, value):
192
+ __cluster = getattr(value, "__cluster")
193
+ if type(__cluster) is not dict:
194
+ return value
195
+
196
+ clusterObject: ClusterObject = __cluster
197
+
198
+ if clusterObject.get("id", None) != self.clusterId:
199
+ return value
200
+
201
+ address = clusterObject.get("address", None)
202
+ port = clusterObject["port"]
203
+ proxyId = clusterObject["proxyId"]
204
+ if port == self.clusterPort:
205
+ return await self.connectRPCObject(clusterObject)
206
+
207
+ clusterPeerPromise = self.ensureClusterPeer(address, port)
208
+
209
+ try:
210
+ clusterPeer = await clusterPeerPromise
211
+ weakref = clusterPeer.remoteWeakProxies.get(proxyId, None)
212
+ existing = weakref() if weakref else None
213
+ if existing:
214
+ return existing
215
+
216
+ peerConnectRPCObject = clusterPeer.tags.get("connectRPCObject")
217
+ if not peerConnectRPCObject:
218
+ peerConnectRPCObject = await clusterPeer.getParam(
219
+ "connectRPCObject"
220
+ )
221
+ clusterPeer.tags["connectRPCObject"] = peerConnectRPCObject
222
+ newValue = await peerConnectRPCObject(clusterObject)
223
+ if not newValue:
224
+ raise Exception("rpc object not found?")
225
+ return newValue
226
+ except Exception as e:
227
+ return value
@@ -1,9 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
- import base64
5
4
  import gc
6
- import hashlib
7
5
  import inspect
8
6
  import multiprocessing
9
7
  import multiprocessing.connection
@@ -19,39 +17,27 @@ from asyncio.futures import Future
19
17
  from asyncio.streams import StreamReader, StreamWriter
20
18
  from collections.abc import Mapping
21
19
  from io import StringIO
22
- from typing import Any, Optional, Set, Tuple, TypedDict, Callable, Coroutine
20
+ from typing import Any, Callable, Coroutine, Optional, Set, Tuple, TypedDict
23
21
 
24
22
  import plugin_volume as pv
25
23
  import rpc
26
24
  import rpc_reader
27
25
  import scrypted_python.scrypted_sdk.types
26
+ from cluster_setup import ClusterSetup
28
27
  from plugin_pip import install_with_pip, need_requirements, remove_pip_dirs
29
28
  from scrypted_python.scrypted_sdk import PluginFork, ScryptedStatic
30
- from scrypted_python.scrypted_sdk.types import (
31
- Device,
32
- DeviceManifest,
33
- EventDetails,
34
- ScryptedInterface,
35
- ScryptedInterfaceMethods,
36
- ScryptedInterfaceProperty,
37
- Storage,
38
- )
29
+ from scrypted_python.scrypted_sdk.types import (Device, DeviceManifest,
30
+ EventDetails,
31
+ ScryptedInterface,
32
+ ScryptedInterfaceMethods,
33
+ ScryptedInterfaceProperty,
34
+ Storage)
39
35
 
40
36
  SCRYPTED_REQUIREMENTS = """
41
37
  ptpython
42
38
  wheel
43
39
  """.strip()
44
40
 
45
-
46
- class ClusterObject(TypedDict):
47
- id: str
48
- address: str
49
- port: int
50
- proxyId: str
51
- sourceKey: str
52
- sha256: str
53
-
54
-
55
41
  class SystemDeviceState(TypedDict):
56
42
  lastEventTime: int
57
43
  stateTime: int
@@ -553,214 +539,6 @@ class DeviceManager(scrypted_python.scrypted_sdk.types.DeviceManager):
553
539
  def getDeviceStorage(self, nativeId: str = None) -> Storage:
554
540
  return self.nativeIds.get(nativeId, None)
555
541
 
556
-
557
- def isClusterAddress(address: str):
558
- return not address or address == os.environ.get("SCRYPTED_CLUSTER_ADDRESS", None)
559
-
560
- def getClusterPeerKey(address: str, port: int):
561
- return f"{address}:{port}"
562
-
563
- class ClusterSetup():
564
- def __init__(self, loop: AbstractEventLoop, peer: rpc.RpcPeer):
565
- self.loop = loop
566
- self.peer = peer
567
- self.clusterId: str = None
568
- self.clusterSecret: str = None
569
- self.clusterAddress: str = None
570
- self.clusterPort: int = None
571
- self.SCRYPTED_CLUSTER_ADDRESS: str = None
572
- self.clusterPeers: Mapping[str, asyncio.Future[rpc.RpcPeer]] = {}
573
-
574
- async def resolveObject(self, id: str, sourceKey: str):
575
- sourcePeer: rpc.RpcPeer = (
576
- self.peer
577
- if not sourceKey
578
- else await rpc.maybe_await(self.clusterPeers.get(sourceKey, None))
579
- )
580
- if not sourcePeer:
581
- return
582
- return sourcePeer.localProxyMap.get(id, None)
583
-
584
- async def connectClusterObject(self, o: ClusterObject):
585
- sha256 = self.computeClusterObjectHash(o)
586
- if sha256 != o["sha256"]:
587
- raise Exception("secret incorrect")
588
- return await self.resolveObject(o.get('proxyId', None), o.get('sourceKey', None))
589
-
590
- def onProxySerialization(self, peer: rpc.RpcPeer, value: Any, sourceKey: str = None):
591
- properties: dict = rpc.RpcPeer.prepareProxyProperties(value) or {}
592
- clusterEntry = properties.get("__cluster", None)
593
- proxyId: str
594
- existing = peer.localProxied.get(value, None)
595
- if existing:
596
- proxyId = existing["id"]
597
- else:
598
- proxyId = (
599
- clusterEntry and clusterEntry.get("proxyId", None)
600
- ) or rpc.RpcPeer.generateId()
601
-
602
- if clusterEntry:
603
- if (
604
- isClusterAddress(clusterEntry.get("address", None))
605
- and self.clusterPort == clusterEntry["port"]
606
- and sourceKey != clusterEntry.get("sourceKey", None)
607
- ):
608
- clusterEntry = None
609
-
610
- if not clusterEntry:
611
- clusterEntry: ClusterObject = {
612
- "id": self.clusterId,
613
- "proxyId": proxyId,
614
- "address": self.SCRYPTED_CLUSTER_ADDRESS,
615
- "port": self.clusterPort,
616
- "sourceKey": sourceKey,
617
- }
618
- clusterEntry["sha256"] = self.computeClusterObjectHash(clusterEntry)
619
- properties["__cluster"] = clusterEntry
620
-
621
- return proxyId, properties
622
-
623
- async def initializeCluster(self, options: dict):
624
- if self.clusterPort:
625
- return
626
- self.clusterId = options["clusterId"]
627
- self.clusterSecret = options["clusterSecret"]
628
- self.SCRYPTED_CLUSTER_ADDRESS = os.environ.get("SCRYPTED_CLUSTER_ADDRESS", None)
629
-
630
- async def handleClusterClient(
631
- reader: asyncio.StreamReader, writer: asyncio.StreamWriter
632
- ):
633
- clusterPeerAddress, clusterPeerPort = writer.get_extra_info("peername")
634
- clusterPeerKey = getClusterPeerKey(clusterPeerAddress, clusterPeerPort)
635
- rpcTransport = rpc_reader.RpcStreamTransport(reader, writer)
636
- peer: rpc.RpcPeer
637
- peer, peerReadLoop = await rpc_reader.prepare_peer_readloop(
638
- self.loop, rpcTransport
639
- )
640
- # set all params from self.peer
641
- for key, value in self.peer.params.items():
642
- peer.params[key] = value
643
- peer.onProxySerialization = lambda value: self.onProxySerialization(
644
- peer, value, clusterPeerKey
645
- )
646
- future: asyncio.Future[rpc.RpcPeer] = asyncio.Future()
647
- future.set_result(peer)
648
- self.clusterPeers[clusterPeerKey] = future
649
- peer.params["connectRPCObject"] = lambda o: self.connectClusterObject(o)
650
- try:
651
- await peerReadLoop()
652
- except:
653
- pass
654
- finally:
655
- self.clusterPeers.pop(clusterPeerKey)
656
- peer.kill("cluster client killed")
657
- writer.close()
658
-
659
- listenAddress = "0.0.0.0" if self.SCRYPTED_CLUSTER_ADDRESS else "127.0.0.1"
660
- clusterRpcServer = await asyncio.start_server(
661
- handleClusterClient, listenAddress, 0
662
- )
663
- self.clusterPort = clusterRpcServer.sockets[0].getsockname()[1]
664
- self.peer.onProxySerialization = lambda value: self.onProxySerialization(self.peer, value, None)
665
- del self.peer.params["initializeCluster"]
666
-
667
- def computeClusterObjectHash(self, o: ClusterObject) -> str:
668
- m = hashlib.sha256()
669
- m.update(
670
- bytes(
671
- f"{o['id']}{o.get('address') or ''}{o['port']}{o.get('sourceKey', None) or ''}{o['proxyId']}{self.clusterSecret}",
672
- "utf8",
673
- )
674
- )
675
- return base64.b64encode(m.digest()).decode("utf-8")
676
-
677
- def ensureClusterPeer(self, address: str, port: int):
678
- if isClusterAddress(address):
679
- address = "127.0.0.1"
680
- clusterPeerKey = getClusterPeerKey(address, port)
681
- clusterPeerPromise = self.clusterPeers.get(clusterPeerKey)
682
- if clusterPeerPromise:
683
- return clusterPeerPromise
684
-
685
- async def connectClusterPeer():
686
- try:
687
- reader, writer = await asyncio.open_connection(address, port)
688
- sourceAddress, sourcePort = writer.get_extra_info("sockname")
689
- if (
690
- sourceAddress != self.SCRYPTED_CLUSTER_ADDRESS
691
- and sourceAddress != "127.0.0.1"
692
- ):
693
- print("source address mismatch", sourceAddress)
694
- rpcTransport = rpc_reader.RpcStreamTransport(reader, writer)
695
- clusterPeer, peerReadLoop = await rpc_reader.prepare_peer_readloop(
696
- self.loop, rpcTransport
697
- )
698
- # set all params from self.peer
699
- for key, value in self.peer.params.items():
700
- clusterPeer.params[key] = value
701
- clusterPeer.onProxySerialization = (
702
- lambda value: self.clusterSetup.onProxySerialization(
703
- clusterPeer, value, clusterPeerKey
704
- )
705
- )
706
- except:
707
- self.clusterPeers.pop(clusterPeerKey)
708
- raise
709
-
710
- async def run_loop():
711
- try:
712
- await peerReadLoop()
713
- except:
714
- pass
715
- finally:
716
- self.clusterPeers.pop(clusterPeerKey)
717
-
718
- asyncio.run_coroutine_threadsafe(run_loop(), self.loop)
719
- return clusterPeer
720
-
721
- clusterPeerPromise = self.loop.create_task(connectClusterPeer())
722
-
723
- self.clusterPeers[clusterPeerKey] = clusterPeerPromise
724
- return clusterPeerPromise
725
-
726
- async def connectRPCObject(self, value):
727
- __cluster = getattr(value, "__cluster")
728
- if type(__cluster) is not dict:
729
- return value
730
-
731
- clusterObject: ClusterObject = __cluster
732
-
733
- if clusterObject.get("id", None) != self.clusterId:
734
- return value
735
-
736
- address = clusterObject.get("address", None)
737
- port = clusterObject["port"]
738
- proxyId = clusterObject["proxyId"]
739
- if port == self.clusterPort:
740
- return await self.connectRPCObject(clusterObject)
741
-
742
- clusterPeerPromise = self.ensureClusterPeer(address, port)
743
-
744
- try:
745
- clusterPeer = await clusterPeerPromise
746
- weakref = clusterPeer.remoteWeakProxies.get(proxyId, None)
747
- existing = weakref() if weakref else None
748
- if existing:
749
- return existing
750
-
751
- peerConnectRPCObject = clusterPeer.tags.get("connectRPCObject")
752
- if not peerConnectRPCObject:
753
- peerConnectRPCObject = await clusterPeer.getParam(
754
- "connectRPCObject"
755
- )
756
- clusterPeer.tags["connectRPCObject"] = peerConnectRPCObject
757
- newValue = await peerConnectRPCObject(clusterObject)
758
- if not newValue:
759
- raise Exception("rpc object not found?")
760
- return newValue
761
- except Exception as e:
762
- return value
763
-
764
542
  class PluginRemote:
765
543
  def __init__(
766
544
  self, clusterSetup: ClusterSetup, api, pluginId: str, hostInfo, loop: AbstractEventLoop
@@ -1,5 +1,6 @@
1
1
  import type { ForkOptions } from '@scrypted/types';
2
2
  import { once } from 'events';
3
+ import net from 'net';
3
4
  import { install as installSourceMapSupport } from 'source-map-support';
4
5
  import type { Readable } from 'stream';
5
6
  import tls from 'tls';
@@ -109,9 +110,22 @@ export function startClusterClient(mainFilename: string) {
109
110
  // to hang the app since no window is created yet.
110
111
  await sleep(1000);
111
112
 
112
- const socket = tls.connect({
113
+ const rawSocket = net.connect({
113
114
  host,
114
115
  port,
116
+ // require ipv4 to normalize cluster address.
117
+ family: 4,
118
+ });
119
+
120
+ try {
121
+ await once(rawSocket, 'connect');
122
+ }
123
+ catch( e) {
124
+ continue;
125
+ }
126
+
127
+ const socket = tls.connect({
128
+ socket: rawSocket,
115
129
  rejectUnauthorized: false,
116
130
  });
117
131