@onekeyfe/hd-transport 1.2.0-alpha.127 → 1.2.0-alpha.129

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.
@@ -26,6 +26,9 @@ const protocolV2Messages = parseConfigure({
26
26
  message: { type: 'string', id: 1 },
27
27
  },
28
28
  },
29
+ Cancel: {
30
+ fields: {},
31
+ },
29
32
  Success: {
30
33
  fields: {
31
34
  message: { type: 'string', id: 1 },
@@ -35,6 +38,7 @@ const protocolV2Messages = parseConfigure({
35
38
  values: {
36
39
  MessageType_Ping: 60206,
37
40
  MessageType_Success: 60207,
41
+ MessageType_Cancel: 60004,
38
42
  },
39
43
  },
40
44
  },
@@ -313,6 +317,58 @@ describe('ProtocolV2LinkManager', () => {
313
317
  ]);
314
318
  });
315
319
 
320
+ test('writes flow control while the active call is waiting for its response', async () => {
321
+ const sentSeqs = [];
322
+ let releaseRead;
323
+ let markReadStarted;
324
+ const readStarted = new Promise(resolve => {
325
+ markReadStarted = resolve;
326
+ });
327
+ const readBlocked = new Promise(resolve => {
328
+ releaseRead = resolve;
329
+ });
330
+ const success = ProtocolV2.encodeFrame(
331
+ schemas,
332
+ 'Success',
333
+ { message: 'ok' },
334
+ { router: 1, packetSrc: 0, seq: 1 }
335
+ );
336
+ let requestSeq = 0;
337
+ const adapter = {
338
+ router: 1,
339
+ generation: 1,
340
+ prepareCall: jest.fn(),
341
+ writeFrame: jest.fn(frame => {
342
+ [, , , , , , requestSeq] = frame;
343
+ sentSeqs.push(requestSeq);
344
+ return Promise.resolve();
345
+ }),
346
+ readFrame: jest.fn(async () => {
347
+ markReadStarted();
348
+ await readBlocked;
349
+ return rewriteSeq(success, 1);
350
+ }),
351
+ reset: jest.fn(),
352
+ };
353
+ const manager = new ProtocolV2LinkManager({
354
+ getSchemas: () => schemas,
355
+ classifyError: () => 'recoverable',
356
+ });
357
+ const createAdapter = jest.fn(() => adapter);
358
+
359
+ const activeCall = manager.call('device-a', createAdapter, 'Ping', { message: 'pending' });
360
+ await readStarted;
361
+ await expect(manager.sendFlowControl('device-a', createAdapter, 'Cancel', {})).resolves.toEqual(
362
+ { type: 'WriteCompleted', message: {} }
363
+ );
364
+
365
+ expect(sentSeqs).toEqual([1, 2]);
366
+ expect(adapter.prepareCall).toHaveBeenCalledTimes(1);
367
+ expect(adapter.readFrame).toHaveBeenCalledTimes(1);
368
+ releaseRead();
369
+ await activeCall;
370
+ });
371
+
316
372
  test('keeps a recoverable link after a call error', async () => {
317
373
  const sentSeqs = [];
318
374
  const { adapters, createAdapter } = createAdapterFactory(sentSeqs);
package/dist/index.d.ts CHANGED
@@ -6693,9 +6693,12 @@ declare class ProtocolV2Session {
6693
6693
  private readonly options;
6694
6694
  private readonly sequenceCursor;
6695
6695
  private pendingCall;
6696
+ private pendingWrite;
6696
6697
  private lastResponseSequence?;
6697
6698
  constructor(options: ProtocolV2SessionOptions);
6698
6699
  call(name: string, data: Record<string, unknown>, callOptions?: ProtocolV2CallOptions): Promise<MessageFromOneKey>;
6700
+ sendFlowControl(name: string, data: Record<string, unknown>): Promise<MessageFromOneKey>;
6701
+ private serializeWrite;
6699
6702
  private executeCall;
6700
6703
  }
6701
6704
  declare function probeProtocolV2({ call, timeoutMs, logger, logPrefix, onBeforeProbe, onProbeFailed, }: {
@@ -6735,6 +6738,7 @@ declare class ProtocolV2LinkManager<Key> {
6735
6738
  private readonly options;
6736
6739
  constructor(options: ProtocolV2LinkManagerOptions<Key>);
6737
6740
  call(key: Key, createAdapter: () => ProtocolV2LinkAdapter, name: string, data: Record<string, unknown>, options?: TransportCallOptions): Promise<MessageFromOneKey>;
6741
+ sendFlowControl(key: Key, createAdapter: () => ProtocolV2LinkAdapter, name: string, data: Record<string, unknown>): Promise<MessageFromOneKey>;
6738
6742
  invalidateLink(key: Key, reason: string): Promise<void>;
6739
6743
  invalidateAllLinks(reason: string): Promise<void>;
6740
6744
  dispose(reason: string): Promise<void>;
@@ -6765,6 +6769,7 @@ declare abstract class ProtocolV2UsbTransportBase<Key> {
6765
6769
  protected onProtocolV2UsbLinkInvalidated(_key: Key, _reason: string): Promise<void> | void;
6766
6770
  protected rotateProtocolV2UsbGeneration(key: Key, reason: string): Promise<number>;
6767
6771
  protected callProtocolV2Usb(key: Key, name: string, data: Record<string, unknown>, options?: TransportCallOptions): Promise<MessageFromOneKey>;
6772
+ protected sendProtocolV2UsbFlowControl(key: Key, name: string, data: Record<string, unknown>): Promise<MessageFromOneKey>;
6768
6773
  protected invalidateProtocolV2UsbLink(key: Key, reason: string): Promise<void>;
6769
6774
  protected invalidateAllProtocolV2UsbLinks(reason: string): Promise<void>;
6770
6775
  protected disposeProtocolV2UsbLinks(reason: string): Promise<void>;
package/dist/index.js CHANGED
@@ -1092,6 +1092,7 @@ class ProtocolV2Session {
1092
1092
  constructor(options) {
1093
1093
  var _a;
1094
1094
  this.pendingCall = Promise.resolve();
1095
+ this.pendingWrite = Promise.resolve();
1095
1096
  this.options = options;
1096
1097
  this.sequenceCursor = (_a = options.sequenceCursor) !== null && _a !== void 0 ? _a : new ProtocolV2SequenceCursor();
1097
1098
  }
@@ -1101,6 +1102,34 @@ class ProtocolV2Session {
1101
1102
  this.pendingCall = result.catch(() => undefined);
1102
1103
  return result;
1103
1104
  }
1105
+ sendFlowControl(name, data) {
1106
+ const { schemas, router, packetSrc = PROTOCOL_V2_PACKET_SRC_COMMAND, maxFrameBytes, writeFrame, generation = 0, } = this.options;
1107
+ const abortController = new AbortController();
1108
+ const context = {
1109
+ messageName: name,
1110
+ highThroughput: false,
1111
+ generation,
1112
+ signal: abortController.signal,
1113
+ };
1114
+ const protoSeq = this.sequenceCursor.next();
1115
+ const frame = ProtocolV2.encodeFrame(schemas, name, data, {
1116
+ packetSrc,
1117
+ router,
1118
+ seq: protoSeq,
1119
+ });
1120
+ if (maxFrameBytes !== undefined && frame.length > maxFrameBytes) {
1121
+ return Promise.reject(new Error(`Protocol V2 frame too large for transport: ${frame.length} > ${maxFrameBytes}`));
1122
+ }
1123
+ return this.serializeWrite(() => writeFrame(frame, context)).then(() => ({
1124
+ type: 'WriteCompleted',
1125
+ message: {},
1126
+ }));
1127
+ }
1128
+ serializeWrite(write) {
1129
+ const result = this.pendingWrite.then(write, write);
1130
+ this.pendingWrite = result.catch(() => undefined);
1131
+ return result;
1132
+ }
1104
1133
  executeCall(name, data, callOptions) {
1105
1134
  const { schemas, router, packetSrc = PROTOCOL_V2_PACKET_SRC_COMMAND, maxFrameBytes, prepareCall, writeFrame, readFrame, logger, logPrefix = 'ProtocolV2', createTimeoutError, generation = 0, } = this.options;
1106
1135
  const timeoutMs = callOptions.timeoutMs && callOptions.timeoutMs > 0
@@ -1124,7 +1153,7 @@ class ProtocolV2Session {
1124
1153
  throw new Error(`Protocol V2 frame too large for transport: ${frame.length} > ${maxFrameBytes}`);
1125
1154
  }
1126
1155
  const writeStartedAt = Date.now();
1127
- yield writeFrame(frame, baseCallContext);
1156
+ yield this.serializeWrite(() => writeFrame(frame, baseCallContext));
1128
1157
  try {
1129
1158
  (_a = callOptions.onWriteCompleted) === null || _a === void 0 ? void 0 : _a.call(callOptions, {
1130
1159
  elapsedMs: Math.max(Date.now() - writeStartedAt, 0),
@@ -1259,6 +1288,12 @@ class ProtocolV2LinkManager {
1259
1288
  .catch(() => undefined);
1260
1289
  return result;
1261
1290
  }
1291
+ sendFlowControl(key, createAdapter, name, data) {
1292
+ var _a;
1293
+ const generation = (_a = this.generations.get(key)) !== null && _a !== void 0 ? _a : 0;
1294
+ this.assertCallGeneration(key, generation);
1295
+ return this.getOrCreateLink(key, createAdapter).session.sendFlowControl(name, data);
1296
+ }
1262
1297
  invalidateLink(key, reason) {
1263
1298
  var _a;
1264
1299
  return __awaiter(this, void 0, void 0, function* () {
@@ -1419,6 +1454,9 @@ class ProtocolV2UsbTransportBase {
1419
1454
  callProtocolV2Usb(key, name, data, options) {
1420
1455
  return this.protocolV2UsbLinks.call(key, () => this.createProtocolV2UsbAdapter(key), name, data, options);
1421
1456
  }
1457
+ sendProtocolV2UsbFlowControl(key, name, data) {
1458
+ return this.protocolV2UsbLinks.sendFlowControl(key, () => this.createProtocolV2UsbAdapter(key), name, data);
1459
+ }
1422
1460
  invalidateProtocolV2UsbLink(key, reason) {
1423
1461
  return this.protocolV2UsbLinks.invalidateLink(key, reason);
1424
1462
  }
@@ -28,6 +28,7 @@ export declare class ProtocolV2LinkManager<Key> {
28
28
  private readonly options;
29
29
  constructor(options: ProtocolV2LinkManagerOptions<Key>);
30
30
  call(key: Key, createAdapter: () => ProtocolV2LinkAdapter, name: string, data: Record<string, unknown>, options?: TransportCallOptions): Promise<MessageFromOneKey>;
31
+ sendFlowControl(key: Key, createAdapter: () => ProtocolV2LinkAdapter, name: string, data: Record<string, unknown>): Promise<MessageFromOneKey>;
31
32
  invalidateLink(key: Key, reason: string): Promise<void>;
32
33
  invalidateAllLinks(reason: string): Promise<void>;
33
34
  dispose(reason: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"link-manager.d.ts","sourceRoot":"","sources":["../../../src/protocols/v2/link-manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAEpG,MAAM,MAAM,iCAAiC,GAAG,YAAY,GAAG,aAAa,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,SAAS,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5C,MAAM,CAAC,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;CACrE;AAED,MAAM,MAAM,4BAA4B,CAAC,GAAG,IAAI;IAC9C,UAAU,EAAE,MAAM,iBAAiB,CAAC;IACpC,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,iCAAiC,CAAC;IACrE,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACxE,CAAC;AAUF,qBAAa,qBAAqB,CAAC,GAAG;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IAExD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IAEtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAE/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IAEtD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0D;IAE9F,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiC;IAE/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;gBAEhD,OAAO,EAAE,4BAA4B,CAAC,GAAG,CAAC;IAItD,IAAI,CACF,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,MAAM,qBAAqB,EAC1C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAmBvB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BvD,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASjD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,OAAO,CAAC,eAAe;YA+CT,WAAW;IAkBzB,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,oBAAoB;CAW7B"}
1
+ {"version":3,"file":"link-manager.d.ts","sourceRoot":"","sources":["../../../src/protocols/v2/link-manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAEpG,MAAM,MAAM,iCAAiC,GAAG,YAAY,GAAG,aAAa,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,SAAS,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5C,MAAM,CAAC,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;CACrE;AAED,MAAM,MAAM,4BAA4B,CAAC,GAAG,IAAI;IAC9C,UAAU,EAAE,MAAM,iBAAiB,CAAC;IACpC,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,iCAAiC,CAAC;IACrE,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACxE,CAAC;AAUF,qBAAa,qBAAqB,CAAC,GAAG;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IAExD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IAEtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAE/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IAEtD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0D;IAE9F,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiC;IAE/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;gBAEhD,OAAO,EAAE,4BAA4B,CAAC,GAAG,CAAC;IAItD,IAAI,CACF,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,MAAM,qBAAqB,EAC1C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAmB7B,eAAe,CACb,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,MAAM,qBAAqB,EAC1C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,iBAAiB,CAAC;IAMvB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BvD,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASjD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,OAAO,CAAC,eAAe;YA+CT,WAAW;IAkBzB,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,oBAAoB;CAW7B"}
@@ -53,9 +53,12 @@ export declare class ProtocolV2Session {
53
53
  private readonly options;
54
54
  private readonly sequenceCursor;
55
55
  private pendingCall;
56
+ private pendingWrite;
56
57
  private lastResponseSequence?;
57
58
  constructor(options: ProtocolV2SessionOptions);
58
59
  call(name: string, data: Record<string, unknown>, callOptions?: ProtocolV2CallOptions): Promise<MessageFromOneKey>;
60
+ sendFlowControl(name: string, data: Record<string, unknown>): Promise<MessageFromOneKey>;
61
+ private serializeWrite;
59
62
  private executeCall;
60
63
  }
61
64
  export declare function probeProtocolV2({ call, timeoutMs, logger, logPrefix, onBeforeProbe, onProbeFailed, }: {
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/protocols/v2/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/protocols/v2/session.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAW7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE5E,cAAc,UAAU,CAAC;AAEzB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvE,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,SAAS,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACnE,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,KAAK,CAAC;IAChE,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC/D,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC5D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,CAAC;AAEpC,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAalD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIpD;AAwBD,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,WAE1D;AAoBD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,UAQ7C;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,kBAAkB,EAAE,MAAM,KAAK,EAC/B,SAAS,CAAC,EAAE,MAAM,IAAI,EACtB,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,CAAC,CAAC,CAqCZ;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAEnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA2B;IAI1D,OAAO,CAAC,WAAW,CAAuC;IAI1D,OAAO,CAAC,YAAY,CAAuC;IAE3D,OAAO,CAAC,oBAAoB,CAAC,CAAS;gBAE1B,OAAO,EAAE,wBAAwB;IAK7C,IAAI,CACF,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,WAAW,GAAE,qBAA0B,GACtC,OAAO,CAAC,iBAAiB,CAAC;IAS7B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAmCxF,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,WAAW;CAoKpB;AAED,wBAAsB,eAAe,CAAC,EACpC,IAAI,EACJ,SAAS,EACT,MAAM,EACN,SAAwB,EACxB,aAAa,EACb,aAAa,GACd,EAAE;IACD,IAAI,EAAE,CACJ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,qBAAqB,KAC5B,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC1D,oBAiCA"}
@@ -21,6 +21,7 @@ export declare abstract class ProtocolV2UsbTransportBase<Key> {
21
21
  protected onProtocolV2UsbLinkInvalidated(_key: Key, _reason: string): Promise<void> | void;
22
22
  protected rotateProtocolV2UsbGeneration(key: Key, reason: string): Promise<number>;
23
23
  protected callProtocolV2Usb(key: Key, name: string, data: Record<string, unknown>, options?: TransportCallOptions): Promise<MessageFromOneKey>;
24
+ protected sendProtocolV2UsbFlowControl(key: Key, name: string, data: Record<string, unknown>): Promise<MessageFromOneKey>;
24
25
  protected invalidateProtocolV2UsbLink(key: Key, reason: string): Promise<void>;
25
26
  protected invalidateAllProtocolV2UsbLinks(reason: string): Promise<void>;
26
27
  protected disposeProtocolV2UsbLinks(reason: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"usb-transport-base.d.ts","sourceRoot":"","sources":["../../../src/protocols/v2/usb-transport-base.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAEpG,MAAM,MAAM,iCAAiC,GAAG;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AASF,8BAAsB,0BAA0B,CAAC,GAAG;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAEhE,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA4C;IAEpF,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA0B;IAEnE,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA6C;IAExF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoC;IAEzE,SAAS,aAAa,OAAO,EAAE,iCAAiC;IAahE,SAAS,CAAC,QAAQ,CAAC,uBAAuB,IAAI,iBAAiB;IAE/D,SAAS,CAAC,QAAQ,CAAC,sBAAsB,IAAI,wBAAwB,CAAC,QAAQ,CAAC;IAE/E,SAAS,CAAC,QAAQ,CAAC,wBAAwB,CACzC,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAEhB,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CACxC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC;IAEtB,SAAS,CAAC,QAAQ,CAAC,4BAA4B,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAExF,SAAS,CAAC,QAAQ,CAAC,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK;IAE1F,SAAS,CAAC,8BAA8B,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;cAI1E,6BAA6B,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYxF,SAAS,CAAC,iBAAiB,CACzB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAU7B,SAAS,CAAC,2BAA2B,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E,SAAS,CAAC,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cAIxD,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxE,OAAO,CAAC,0BAA0B;IAsElC,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,+BAA+B;IAgBvC,OAAO,CAAC,0BAA0B;CAQnC"}
1
+ {"version":3,"file":"usb-transport-base.d.ts","sourceRoot":"","sources":["../../../src/protocols/v2/usb-transport-base.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAEpG,MAAM,MAAM,iCAAiC,GAAG;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AASF,8BAAsB,0BAA0B,CAAC,GAAG;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAEhE,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA4C;IAEpF,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA0B;IAEnE,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA6C;IAExF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoC;IAEzE,SAAS,aAAa,OAAO,EAAE,iCAAiC;IAahE,SAAS,CAAC,QAAQ,CAAC,uBAAuB,IAAI,iBAAiB;IAE/D,SAAS,CAAC,QAAQ,CAAC,sBAAsB,IAAI,wBAAwB,CAAC,QAAQ,CAAC;IAE/E,SAAS,CAAC,QAAQ,CAAC,wBAAwB,CACzC,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAEhB,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CACxC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,UAAU,CAAC;IAEtB,SAAS,CAAC,QAAQ,CAAC,4BAA4B,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAExF,SAAS,CAAC,QAAQ,CAAC,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK;IAE1F,SAAS,CAAC,8BAA8B,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;cAI1E,6BAA6B,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYxF,SAAS,CAAC,iBAAiB,CACzB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAU7B,SAAS,CAAC,4BAA4B,CACpC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,iBAAiB,CAAC;IAS7B,SAAS,CAAC,2BAA2B,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E,SAAS,CAAC,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cAIxD,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxE,OAAO,CAAC,0BAA0B;IAsElC,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,+BAA+B;IAgBvC,OAAO,CAAC,0BAA0B;CAQnC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport",
3
- "version": "1.2.0-alpha.127",
3
+ "version": "1.2.0-alpha.129",
4
4
  "description": "Transport layer abstractions and utilities for OneKey hardware SDK.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -28,5 +28,5 @@
28
28
  "long": "^4.0.0",
29
29
  "protobufjs": "^6.11.2"
30
30
  },
31
- "gitHead": "55a124eb1fb7bcdfa7890fa19947f2330d687d14"
31
+ "gitHead": "d996758fef2d61a868b1989efcce1f04c8ef5e22"
32
32
  }
@@ -78,6 +78,17 @@ export class ProtocolV2LinkManager<Key> {
78
78
  return result;
79
79
  }
80
80
 
81
+ sendFlowControl(
82
+ key: Key,
83
+ createAdapter: () => ProtocolV2LinkAdapter,
84
+ name: string,
85
+ data: Record<string, unknown>
86
+ ): Promise<MessageFromOneKey> {
87
+ const generation = this.generations.get(key) ?? 0;
88
+ this.assertCallGeneration(key, generation);
89
+ return this.getOrCreateLink(key, createAdapter).session.sendFlowControl(name, data);
90
+ }
91
+
81
92
  async invalidateLink(key: Key, reason: string): Promise<void> {
82
93
  const generation = (this.generations.get(key) ?? 0) + 1;
83
94
  this.generations.set(key, generation);
@@ -195,6 +195,10 @@ export class ProtocolV2Session {
195
195
  // in-flight calls on the same session would steal each other's responses.
196
196
  private pendingCall: Promise<unknown> = Promise.resolve();
197
197
 
198
+ // Flow-control messages may interrupt a call that is waiting for a device UI
199
+ // response, but their frames must never interleave with the active request write.
200
+ private pendingWrite: Promise<unknown> = Promise.resolve();
201
+
198
202
  private lastResponseSequence?: number;
199
203
 
200
204
  constructor(options: ProtocolV2SessionOptions) {
@@ -215,6 +219,47 @@ export class ProtocolV2Session {
215
219
  return result;
216
220
  }
217
221
 
222
+ sendFlowControl(name: string, data: Record<string, unknown>): Promise<MessageFromOneKey> {
223
+ const {
224
+ schemas,
225
+ router,
226
+ packetSrc = PROTOCOL_V2_PACKET_SRC_COMMAND,
227
+ maxFrameBytes,
228
+ writeFrame,
229
+ generation = 0,
230
+ } = this.options;
231
+ const abortController = new AbortController();
232
+ const context: ProtocolV2CallContext = {
233
+ messageName: name,
234
+ highThroughput: false,
235
+ generation,
236
+ signal: abortController.signal,
237
+ };
238
+ const protoSeq = this.sequenceCursor.next();
239
+ const frame = ProtocolV2.encodeFrame(schemas, name, data, {
240
+ packetSrc,
241
+ router,
242
+ seq: protoSeq,
243
+ });
244
+
245
+ if (maxFrameBytes !== undefined && frame.length > maxFrameBytes) {
246
+ return Promise.reject(
247
+ new Error(`Protocol V2 frame too large for transport: ${frame.length} > ${maxFrameBytes}`)
248
+ );
249
+ }
250
+
251
+ return this.serializeWrite(() => writeFrame(frame, context)).then(() => ({
252
+ type: 'WriteCompleted',
253
+ message: {},
254
+ }));
255
+ }
256
+
257
+ private serializeWrite<T>(write: () => Promise<T>): Promise<T> {
258
+ const result = this.pendingWrite.then(write, write);
259
+ this.pendingWrite = result.catch(() => undefined);
260
+ return result;
261
+ }
262
+
218
263
  private executeCall(
219
264
  name: string,
220
265
  data: Record<string, unknown>,
@@ -267,7 +312,7 @@ export class ProtocolV2Session {
267
312
  }
268
313
 
269
314
  const writeStartedAt = Date.now();
270
- await writeFrame(frame, baseCallContext);
315
+ await this.serializeWrite(() => writeFrame(frame, baseCallContext));
271
316
  try {
272
317
  callOptions.onWriteCompleted?.({
273
318
  elapsedMs: Math.max(Date.now() - writeStartedAt, 0),
@@ -93,6 +93,19 @@ export abstract class ProtocolV2UsbTransportBase<Key> {
93
93
  );
94
94
  }
95
95
 
96
+ protected sendProtocolV2UsbFlowControl(
97
+ key: Key,
98
+ name: string,
99
+ data: Record<string, unknown>
100
+ ): Promise<MessageFromOneKey> {
101
+ return this.protocolV2UsbLinks.sendFlowControl(
102
+ key,
103
+ () => this.createProtocolV2UsbAdapter(key),
104
+ name,
105
+ data
106
+ );
107
+ }
108
+
96
109
  protected invalidateProtocolV2UsbLink(key: Key, reason: string): Promise<void> {
97
110
  return this.protocolV2UsbLinks.invalidateLink(key, reason);
98
111
  }