Browse Source

Merge pull request #1340 from MortalKastor/usb-detect

Use new USB device detection from ledgerjs
master
Thibaut 7 years ago
committed by GitHub
parent
commit
70498f4922
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .circleci/config.yml
  2. 1
      README.md
  3. 2
      package.json
  4. 56
      src/commands/listenDevices.js
  5. 3
      src/config/constants.js
  6. 6
      src/helpers/deviceAccess.js
  7. 25
      yarn.lock

1
.circleci/config.yml

@ -9,6 +9,7 @@ jobs:
build:
<<: *defaults
steps:
- run: sudo apt-get install -y libudev-dev
- checkout
- restore_cache:
keys:

1
README.md

@ -95,7 +95,6 @@ SYNC_ALL_INTERVAL=60000
CHECK_APP_INTERVAL_WHEN_INVALID=600
CHECK_APP_INTERVAL_WHEN_VALID=1200
CHECK_UPDATE_DELAY=5000
DEVICE_DISCONNECT_DEBOUNCE=500
```
### Launch storybook

2
package.json

@ -36,7 +36,7 @@
"@ledgerhq/hw-app-eth": "^4.14.0",
"@ledgerhq/hw-app-xrp": "^4.13.0",
"@ledgerhq/hw-transport": "^4.13.0",
"@ledgerhq/hw-transport-node-hid": "^4.13.0",
"@ledgerhq/hw-transport-node-hid": "4.22.0",
"@ledgerhq/ledger-core": "2.0.0-rc.5",
"@ledgerhq/live-common": "3.0.0-beta.2",
"animated": "^0.2.2",

56
src/commands/listenDevices.js

@ -4,57 +4,17 @@ import logger from 'logger'
import { createCommand } from 'helpers/ipc'
import { Observable } from 'rxjs'
import CommNodeHid from '@ledgerhq/hw-transport-node-hid'
import { DEVICE_DISCONNECT_DEBOUNCE, LISTEN_DEVICES_POLLING_INTERVAL } from 'config/constants'
import { LISTEN_DEVICES_DEBOUNCE } from 'config/constants'
CommNodeHid.setListenDevicesPollingInterval(LISTEN_DEVICES_POLLING_INTERVAL)
CommNodeHid.setListenDevicesDebounce(LISTEN_DEVICES_DEBOUNCE)
const cmd = createCommand('listenDevices', () =>
Observable.create(o => {
const pendingRemovePerPath = {}
const sub = CommNodeHid.listen({
next: e => {
// debounce the add/remove in case we see quick `remove,add` events on same path.
switch (e.type) {
case 'add': {
const pendingRemove = pendingRemovePerPath[e.descriptor]
if (pendingRemove) {
logger.warn(`Skipping remove/add usb event for ${e.descriptor}`)
// there where a recent "remove" event, we don't emit add because we didn't emit "remove" yet.
clearTimeout(pendingRemove)
delete pendingRemovePerPath[e.descriptor]
} else {
// if there were no recent "remove", we just emit the "add"
o.next(e)
}
break
}
case 'remove': {
// we we always debounce the "remove" event. emit it a bit later in case a "add" of same descriptor happen soon.
if (pendingRemovePerPath[e.descriptor]) {
clearTimeout(pendingRemovePerPath[e.descriptor])
}
pendingRemovePerPath[e.descriptor] = setTimeout(() => {
delete pendingRemovePerPath[e.descriptor]
o.next(e)
}, DEVICE_DISCONNECT_DEBOUNCE)
break
}
default:
o.next(e)
}
},
complete: () => {
o.complete()
},
error: err => {
o.error(err)
},
})
return () => {
Object.keys(pendingRemovePerPath).map(k => clearTimeout(pendingRemovePerPath[k]))
sub.unsubscribe()
}
CommNodeHid.setListenDevicesDebug((msg, ...args) =>
logger.debug(msg, {
type: 'listenDevices',
args,
}),
)
const cmd = createCommand('listenDevices', () => Observable.create(CommNodeHid.listen))
export default cmd

3
src/config/constants.js

@ -32,13 +32,12 @@ export const MIN_HEIGHT = intFromEnv('LEDGER_MIN_HEIGHT', 700)
export const CHECK_APP_INTERVAL_WHEN_INVALID = 600
export const CHECK_APP_INTERVAL_WHEN_VALID = 1200
export const CHECK_UPDATE_DELAY = 5000
export const DEVICE_DISCONNECT_DEBOUNCE = intFromEnv('LEDGER_DEVICE_DISCONNECT_DEBOUNCE', 1000)
export const DEVICE_INFOS_TIMEOUT = intFromEnv('DEVICE_INFOS_TIMEOUT', 5 * 1000)
export const GENUINE_CACHE_DELAY = intFromEnv('GENUINE_CACHE_DELAY', 1000)
export const GENUINE_TIMEOUT = intFromEnv('GENUINE_TIMEOUT', 120 * 1000)
export const GET_CALLS_RETRY = intFromEnv('GET_CALLS_RETRY', 2)
export const GET_CALLS_TIMEOUT = intFromEnv('GET_CALLS_TIMEOUT', 30 * 1000)
export const LISTEN_DEVICES_POLLING_INTERVAL = intFromEnv('LISTEN_DEVICES_POLLING_INTERVAL', 1000)
export const LISTEN_DEVICES_DEBOUNCE = intFromEnv('LISTEN_DEVICES_DEBOUNCE', 200)
// NB: technically speaking OUTDATED_CONSIDERED_DELAY should be set to ZERO.
// but we'll only do that when we're sure the sync is performant and all is working smoothly
export const OUTDATED_CONSIDERED_DELAY = intFromEnv('OUTDATED_CONSIDERED_DELAY', 2 * 60 * 1000)

6
src/helpers/deviceAccess.js

@ -4,6 +4,7 @@ import throttle from 'lodash/throttle'
import type Transport from '@ledgerhq/hw-transport'
import TransportNodeHid from '@ledgerhq/hw-transport-node-hid'
import { DisconnectedDevice, CantOpenDevice } from 'config/errors'
import { retry } from './promise'
// all open to device must use openDevice so we can prevent race conditions
// and guarantee we do one device access at a time. It also will handle the .close()
@ -39,7 +40,10 @@ export const withDevice: WithDevice = devicePath => job => {
busy = true
refreshBusyUIState()
try {
const t = await TransportNodeHid.open(devicePath).catch(mapError)
// $FlowFixMe not sure what's wrong
const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 2 }).catch(
mapError,
)
t.setDebugMode(logger.apdu)
try {
const res = await job(t).catch(mapError)

25
yarn.lock

@ -1501,12 +1501,14 @@
"@ledgerhq/hw-transport" "^4.21.0"
bip32-path "0.4.2"
"@ledgerhq/hw-transport-node-hid@^4.13.0":
version "4.21.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.21.0.tgz#fffdae5314bb969473a763e59fe1dfdde3fd7aed"
"@ledgerhq/hw-transport-node-hid@4.22.0-beta.a1987cb3":
version "4.22.0-beta.a1987cb3"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.22.0-beta.a1987cb3.tgz#89dd5b30239ed81e41fd3a1a37a48d5e9cd8529b"
dependencies:
"@ledgerhq/hw-transport" "^4.21.0"
"@ledgerhq/hw-transport" "^4.22.0-beta.a1987cb3"
lodash "^4.17.10"
node-hid "^0.7.2"
usb "^1.3.2"
"@ledgerhq/hw-transport-node-hid@^4.7.6":
version "4.16.0"
@ -1527,6 +1529,12 @@
dependencies:
events "^2.0.0"
"@ledgerhq/hw-transport@^4.22.0-beta.a1987cb3":
version "4.22.0-beta.ae6f5c51"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.22.0-beta.ae6f5c51.tgz#a9f17ff8fa792a19e01d82d72f14ff7f7a211209"
dependencies:
events "^2.0.0"
"@ledgerhq/ledger-core@2.0.0-rc.5":
version "2.0.0-rc.5"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.5.tgz#ec42f6c3cc265fc5ca82e01d27df38357642d3ed"
@ -9905,7 +9913,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
nan@^2.10.0, nan@^2.2.1, nan@^2.6.2, nan@^2.9.2:
nan@^2.10.0, nan@^2.2.1, nan@^2.6.2, nan@^2.8.0, nan@^2.9.2:
version "2.10.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
@ -14352,6 +14360,13 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"
usb@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/usb/-/usb-1.3.2.tgz#4563a32323856e26c97dae374b34c66c3d83b5f4"
dependencies:
nan "^2.8.0"
node-pre-gyp "^0.10.0"
use@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544"

Loading…
Cancel
Save