@itwin/core-mobile 5.15.0-dev.5 → 5.15.0-dev.7

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.
@@ -3,6 +3,8 @@ import { MobileRpcGateway } from "../common/MobileRpcProtocol";
3
3
  export declare class MobileRpcServer {
4
4
  private _pendingMessages;
5
5
  private static _nextId;
6
+ private static readonly _rpcToken;
7
+ static get rpcToken(): string;
6
8
  static interop: MobileRpcGateway;
7
9
  private _server;
8
10
  private _connection;
@@ -1 +1 @@
1
- {"version":3,"file":"MobileRpcServer.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,6BAA6B,CAAC;AAYlF,gBAAgB;AAChB,qBAAa,eAAe;IAgBP,OAAO,CAAC,gBAAgB;IAf3C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAM;IAE5B,OAAc,OAAO,EAAE,gBAAgB,CAMrC;IAEF,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAiB;gBACR,gBAAgB,GAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,SAAqB;IAmB/F,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,oBAAoB;IAiBrB,CAAC,MAAM,CAAC,OAAO,CAAC;CAUxB;AAKD,wBAAgB,cAAc,SAoE7B"}
1
+ {"version":3,"file":"MobileRpcServer.d.ts","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAqB,MAAM,6BAA6B,CAAC;AAYlF,gBAAgB;AAChB,qBAAa,eAAe;IAmBP,OAAO,CAAC,gBAAgB;IAlB3C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAM;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAEpE,WAAkB,QAAQ,WAA6B;IAEvD,OAAc,OAAO,EAAE,gBAAgB,CAMrC;IAEF,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAiB;gBACR,gBAAgB,GAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,SAAqB;IA8B/F,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,oBAAoB;IAiBrB,CAAC,MAAM,CAAC,OAAO,CAAC;CAUxB;AAKD,wBAAgB,cAAc,SAoE7B"}
@@ -6,6 +6,7 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.MobileRpcServer = void 0;
8
8
  exports.setupMobileRpc = setupMobileRpc;
9
+ const node_crypto_1 = require("node:crypto");
9
10
  const ws = require("ws");
10
11
  const core_common_1 = require("@itwin/core-common");
11
12
  const MobileRpcProtocol_1 = require("../common/MobileRpcProtocol");
@@ -17,6 +18,8 @@ let addon;
17
18
  class MobileRpcServer {
18
19
  _pendingMessages;
19
20
  static _nextId = -1;
21
+ static _rpcToken = (0, node_crypto_1.randomBytes)(32).toString("hex");
22
+ static get rpcToken() { return this._rpcToken; }
20
23
  static interop = {
21
24
  handler: (_payload) => { throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Not implemented."); },
22
25
  sendString: (_message, _connectionId) => { throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "No connection."); },
@@ -42,7 +45,17 @@ class MobileRpcServer {
42
45
  */
43
46
  this._pingTimer = setInterval(() => { }, 5);
44
47
  this._port = MobileRpcManager_1.MobileRpcConfiguration.setup.obtainPort();
45
- this._server = new ws.Server({ host: "127.0.0.1", port: this._port });
48
+ this._server = new ws.Server({
49
+ host: "127.0.0.1", port: this._port,
50
+ verifyClient: (info) => {
51
+ const protocol = info.req.headers["sec-websocket-protocol"];
52
+ const expected = Buffer.from(`itwin-rpc.${MobileRpcServer._rpcToken}`);
53
+ if (typeof protocol !== "string")
54
+ return false;
55
+ const supplied = Buffer.from(protocol);
56
+ return supplied.length === expected.length && (0, node_crypto_1.timingSafeEqual)(supplied, expected);
57
+ },
58
+ });
46
59
  this._connectionId = ++MobileRpcServer._nextId;
47
60
  MobileRpcServer.interop.connectionId = this._connectionId;
48
61
  this._onListening();
@@ -59,7 +72,7 @@ class MobileRpcServer {
59
72
  _notifyListening() {
60
73
  MobileRpcServer.interop.port = this._port;
61
74
  if (addon) {
62
- addon.notifyListening(this._port);
75
+ addon.notifyListening(this._port, MobileRpcServer._rpcToken);
63
76
  }
64
77
  if (this._connectionId !== 0) {
65
78
  MobileHost_1.MobileHost.reconnect(this._port);
@@ -1 +1 @@
1
- {"version":3,"file":"MobileRpcServer.js","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\nimport * as ws from \"ws\";\r\nimport { IModelError } from \"@itwin/core-common\";\r\nimport { MobileRpcGateway, MobileRpcProtocol } from \"../common/MobileRpcProtocol\";\r\nimport { MobileRpcConfiguration } from \"../common/MobileRpcManager\";\r\nimport { MobileHost } from \"./MobileHost\";\r\nimport { BentleyStatus, expectDefined, ProcessDetector } from \"@itwin/core-bentley\";\r\n\r\ninterface MobileAddon {\r\n notifyListening: (port: number) => void;\r\n registerDeviceImpl: () => void;\r\n}\r\n\r\nlet addon: MobileAddon | undefined;\r\n\r\n/** @internal */\r\nexport class MobileRpcServer {\r\n private static _nextId = -1;\r\n\r\n public static interop: MobileRpcGateway = {\r\n handler: (_payload: ArrayBuffer | string) => { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); },\r\n sendString: (_message: string, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n sendBinary: (_message: Uint8Array, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n port: 0,\r\n connectionId: 0,\r\n };\r\n\r\n private _server: ws.Server;\r\n private _connection: ws | undefined;\r\n private _port: number;\r\n private _connectionId: number;\r\n private _pingTimer: NodeJS.Timeout;\r\n public constructor(private _pendingMessages: Array<string | Uint8Array> | undefined = undefined) {\r\n /* _pingTime is a fix for ios/mobile case where when the app moves into foreground from\r\n * background backend restart ws.Server and then notify frontend to reconnect. But ws.Server\r\n * listening event is not fired as node yield to kevent and wait for some io event to happen.\r\n * This causes a delay in reconnection which may be as long a 40 secs. To solve the issue we\r\n * create _pingTimer which causes kevent to yield back to uv poll so timer event can be fired.\r\n * This allow listening event to go through quickly (max 5ms). Once the listening event occur we\r\n * clear the timer. Here we use setInterval() just to make sure otherwise setTimeout() could equally\r\n * be effective\r\n */\r\n this._pingTimer = setInterval(() => { }, 5);\r\n this._port = MobileRpcConfiguration.setup.obtainPort();\r\n this._server = new ws.Server({ host: \"127.0.0.1\", port: this._port });\r\n this._connectionId = ++MobileRpcServer._nextId;\r\n MobileRpcServer.interop.connectionId = this._connectionId;\r\n this._onListening();\r\n this._onConnection();\r\n }\r\n\r\n private _onListening() {\r\n this._server.on(\"listening\", () => {\r\n const address = this._server.address() as ws.AddressInfo;\r\n this._port = address.port;\r\n clearInterval(this._pingTimer);\r\n this._notifyListening();\r\n });\r\n }\r\n\r\n private _notifyListening() {\r\n MobileRpcServer.interop.port = this._port;\r\n\r\n if (addon) {\r\n addon.notifyListening(this._port);\r\n }\r\n\r\n if (this._connectionId !== 0) {\r\n MobileHost.reconnect(this._port);\r\n }\r\n }\r\n\r\n private _onConnection() {\r\n this._server.on(\"connection\", (connection) => {\r\n this._connection = connection;\r\n this._connection.on(\"message\", (data) => this._onConnectionMessage(data));\r\n this._createSender();\r\n this._sendPending();\r\n (global as any).__iTwinJsRpcReady = true;\r\n MobileHost.onConnected.raiseEvent();\r\n });\r\n }\r\n\r\n private _createSender() {\r\n const sender = (message: string | Uint8Array, connectionId: number) => {\r\n if (connectionId !== this._connectionId) {\r\n return;\r\n }\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n };\r\n\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n private _sendPending() {\r\n if (this._pendingMessages === undefined)\r\n return;\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n for (const message of this._pendingMessages) {\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n }\r\n this._pendingMessages.length = 0;\r\n }\r\n\r\n private _onConnectionMessage(data: ws.Data) {\r\n let message = data;\r\n if (Array.isArray(message)) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Unsupported data type\");\r\n }\r\n\r\n if (Buffer.isBuffer(message)) {\r\n if (message.byteOffset !== 0 || message.byteLength !== message.buffer.byteLength) {\r\n message = new Uint8Array(message.buffer, message.byteOffset, message.byteLength);\r\n } else {\r\n message = message.buffer;\r\n }\r\n }\r\n\r\n MobileRpcServer.interop.handler(message, this._connectionId);\r\n }\r\n\r\n public [Symbol.dispose]() {\r\n clearInterval(this._pingTimer);\r\n if (this._connection) {\r\n MobileRpcServer.interop.sendString = () => { };\r\n MobileRpcServer.interop.sendBinary = () => { };\r\n this._connection.close();\r\n }\r\n\r\n this._server.close();\r\n }\r\n}\r\n\r\nlet mobileReady = false;\r\nlet hasSuspended = false;\r\n\r\nexport function setupMobileRpc() {\r\n if (mobileReady) {\r\n return;\r\n }\r\n\r\n if (ProcessDetector.isMobileAppBackend) {\r\n addon = (process as any)._linkedBinding(\"iModelJsMobile\");\r\n addon?.registerDeviceImpl();\r\n }\r\n\r\n let server: MobileRpcServer | null = new MobileRpcServer();\r\n\r\n /* The UV event loop (internal to node) is retained by handles,\r\n such as those created for setInterval/setTimeout and client/server connections.\r\n In a simple app, the RPC server may be the only handle retaining the UV loop.\r\n Thus, we install a temporary timer on suspend to prevent the loop from exiting prematurely.\r\n */\r\n let retainUvLoop: NodeJS.Timeout | undefined;\r\n const pendingMessages: Array<string | Uint8Array> = [];\r\n\r\n function usePendingSender() {\r\n const sender = (message: string | Uint8Array, _connectionId: number) => {\r\n pendingMessages.push(message);\r\n };\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n MobileHost.onEnterBackground.addListener(() => {\r\n hasSuspended = true;\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n retainUvLoop = setInterval(() => { }, 1000);\r\n server[Symbol.dispose]();\r\n usePendingSender();\r\n server = null;\r\n (global as any).__iTwinJsRpcReady = false;\r\n });\r\n\r\n MobileHost.onEnterForeground.addListener(() => {\r\n if (!hasSuspended) {\r\n return;\r\n }\r\n\r\n server = new MobileRpcServer(pendingMessages);\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n });\r\n\r\n MobileHost.onWillTerminate.addListener(() => {\r\n if (typeof (retainUvLoop) !== \"undefined\") {\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n }\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n server[Symbol.dispose]();\r\n server = null;\r\n });\r\n\r\n MobileRpcProtocol.obtainInterop = () => MobileRpcServer.interop;\r\n mobileReady = true;\r\n}\r\n"]}
1
+ {"version":3,"file":"MobileRpcServer.js","sourceRoot":"","sources":["../../../src/backend/MobileRpcServer.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\nimport { randomBytes, timingSafeEqual } from \"node:crypto\";\r\nimport * as ws from \"ws\";\r\nimport { IModelError } from \"@itwin/core-common\";\r\nimport { MobileRpcGateway, MobileRpcProtocol } from \"../common/MobileRpcProtocol\";\r\nimport { MobileRpcConfiguration } from \"../common/MobileRpcManager\";\r\nimport { MobileHost } from \"./MobileHost\";\r\nimport { BentleyStatus, expectDefined, ProcessDetector } from \"@itwin/core-bentley\";\r\n\r\ninterface MobileAddon {\r\n notifyListening: (port: number, rpcToken: string) => void;\r\n registerDeviceImpl: () => void;\r\n}\r\n\r\nlet addon: MobileAddon | undefined;\r\n\r\n/** @internal */\r\nexport class MobileRpcServer {\r\n private static _nextId = -1;\r\n private static readonly _rpcToken = randomBytes(32).toString(\"hex\");\r\n\r\n public static get rpcToken() { return this._rpcToken; }\r\n\r\n public static interop: MobileRpcGateway = {\r\n handler: (_payload: ArrayBuffer | string) => { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); },\r\n sendString: (_message: string, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n sendBinary: (_message: Uint8Array, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, \"No connection.\"); },\r\n port: 0,\r\n connectionId: 0,\r\n };\r\n\r\n private _server: ws.Server;\r\n private _connection: ws | undefined;\r\n private _port: number;\r\n private _connectionId: number;\r\n private _pingTimer: NodeJS.Timeout;\r\n public constructor(private _pendingMessages: Array<string | Uint8Array> | undefined = undefined) {\r\n /* _pingTime is a fix for ios/mobile case where when the app moves into foreground from\r\n * background backend restart ws.Server and then notify frontend to reconnect. But ws.Server\r\n * listening event is not fired as node yield to kevent and wait for some io event to happen.\r\n * This causes a delay in reconnection which may be as long a 40 secs. To solve the issue we\r\n * create _pingTimer which causes kevent to yield back to uv poll so timer event can be fired.\r\n * This allow listening event to go through quickly (max 5ms). Once the listening event occur we\r\n * clear the timer. Here we use setInterval() just to make sure otherwise setTimeout() could equally\r\n * be effective\r\n */\r\n this._pingTimer = setInterval(() => { }, 5);\r\n this._port = MobileRpcConfiguration.setup.obtainPort();\r\n this._server = new ws.Server({\r\n host: \"127.0.0.1\", port: this._port,\r\n verifyClient: (info: Parameters<ws.VerifyClientCallbackSync>[0]) => {\r\n const protocol = info.req.headers[\"sec-websocket-protocol\"];\r\n const expected = Buffer.from(`itwin-rpc.${MobileRpcServer._rpcToken}`);\r\n if (typeof protocol !== \"string\")\r\n return false;\r\n\r\n const supplied = Buffer.from(protocol);\r\n return supplied.length === expected.length && timingSafeEqual(supplied, expected);\r\n },\r\n });\r\n this._connectionId = ++MobileRpcServer._nextId;\r\n MobileRpcServer.interop.connectionId = this._connectionId;\r\n this._onListening();\r\n this._onConnection();\r\n }\r\n\r\n private _onListening() {\r\n this._server.on(\"listening\", () => {\r\n const address = this._server.address() as ws.AddressInfo;\r\n this._port = address.port;\r\n clearInterval(this._pingTimer);\r\n this._notifyListening();\r\n });\r\n }\r\n\r\n private _notifyListening() {\r\n MobileRpcServer.interop.port = this._port;\r\n\r\n if (addon) {\r\n addon.notifyListening(this._port, MobileRpcServer._rpcToken);\r\n }\r\n\r\n if (this._connectionId !== 0) {\r\n MobileHost.reconnect(this._port);\r\n }\r\n }\r\n\r\n private _onConnection() {\r\n this._server.on(\"connection\", (connection) => {\r\n this._connection = connection;\r\n this._connection.on(\"message\", (data) => this._onConnectionMessage(data));\r\n this._createSender();\r\n this._sendPending();\r\n (global as any).__iTwinJsRpcReady = true;\r\n MobileHost.onConnected.raiseEvent();\r\n });\r\n }\r\n\r\n private _createSender() {\r\n const sender = (message: string | Uint8Array, connectionId: number) => {\r\n if (connectionId !== this._connectionId) {\r\n return;\r\n }\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n };\r\n\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n private _sendPending() {\r\n if (this._pendingMessages === undefined)\r\n return;\r\n\r\n const connection = expectDefined(this._connection, \"No connection.\");\r\n for (const message of this._pendingMessages) {\r\n connection.send(message, (err) => {\r\n if (err) {\r\n throw err;\r\n }\r\n });\r\n }\r\n this._pendingMessages.length = 0;\r\n }\r\n\r\n private _onConnectionMessage(data: ws.Data) {\r\n let message = data;\r\n if (Array.isArray(message)) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Unsupported data type\");\r\n }\r\n\r\n if (Buffer.isBuffer(message)) {\r\n if (message.byteOffset !== 0 || message.byteLength !== message.buffer.byteLength) {\r\n message = new Uint8Array(message.buffer, message.byteOffset, message.byteLength);\r\n } else {\r\n message = message.buffer;\r\n }\r\n }\r\n\r\n MobileRpcServer.interop.handler(message, this._connectionId);\r\n }\r\n\r\n public [Symbol.dispose]() {\r\n clearInterval(this._pingTimer);\r\n if (this._connection) {\r\n MobileRpcServer.interop.sendString = () => { };\r\n MobileRpcServer.interop.sendBinary = () => { };\r\n this._connection.close();\r\n }\r\n\r\n this._server.close();\r\n }\r\n}\r\n\r\nlet mobileReady = false;\r\nlet hasSuspended = false;\r\n\r\nexport function setupMobileRpc() {\r\n if (mobileReady) {\r\n return;\r\n }\r\n\r\n if (ProcessDetector.isMobileAppBackend) {\r\n addon = (process as any)._linkedBinding(\"iModelJsMobile\");\r\n addon?.registerDeviceImpl();\r\n }\r\n\r\n let server: MobileRpcServer | null = new MobileRpcServer();\r\n\r\n /* The UV event loop (internal to node) is retained by handles,\r\n such as those created for setInterval/setTimeout and client/server connections.\r\n In a simple app, the RPC server may be the only handle retaining the UV loop.\r\n Thus, we install a temporary timer on suspend to prevent the loop from exiting prematurely.\r\n */\r\n let retainUvLoop: NodeJS.Timeout | undefined;\r\n const pendingMessages: Array<string | Uint8Array> = [];\r\n\r\n function usePendingSender() {\r\n const sender = (message: string | Uint8Array, _connectionId: number) => {\r\n pendingMessages.push(message);\r\n };\r\n MobileRpcServer.interop.sendString = sender;\r\n MobileRpcServer.interop.sendBinary = sender;\r\n }\r\n\r\n MobileHost.onEnterBackground.addListener(() => {\r\n hasSuspended = true;\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n retainUvLoop = setInterval(() => { }, 1000);\r\n server[Symbol.dispose]();\r\n usePendingSender();\r\n server = null;\r\n (global as any).__iTwinJsRpcReady = false;\r\n });\r\n\r\n MobileHost.onEnterForeground.addListener(() => {\r\n if (!hasSuspended) {\r\n return;\r\n }\r\n\r\n server = new MobileRpcServer(pendingMessages);\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n });\r\n\r\n MobileHost.onWillTerminate.addListener(() => {\r\n if (typeof (retainUvLoop) !== \"undefined\") {\r\n clearInterval(retainUvLoop);\r\n retainUvLoop = undefined;\r\n }\r\n\r\n if (server === null) {\r\n return;\r\n }\r\n\r\n server[Symbol.dispose]();\r\n server = null;\r\n });\r\n\r\n MobileRpcProtocol.obtainInterop = () => MobileRpcServer.interop;\r\n mobileReady = true;\r\n}\r\n"]}
@@ -29,6 +29,7 @@ export declare class MobileRpcProtocol extends RpcProtocol {
29
29
  private _partialFulfillment;
30
30
  private _partialData;
31
31
  private _port;
32
+ private _rpcToken;
32
33
  private _transport?;
33
34
  private _ipc;
34
35
  static obtainInterop(): MobileRpcGateway;
@@ -36,6 +37,7 @@ export declare class MobileRpcProtocol extends RpcProtocol {
36
37
  static encodeResponse(fulfillment: RpcRequestFulfillment): MobileRpcChunks;
37
38
  constructor(configuration: MobileRpcConfiguration, endPoint: RpcEndpoint);
38
39
  private initializeFrontend;
40
+ private setRpcToken;
39
41
  private connect;
40
42
  private connectMessageHandler;
41
43
  private connectOpenHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"MobileRpcProtocol.d.ts","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EACsB,WAAW,EAAE,WAAW,EAAiD,qBAAqB,EAE1H,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,gBAAgB;AAChB,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;AAEzD,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,UAAU,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IACzC,MAAM,EAAE,SAAS,CAAsB;IACvC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAa;IAC3D,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,oBAAoB,CAAwB;IACpD,SAAgB,WAAW,0BAAoB;IAC/C,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,mBAAmB,CAAgD;IAC3E,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,UAAU,CAAC,CAAsB;IACzC,OAAO,CAAC,IAAI,CAAqB;WACnB,aAAa,IAAI,gBAAgB;WAE3B,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;WAOxE,cAAc,CAAC,WAAW,EAAE,qBAAqB,GAAG,eAAe;gBAUrE,aAAa,EAAE,sBAAsB,EAAE,QAAQ,EAAE,WAAW;IAaxE,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,KAAK;IAcb,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,OAAO;IAmBf,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,wBAAwB;YAYlB,aAAa;IAqBpB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAK7C,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;CAW3E"}
1
+ {"version":3,"file":"MobileRpcProtocol.d.ts","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":"AAIA;;GAEG;AAGH,OAAO,EACsB,WAAW,EAAE,WAAW,EAAiD,qBAAqB,EAE1H,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,gBAAgB;AAChB,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;AAEzD,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,UAAU,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IACzC,MAAM,EAAE,SAAS,CAAsB;IACvC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAa;IAC3D,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,oBAAoB,CAAwB;IACpD,SAAgB,WAAW,0BAAoB;IAC/C,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,mBAAmB,CAAgD;IAC3E,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,UAAU,CAAC,CAAsB;IACzC,OAAO,CAAC,IAAI,CAAqB;WACnB,aAAa,IAAI,gBAAgB;WAE3B,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;WAOxE,cAAc,CAAC,WAAW,EAAE,qBAAqB,GAAG,eAAe;gBAUrE,aAAa,EAAE,sBAAsB,EAAE,QAAQ,EAAE,WAAW;IAaxE,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,KAAK;IAcb,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,OAAO;IAmBf,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,wBAAwB;YAYlB,aAAa;IAqBpB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAK7C,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;CAW3E"}
@@ -30,6 +30,7 @@ class MobileRpcProtocol extends core_common_1.RpcProtocol {
30
30
  _partialFulfillment = undefined;
31
31
  _partialData = [];
32
32
  _port = 0;
33
+ _rpcToken = "";
33
34
  _transport;
34
35
  _ipc;
35
36
  static obtainInterop() { throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "Not implemented."); }
@@ -67,8 +68,10 @@ class MobileRpcProtocol extends core_common_1.RpcProtocol {
67
68
  throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "MobileRpcProtocol require 'port' parameter");
68
69
  }
69
70
  this._port = MobileRpcManager_1.MobileRpcConfiguration.args.port;
71
+ this.setRpcToken(window.__iTwinJsRpcToken ?? MobileRpcManager_1.MobileRpcConfiguration.args.rpcToken);
70
72
  this.connect(this._port, false);
71
- window._imodeljs_rpc_reconnect = (port) => {
73
+ window._imodeljs_rpc_reconnect = (port, rpcToken) => {
74
+ this.setRpcToken(rpcToken);
72
75
  this.socket.close();
73
76
  window.location.hash = window.location.hash.replace(`port=${this._port}`, `port=${port}`);
74
77
  this._port = port;
@@ -78,8 +81,13 @@ class MobileRpcProtocol extends core_common_1.RpcProtocol {
78
81
  this._transport = transport;
79
82
  core_common_1.RpcPushChannel.setup(transport);
80
83
  }
84
+ setRpcToken(rpcToken) {
85
+ if (typeof rpcToken !== "string" || !/^[0-9a-f]{64}$/.test(rpcToken))
86
+ throw new core_common_1.IModelError(core_bentley_1.BentleyStatus.ERROR, "MobileRpcProtocol requires a native RPC authentication token. Update the mobile native runtime and startup configuration.");
87
+ this._rpcToken = rpcToken;
88
+ }
81
89
  connect(port, reset) {
82
- const socket = new WebSocket(`ws://127.0.0.1:${port}`);
90
+ const socket = new WebSocket(`ws://127.0.0.1:${port}`, `itwin-rpc.${this._rpcToken}`);
83
91
  socket.binaryType = "arraybuffer";
84
92
  this.connectMessageHandler(socket);
85
93
  this.connectOpenHandler(socket, reset);
@@ -1 +1 @@
1
- {"version":3,"file":"MobileRpcProtocol.js","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module RpcInterface\r\n */\r\n\r\nimport { BentleyStatus, expectDefined } from \"@itwin/core-bentley\";\r\nimport {\r\n IModelError, IpcWebSocket, RpcEndpoint, RpcProtocol, RpcPushChannel, RpcPushConnection, RpcRequest, RpcRequestFulfillment, RpcSerializedValue,\r\n SerializedRpcRequest,\r\n} from \"@itwin/core-common\";\r\nimport { MobileEventLoop } from \"./MobileEventLoop\";\r\nimport { MobileIpcTransport } from \"./MobileIpc\";\r\nimport { MobilePushConnection, MobilePushTransport } from \"./MobilePush\";\r\nimport { MobileRpcConfiguration } from \"./MobileRpcManager\";\r\nimport { MobileRpcRequest } from \"./MobileRpcRequest\";\r\n\r\n/* eslint-disable @typescript-eslint/no-deprecated */\r\n\r\n/** @internal */\r\nexport type MobileRpcChunks = Array<string | Uint8Array>;\r\n\r\n/** @internal */\r\nexport interface MobileRpcGateway {\r\n handler: (payload: ArrayBuffer | string, connectionId: number) => void;\r\n sendString: (message: string, connectionId: number) => void;\r\n sendBinary: (message: Uint8Array, connectionId: number) => void;\r\n port: number;\r\n connectionId: number;\r\n}\r\n\r\n/** RPC interface protocol for an Mobile-based application.\r\n * @internal\r\n */\r\nexport class MobileRpcProtocol extends RpcProtocol {\r\n public socket: WebSocket = (undefined as any);\r\n public requests: Map<string, MobileRpcRequest> = new Map();\r\n private _pending: MobileRpcChunks[] = [];\r\n private _capacity: number = Number.MAX_SAFE_INTEGER;\r\n private _sendInterval: number | undefined = undefined;\r\n private _sendIntervalHandler = () => this.trySend();\r\n public readonly requestType = MobileRpcRequest;\r\n private _partialRequest: SerializedRpcRequest | undefined = undefined;\r\n private _partialFulfillment: RpcRequestFulfillment | undefined = undefined;\r\n private _partialData: Uint8Array[] = [];\r\n private _port: number = 0;\r\n private _transport?: MobilePushTransport;\r\n private _ipc: MobileIpcTransport;\r\n public static obtainInterop(): MobileRpcGateway { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); }\r\n\r\n public static async encodeRequest(request: MobileRpcRequest): Promise<MobileRpcChunks> {\r\n const serialized = await request.protocol.serialize(request);\r\n const data = serialized.parameters.data;\r\n serialized.parameters.data = data.map((v) => v.byteLength) as any[];\r\n return [JSON.stringify(serialized), ...data];\r\n }\r\n\r\n public static encodeResponse(fulfillment: RpcRequestFulfillment): MobileRpcChunks {\r\n const data = fulfillment.result.data;\r\n fulfillment.result.data = data.map((v) => v.byteLength) as any[];\r\n const raw = fulfillment.rawResult;\r\n fulfillment.rawResult = undefined;\r\n const encoded = [JSON.stringify(fulfillment), ...data];\r\n fulfillment.rawResult = raw;\r\n return encoded;\r\n }\r\n\r\n constructor(configuration: MobileRpcConfiguration, endPoint: RpcEndpoint) {\r\n super(configuration);\r\n\r\n if (endPoint === RpcEndpoint.Frontend) {\r\n this.initializeFrontend();\r\n } else if (endPoint === RpcEndpoint.Backend) {\r\n this.initializeBackend();\r\n }\r\n\r\n this._ipc = new MobileIpcTransport(this);\r\n IpcWebSocket.transport = this._ipc;\r\n }\r\n\r\n private initializeFrontend() {\r\n if (typeof (WebSocket) === \"undefined\") {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on frontend require websocket to work\");\r\n }\r\n if (!MobileRpcConfiguration.args.port) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol require 'port' parameter\");\r\n }\r\n\r\n this._port = MobileRpcConfiguration.args.port;\r\n this.connect(this._port, false);\r\n\r\n (window as any)._imodeljs_rpc_reconnect = (port: number) => {\r\n this.socket.close();\r\n window.location.hash = window.location.hash.replace(`port=${this._port}`, `port=${port}`);\r\n this._port = port;\r\n this.connect(port, true);\r\n };\r\n\r\n const transport = new MobilePushTransport(this);\r\n this._transport = transport;\r\n RpcPushChannel.setup(transport);\r\n }\r\n\r\n private connect(port: number, reset: boolean) {\r\n const socket = new WebSocket(`ws://127.0.0.1:${port}`);\r\n socket.binaryType = \"arraybuffer\";\r\n this.connectMessageHandler(socket);\r\n this.connectOpenHandler(socket, reset);\r\n this.connectErrorHandler(socket);\r\n this.socket = socket;\r\n }\r\n\r\n private connectMessageHandler(socket: WebSocket) {\r\n socket.addEventListener(\"message\", async (event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n this.handleMessageFromBackend(event.data);\r\n });\r\n }\r\n\r\n private connectOpenHandler(socket: WebSocket, reset: boolean) {\r\n socket.addEventListener(\"open\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n if (reset) {\r\n this.reset();\r\n\r\n const requests = new Map(RpcRequest.activeRequests);\r\n requests.forEach((req) => {\r\n req.cancel();\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n req.submit();\r\n });\r\n }\r\n\r\n this.scheduleSend();\r\n });\r\n }\r\n\r\n private connectErrorHandler(socket: WebSocket) {\r\n socket.addEventListener(\"error\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n throw new IModelError(BentleyStatus.ERROR, \"Socket error.\");\r\n });\r\n }\r\n\r\n private reset() {\r\n this.requests.clear();\r\n this._capacity = Number.MAX_SAFE_INTEGER;\r\n\r\n if (typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n\r\n this._partialRequest = undefined;\r\n this._partialFulfillment = undefined;\r\n this._partialData.length = 0;\r\n }\r\n\r\n private scheduleSend() {\r\n if (!this._pending.length) {\r\n return;\r\n }\r\n\r\n this.trySend();\r\n\r\n if (this._pending.length && typeof (this._sendInterval) === \"undefined\") {\r\n this._sendInterval = window.setInterval(this._sendIntervalHandler, 0);\r\n }\r\n }\r\n\r\n private trySend() {\r\n if (this.socket.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n while (this._capacity !== 0 && this._pending.length) {\r\n --this._capacity;\r\n const next = expectDefined(this._pending.shift(), \"Expected pending RPC chunk after queue length check.\");\r\n for (const chunk of next) {\r\n this.socket.send(chunk);\r\n }\r\n }\r\n\r\n if (!this._pending.length && typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n }\r\n\r\n private handleMessageFromBackend(data: string | ArrayBuffer) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromBackend(data);\r\n } else {\r\n this.handleBinaryFromBackend(data);\r\n }\r\n }\r\n\r\n private handleStringFromBackend(data: string) {\r\n if (this._partialFulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving response).\");\r\n }\r\n\r\n const response = JSON.parse(data) as RpcRequestFulfillment;\r\n this._partialFulfillment = response;\r\n\r\n if (!response.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private handleBinaryFromBackend(data: ArrayBuffer) {\r\n const fulfillment = this._partialFulfillment;\r\n if (!fulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === fulfillment.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private notifyResponse() {\r\n const response = this._partialFulfillment;\r\n if (!response) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response exists).\");\r\n }\r\n\r\n ++this._capacity;\r\n this.consumePartialData(response.result);\r\n this._partialFulfillment = undefined;\r\n\r\n if (this._transport && this._transport.consume(response)) {\r\n return;\r\n }\r\n\r\n if (this._ipc.consumeResponse(response)) {\r\n return;\r\n }\r\n\r\n const request = this.requests.get(response.id) as MobileRpcRequest;\r\n this.requests.delete(response.id);\r\n request.notifyResponse(response);\r\n }\r\n\r\n private consumePartialData(value: RpcSerializedValue) {\r\n for (let i = 0, l = value.data.length; i !== l; ++i) {\r\n value.data[i] = this._partialData[i];\r\n }\r\n\r\n this._partialData.length = 0;\r\n }\r\n\r\n private initializeBackend() {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n if (mobilegateway === undefined || mobilegateway == null) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on backend require native bridge to be setup\");\r\n }\r\n\r\n mobilegateway.handler = (payload, connectionId) => this.handleMessageFromFrontend(payload, connectionId);\r\n RpcPushConnection.for = (channel, client) => new MobilePushConnection(channel, client, this);\r\n RpcPushChannel.enabled = true;\r\n }\r\n\r\n private handleMessageFromFrontend(data: string | ArrayBuffer, connectionId: number) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromFrontend(data, connectionId);\r\n } else {\r\n this.handleBinaryFromFrontend(data, connectionId);\r\n }\r\n }\r\n\r\n private handleStringFromFrontend(data: string, connection: number) {\r\n if (this._partialRequest) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving request).\");\r\n }\r\n\r\n const request = JSON.parse(data) as SerializedRpcRequest;\r\n this._partialRequest = request;\r\n\r\n if (!request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private handleBinaryFromFrontend(data: ArrayBuffer, connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private async notifyRequest(connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request exists).\");\r\n }\r\n\r\n this.consumePartialData(request.parameters);\r\n this._partialRequest = undefined;\r\n\r\n if (this._ipc.consumeRequest(request)) {\r\n return;\r\n }\r\n\r\n MobileEventLoop.addTask();\r\n const fulfillment = await this.fulfill(request);\r\n MobileEventLoop.removeTask();\r\n\r\n const response = MobileRpcProtocol.encodeResponse(fulfillment);\r\n this.sendToFrontend(response, connection);\r\n }\r\n\r\n public sendToBackend(message: MobileRpcChunks): void {\r\n this._pending.push(message);\r\n this.scheduleSend();\r\n }\r\n\r\n public sendToFrontend(message: MobileRpcChunks, connection?: number): void {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n\r\n for (const chunk of message) {\r\n if (typeof (chunk) === \"string\") {\r\n mobilegateway.sendString(chunk, connection || mobilegateway.connectionId);\r\n } else {\r\n mobilegateway.sendBinary(chunk, connection || mobilegateway.connectionId);\r\n }\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"MobileRpcProtocol.js","sourceRoot":"","sources":["../../../src/common/MobileRpcProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module RpcInterface\r\n */\r\n\r\nimport { BentleyStatus, expectDefined } from \"@itwin/core-bentley\";\r\nimport {\r\n IModelError, IpcWebSocket, RpcEndpoint, RpcProtocol, RpcPushChannel, RpcPushConnection, RpcRequest, RpcRequestFulfillment, RpcSerializedValue,\r\n SerializedRpcRequest,\r\n} from \"@itwin/core-common\";\r\nimport { MobileEventLoop } from \"./MobileEventLoop\";\r\nimport { MobileIpcTransport } from \"./MobileIpc\";\r\nimport { MobilePushConnection, MobilePushTransport } from \"./MobilePush\";\r\nimport { MobileRpcConfiguration } from \"./MobileRpcManager\";\r\nimport { MobileRpcRequest } from \"./MobileRpcRequest\";\r\n\r\n/* eslint-disable @typescript-eslint/no-deprecated */\r\n\r\n/** @internal */\r\nexport type MobileRpcChunks = Array<string | Uint8Array>;\r\n\r\n/** @internal */\r\nexport interface MobileRpcGateway {\r\n handler: (payload: ArrayBuffer | string, connectionId: number) => void;\r\n sendString: (message: string, connectionId: number) => void;\r\n sendBinary: (message: Uint8Array, connectionId: number) => void;\r\n port: number;\r\n connectionId: number;\r\n}\r\n\r\n/** RPC interface protocol for an Mobile-based application.\r\n * @internal\r\n */\r\nexport class MobileRpcProtocol extends RpcProtocol {\r\n public socket: WebSocket = (undefined as any);\r\n public requests: Map<string, MobileRpcRequest> = new Map();\r\n private _pending: MobileRpcChunks[] = [];\r\n private _capacity: number = Number.MAX_SAFE_INTEGER;\r\n private _sendInterval: number | undefined = undefined;\r\n private _sendIntervalHandler = () => this.trySend();\r\n public readonly requestType = MobileRpcRequest;\r\n private _partialRequest: SerializedRpcRequest | undefined = undefined;\r\n private _partialFulfillment: RpcRequestFulfillment | undefined = undefined;\r\n private _partialData: Uint8Array[] = [];\r\n private _port: number = 0;\r\n private _rpcToken: string = \"\";\r\n private _transport?: MobilePushTransport;\r\n private _ipc: MobileIpcTransport;\r\n public static obtainInterop(): MobileRpcGateway { throw new IModelError(BentleyStatus.ERROR, \"Not implemented.\"); }\r\n\r\n public static async encodeRequest(request: MobileRpcRequest): Promise<MobileRpcChunks> {\r\n const serialized = await request.protocol.serialize(request);\r\n const data = serialized.parameters.data;\r\n serialized.parameters.data = data.map((v) => v.byteLength) as any[];\r\n return [JSON.stringify(serialized), ...data];\r\n }\r\n\r\n public static encodeResponse(fulfillment: RpcRequestFulfillment): MobileRpcChunks {\r\n const data = fulfillment.result.data;\r\n fulfillment.result.data = data.map((v) => v.byteLength) as any[];\r\n const raw = fulfillment.rawResult;\r\n fulfillment.rawResult = undefined;\r\n const encoded = [JSON.stringify(fulfillment), ...data];\r\n fulfillment.rawResult = raw;\r\n return encoded;\r\n }\r\n\r\n constructor(configuration: MobileRpcConfiguration, endPoint: RpcEndpoint) {\r\n super(configuration);\r\n\r\n if (endPoint === RpcEndpoint.Frontend) {\r\n this.initializeFrontend();\r\n } else if (endPoint === RpcEndpoint.Backend) {\r\n this.initializeBackend();\r\n }\r\n\r\n this._ipc = new MobileIpcTransport(this);\r\n IpcWebSocket.transport = this._ipc;\r\n }\r\n\r\n private initializeFrontend() {\r\n if (typeof (WebSocket) === \"undefined\") {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on frontend require websocket to work\");\r\n }\r\n if (!MobileRpcConfiguration.args.port) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol require 'port' parameter\");\r\n }\r\n\r\n this._port = MobileRpcConfiguration.args.port;\r\n this.setRpcToken((window as any).__iTwinJsRpcToken ?? MobileRpcConfiguration.args.rpcToken);\r\n this.connect(this._port, false);\r\n\r\n (window as any)._imodeljs_rpc_reconnect = (port: number, rpcToken: string) => {\r\n this.setRpcToken(rpcToken);\r\n this.socket.close();\r\n window.location.hash = window.location.hash.replace(`port=${this._port}`, `port=${port}`);\r\n this._port = port;\r\n this.connect(port, true);\r\n };\r\n\r\n const transport = new MobilePushTransport(this);\r\n this._transport = transport;\r\n RpcPushChannel.setup(transport);\r\n }\r\n\r\n private setRpcToken(rpcToken: unknown) {\r\n if (typeof rpcToken !== \"string\" || !/^[0-9a-f]{64}$/.test(rpcToken))\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol requires a native RPC authentication token. Update the mobile native runtime and startup configuration.\");\r\n\r\n this._rpcToken = rpcToken;\r\n }\r\n\r\n private connect(port: number, reset: boolean) {\r\n const socket = new WebSocket(`ws://127.0.0.1:${port}`, `itwin-rpc.${this._rpcToken}`);\r\n socket.binaryType = \"arraybuffer\";\r\n this.connectMessageHandler(socket);\r\n this.connectOpenHandler(socket, reset);\r\n this.connectErrorHandler(socket);\r\n this.socket = socket;\r\n }\r\n\r\n private connectMessageHandler(socket: WebSocket) {\r\n socket.addEventListener(\"message\", async (event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n this.handleMessageFromBackend(event.data);\r\n });\r\n }\r\n\r\n private connectOpenHandler(socket: WebSocket, reset: boolean) {\r\n socket.addEventListener(\"open\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n if (reset) {\r\n this.reset();\r\n\r\n const requests = new Map(RpcRequest.activeRequests);\r\n requests.forEach((req) => {\r\n req.cancel();\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n req.submit();\r\n });\r\n }\r\n\r\n this.scheduleSend();\r\n });\r\n }\r\n\r\n private connectErrorHandler(socket: WebSocket) {\r\n socket.addEventListener(\"error\", (_event) => {\r\n if (this.socket !== socket) {\r\n return;\r\n }\r\n\r\n throw new IModelError(BentleyStatus.ERROR, \"Socket error.\");\r\n });\r\n }\r\n\r\n private reset() {\r\n this.requests.clear();\r\n this._capacity = Number.MAX_SAFE_INTEGER;\r\n\r\n if (typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n\r\n this._partialRequest = undefined;\r\n this._partialFulfillment = undefined;\r\n this._partialData.length = 0;\r\n }\r\n\r\n private scheduleSend() {\r\n if (!this._pending.length) {\r\n return;\r\n }\r\n\r\n this.trySend();\r\n\r\n if (this._pending.length && typeof (this._sendInterval) === \"undefined\") {\r\n this._sendInterval = window.setInterval(this._sendIntervalHandler, 0);\r\n }\r\n }\r\n\r\n private trySend() {\r\n if (this.socket.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n while (this._capacity !== 0 && this._pending.length) {\r\n --this._capacity;\r\n const next = expectDefined(this._pending.shift(), \"Expected pending RPC chunk after queue length check.\");\r\n for (const chunk of next) {\r\n this.socket.send(chunk);\r\n }\r\n }\r\n\r\n if (!this._pending.length && typeof (this._sendInterval) !== \"undefined\") {\r\n window.clearInterval(this._sendInterval);\r\n this._sendInterval = undefined;\r\n }\r\n }\r\n\r\n private handleMessageFromBackend(data: string | ArrayBuffer) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromBackend(data);\r\n } else {\r\n this.handleBinaryFromBackend(data);\r\n }\r\n }\r\n\r\n private handleStringFromBackend(data: string) {\r\n if (this._partialFulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving response).\");\r\n }\r\n\r\n const response = JSON.parse(data) as RpcRequestFulfillment;\r\n this._partialFulfillment = response;\r\n\r\n if (!response.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private handleBinaryFromBackend(data: ArrayBuffer) {\r\n const fulfillment = this._partialFulfillment;\r\n if (!fulfillment) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === fulfillment.result.data.length) {\r\n this.notifyResponse();\r\n }\r\n }\r\n\r\n private notifyResponse() {\r\n const response = this._partialFulfillment;\r\n if (!response) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no response exists).\");\r\n }\r\n\r\n ++this._capacity;\r\n this.consumePartialData(response.result);\r\n this._partialFulfillment = undefined;\r\n\r\n if (this._transport && this._transport.consume(response)) {\r\n return;\r\n }\r\n\r\n if (this._ipc.consumeResponse(response)) {\r\n return;\r\n }\r\n\r\n const request = this.requests.get(response.id) as MobileRpcRequest;\r\n this.requests.delete(response.id);\r\n request.notifyResponse(response);\r\n }\r\n\r\n private consumePartialData(value: RpcSerializedValue) {\r\n for (let i = 0, l = value.data.length; i !== l; ++i) {\r\n value.data[i] = this._partialData[i];\r\n }\r\n\r\n this._partialData.length = 0;\r\n }\r\n\r\n private initializeBackend() {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n if (mobilegateway === undefined || mobilegateway == null) {\r\n throw new IModelError(BentleyStatus.ERROR, \"MobileRpcProtocol on backend require native bridge to be setup\");\r\n }\r\n\r\n mobilegateway.handler = (payload, connectionId) => this.handleMessageFromFrontend(payload, connectionId);\r\n RpcPushConnection.for = (channel, client) => new MobilePushConnection(channel, client, this);\r\n RpcPushChannel.enabled = true;\r\n }\r\n\r\n private handleMessageFromFrontend(data: string | ArrayBuffer, connectionId: number) {\r\n if (typeof (data) === \"string\") {\r\n this.handleStringFromFrontend(data, connectionId);\r\n } else {\r\n this.handleBinaryFromFrontend(data, connectionId);\r\n }\r\n }\r\n\r\n private handleStringFromFrontend(data: string, connection: number) {\r\n if (this._partialRequest) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (already receiving request).\");\r\n }\r\n\r\n const request = JSON.parse(data) as SerializedRpcRequest;\r\n this._partialRequest = request;\r\n\r\n if (!request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private handleBinaryFromFrontend(data: ArrayBuffer, connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request received).\");\r\n }\r\n\r\n this._partialData.push(new Uint8Array(data));\r\n if (this._partialData.length === request.parameters.data.length) {\r\n this.notifyRequest(connection); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n\r\n private async notifyRequest(connection: number) {\r\n const request = this._partialRequest;\r\n if (!request) {\r\n throw new IModelError(BentleyStatus.ERROR, \"Invalid state (no request exists).\");\r\n }\r\n\r\n this.consumePartialData(request.parameters);\r\n this._partialRequest = undefined;\r\n\r\n if (this._ipc.consumeRequest(request)) {\r\n return;\r\n }\r\n\r\n MobileEventLoop.addTask();\r\n const fulfillment = await this.fulfill(request);\r\n MobileEventLoop.removeTask();\r\n\r\n const response = MobileRpcProtocol.encodeResponse(fulfillment);\r\n this.sendToFrontend(response, connection);\r\n }\r\n\r\n public sendToBackend(message: MobileRpcChunks): void {\r\n this._pending.push(message);\r\n this.scheduleSend();\r\n }\r\n\r\n public sendToFrontend(message: MobileRpcChunks, connection?: number): void {\r\n const mobilegateway = MobileRpcProtocol.obtainInterop();\r\n\r\n for (const chunk of message) {\r\n if (typeof (chunk) === \"string\") {\r\n mobilegateway.sendString(chunk, connection || mobilegateway.connectionId);\r\n } else {\r\n mobilegateway.sendBinary(chunk, connection || mobilegateway.connectionId);\r\n }\r\n }\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/core-mobile",
3
- "version": "5.15.0-dev.5",
3
+ "version": "5.15.0-dev.7",
4
4
  "description": "iTwin.js MobileHost and MobileApp",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -22,10 +22,10 @@
22
22
  "url": "http://www.bentley.com"
23
23
  },
24
24
  "peerDependencies": {
25
- "@itwin/core-backend": "5.15.0-dev.5",
26
- "@itwin/core-bentley": "5.15.0-dev.5",
27
- "@itwin/core-common": "5.15.0-dev.5",
28
- "@itwin/core-frontend": "5.15.0-dev.5"
25
+ "@itwin/core-backend": "5.15.0-dev.7",
26
+ "@itwin/core-common": "5.15.0-dev.7",
27
+ "@itwin/core-bentley": "5.15.0-dev.7",
28
+ "@itwin/core-frontend": "5.15.0-dev.7"
29
29
  },
30
30
  "dependencies": {
31
31
  "lodash": "^4.18.0",
@@ -41,11 +41,11 @@
41
41
  "eslint": "^9.31.0",
42
42
  "rimraf": "^6.0.1",
43
43
  "typescript": "~5.6.2",
44
- "@itwin/build-tools": "5.15.0-dev.5",
45
- "@itwin/core-frontend": "5.15.0-dev.5",
46
- "@itwin/core-backend": "5.15.0-dev.5",
47
- "@itwin/core-common": "5.15.0-dev.5",
48
- "@itwin/core-bentley": "5.15.0-dev.5"
44
+ "@itwin/core-backend": "5.15.0-dev.7",
45
+ "@itwin/build-tools": "5.15.0-dev.7",
46
+ "@itwin/core-frontend": "5.15.0-dev.7",
47
+ "@itwin/core-common": "5.15.0-dev.7",
48
+ "@itwin/core-bentley": "5.15.0-dev.7"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "npm run -s build:cjs",