aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2019-01-27 15:43:32 +0000
committerRobin Krahl <robin.krahl@ireas.org>2019-07-08 21:27:11 +0000
commit588066f415e956fdcd2c6f6216c52b25911a3b1d (patch)
treeb16014285812bf8286a6f76800c978f8da864486 /src/lib.rs
parenta52676d9577f587e0f4d8e47ddc71ba34f0b31ca (diff)
downloadnitrokey-rs-588066f415e956fdcd2c6f6216c52b25911a3b1d.tar.gz
nitrokey-rs-588066f415e956fdcd2c6f6216c52b25911a3b1d.tar.bz2
Add Manager struct to manage Nitrokey connections
As part of the connection refactoring, we introduce the Manager struct that deals with connection management. To make sure there can be only once instance of the manager, we add a global static Mutex that holds the single Manager instance. We use the struct to ensure that the user can only connect to one device at a time. This also changes the Error::PoisonError variant to store the sync::PoisonError. This allows the user to call into_inner on the PoisonError to retrieve the MutexGuard and to ignore the error (for example useful during testing).
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c35829c..573f45f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -89,6 +89,9 @@
#![warn(missing_docs, rust_2018_compatibility, rust_2018_idioms, unused)]
+#[macro_use(lazy_static)]
+extern crate lazy_static;
+
mod auth;
mod config;
mod device;
@@ -98,6 +101,8 @@ mod pws;
mod util;
use std::fmt;
+use std::marker;
+use std::sync;
use nitrokey_sys;
@@ -117,6 +122,10 @@ pub const DEFAULT_ADMIN_PIN: &str = "12345678";
/// The default user PIN for all Nitrokey devices.
pub const DEFAULT_USER_PIN: &str = "123456";
+lazy_static! {
+ static ref MANAGER: sync::Mutex<Manager> = sync::Mutex::new(Manager::new());
+}
+
/// A version of the libnitrokey library.
///
/// Use the [`get_library_version`](fn.get_library_version.html) function to query the library
@@ -147,6 +156,63 @@ impl fmt::Display for Version {
}
}
+/// A manager for connections to Nitrokey devices.
+///
+/// Currently, libnitrokey only provides access to one Nitrokey device at the same time. This
+/// manager struct makes sure that `nitrokey-rs` does not try to connect to two devices at the same
+/// time.
+///
+/// To obtain an instance of this manager, use the [`take`][] function.
+///
+/// [`take`]: fn.take.html
+#[derive(Debug)]
+pub struct Manager {
+ marker: marker::PhantomData<()>,
+}
+
+impl Manager {
+ fn new() -> Self {
+ Manager {
+ marker: marker::PhantomData,
+ }
+ }
+}
+
+/// Take an instance of the connection manager, blocking until an instance is available.
+///
+/// There may only be one [`Manager`][] instance at the same time. If there already is an
+/// instance, this method blocks. If you want a non-blocking version, use [`take`][].
+///
+/// # Errors
+///
+/// - [`PoisonError`][] if the lock is poisoned
+///
+/// [`take`]: fn.take.html
+/// [`PoisonError`]: struct.Error.html#variant.PoisonError
+/// [`Manager`]: struct.Manager.html
+pub fn take_blocking() -> Result<sync::MutexGuard<'static, Manager>, Error> {
+ MANAGER.lock().map_err(Into::into)
+}
+
+/// Try to take an instance of the connection manager.
+///
+/// There may only be one [`Manager`][] instance at the same time. If there already is an
+/// instance, a [`ConcurrentAccessError`][] is returned. If you want a blocking version, use
+/// [`take_blocking`][].
+///
+/// # Errors
+///
+/// - [`ConcurrentAccessError`][] if the token for the `Manager` instance cannot be locked
+/// - [`PoisonError`][] if the lock is poisoned
+///
+/// [`take_blocking`]: fn.take_blocking.html
+/// [`ConcurrentAccessError`]: struct.Error.html#variant.ConcurrentAccessError
+/// [`PoisonError`]: struct.Error.html#variant.PoisonError
+/// [`Manager`]: struct.Manager.html
+pub fn take() -> Result<sync::MutexGuard<'static, Manager>, Error> {
+ MANAGER.try_lock().map_err(Into::into)
+}
+
/// Enables or disables debug output. Calling this method with `true` is equivalent to setting the
/// log level to `Debug`; calling it with `false` is equivalent to the log level `Error` (see
/// [`set_log_level`][]).