|
| 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