[hardware wallet] sleeping -> pollling (#8018)

* Use polling, enable missing doc warnings & docs

* make try_connect_polling() a free function
This commit is contained in:
Niklas Adolfsson 2018-03-02 18:30:25 +01:00 committed by Robert Habermeier
parent fb17ae7751
commit 81b52c7336
3 changed files with 53 additions and 25 deletions

View File

@ -21,8 +21,7 @@ use std::cmp::min;
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::time::Duration; use std::time::{Duration, Instant};
use std::thread;
use ethereum_types::{H256, Address}; use ethereum_types::{H256, Address};
use ethkey::Signature; use ethkey::Signature;
@ -353,11 +352,24 @@ impl Manager {
Err(Error::InvalidDevice) Err(Error::InvalidDevice)
} }
} }
}
// Try to connect to the device using polling in at most the time specified by the `timeout`
fn try_connect_polling(ledger: Arc<Manager>, timeout: Duration) -> bool {
let start_time = Instant::now();
while start_time.elapsed() <= timeout {
if let Ok(_) = ledger.update_devices() {
return true
}
}
false
} }
/// Ledger event handler /// Ledger event handler
/// A seperate thread is handling incoming events /// A seperate thread is hanedling incoming events
///
/// Note, that this run to completion and race-conditions can't occur but this can
/// therefore starve other events for being process with a spinlock or similar
pub struct EventHandler { pub struct EventHandler {
ledger: Weak<Manager>, ledger: Weak<Manager>,
} }
@ -371,21 +383,19 @@ impl EventHandler {
impl libusb::Hotplug for EventHandler { impl libusb::Hotplug for EventHandler {
fn device_arrived(&mut self, device: libusb::Device) { fn device_arrived(&mut self, device: libusb::Device) {
if let (Some(ledger), Ok(_)) = (self.ledger.upgrade(), Manager::is_valid_ledger(&device)) {
debug!(target: "hw", "Ledger arrived"); debug!(target: "hw", "Ledger arrived");
// Wait for the device to boot up if let (Some(ledger), Ok(_)) = (self.ledger.upgrade(), Manager::is_valid_ledger(&device)) {
thread::sleep(Duration::from_millis(1000)); if try_connect_polling(ledger, Duration::from_millis(500)) != true {
if let Err(e) = ledger.update_devices() { debug!(target: "hw", "Ledger connect timeout");
debug!(target: "hw", "Ledger connect error: {:?}", e);
} }
} }
} }
fn device_left(&mut self, device: libusb::Device) { fn device_left(&mut self, device: libusb::Device) {
if let (Some(ledger), Ok(_)) = (self.ledger.upgrade(), Manager::is_valid_ledger(&device)) {
debug!(target: "hw", "Ledger left"); debug!(target: "hw", "Ledger left");
if let Err(e) = ledger.update_devices() { if let (Some(ledger), Ok(_)) = (self.ledger.upgrade(), Manager::is_valid_ledger(&device)) {
debug!(target: "hw", "Ledger disconnect error: {:?}", e); if try_connect_polling(ledger, Duration::from_millis(500)) != true {
debug!(target: "hw", "Ledger disconnect timeout");
} }
} }
} }

View File

@ -16,6 +16,8 @@
//! Hardware wallet management. //! Hardware wallet management.
#![warn(missing_docs)]
extern crate ethereum_types; extern crate ethereum_types;
extern crate ethkey; extern crate ethkey;
extern crate hidapi; extern crate hidapi;
@ -61,12 +63,19 @@ pub enum Error {
/// or less a duplicate of ethcore::transaction::Transaction, but we can't /// or less a duplicate of ethcore::transaction::Transaction, but we can't
/// import ethcore here as that would be a circular dependency. /// import ethcore here as that would be a circular dependency.
pub struct TransactionInfo { pub struct TransactionInfo {
/// Nonce
pub nonce: U256, pub nonce: U256,
/// Gas price
pub gas_price: U256, pub gas_price: U256,
/// Gas limit
pub gas_limit: U256, pub gas_limit: U256,
/// Receiver
pub to: Option<Address>, pub to: Option<Address>,
/// Value
pub value: U256, pub value: U256,
/// Data
pub data: Vec<u8>, pub data: Vec<u8>,
/// Chain ID
pub chain_id: Option<u64>, pub chain_id: Option<u64>,
} }

View File

@ -24,11 +24,9 @@ use super::{WalletInfo, TransactionInfo, KeyPath};
use std::cmp::{min, max}; use std::cmp::{min, max};
use std::fmt; use std::fmt;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::time::Duration; use std::time::{Duration, Instant};
use std::thread;
use ethereum_types::{U256, H256, Address}; use ethereum_types::{U256, H256, Address};
use ethkey::Signature; use ethkey::Signature;
use hidapi; use hidapi;
use libusb; use libusb;
@ -402,14 +400,28 @@ impl Manager {
} }
} }
// Try to connect to the device using polling in at most the time specified by the `timeout`
fn try_connect_polling(trezor: Arc<Manager>, duration: Duration) -> bool {
let start_time = Instant::now();
while start_time.elapsed() <= duration {
if let Ok(_) = trezor.update_devices() {
return true
}
}
false
}
/// Trezor event handler /// Trezor event handler
/// A separate thread is handeling incoming events /// A separate thread is handeling incoming events
///
/// Note, that this run to completion and race-conditions can't occur but this can
/// therefore starve other events for being process with a spinlock or similar
pub struct EventHandler { pub struct EventHandler {
trezor: Weak<Manager>, trezor: Weak<Manager>,
} }
impl EventHandler { impl EventHandler {
// Trezor event handler constructor /// Trezor event handler constructor
pub fn new(trezor: Weak<Manager>) -> Self { pub fn new(trezor: Weak<Manager>) -> Self {
Self { trezor: trezor } Self { trezor: trezor }
} }
@ -419,20 +431,17 @@ impl libusb::Hotplug for EventHandler {
fn device_arrived(&mut self, _device: libusb::Device) { fn device_arrived(&mut self, _device: libusb::Device) {
debug!(target: "hw", "Trezor V1 arrived"); debug!(target: "hw", "Trezor V1 arrived");
if let Some(trezor) = self.trezor.upgrade() { if let Some(trezor) = self.trezor.upgrade() {
// Wait for the device to boot up if try_connect_polling(trezor, Duration::from_millis(500)) != true {
thread::sleep(Duration::from_millis(1000)); debug!(target: "hw", "Ledger connect timeout");
if let Err(e) = trezor.update_devices() {
debug!(target: "hw", "Trezor V1 connect error: {:?}", e);
} }
} }
} }
fn device_left(&mut self, _device: libusb::Device) { fn device_left(&mut self, _device: libusb::Device) {
debug!(target: "hw", "Trezor V1 left"); debug!(target: "hw", "Trezor V1 left");
if let Some(trezor) = self.trezor.upgrade() { if let Some(trezor) = self.trezor.upgrade() {
if let Err(e) = trezor.update_devices() { if try_connect_polling(trezor, Duration::from_millis(500)) != true {
debug!(target: "hw", "Trezor V1 disconnect error: {:?}", e); debug!(target: "hw", "Ledger disconnect timeout");
} }
} }
} }