Skip to content

Commit de11920

Browse files
Moves UX updates to Channel (#128)
Requires #126. Changes: * Moves UX updates to `Channel`, so that `Device::channel()` no longer needs to return a tuple (Channel, Channel::UxUpdate) * Changes updates channel implementation from multi-producer, single-consumer `mpsc` to `broadcast`, allowing subscribing more than once. This allows subscribing to events without borrowing the channel mutably * Wraps PIN entry callback with `Arc`, and makes all `UxUpdate`s `Clone`, as `broadcast` requires the message to be `Clone`
1 parent 38d6975 commit de11920

25 files changed

+164
-154
lines changed

libwebauthn/examples/authenticator_config_hid.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ use libwebauthn::management::AuthenticatorConfig;
66
use libwebauthn::pin::PinRequestReason;
77
use libwebauthn::proto::ctap2::{Ctap2, Ctap2GetInfoResponse};
88
use libwebauthn::transport::hid::list_devices;
9-
use libwebauthn::transport::Device;
9+
use libwebauthn::transport::{Channel as _, Device};
1010
use libwebauthn::webauthn::Error as WebAuthnError;
1111
use libwebauthn::UvUpdate;
1212
use std::io::{self, Write};
1313
use text_io::read;
14-
use tokio::sync::mpsc::Receiver;
14+
use tokio::sync::broadcast::Receiver;
1515
use tracing_subscriber::{self, EnvFilter};
1616

1717
const TIMEOUT: Duration = Duration::from_secs(10);
@@ -24,7 +24,7 @@ fn setup_logging() {
2424
}
2525

2626
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
27-
while let Some(update) = state_recv.recv().await {
27+
while let Ok(update) = state_recv.recv().await {
2828
match update {
2929
UvUpdate::PresenceRequired => println!("Please touch your device!"),
3030
UvUpdate::UvRetry { attempts_left } => {
@@ -123,9 +123,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
123123

124124
for mut device in devices {
125125
println!("Selected HID authenticator: {}", &device);
126-
let (mut channel, state_recv) = device.channel().await?;
126+
let mut channel = device.channel().await?;
127127
channel.wink(TIMEOUT).await?;
128128

129+
let state_recv = channel.get_ux_update_receiver();
129130
tokio::spawn(handle_updates(state_recv));
130131

131132
let info = channel.ctap2_get_info().await?;

libwebauthn/examples/bio_enrollment_hid.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use std::fmt::Display;
44
use std::io::{self, Write};
55
use std::time::Duration;
66
use text_io::read;
7-
use tokio::sync::mpsc::Receiver;
7+
use tokio::sync::broadcast::Receiver;
88
use tracing_subscriber::{self, EnvFilter};
99

1010
use libwebauthn::management::BioEnrollment;
1111
use libwebauthn::pin::PinRequestReason;
1212
use libwebauthn::proto::ctap2::{Ctap2, Ctap2GetInfoResponse, Ctap2LastEnrollmentSampleStatus};
1313
use libwebauthn::transport::hid::list_devices;
14-
use libwebauthn::transport::Device;
14+
use libwebauthn::transport::{Channel as _, Device};
1515
use libwebauthn::webauthn::Error as WebAuthnError;
1616

1717
const TIMEOUT: Duration = Duration::from_secs(10);
@@ -24,7 +24,7 @@ fn setup_logging() {
2424
}
2525

2626
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
27-
while let Some(update) = state_recv.recv().await {
27+
while let Ok(update) = state_recv.recv().await {
2828
match update {
2929
UvUpdate::PresenceRequired => println!("Please touch your device!"),
3030
UvUpdate::UvRetry { attempts_left } => {
@@ -148,9 +148,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
148148

149149
for mut device in devices {
150150
println!("Selected HID authenticator: {}", &device);
151-
let (mut channel, state_recv) = device.channel().await?;
151+
let mut channel = device.channel().await?;
152152
channel.wink(TIMEOUT).await?;
153153

154+
let state_recv = channel.get_ux_update_receiver();
154155
tokio::spawn(handle_updates(state_recv));
155156

156157
let info = channel.ctap2_get_info().await?;

libwebauthn/examples/change_pin_hid.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use std::time::Duration;
33

44
use libwebauthn::{
55
pin::{PinManagement, PinRequestReason},
6+
transport::Channel as _,
67
UvUpdate,
78
};
8-
use tokio::sync::mpsc::Receiver;
9+
use tokio::sync::broadcast::Receiver;
910
use tracing_subscriber::{self, EnvFilter};
1011

1112
use libwebauthn::transport::hid::list_devices;
@@ -24,7 +25,7 @@ fn setup_logging() {
2425
}
2526

2627
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
27-
while let Some(update) = state_recv.recv().await {
28+
while let Ok(update) = state_recv.recv().await {
2829
match update {
2930
UvUpdate::PresenceRequired => println!("Please touch your device!"),
3031
UvUpdate::UvRetry { attempts_left } => {
@@ -72,7 +73,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
7273

7374
for mut device in devices {
7475
println!("Selected HID authenticator: {}", &device);
75-
let (mut channel, state_recv) = device.channel().await?;
76+
let mut channel = device.channel().await?;
7677
channel.wink(TIMEOUT).await?;
7778

7879
print!("PIN: Please enter the _new_ PIN: ");
@@ -84,6 +85,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
8485
return Ok(());
8586
}
8687

88+
let state_recv = channel.get_ux_update_receiver();
8789
tokio::spawn(handle_updates(state_recv));
8890

8991
let response = loop {

libwebauthn/examples/cred_management.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ use libwebauthn::proto::ctap2::{
55
};
66
use libwebauthn::proto::CtapError;
77
use libwebauthn::transport::hid::list_devices;
8-
use libwebauthn::transport::Device;
8+
use libwebauthn::transport::{Channel as _, Device};
99
use libwebauthn::webauthn::Error as WebAuthnError;
1010
use libwebauthn::UvUpdate;
1111
use std::fmt::Display;
1212
use std::io::{self, Write};
1313
use std::time::Duration;
1414
use text_io::read;
15-
use tokio::sync::mpsc::Receiver;
15+
use tokio::sync::broadcast::Receiver;
1616
use tracing_subscriber::{self, EnvFilter};
1717

1818
const TIMEOUT: Duration = Duration::from_secs(10);
@@ -25,7 +25,7 @@ fn setup_logging() {
2525
}
2626

2727
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
28-
while let Some(update) = state_recv.recv().await {
28+
while let Ok(update) = state_recv.recv().await {
2929
match update {
3030
UvUpdate::PresenceRequired => println!("Please touch your device!"),
3131
UvUpdate::UvRetry { attempts_left } => {
@@ -167,9 +167,10 @@ pub async fn main() -> Result<(), WebAuthnError> {
167167

168168
for mut device in devices {
169169
println!("Selected HID authenticator: {}", &device);
170-
let (mut channel, state_recv) = device.channel().await?;
170+
let mut channel = device.channel().await?;
171171
channel.wink(TIMEOUT).await?;
172172

173+
let state_recv = channel.get_ux_update_receiver();
173174
tokio::spawn(handle_updates(state_recv));
174175

175176
let info = channel.ctap2_get_info().await?;

libwebauthn/examples/hid_device_selection.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
4343

4444
tokio::spawn(async move {
4545
let dev = device.clone();
46-
let (mut channel, _state_rx) = device.channel().await.unwrap();
46+
let mut channel = device.channel().await.unwrap();
4747
let handle = channel.get_handle();
4848
stx.send((idx, dev, handle)).await.unwrap();
4949
drop(stx);

libwebauthn/examples/prf_test.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use libwebauthn::UvUpdate;
99
use rand::{thread_rng, Rng};
1010
use serde_bytes::ByteBuf;
1111
use text_io::read;
12-
use tokio::sync::mpsc::Receiver;
12+
use tokio::sync::broadcast::Receiver;
1313
use tracing_subscriber::{self, EnvFilter};
1414

1515
use libwebauthn::ops::webauthn::{
@@ -19,7 +19,7 @@ use libwebauthn::ops::webauthn::{
1919
use libwebauthn::pin::PinRequestReason;
2020
use libwebauthn::proto::ctap2::{Ctap2PublicKeyCredentialDescriptor, Ctap2PublicKeyCredentialType};
2121
use libwebauthn::transport::hid::list_devices;
22-
use libwebauthn::transport::Device;
22+
use libwebauthn::transport::{Channel as _, Device};
2323
use libwebauthn::webauthn::{Error as WebAuthnError, WebAuthn};
2424

2525
const TIMEOUT: Duration = Duration::from_secs(10);
@@ -32,7 +32,7 @@ fn setup_logging() {
3232
}
3333

3434
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
35-
while let Some(update) = state_recv.recv().await {
35+
while let Ok(update) = state_recv.recv().await {
3636
match update {
3737
UvUpdate::PresenceRequired => println!("Please touch your device!"),
3838
UvUpdate::UvRetry { attempts_left } => {
@@ -107,9 +107,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
107107

108108
for mut device in devices {
109109
println!("Selected HID authenticator: {}", &device);
110-
let (mut channel, state_recv) = device.channel().await?;
110+
let mut channel = device.channel().await?;
111111
channel.wink(TIMEOUT).await?;
112112

113+
let state_recv = channel.get_ux_update_receiver();
113114
tokio::spawn(handle_updates(state_recv));
114115

115116
let credential = Ctap2PublicKeyCredentialDescriptor {

libwebauthn/examples/u2f_ble.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ use std::error::Error;
22
use std::time::Duration;
33

44
use libwebauthn::UvUpdate;
5-
use tokio::sync::mpsc::Receiver;
5+
use tokio::sync::broadcast::Receiver;
66
use tracing_subscriber::{self, EnvFilter};
77

88
use libwebauthn::ops::u2f::{RegisterRequest, SignRequest};
99
use libwebauthn::transport::ble::list_devices;
10-
use libwebauthn::transport::Device;
10+
use libwebauthn::transport::{Channel as _, Device};
1111
use libwebauthn::u2f::U2F;
1212

1313
const TIMEOUT: Duration = Duration::from_secs(10);
@@ -20,7 +20,7 @@ fn setup_logging() {
2020
}
2121

2222
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
23-
while let Some(update) = state_recv.recv().await {
23+
while let Ok(update) = state_recv.recv().await {
2424
match update {
2525
UvUpdate::PresenceRequired => println!("Please touch your device!"),
2626
_ => { /* U2F doesn't use other state updates */ }
@@ -36,7 +36,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
3636
println!("Found {} devices.", devices.len());
3737

3838
for mut device in devices {
39-
let (mut channel, state_recv) = device.channel().await?;
39+
let mut channel = device.channel().await?;
4040

4141
const APP_ID: &str = "https://foo.example.org";
4242
let challenge: &[u8] =
@@ -46,7 +46,9 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
4646
let register_request =
4747
RegisterRequest::new_u2f_v2(&APP_ID, &challenge, vec![], TIMEOUT, false);
4848

49+
let state_recv = channel.get_ux_update_receiver();
4950
tokio::spawn(handle_updates(state_recv));
51+
5052
let response = channel.u2f_register(&register_request).await?;
5153
println!("Response: {:?}", response);
5254

libwebauthn/examples/u2f_hid.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ use std::error::Error;
22
use std::time::Duration;
33

44
use libwebauthn::UvUpdate;
5-
use tokio::sync::mpsc::Receiver;
5+
use tokio::sync::broadcast::Receiver;
66
use tracing_subscriber::{self, EnvFilter};
77

88
use libwebauthn::ops::u2f::{RegisterRequest, SignRequest};
99
use libwebauthn::transport::hid::list_devices;
10-
use libwebauthn::transport::Device;
10+
use libwebauthn::transport::{Channel as _, Device};
1111
use libwebauthn::u2f::U2F;
1212

1313
const TIMEOUT: Duration = Duration::from_secs(10);
@@ -21,7 +21,7 @@ fn setup_logging() {
2121
}
2222

2323
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
24-
while let Some(update) = state_recv.recv().await {
24+
while let Ok(update) = state_recv.recv().await {
2525
match update {
2626
UvUpdate::PresenceRequired => println!("Please touch your device!"),
2727
_ => { /* U2F doesn't use other state updates */ }
@@ -38,7 +38,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
3838
println!("Found {} devices.", devices.len());
3939
for mut device in devices {
4040
println!("Winking device: {}", device);
41-
let (mut channel, state_recv) = device.channel().await?;
41+
let mut channel = device.channel().await?;
4242
channel.wink(TIMEOUT).await?;
4343

4444
const APP_ID: &str = "https://foo.example.org";
@@ -49,7 +49,9 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
4949
let register_request =
5050
RegisterRequest::new_u2f_v2(&APP_ID, &challenge, vec![], TIMEOUT, false);
5151

52+
let state_recv = channel.get_ux_update_receiver();
5253
tokio::spawn(handle_updates(state_recv));
54+
5355
let response = channel.u2f_register(&register_request).await?;
5456
println!("Response: {:?}", response);
5557

libwebauthn/examples/webauthn_cable.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use qrcode::render::unicode;
1414
use qrcode::QrCode;
1515
use rand::{thread_rng, Rng};
1616
use text_io::read;
17-
use tokio::sync::mpsc::Receiver;
17+
use tokio::sync::broadcast::Receiver;
1818
use tokio::time::sleep;
1919
use tracing_subscriber::{self, EnvFilter};
2020

@@ -25,7 +25,7 @@ use libwebauthn::proto::ctap2::{
2525
Ctap2CredentialType, Ctap2PublicKeyCredentialDescriptor, Ctap2PublicKeyCredentialRpEntity,
2626
Ctap2PublicKeyCredentialUserEntity,
2727
};
28-
use libwebauthn::transport::Device;
28+
use libwebauthn::transport::{Channel as _, Device};
2929
use libwebauthn::webauthn::{Error as WebAuthnError, WebAuthn};
3030

3131
const TIMEOUT: Duration = Duration::from_secs(120);
@@ -38,7 +38,7 @@ fn setup_logging() {
3838
}
3939

4040
async fn handle_updates(mut state_recv: Receiver<CableUxUpdate>) {
41-
while let Some(update) = state_recv.recv().await {
41+
while let Ok(update) = state_recv.recv().await {
4242
match update {
4343
CableUxUpdate::UvUpdate(uv_update) => match uv_update {
4444
UvUpdate::PresenceRequired => println!("Please touch your device!"),
@@ -111,9 +111,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
111111
println!("{}", image);
112112

113113
// Connect to a known device
114-
let (mut channel, state_recv) = device.channel().await.unwrap();
114+
let mut channel = device.channel().await.unwrap();
115115
println!("Tunnel established {:?}", channel);
116116

117+
let state_recv = channel.get_ux_update_receiver();
117118
tokio::spawn(handle_updates(state_recv));
118119

119120
// Make Credentials ceremony
@@ -177,9 +178,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
177178
.unwrap();
178179

179180
// Connect to a known device
180-
let (mut channel, state_recv) = known_device.channel().await.unwrap();
181+
let mut channel = known_device.channel().await.unwrap();
181182
println!("Tunnel established {:?}", channel);
182183

184+
let state_recv = channel.get_ux_update_receiver();
183185
tokio::spawn(handle_updates(state_recv));
184186

185187
let response = loop {

libwebauthn/examples/webauthn_extensions_hid.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::time::Duration;
66
use libwebauthn::UvUpdate;
77
use rand::{thread_rng, Rng};
88
use text_io::read;
9-
use tokio::sync::mpsc::Receiver;
9+
use tokio::sync::broadcast::Receiver;
1010
use tracing_subscriber::{self, EnvFilter};
1111

1212
use libwebauthn::ops::webauthn::{
@@ -21,7 +21,7 @@ use libwebauthn::proto::ctap2::{
2121
Ctap2PublicKeyCredentialUserEntity,
2222
};
2323
use libwebauthn::transport::hid::list_devices;
24-
use libwebauthn::transport::Device;
24+
use libwebauthn::transport::{Channel as _, Device};
2525
use libwebauthn::webauthn::{Error as WebAuthnError, WebAuthn};
2626

2727
const TIMEOUT: Duration = Duration::from_secs(10);
@@ -34,7 +34,7 @@ fn setup_logging() {
3434
}
3535

3636
async fn handle_updates(mut state_recv: Receiver<UvUpdate>) {
37-
while let Some(update) = state_recv.recv().await {
37+
while let Ok(update) = state_recv.recv().await {
3838
match update {
3939
UvUpdate::PresenceRequired => println!("Please touch your device!"),
4040
UvUpdate::UvRetry { attempts_left } => {
@@ -97,9 +97,10 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
9797

9898
for mut device in devices {
9999
println!("Selected HID authenticator: {}", &device);
100-
let (mut channel, state_recv) = device.channel().await?;
100+
let mut channel = device.channel().await?;
101101
channel.wink(TIMEOUT).await?;
102102

103+
let state_recv = channel.get_ux_update_receiver();
103104
tokio::spawn(handle_updates(state_recv));
104105

105106
// Make Credentials ceremony

0 commit comments

Comments
 (0)