Skip to content

Commit 9fa4b54

Browse files
authored
support pairing pin code and passkey (#93)
1 parent f25e2ef commit 9fa4b54

18 files changed

+1428
-358
lines changed

Cargo.lock

Lines changed: 51 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ toml = "0.9"
2323
serde = { version = "1", features = ["derive"] }
2424
clap = { version = "4", features = ["derive", "cargo"] }
2525
tui-input = "0.12"
26+
tui-big-text = "0.7"
27+
anyhow = "1"
2628

2729
[profile.release]
2830
strip = true

src/agent.rs

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
use async_channel::{Receiver, Sender};
2+
use tokio::sync::mpsc::UnboundedSender;
3+
4+
use bluer::agent::{
5+
DisplayPasskey, DisplayPinCode, ReqError, ReqResult, RequestConfirmation, RequestPasskey,
6+
RequestPinCode,
7+
};
8+
9+
use crate::{
10+
event::Event,
11+
requests::{
12+
confirmation::Confirmation, enter_passkey::EnterPasskey, enter_pin_code::EnterPinCode,
13+
},
14+
};
15+
16+
#[derive(Debug, Clone)]
17+
pub struct AuthAgent {
18+
pub event_sender: UnboundedSender<Event>,
19+
pub tx_cancel: Sender<()>,
20+
pub rx_cancel: Receiver<()>,
21+
pub tx_pin_code: Sender<String>,
22+
pub rx_pin_code: Receiver<String>,
23+
pub tx_display_pin_code: Sender<()>,
24+
pub rx_display_pin_code: Receiver<()>,
25+
pub tx_display_passkey: Sender<()>,
26+
pub rx_display_passkey: Receiver<()>,
27+
pub tx_passkey: Sender<u32>,
28+
pub rx_passkey: Receiver<u32>,
29+
pub tx_request_confirmation: Sender<bool>,
30+
pub rx_request_confirmation: Receiver<bool>,
31+
}
32+
33+
impl AuthAgent {
34+
pub fn new(sender: UnboundedSender<Event>) -> Self {
35+
let (tx_passkey, rx_passkey) = async_channel::unbounded();
36+
let (tx_display_passkey, rx_display_passkey) = async_channel::unbounded();
37+
38+
let (tx_pin_code, rx_pin_code) = async_channel::unbounded();
39+
let (tx_display_pin_code, rx_display_pin_code) = async_channel::unbounded();
40+
41+
let (tx_request_confirmation, rx_request_confirmation) = async_channel::unbounded();
42+
let (tx_cancel, rx_cancel) = async_channel::unbounded();
43+
44+
Self {
45+
event_sender: sender,
46+
tx_cancel,
47+
rx_cancel,
48+
tx_pin_code,
49+
rx_pin_code,
50+
tx_display_pin_code,
51+
rx_display_pin_code,
52+
tx_display_passkey,
53+
rx_display_passkey,
54+
tx_passkey,
55+
rx_passkey,
56+
tx_request_confirmation,
57+
rx_request_confirmation,
58+
}
59+
}
60+
}
61+
62+
pub async fn request_confirmation(request: RequestConfirmation, agent: AuthAgent) -> ReqResult<()> {
63+
agent
64+
.event_sender
65+
.send(Event::RequestConfirmation(Confirmation::new(
66+
request.adapter,
67+
request.device,
68+
request.passkey,
69+
)))
70+
.unwrap();
71+
72+
tokio::select! {
73+
r = agent.rx_request_confirmation.recv() => {
74+
match r {
75+
Ok(v) => {
76+
match v {
77+
true => Ok(()),
78+
false => Err(ReqError::Rejected)
79+
}
80+
}
81+
Err(_) => {
82+
Err(ReqError::Canceled)
83+
}
84+
}
85+
86+
}
87+
88+
_ = agent.rx_cancel.recv() => {
89+
Err(ReqError::Canceled)
90+
}
91+
92+
}
93+
}
94+
95+
pub async fn request_pin_code(request: RequestPinCode, agent: AuthAgent) -> ReqResult<String> {
96+
agent
97+
.event_sender
98+
.send(Event::RequestEnterPinCode(EnterPinCode::new(
99+
request.adapter,
100+
request.device,
101+
)))
102+
.unwrap();
103+
104+
tokio::select! {
105+
r = agent.rx_pin_code.recv() => {
106+
match r {
107+
Ok(v) => Ok(v),
108+
Err(_) => Err(ReqError::Canceled)
109+
}
110+
111+
}
112+
113+
_ = agent.rx_cancel.recv() => {
114+
Err(ReqError::Canceled)
115+
}
116+
117+
}
118+
}
119+
120+
pub async fn request_passkey(request: RequestPasskey, agent: AuthAgent) -> ReqResult<u32> {
121+
agent
122+
.event_sender
123+
.send(Event::RequestEnterPasskey(EnterPasskey::new(
124+
request.adapter,
125+
request.device,
126+
)))
127+
.unwrap();
128+
129+
tokio::select! {
130+
r = agent.rx_passkey.recv() => {
131+
match r {
132+
Ok(v) => Ok(v),
133+
Err(_) => Err(ReqError::Canceled)
134+
}
135+
}
136+
137+
_ = agent.rx_cancel.recv() => {
138+
Err(ReqError::Canceled)
139+
}
140+
141+
}
142+
}
143+
144+
pub async fn display_pin_code(request: DisplayPinCode, agent: AuthAgent) -> ReqResult<()> {
145+
agent
146+
.event_sender
147+
.send(Event::RequestDisplayPinCode(
148+
crate::requests::display_pin_code::DisplayPinCode::new(
149+
request.adapter,
150+
request.device,
151+
request.pincode,
152+
),
153+
))
154+
.unwrap();
155+
156+
tokio::select! {
157+
_ = agent.rx_display_pin_code.recv() => {
158+
Ok(())
159+
}
160+
161+
_ = agent.rx_cancel.recv() => {
162+
Err(ReqError::Canceled)
163+
}
164+
}
165+
}
166+
167+
pub async fn display_passkey(request: DisplayPasskey, agent: AuthAgent) -> ReqResult<()> {
168+
let _ = agent.event_sender.send(Event::RequestDisplayPasskey(
169+
crate::requests::display_passkey::DisplayPasskey::new(
170+
request.adapter,
171+
request.device,
172+
request.passkey,
173+
request.entered,
174+
),
175+
));
176+
177+
tokio::select! {
178+
_ = agent.rx_display_passkey.recv() => {
179+
Ok(())
180+
}
181+
182+
_ = agent.rx_cancel.recv() => {
183+
let _ = agent.event_sender.send(Event::DisplayPasskeyCanceled);
184+
Err(ReqError::Canceled)
185+
}
186+
}
187+
}

0 commit comments

Comments
 (0)