1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use crate::errors; 6 use crate::platform::monitor::{FidoDev, Monitor}; 7 use crate::statecallback::StateCallback; 8 use runloop::RunLoop; 9 10 pub struct Transaction { 11 // Handle to the thread loop. 12 thread: Option<RunLoop>, 13 } 14 15 impl Transaction { new<F, T>( timeout: u64, callback: StateCallback<crate::Result<T>>, new_device_cb: F, ) -> crate::Result<Self> where F: Fn(FidoDev, &dyn Fn() -> bool) + Sync + Send + 'static, T: 'static,16 pub fn new<F, T>( 17 timeout: u64, 18 callback: StateCallback<crate::Result<T>>, 19 new_device_cb: F, 20 ) -> crate::Result<Self> 21 where 22 F: Fn(FidoDev, &dyn Fn() -> bool) + Sync + Send + 'static, 23 T: 'static, 24 { 25 let thread = RunLoop::new_with_timeout( 26 move |alive| { 27 // Create a new device monitor. 28 let mut monitor = Monitor::new(new_device_cb); 29 30 // Start polling for new devices. 31 try_or!(monitor.run(alive), |_| callback 32 .call(Err(errors::AuthenticatorError::Platform))); 33 34 // Send an error, if the callback wasn't called already. 35 callback.call(Err(errors::AuthenticatorError::U2FToken( 36 errors::U2FTokenError::NotAllowed, 37 ))); 38 }, 39 timeout, 40 ) 41 .map_err(|_| errors::AuthenticatorError::Platform)?; 42 43 Ok(Self { 44 thread: Some(thread), 45 }) 46 } 47 cancel(&mut self)48 pub fn cancel(&mut self) { 49 // This must never be None. 50 self.thread.take().unwrap().cancel(); 51 } 52 } 53