From 162c01568048ef2747eed4b67eb2c0df74444a3a Mon Sep 17 00:00:00 2001 From: Aram Peres Date: Wed, 4 Aug 2021 22:41:19 -0400 Subject: [PATCH] Start re-implementing client API --- rups/src/blocking/client.rs | 31 +++++++++++------- rups/src/blocking/mod.rs | 2 ++ rups/src/cmd.rs | 63 +++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/rups/src/blocking/client.rs b/rups/src/blocking/client.rs index 62a02ff..8ca041e 100644 --- a/rups/src/blocking/client.rs +++ b/rups/src/blocking/client.rs @@ -8,7 +8,7 @@ pub struct Client { /// The client configuration. config: Config, /// The client connection. - stream: ConnectionStream, + pub(crate) stream: ConnectionStream, } impl Client { @@ -30,22 +30,31 @@ impl Client { client = client.enable_ssl()?; - // TODO: Enable SSL - // TODO: Login Ok(client) } + /// Authenticates to the given UPS device with the username and password set in the config. + pub fn login(&mut self, ups_name: String) -> crate::Result<()> { + if let Some(auth) = self.config.auth.clone() { + // Pass username and check for 'OK' + self.set_username(auth.username)?; + + // Pass password and check for 'OK' + if let Some(password) = auth.password { + self.set_password(password)?; + } + + // Submit login + self.exec_login(ups_name) + } else { + Ok(()) + } + } + #[cfg(feature = "ssl")] fn enable_ssl(mut self) -> crate::Result { if self.config.ssl { - // Send STARTTLS - self.stream - .write_sentence(&ServerSentences::ExecStartTLS {})?; - - // Expect the OK - self.stream - .read_sentence::()? - .exactly(ClientSentences::StartTLSOk {})?; + self.exec_start_tls()?; // Initialize SSL configurations let mut ssl_config = rustls::ClientConfig::new(); diff --git a/rups/src/blocking/mod.rs b/rups/src/blocking/mod.rs index 2019c9e..0ebb78e 100644 --- a/rups/src/blocking/mod.rs +++ b/rups/src/blocking/mod.rs @@ -8,6 +8,8 @@ use crate::{Config, Error, Host, NutError}; mod client; mod stream; +pub use client::Client; + /// A blocking NUT client connection. pub enum Connection { /// A TCP connection. diff --git a/rups/src/cmd.rs b/rups/src/cmd.rs index 312883c..3f1b701 100644 --- a/rups/src/cmd.rs +++ b/rups/src/cmd.rs @@ -693,6 +693,37 @@ macro_rules! implement_action_commands { }; } +/// A macro for implementing client action commands that return `OK`. +/// +/// Each function should return the sentence to pass. +macro_rules! implement_client_action_commands { + ( + $( + $(#[$attr:meta])+ + $vis:vis fn $name:ident($($argname:ident: $argty:ty),*) { + $cmd:block, + $ret:block + } + )* + ) => { + impl crate::blocking::Client { + $( + $(#[$attr])* + #[allow(dead_code)] + $vis fn $name(&mut self$(, $argname: $argty)*) -> crate::Result<()> { + use crate::proto::{Sentence, ClientSentences, ClientSentences::*, ServerSentences::*}; + self.stream + .write_sentence(&$cmd)?; + self.stream + .read_sentence::()? + .exactly($ret) + .map(|_| ()) + } + )* + } + }; +} + implement_list_commands! { /// Queries a list of UPS devices. pub fn list_ups() -> Vec<(String, String)> { @@ -835,3 +866,35 @@ implement_action_commands! { Command::Logout } } + +implement_client_action_commands! { + /// Sends the login username. + pub(crate) fn set_username(username: String) { + { SetUsername { username } }, + { GenericOk {} } + } + + /// Sends the login password. + pub(crate) fn set_password(password: String) { + { SetPassword { password } }, + { GenericOk {} } + } + + /// Executes the login. + pub(crate) fn exec_login(ups_name: String) { + { ExecLogin { ups_name } }, + { GenericOk {} } + } + + /// Executes the logout. + pub(crate) fn exec_logout() { + { ExecLogout {} }, + { LogoutOk {} } + } + + /// Asks the server to upgrade to TLS. + pub(crate) fn exec_start_tls() { + { ExecStartTLS {} }, + { StartTLSOk {} } + } +}