@@ -10,15 +10,18 @@ use std::{
1010} ;
1111
1212use async_trait:: async_trait;
13- use futures_lite:: { FutureExt , Stream , StreamExt } ;
13+ use futures_lite:: { stream , FutureExt , Stream , StreamExt } ;
1414use libwebauthn:: {
1515 self ,
1616 ops:: webauthn:: { GetAssertionResponse , MakeCredentialResponse } ,
1717} ;
1818use nfc:: { NfcEvent , NfcHandler , NfcState , NfcStateInternal } ;
1919use tokio:: sync:: oneshot;
2020
21- use credentialsd_common:: model:: { Device , Error as CredentialServiceError , RequestId , Transport } ;
21+ use credentialsd_common:: {
22+ model:: { Device , Error as CredentialServiceError , RequestId , Transport } ,
23+ server:: BackgroundEvent ,
24+ } ;
2225
2326use crate :: {
2427 credential_service:: { hybrid:: HybridEvent , usb:: UsbEvent } ,
@@ -59,11 +62,9 @@ pub trait ManageDevice {
5962 ) -> Result < RequestId , CredentialServiceError > ;
6063 async fn cancel_request ( & self , request_id : RequestId ) ;
6164 async fn get_available_public_key_devices ( & self ) -> Result < Vec < Device > , ( ) > ;
62- async fn get_hybrid_credential (
65+ async fn start_discovery (
6366 & self ,
64- ) -> Pin < Box < dyn Stream < Item = HybridState > + Send + ' static > > ;
65- async fn get_nfc_credential ( & self ) -> Pin < Box < dyn Stream < Item = NfcState > + Send + ' static > > ;
66- async fn get_usb_credential ( & self ) -> Pin < Box < dyn Stream < Item = UsbState > + Send + ' static > > ;
67+ ) -> Pin < Box < dyn Stream < Item = DeviceStateUpdate > + Send + ' static > > ;
6768}
6869
6970#[ derive( Debug ) ]
@@ -90,6 +91,54 @@ impl<H: HybridHandler + Debug, N: NfcHandler + Debug, U: UsbHandler + Debug>
9091 }
9192}
9293
94+ impl < H : HybridHandler + Send , N : NfcHandler + Send , U : UsbHandler + Send >
95+ CredentialService < H , N , U >
96+ {
97+ async fn get_hybrid_credential (
98+ & self ,
99+ ) -> Pin < Box < dyn Stream < Item = HybridState > + Send + ' static > > {
100+ let guard = self . ctx . lock ( ) . unwrap ( ) ;
101+ if let Some ( RequestContext { ref request, .. } ) = * guard {
102+ let stream = self . hybrid_handler . lock ( ) . unwrap ( ) . start ( request) ;
103+ let ctx = self . ctx . clone ( ) ;
104+ Box :: pin ( HybridStateStream { inner : stream, ctx } )
105+ } else {
106+ tracing:: error!(
107+ "Attempted to start hybrid credential flow, but no request context was found."
108+ ) ;
109+ todo ! ( "Handle error when context is not set up." )
110+ }
111+ }
112+
113+ async fn get_usb_credential ( & self ) -> Pin < Box < dyn Stream < Item = UsbState > + Send + ' static > > {
114+ let guard = self . ctx . lock ( ) . unwrap ( ) ;
115+ if let Some ( RequestContext { ref request, .. } ) = * guard {
116+ let stream = self . usb_handler . lock ( ) . unwrap ( ) . start ( request) ;
117+ let ctx = self . ctx . clone ( ) ;
118+ Box :: pin ( UsbStateStream { inner : stream, ctx } )
119+ } else {
120+ tracing:: error!(
121+ "Attempted to start usb credential flow, but no request context was found."
122+ ) ;
123+ todo ! ( "Handle error when context is not set up." )
124+ }
125+ }
126+
127+ async fn get_nfc_credential ( & self ) -> Pin < Box < dyn Stream < Item = NfcState > + Send + ' static > > {
128+ let guard = self . ctx . lock ( ) . unwrap ( ) ;
129+ if let Some ( RequestContext { ref request, .. } ) = * guard {
130+ let stream = self . nfc_handler . lock ( ) . unwrap ( ) . start ( request) ;
131+ let ctx = self . ctx . clone ( ) ;
132+ Box :: pin ( NfcStateStream { inner : stream, ctx } )
133+ } else {
134+ tracing:: error!(
135+ "Attempted to start nfc credential flow, but no request context was found."
136+ ) ;
137+ todo ! ( "Handle error when context is not set up." )
138+ }
139+ }
140+ }
141+
93142#[ async_trait]
94143impl < H : HybridHandler + Send , N : NfcHandler + Send , U : UsbHandler + Send > ManageDevice
95144 for CredentialService < H , N , U >
@@ -158,48 +207,27 @@ impl<H: HybridHandler + Send, N: NfcHandler + Send, U: UsbHandler + Send> Manage
158207 Ok ( devices)
159208 }
160209
161- async fn get_hybrid_credential (
210+ async fn start_discovery (
162211 & self ,
163- ) -> Pin < Box < dyn Stream < Item = HybridState > + Send + ' static > > {
164- let guard = self . ctx . lock ( ) . unwrap ( ) ;
165- if let Some ( RequestContext { ref request, .. } ) = * guard {
166- let stream = self . hybrid_handler . lock ( ) . unwrap ( ) . start ( request) ;
167- let ctx = self . ctx . clone ( ) ;
168- Box :: pin ( HybridStateStream { inner : stream, ctx } )
169- } else {
170- tracing:: error!(
171- "Attempted to start hybrid credential flow, but no request context was found."
172- ) ;
173- todo ! ( "Handle error when context is not set up." )
174- }
175- }
176-
177- async fn get_usb_credential ( & self ) -> Pin < Box < dyn Stream < Item = UsbState > + Send + ' static > > {
178- let guard = self . ctx . lock ( ) . unwrap ( ) ;
179- if let Some ( RequestContext { ref request, .. } ) = * guard {
180- let stream = self . usb_handler . lock ( ) . unwrap ( ) . start ( request) ;
181- let ctx = self . ctx . clone ( ) ;
182- Box :: pin ( UsbStateStream { inner : stream, ctx } )
183- } else {
184- tracing:: error!(
185- "Attempted to start usb credential flow, but no request context was found."
186- ) ;
187- todo ! ( "Handle error when context is not set up." )
188- }
189- }
190-
191- async fn get_nfc_credential ( & self ) -> Pin < Box < dyn Stream < Item = NfcState > + Send + ' static > > {
192- let guard = self . ctx . lock ( ) . unwrap ( ) ;
193- if let Some ( RequestContext { ref request, .. } ) = * guard {
194- let stream = self . nfc_handler . lock ( ) . unwrap ( ) . start ( request) ;
195- let ctx = self . ctx . clone ( ) ;
196- Box :: pin ( NfcStateStream { inner : stream, ctx } )
197- } else {
198- tracing:: error!(
199- "Attempted to start nfc credential flow, but no request context was found."
200- ) ;
201- todo ! ( "Handle error when context is not set up." )
202- }
212+ ) -> Pin < Box < dyn Stream < Item = DeviceStateUpdate > + Send + ' static > > {
213+ let usb = self
214+ . get_usb_credential ( )
215+ . await
216+ . map ( DeviceStateUpdate :: from)
217+ . boxed ( ) ;
218+ /*
219+ let nfc = self
220+ .get_nfc_credential()
221+ .await
222+ .map(DeviceStateUpdate::from)
223+ .boxed();
224+ */
225+ let hybrid = self
226+ . get_hybrid_credential ( )
227+ . await
228+ . map ( DeviceStateUpdate :: from)
229+ . boxed ( ) ;
230+ futures:: stream:: select_all ( [ usb, /* nfc, */ hybrid] ) . boxed ( )
203231 }
204232}
205233
@@ -309,6 +337,40 @@ where
309337 }
310338}
311339
340+ pub enum DeviceStateUpdate {
341+ Hybrid ( HybridState ) ,
342+ Nfc ( NfcState ) ,
343+ Usb ( UsbState ) ,
344+ }
345+
346+ impl From < DeviceStateUpdate > for BackgroundEvent {
347+ fn from ( value : DeviceStateUpdate ) -> Self {
348+ match value {
349+ DeviceStateUpdate :: Hybrid ( state) => ( & state) . into ( ) ,
350+ DeviceStateUpdate :: Nfc ( state) => ( & state) . into ( ) ,
351+ DeviceStateUpdate :: Usb ( state) => ( & state) . into ( ) ,
352+ }
353+ }
354+ }
355+
356+ impl From < HybridState > for DeviceStateUpdate {
357+ fn from ( value : HybridState ) -> Self {
358+ Self :: Hybrid ( value)
359+ }
360+ }
361+
362+ impl From < NfcState > for DeviceStateUpdate {
363+ fn from ( value : NfcState ) -> Self {
364+ Self :: Nfc ( value)
365+ }
366+ }
367+
368+ impl From < UsbState > for DeviceStateUpdate {
369+ fn from ( value : UsbState ) -> Self {
370+ Self :: Usb ( value)
371+ }
372+ }
373+
312374fn complete_request ( ctx : & Mutex < Option < RequestContext > > , response : CredentialResponse ) {
313375 if let Some ( ctx) = ctx. lock ( ) . unwrap ( ) . take ( ) {
314376 ctx. send_response ( Ok ( response) ) ;
0 commit comments