Start re-implementing client API

This commit is contained in:
Aram 🍐 2021-08-04 22:41:19 -04:00
parent 92268b742f
commit 162c015680
3 changed files with 85 additions and 11 deletions

View file

@ -8,7 +8,7 @@ pub struct Client {
/// The client configuration. /// The client configuration.
config: Config, config: Config,
/// The client connection. /// The client connection.
stream: ConnectionStream, pub(crate) stream: ConnectionStream,
} }
impl Client { impl Client {
@ -30,22 +30,31 @@ impl Client {
client = client.enable_ssl()?; client = client.enable_ssl()?;
// TODO: Enable SSL
// TODO: Login
Ok(client) 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")] #[cfg(feature = "ssl")]
fn enable_ssl(mut self) -> crate::Result<Self> { fn enable_ssl(mut self) -> crate::Result<Self> {
if self.config.ssl { if self.config.ssl {
// Send STARTTLS self.exec_start_tls()?;
self.stream
.write_sentence(&ServerSentences::ExecStartTLS {})?;
// Expect the OK
self.stream
.read_sentence::<ClientSentences>()?
.exactly(ClientSentences::StartTLSOk {})?;
// Initialize SSL configurations // Initialize SSL configurations
let mut ssl_config = rustls::ClientConfig::new(); let mut ssl_config = rustls::ClientConfig::new();

View file

@ -8,6 +8,8 @@ use crate::{Config, Error, Host, NutError};
mod client; mod client;
mod stream; mod stream;
pub use client::Client;
/// A blocking NUT client connection. /// A blocking NUT client connection.
pub enum Connection { pub enum Connection {
/// A TCP connection. /// A TCP connection.

View file

@ -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::<ClientSentences>()?
.exactly($ret)
.map(|_| ())
}
)*
}
};
}
implement_list_commands! { implement_list_commands! {
/// Queries a list of UPS devices. /// Queries a list of UPS devices.
pub fn list_ups() -> Vec<(String, String)> { pub fn list_ups() -> Vec<(String, String)> {
@ -835,3 +866,35 @@ implement_action_commands! {
Command::Logout 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 {} }
}
}