@onekeyfe/hd-transport-react-native 1.2.3-alpha.9 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bleEncryption.d.ts +17 -0
- package/dist/bleEncryption.d.ts.map +1 -0
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +229 -17
- package/package.json +6 -6
- package/src/__tests__/androidEncryption.test.ts +482 -0
- package/src/__tests__/enumerate.test.ts +8 -1
- package/src/__tests__/protocolV2Link.test.ts +8 -1
- package/src/bleEncryption.ts +267 -0
- package/src/index.ts +71 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const HCI_PIN_OR_KEY_MISSING = 6;
|
|
2
|
+
export type AndroidLinkEncryption = 'encrypted' | 'already-encrypted' | 're-paired' | 'unresolved';
|
|
3
|
+
export declare const isBleEncryptionTrackingSupported: () => boolean;
|
|
4
|
+
export declare const startBleEncryptionTracking: () => boolean;
|
|
5
|
+
export declare const stopBleEncryptionTracking: () => void;
|
|
6
|
+
export declare const markBleLinkEncrypted: (deviceId: string) => void;
|
|
7
|
+
export type WaitForAndroidLinkEncryptionOptions = {
|
|
8
|
+
deviceId: string;
|
|
9
|
+
linkStartedAt: number;
|
|
10
|
+
resultTimeoutMs: number;
|
|
11
|
+
repairTimeoutMs: number;
|
|
12
|
+
keyMissingGraceMs: number;
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
onRepairStarted?: () => void;
|
|
15
|
+
};
|
|
16
|
+
export declare const waitForAndroidLinkEncryption: ({ deviceId, linkStartedAt, resultTimeoutMs, repairTimeoutMs, keyMissingGraceMs, signal, onRepairStarted, }: WaitForAndroidLinkEncryptionOptions) => Promise<AndroidLinkEncryption>;
|
|
17
|
+
//# sourceMappingURL=bleEncryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bleEncryption.d.ts","sourceRoot":"","sources":["../src/bleEncryption.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,sBAAsB,IAAO,CAAC;AAE3C,MAAM,MAAM,qBAAqB,GAE7B,WAAW,GAEX,mBAAmB,GAEnB,WAAW,GAEX,YAAY,CAAC;AA0CjB,eAAO,MAAM,gCAAgC,eAA2C,CAAC;AAGzF,eAAO,MAAM,0BAA0B,QAAO,OAwB7C,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAMrC,CAAC;AAMF,eAAO,MAAM,oBAAoB,aAAc,MAAM,SAGpD,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,QAAQ,EAAE,MAAM,CAAC;IAEjB,aAAa,EAAE,MAAM,CAAC;IAEtB,eAAe,EAAE,MAAM,CAAC;IAExB,eAAe,EAAE,MAAM,CAAC;IAExB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAOF,eAAO,MAAM,4BAA4B,+GAQtC,mCAAmC,KAAG,QAAQ,qBAAqB,CAuHrE,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -70,6 +70,16 @@ declare const BLE_NATIVE_TEARDOWN_TIMEOUT_MS = 3000;
|
|
|
70
70
|
declare const ANDROID_KEY_MISSING_LINK_WINDOW_MS = 10000;
|
|
71
71
|
/** The broadcast and the GATT disconnect it explains travel separately; either can land first. */
|
|
72
72
|
declare const ANDROID_KEY_MISSING_GRACE_MS = 500;
|
|
73
|
+
/**
|
|
74
|
+
* Android reports a bonded link's first encryption result within about half a second of
|
|
75
|
+
* connecting. Past this, the result is treated as unknown and the link is used as before.
|
|
76
|
+
*/
|
|
77
|
+
declare const ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS = 1500;
|
|
78
|
+
/**
|
|
79
|
+
* A system re-pairing needs the user to accept a pairing request and confirm the code on the
|
|
80
|
+
* device. The Bluetooth stack gives up after 30s and then reports key missing.
|
|
81
|
+
*/
|
|
82
|
+
declare const ANDROID_SYSTEM_REPAIR_TIMEOUT_MS = 35000;
|
|
73
83
|
/** Consecutive wedged writes on one device before the BLE manager itself is recreated. */
|
|
74
84
|
declare const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
75
85
|
type ProtocolV2BleTuning = {
|
|
@@ -216,6 +226,14 @@ declare class ReactNativeBleTransport {
|
|
|
216
226
|
* connect is re-read as an invalid bond when that signal belongs to the same attempt.
|
|
217
227
|
*/
|
|
218
228
|
private resolveAndroidBondInvalid;
|
|
229
|
+
/**
|
|
230
|
+
* Android 16+ encrypts a bonded link on its own right after connecting. Subscribing to
|
|
231
|
+
* notifications before that finishes gets the CCCD write rejected, and the framework's retry
|
|
232
|
+
* encrypts again with the same stale key; firmware that allows one failure per link then drops
|
|
233
|
+
* it before the system can re-pair. Holding GATT until the result lets a lost bond be re-paired
|
|
234
|
+
* in place. Without the platform signal this resolves immediately.
|
|
235
|
+
*/
|
|
236
|
+
private waitForAndroidLinkSecurity;
|
|
219
237
|
private callProtocolV1;
|
|
220
238
|
stop(): Promise<void>;
|
|
221
239
|
disconnect(session: string): Promise<void>;
|
|
@@ -295,4 +313,4 @@ declare class ReactNativeBleTransport {
|
|
|
295
313
|
getProtocolType(path: string): ProtocolType | undefined;
|
|
296
314
|
}
|
|
297
315
|
|
|
298
|
-
export { ANDROID_KEY_MISSING_GRACE_MS, ANDROID_KEY_MISSING_LINK_WINDOW_MS, ANDROID_LINK_DROP_QUIET_MS, ANDROID_MTU_EXCHANGE_TIMEOUT_MS, BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD, BLE_CONNECT_TIMEOUT_MS, BLE_GATT_SETUP_TIMEOUT_MS, BLE_NATIVE_TEARDOWN_TIMEOUT_MS, BLE_SETUP_WEDGED_MESSAGE, BLE_WRITE_PACKET_TIMEOUT_MS, BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD, IOneKeyDevice, PROTOCOL_REPROBE_FALLBACK_ATTEMPTS, ProtocolV2BleTuning, configureProtocolV2BleTuning, ReactNativeBleTransport as default, getFirmwareUploadWriteRetryType, getProtocolV2BleTuning, resetProtocolV2BleTuning };
|
|
316
|
+
export { ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS, ANDROID_KEY_MISSING_GRACE_MS, ANDROID_KEY_MISSING_LINK_WINDOW_MS, ANDROID_LINK_DROP_QUIET_MS, ANDROID_MTU_EXCHANGE_TIMEOUT_MS, ANDROID_SYSTEM_REPAIR_TIMEOUT_MS, BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD, BLE_CONNECT_TIMEOUT_MS, BLE_GATT_SETUP_TIMEOUT_MS, BLE_NATIVE_TEARDOWN_TIMEOUT_MS, BLE_SETUP_WEDGED_MESSAGE, BLE_WRITE_PACKET_TIMEOUT_MS, BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD, IOneKeyDevice, PROTOCOL_REPROBE_FALLBACK_ATTEMPTS, ProtocolV2BleTuning, configureProtocolV2BleTuning, ReactNativeBleTransport as default, getFirmwareUploadWriteRetryType, getProtocolV2BleTuning, resetProtocolV2BleTuning };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAGL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -47,10 +47,10 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
const lastKeyMissingAt = new Map();
|
|
50
|
-
const listeners = new Set();
|
|
51
|
-
let unsubscribeNative;
|
|
52
|
-
const normalizeDeviceId = (deviceId) => deviceId.toLowerCase();
|
|
53
|
-
const getCapableBleUtils = () => {
|
|
50
|
+
const listeners$1 = new Set();
|
|
51
|
+
let unsubscribeNative$1;
|
|
52
|
+
const normalizeDeviceId$1 = (deviceId) => deviceId.toLowerCase();
|
|
53
|
+
const getCapableBleUtils$1 = () => {
|
|
54
54
|
if (reactNative.Platform.OS !== 'android')
|
|
55
55
|
return undefined;
|
|
56
56
|
const bleUtils = BleUtils__default["default"];
|
|
@@ -60,41 +60,41 @@ const getCapableBleUtils = () => {
|
|
|
60
60
|
}
|
|
61
61
|
return bleUtils.supportsDeviceKeyMissing() ? bleUtils : undefined;
|
|
62
62
|
};
|
|
63
|
-
const isBleKeyMissingSupported = () => getCapableBleUtils() !== undefined;
|
|
63
|
+
const isBleKeyMissingSupported = () => getCapableBleUtils$1() !== undefined;
|
|
64
64
|
const startBleKeyMissingTracking = () => {
|
|
65
|
-
if (unsubscribeNative)
|
|
65
|
+
if (unsubscribeNative$1)
|
|
66
66
|
return true;
|
|
67
|
-
const bleUtils = getCapableBleUtils();
|
|
67
|
+
const bleUtils = getCapableBleUtils$1();
|
|
68
68
|
if (!(bleUtils === null || bleUtils === void 0 ? void 0 : bleUtils.onDeviceKeyMissing))
|
|
69
69
|
return false;
|
|
70
|
-
unsubscribeNative = bleUtils.onDeviceKeyMissing(event => {
|
|
70
|
+
unsubscribeNative$1 = bleUtils.onDeviceKeyMissing(event => {
|
|
71
71
|
if (typeof (event === null || event === void 0 ? void 0 : event.id) !== 'string')
|
|
72
72
|
return;
|
|
73
|
-
const deviceId = normalizeDeviceId(event.id);
|
|
73
|
+
const deviceId = normalizeDeviceId$1(event.id);
|
|
74
74
|
lastKeyMissingAt.set(deviceId, Date.now());
|
|
75
|
-
listeners.forEach(listener => listener(deviceId));
|
|
75
|
+
listeners$1.forEach(listener => listener(deviceId));
|
|
76
76
|
});
|
|
77
77
|
return true;
|
|
78
78
|
};
|
|
79
79
|
const stopBleKeyMissingTracking = () => {
|
|
80
|
-
unsubscribeNative === null || unsubscribeNative === void 0 ? void 0 : unsubscribeNative();
|
|
81
|
-
unsubscribeNative = undefined;
|
|
80
|
+
unsubscribeNative$1 === null || unsubscribeNative$1 === void 0 ? void 0 : unsubscribeNative$1();
|
|
81
|
+
unsubscribeNative$1 = undefined;
|
|
82
82
|
lastKeyMissingAt.clear();
|
|
83
|
-
listeners.clear();
|
|
83
|
+
listeners$1.clear();
|
|
84
84
|
};
|
|
85
85
|
const hasBleKeyMissingSince = (deviceId, sinceMs) => {
|
|
86
|
-
const at = lastKeyMissingAt.get(normalizeDeviceId(deviceId));
|
|
86
|
+
const at = lastKeyMissingAt.get(normalizeDeviceId$1(deviceId));
|
|
87
87
|
return at !== undefined && at >= sinceMs;
|
|
88
88
|
};
|
|
89
89
|
const onBleKeyMissing = (deviceId, callback) => {
|
|
90
|
-
const target = normalizeDeviceId(deviceId);
|
|
90
|
+
const target = normalizeDeviceId$1(deviceId);
|
|
91
91
|
const listener = id => {
|
|
92
92
|
if (id === target)
|
|
93
93
|
callback();
|
|
94
94
|
};
|
|
95
|
-
listeners.add(listener);
|
|
95
|
+
listeners$1.add(listener);
|
|
96
96
|
return () => {
|
|
97
|
-
listeners.delete(listener);
|
|
97
|
+
listeners$1.delete(listener);
|
|
98
98
|
};
|
|
99
99
|
};
|
|
100
100
|
const waitForBleKeyMissing = (deviceId, sinceMs, timeoutMs) => {
|
|
@@ -328,6 +328,172 @@ const subscribeBleOn = (bleManager, ms = 1000) => new Promise((resolve, reject)
|
|
|
328
328
|
}, ms);
|
|
329
329
|
});
|
|
330
330
|
|
|
331
|
+
const HCI_PIN_OR_KEY_MISSING = 0x06;
|
|
332
|
+
const lastEncryption = new Map();
|
|
333
|
+
const lastAclDisconnectAt = new Map();
|
|
334
|
+
const listeners = new Set();
|
|
335
|
+
let unsubscribeNative;
|
|
336
|
+
const normalizeDeviceId = (deviceId) => deviceId.toLowerCase();
|
|
337
|
+
const isEncrypted = (record) => record.status === 0 && record.enabled;
|
|
338
|
+
const getCapableBleUtils = () => {
|
|
339
|
+
if (reactNative.Platform.OS !== 'android')
|
|
340
|
+
return undefined;
|
|
341
|
+
const bleUtils = BleUtils__default["default"];
|
|
342
|
+
if (typeof bleUtils.supportsDeviceEncryptionChange !== 'function' ||
|
|
343
|
+
typeof bleUtils.onDeviceEncryptionChange !== 'function' ||
|
|
344
|
+
typeof bleUtils.onDeviceAclDisconnected !== 'function') {
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
return bleUtils.supportsDeviceEncryptionChange() ? bleUtils : undefined;
|
|
348
|
+
};
|
|
349
|
+
const notify = (deviceId) => {
|
|
350
|
+
listeners.forEach(listener => listener(deviceId));
|
|
351
|
+
};
|
|
352
|
+
const startBleEncryptionTracking = () => {
|
|
353
|
+
if (unsubscribeNative)
|
|
354
|
+
return true;
|
|
355
|
+
const bleUtils = getCapableBleUtils();
|
|
356
|
+
if (!(bleUtils === null || bleUtils === void 0 ? void 0 : bleUtils.onDeviceEncryptionChange) || !bleUtils.onDeviceAclDisconnected)
|
|
357
|
+
return false;
|
|
358
|
+
unsubscribeNative = [
|
|
359
|
+
bleUtils.onDeviceEncryptionChange(event => {
|
|
360
|
+
if (typeof (event === null || event === void 0 ? void 0 : event.id) !== 'string')
|
|
361
|
+
return;
|
|
362
|
+
const deviceId = normalizeDeviceId(event.id);
|
|
363
|
+
lastEncryption.set(deviceId, {
|
|
364
|
+
at: Date.now(),
|
|
365
|
+
status: Number(event.status),
|
|
366
|
+
enabled: event.enabled === true,
|
|
367
|
+
});
|
|
368
|
+
notify(deviceId);
|
|
369
|
+
}),
|
|
370
|
+
bleUtils.onDeviceAclDisconnected(event => {
|
|
371
|
+
if (typeof (event === null || event === void 0 ? void 0 : event.id) !== 'string')
|
|
372
|
+
return;
|
|
373
|
+
const deviceId = normalizeDeviceId(event.id);
|
|
374
|
+
lastAclDisconnectAt.set(deviceId, Date.now());
|
|
375
|
+
notify(deviceId);
|
|
376
|
+
}),
|
|
377
|
+
];
|
|
378
|
+
return true;
|
|
379
|
+
};
|
|
380
|
+
const stopBleEncryptionTracking = () => {
|
|
381
|
+
unsubscribeNative === null || unsubscribeNative === void 0 ? void 0 : unsubscribeNative.forEach(unsubscribe => unsubscribe());
|
|
382
|
+
unsubscribeNative = undefined;
|
|
383
|
+
lastEncryption.clear();
|
|
384
|
+
lastAclDisconnectAt.clear();
|
|
385
|
+
listeners.clear();
|
|
386
|
+
};
|
|
387
|
+
const markBleLinkEncrypted = (deviceId) => {
|
|
388
|
+
if (!unsubscribeNative)
|
|
389
|
+
return;
|
|
390
|
+
lastEncryption.set(normalizeDeviceId(deviceId), { at: Date.now(), status: 0, enabled: true });
|
|
391
|
+
};
|
|
392
|
+
const waitForAndroidLinkEncryption = ({ deviceId, linkStartedAt, resultTimeoutMs, repairTimeoutMs, keyMissingGraceMs, signal, onRepairStarted, }) => {
|
|
393
|
+
if (!startBleEncryptionTracking())
|
|
394
|
+
return Promise.resolve('unresolved');
|
|
395
|
+
startBleKeyMissingTracking();
|
|
396
|
+
const target = normalizeDeviceId(deviceId);
|
|
397
|
+
const previous = lastEncryption.get(target);
|
|
398
|
+
const previousDropAt = lastAclDisconnectAt.get(target);
|
|
399
|
+
if (previous &&
|
|
400
|
+
previous.at < linkStartedAt &&
|
|
401
|
+
isEncrypted(previous) &&
|
|
402
|
+
(previousDropAt === undefined || previousDropAt < previous.at)) {
|
|
403
|
+
return Promise.resolve('already-encrypted');
|
|
404
|
+
}
|
|
405
|
+
return new Promise((resolve, reject) => {
|
|
406
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
407
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected));
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
let repairStartedAt;
|
|
411
|
+
let droppedDuringRepair = false;
|
|
412
|
+
let timer;
|
|
413
|
+
let settled = false;
|
|
414
|
+
const cleanup = () => {
|
|
415
|
+
settled = true;
|
|
416
|
+
if (timer)
|
|
417
|
+
clearTimeout(timer);
|
|
418
|
+
listeners.delete(onLinkEvent);
|
|
419
|
+
cleanupKeyMissing();
|
|
420
|
+
signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
|
|
421
|
+
};
|
|
422
|
+
const finish = (result) => {
|
|
423
|
+
cleanup();
|
|
424
|
+
resolve(result);
|
|
425
|
+
};
|
|
426
|
+
const fail = (error) => {
|
|
427
|
+
cleanup();
|
|
428
|
+
reject(error);
|
|
429
|
+
};
|
|
430
|
+
const arm = (ms, onExpire) => {
|
|
431
|
+
if (timer)
|
|
432
|
+
clearTimeout(timer);
|
|
433
|
+
timer = setTimeout(onExpire, ms);
|
|
434
|
+
};
|
|
435
|
+
const bondInvalid = () => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleBondInvalid, undefined, {
|
|
436
|
+
phase: 'connect',
|
|
437
|
+
reason: 'key_missing',
|
|
438
|
+
});
|
|
439
|
+
const evaluate = () => {
|
|
440
|
+
if (settled)
|
|
441
|
+
return;
|
|
442
|
+
const record = lastEncryption.get(target);
|
|
443
|
+
const dropAt = lastAclDisconnectAt.get(target);
|
|
444
|
+
if (repairStartedAt === undefined) {
|
|
445
|
+
if (hasBleKeyMissingSince(target, linkStartedAt)) {
|
|
446
|
+
fail(bondInvalid());
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (dropAt !== undefined && dropAt >= linkStartedAt) {
|
|
450
|
+
finish('unresolved');
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (!record || record.at < linkStartedAt)
|
|
454
|
+
return;
|
|
455
|
+
if (isEncrypted(record)) {
|
|
456
|
+
finish('encrypted');
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
if (record.status !== HCI_PIN_OR_KEY_MISSING) {
|
|
460
|
+
finish('unresolved');
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
repairStartedAt = record.at;
|
|
464
|
+
onRepairStarted === null || onRepairStarted === void 0 ? void 0 : onRepairStarted();
|
|
465
|
+
arm(repairTimeoutMs, () => fail(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'Bluetooth pairing timed out', {
|
|
466
|
+
phase: 'bond',
|
|
467
|
+
reason: 'timeout',
|
|
468
|
+
})));
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (hasBleKeyMissingSince(target, repairStartedAt)) {
|
|
472
|
+
fail(bondInvalid());
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
if (record && record.at > repairStartedAt && isEncrypted(record)) {
|
|
476
|
+
finish('re-paired');
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
if (!droppedDuringRepair && dropAt !== undefined && dropAt >= repairStartedAt) {
|
|
480
|
+
droppedDuringRepair = true;
|
|
481
|
+
arm(keyMissingGraceMs, () => fail(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected)));
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
const onLinkEvent = id => {
|
|
485
|
+
if (id === target)
|
|
486
|
+
evaluate();
|
|
487
|
+
};
|
|
488
|
+
const onAbort = () => fail(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected));
|
|
489
|
+
listeners.add(onLinkEvent);
|
|
490
|
+
const cleanupKeyMissing = onBleKeyMissing(target, evaluate);
|
|
491
|
+
signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
|
|
492
|
+
arm(resultTimeoutMs, () => finish('unresolved'));
|
|
493
|
+
evaluate();
|
|
494
|
+
});
|
|
495
|
+
};
|
|
496
|
+
|
|
331
497
|
const BLE_PLX_DEVICE_DISCONNECTED = 201;
|
|
332
498
|
const IOS_PERIPHERAL_DISCONNECTED = 7;
|
|
333
499
|
const nativeErrorText$1 = (error) => [error.reason, error.message]
|
|
@@ -485,6 +651,8 @@ const shouldRethrowProtocolProbeError = (error) => {
|
|
|
485
651
|
};
|
|
486
652
|
const ANDROID_KEY_MISSING_LINK_WINDOW_MS = 10000;
|
|
487
653
|
const ANDROID_KEY_MISSING_GRACE_MS = 500;
|
|
654
|
+
const ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS = 1500;
|
|
655
|
+
const ANDROID_SYSTEM_REPAIR_TIMEOUT_MS = 35000;
|
|
488
656
|
const isAndroidLinkLossError = (error) => {
|
|
489
657
|
const code = error === null || error === void 0 ? void 0 : error.errorCode;
|
|
490
658
|
return (isNativeBleDisconnectError(error) ||
|
|
@@ -738,6 +906,10 @@ class ReactNativeBleTransport {
|
|
|
738
906
|
init(logger, emitter) {
|
|
739
907
|
setBleLogger(logger);
|
|
740
908
|
this.emitter = emitter;
|
|
909
|
+
if (reactNative.Platform.OS === 'android') {
|
|
910
|
+
startBleKeyMissingTracking();
|
|
911
|
+
startBleEncryptionTracking();
|
|
912
|
+
}
|
|
741
913
|
}
|
|
742
914
|
configure(signedData) {
|
|
743
915
|
const messages = parseConfigure(signedData);
|
|
@@ -1186,6 +1358,7 @@ class ReactNativeBleTransport {
|
|
|
1186
1358
|
}
|
|
1187
1359
|
let device = null;
|
|
1188
1360
|
const isAndroid = reactNative.Platform.OS === 'android';
|
|
1361
|
+
let androidBondedBeforeConnect = false;
|
|
1189
1362
|
const refreshAndroidGattCache = isAndroid && (!!skipProtocolProbe || this.androidGattCacheRefreshes.has(uuid));
|
|
1190
1363
|
let nativeConnectOptions = connectOptions;
|
|
1191
1364
|
if (isAndroid) {
|
|
@@ -1214,9 +1387,11 @@ class ReactNativeBleTransport {
|
|
|
1214
1387
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1215
1388
|
if (reactNative.Platform.OS === 'android') {
|
|
1216
1389
|
startBleKeyMissingTracking();
|
|
1390
|
+
startBleEncryptionTracking();
|
|
1217
1391
|
this.androidLinkStartedAt.delete(uuid);
|
|
1218
1392
|
try {
|
|
1219
1393
|
const bondState = yield pairDevice(uuid);
|
|
1394
|
+
androidBondedBeforeConnect = !bondState.bonding && bondState.bonded;
|
|
1220
1395
|
if (bondState.bonding) {
|
|
1221
1396
|
yield onDeviceBondState(uuid, this.bondAbortController.signal, {
|
|
1222
1397
|
systemInitiated: bondState.initiated === false,
|
|
@@ -1390,7 +1565,13 @@ class ReactNativeBleTransport {
|
|
|
1390
1565
|
if (shouldMapProtocolV2StaleBond) {
|
|
1391
1566
|
this.acquiringProtocolV2.add(uuid);
|
|
1392
1567
|
}
|
|
1568
|
+
let linkEncryption;
|
|
1393
1569
|
try {
|
|
1570
|
+
if (androidBondedBeforeConnect && !skipProtocolProbe) {
|
|
1571
|
+
linkEncryption = yield this.waitForAndroidLinkSecurity(uuid);
|
|
1572
|
+
if (this.stopped)
|
|
1573
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1574
|
+
}
|
|
1394
1575
|
yield this.installTransportForAcquire(uuid, acquiredDevice, {
|
|
1395
1576
|
writeCharacteristic,
|
|
1396
1577
|
notifyCharacteristic,
|
|
@@ -1429,6 +1610,9 @@ class ReactNativeBleTransport {
|
|
|
1429
1610
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
1430
1611
|
}
|
|
1431
1612
|
this.attachDisconnectSubscription(currentTransport, currentTransport.device, uuid);
|
|
1613
|
+
if (linkEncryption === 'unresolved') {
|
|
1614
|
+
markBleLinkEncrypted(uuid);
|
|
1615
|
+
}
|
|
1432
1616
|
return { uuid, protocolType };
|
|
1433
1617
|
}
|
|
1434
1618
|
catch (error) {
|
|
@@ -1665,6 +1849,31 @@ class ReactNativeBleTransport {
|
|
|
1665
1849
|
});
|
|
1666
1850
|
});
|
|
1667
1851
|
}
|
|
1852
|
+
waitForAndroidLinkSecurity(uuid) {
|
|
1853
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1854
|
+
const linkStartedAt = this.androidLinkStartedAt.get(uuid);
|
|
1855
|
+
if (linkStartedAt === undefined)
|
|
1856
|
+
return 'unresolved';
|
|
1857
|
+
const waitStartedAt = Date.now();
|
|
1858
|
+
const result = yield waitForAndroidLinkEncryption({
|
|
1859
|
+
deviceId: uuid,
|
|
1860
|
+
linkStartedAt,
|
|
1861
|
+
resultTimeoutMs: ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS,
|
|
1862
|
+
repairTimeoutMs: ANDROID_SYSTEM_REPAIR_TIMEOUT_MS,
|
|
1863
|
+
keyMissingGraceMs: ANDROID_KEY_MISSING_GRACE_MS,
|
|
1864
|
+
signal: this.bondAbortController.signal,
|
|
1865
|
+
onRepairStarted: () => {
|
|
1866
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android bond lost, waiting for system re-pairing:', uuid);
|
|
1867
|
+
},
|
|
1868
|
+
});
|
|
1869
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android link encryption', {
|
|
1870
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1871
|
+
result,
|
|
1872
|
+
waitedMs: Date.now() - waitStartedAt,
|
|
1873
|
+
});
|
|
1874
|
+
return result;
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1668
1877
|
callProtocolV1(uuid, name, data, options) {
|
|
1669
1878
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1670
1879
|
if (!this._messages) {
|
|
@@ -1880,6 +2089,7 @@ class ReactNativeBleTransport {
|
|
|
1880
2089
|
this.androidHighPriorityDevices.clear();
|
|
1881
2090
|
this.androidLinkStartedAt.clear();
|
|
1882
2091
|
stopBleKeyMissingTracking();
|
|
2092
|
+
stopBleEncryptionTracking();
|
|
1883
2093
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1884
2094
|
(_a = this.runPromise) === null || _a === void 0 ? void 0 : _a.reject(error);
|
|
1885
2095
|
this.runPromise = null;
|
|
@@ -2913,10 +3123,12 @@ class ReactNativeBleTransport {
|
|
|
2913
3123
|
}
|
|
2914
3124
|
}
|
|
2915
3125
|
|
|
3126
|
+
exports.ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS = ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS;
|
|
2916
3127
|
exports.ANDROID_KEY_MISSING_GRACE_MS = ANDROID_KEY_MISSING_GRACE_MS;
|
|
2917
3128
|
exports.ANDROID_KEY_MISSING_LINK_WINDOW_MS = ANDROID_KEY_MISSING_LINK_WINDOW_MS;
|
|
2918
3129
|
exports.ANDROID_LINK_DROP_QUIET_MS = ANDROID_LINK_DROP_QUIET_MS;
|
|
2919
3130
|
exports.ANDROID_MTU_EXCHANGE_TIMEOUT_MS = ANDROID_MTU_EXCHANGE_TIMEOUT_MS;
|
|
3131
|
+
exports.ANDROID_SYSTEM_REPAIR_TIMEOUT_MS = ANDROID_SYSTEM_REPAIR_TIMEOUT_MS;
|
|
2920
3132
|
exports.BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2921
3133
|
exports.BLE_CONNECT_TIMEOUT_MS = BLE_CONNECT_TIMEOUT_MS;
|
|
2922
3134
|
exports.BLE_GATT_SETUP_TIMEOUT_MS = BLE_GATT_SETUP_TIMEOUT_MS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-react-native",
|
|
3
|
-
"version": "1.2.3
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"lint:fix": "eslint . --fix"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@onekeyfe/hd-core": "1.2.3
|
|
24
|
-
"@onekeyfe/hd-shared": "1.2.3
|
|
25
|
-
"@onekeyfe/hd-transport": "1.2.3
|
|
26
|
-
"@onekeyfe/react-native-ble-utils": "0.1.
|
|
23
|
+
"@onekeyfe/hd-core": "1.2.3",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.3",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.3",
|
|
26
|
+
"@onekeyfe/react-native-ble-utils": "0.1.9",
|
|
27
27
|
"react-native-ble-plx": "3.5.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "de8e0beb9d993464fbcac6231d7efe501d789c7d"
|
|
30
30
|
}
|