diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/authenticator/src/manager.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/authenticator/src/manager.rs')
-rw-r--r-- | third_party/rust/authenticator/src/manager.rs | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/third_party/rust/authenticator/src/manager.rs b/third_party/rust/authenticator/src/manager.rs new file mode 100644 index 0000000000..3a62a92252 --- /dev/null +++ b/third_party/rust/authenticator/src/manager.rs @@ -0,0 +1,218 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::authenticatorservice::AuthenticatorTransport; +use crate::authenticatorservice::{RegisterArgs, SignArgs}; +use crate::errors::*; +use crate::statecallback::StateCallback; +use crate::statemachine::StateMachine; +use crate::Pin; +use runloop::RunLoop; +use std::io; +use std::sync::mpsc::{channel, RecvTimeoutError, Sender}; +use std::time::Duration; + +enum QueueAction { + Register { + timeout: u64, + register_args: RegisterArgs, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::RegisterResult>>, + }, + Sign { + timeout: u64, + sign_args: SignArgs, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::SignResult>>, + }, + Cancel, + Reset { + timeout: u64, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::ResetResult>>, + }, + SetPin { + timeout: u64, + new_pin: Pin, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::ResetResult>>, + }, + InteractiveManagement { + timeout: u64, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::ResetResult>>, + }, +} + +pub struct Manager { + queue: RunLoop, + tx: Sender<QueueAction>, +} + +impl Manager { + pub fn new() -> io::Result<Self> { + let (tx, rx) = channel(); + + // Start a new work queue thread. + let queue = RunLoop::new(move |alive| { + let mut sm = StateMachine::new(); + + while alive() { + match rx.recv_timeout(Duration::from_millis(50)) { + Ok(QueueAction::Register { + timeout, + register_args, + status, + callback, + }) => { + // This must not block, otherwise we can't cancel. + sm.register(timeout, register_args, status, callback); + } + + Ok(QueueAction::Sign { + timeout, + sign_args, + status, + callback, + }) => { + // This must not block, otherwise we can't cancel. + sm.sign(timeout, sign_args, status, callback); + } + + Ok(QueueAction::Cancel) => { + // Cancelling must block so that we don't start a new + // polling thread before the old one has shut down. + sm.cancel(); + } + + Ok(QueueAction::Reset { + timeout, + status, + callback, + }) => { + // Reset the token: Delete all keypairs, reset PIN + sm.reset(timeout, status, callback); + } + + Ok(QueueAction::SetPin { + timeout, + new_pin, + status, + callback, + }) => { + // This must not block, otherwise we can't cancel. + sm.set_pin(timeout, new_pin, status, callback); + } + + Ok(QueueAction::InteractiveManagement { + timeout, + status, + callback, + }) => { + // Manage token interactively + sm.manage(timeout, status, callback); + } + + Err(RecvTimeoutError::Disconnected) => { + break; + } + + _ => { /* continue */ } + } + } + + // Cancel any ongoing activity. + sm.cancel(); + })?; + + Ok(Self { queue, tx }) + } +} + +impl Drop for Manager { + fn drop(&mut self) { + self.queue.cancel(); + } +} + +impl AuthenticatorTransport for Manager { + fn register( + &mut self, + timeout: u64, + register_args: RegisterArgs, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::RegisterResult>>, + ) -> Result<(), AuthenticatorError> { + let action = QueueAction::Register { + timeout, + register_args, + status, + callback, + }; + Ok(self.tx.send(action)?) + } + + fn sign( + &mut self, + timeout: u64, + sign_args: SignArgs, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::SignResult>>, + ) -> crate::Result<()> { + let action = QueueAction::Sign { + timeout, + sign_args, + status, + callback, + }; + + self.tx.send(action)?; + Ok(()) + } + + fn cancel(&mut self) -> Result<(), AuthenticatorError> { + Ok(self.tx.send(QueueAction::Cancel)?) + } + + fn reset( + &mut self, + timeout: u64, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::ResetResult>>, + ) -> Result<(), AuthenticatorError> { + Ok(self.tx.send(QueueAction::Reset { + timeout, + status, + callback, + })?) + } + + fn set_pin( + &mut self, + timeout: u64, + new_pin: Pin, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::ResetResult>>, + ) -> crate::Result<()> { + Ok(self.tx.send(QueueAction::SetPin { + timeout, + new_pin, + status, + callback, + })?) + } + + fn manage( + &mut self, + timeout: u64, + status: Sender<crate::StatusUpdate>, + callback: StateCallback<crate::Result<crate::ResetResult>>, + ) -> Result<(), AuthenticatorError> { + Ok(self.tx.send(QueueAction::InteractiveManagement { + timeout, + status, + callback, + })?) + } +} |