diff --git a/src/lib.rs b/src/lib.rs index 9d9ad00..88012a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,10 +4,11 @@ mod ccid; mod ctaphid; use std::{ - cell::RefCell, marker::PhantomData, - rc::Rc, - sync::atomic::{AtomicBool, Ordering}, + sync::{ + atomic::{AtomicBool, Ordering}, + mpsc::{self, Receiver, Sender}, + }, thread, time::{Duration, Instant}, }; @@ -15,6 +16,7 @@ use std::{ use trussed::{ backend::{BackendId, CoreOnly, Dispatch}, client, + service::Service, virt::{self, Platform, StoreProvider}, ClientImplementation, }; @@ -30,7 +32,7 @@ pub fn set_waiting(waiting: bool) { IS_WAITING.store(waiting, Ordering::Relaxed) } -pub type Client = ClientImplementation, D>; +pub type Client = ClientImplementation; pub type InitPlatform = Box)>; @@ -51,7 +53,7 @@ impl Options { pub trait Apps<'interrupt, C: trussed::Client, D: Dispatch> { type Data; - fn new>(builder: &B, data: Self::Data) -> Self; + fn new>(builder: &mut B, data: Self::Data) -> Self; #[cfg(feature = "ctaphid")] fn with_ctaphid_apps( @@ -67,7 +69,7 @@ pub trait Apps<'interrupt, C: trussed::Client, D: Dispatch> { } pub trait ClientBuilder { - fn build(&self, id: &str, backends: &'static [BackendId]) -> C; + fn build(&mut self, id: &str, backends: &'static [BackendId]) -> C; } pub struct Runner { @@ -78,9 +80,7 @@ pub struct Runner { _marker: PhantomData, } -impl<'interrupt, S: StoreProvider, D: Dispatch, A: Apps<'interrupt, Client, D>> - Runner -{ +impl<'interrupt, S: StoreProvider, D: Dispatch, A: Apps<'interrupt, Client, D>> Runner { pub fn builder(store: S, options: Options) -> Builder { Builder::new(store, options) } @@ -106,11 +106,12 @@ impl<'interrupt, S: StoreProvider, D: Dispatch, A: Apps<'interrupt, Client let (mut ccid, mut apdu_dispatch) = ccid::setup(&bus_allocator, &contact, &contactless); let mut usb_device = build_device(&bus_allocator, &self.options); - let service = Service::new(platform, self.dispatch); - let mut apps = A::new(&service, data); + let mut trussed = Trussed::new(platform, self.dispatch); + let mut apps = A::new(&mut trussed, data); log::info!("Ready for work"); thread::scope(|s| { + // usb poll + keepalive task s.spawn(move || { let _epoch = Instant::now(); #[cfg(feature = "ctaphid")] @@ -134,6 +135,10 @@ impl<'interrupt, S: StoreProvider, D: Dispatch, A: Apps<'interrupt, Client } }); + // trussed task + s.spawn(move || trussed.process()); + + // apps task loop { thread::sleep(Duration::from_millis(5)); #[cfg(feature = "ctaphid")] @@ -184,7 +189,7 @@ impl Builder { } impl Builder { - pub fn build<'interrupt, A: Apps<'interrupt, Client, D>>(self) -> Runner { + pub fn build<'interrupt, A: Apps<'interrupt, Client, D>>(self) -> Runner { Runner { store: self.store, options: self.options, @@ -195,35 +200,48 @@ impl Builder { } } -pub struct Service(Rc, D>>>); +struct Trussed { + service: Service, D>, + syscall: Syscall, + receiver: Receiver<()>, +} -impl Service { +impl Trussed { fn new(platform: Platform, dispatch: D) -> Self { - let service = trussed::Service::with_dispatch(platform, dispatch); - Self(Rc::new(RefCell::new(service))) + let service = Service::with_dispatch(platform, dispatch); + let (sender, receiver) = mpsc::channel(); + let syscall = Syscall(sender); + Self { + service, + syscall, + receiver, + } + } + + fn process(&mut self) { + for _ in self.receiver.iter() { + self.service.process() + } } } -impl ClientBuilder, D> for Service { - fn build(&self, id: &str, backends: &'static [BackendId]) -> Client { +impl ClientBuilder, D> for Trussed { + fn build(&mut self, id: &str, backends: &'static [BackendId]) -> Client { client::ClientBuilder::new(id) .backends(backends) - .prepare(&mut *self.0.borrow_mut()) + .prepare(&mut self.service) .expect("failed to create client") - .build(self.clone()) + .build(self.syscall.clone()) } } -impl Clone for Service { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} +#[derive(Clone)] +pub struct Syscall(Sender<()>); -impl trussed::client::Syscall for Service { +impl trussed::client::Syscall for Syscall { fn syscall(&mut self) { log::debug!("syscall"); - self.0.borrow_mut().process(); + self.0.send(()).ok(); } }