Skip to content

Commit

Permalink
Merge pull request #3 from ByteOtter/add-logging-feature
Browse files Browse the repository at this point in the history
Add logging feature
  • Loading branch information
ByteOtter authored Aug 6, 2024
2 parents 6e7e6cc + 0890235 commit 269cd52
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 12 deletions.
6 changes: 6 additions & 0 deletions isototest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ license = "GPL-2.0"

[dependencies]
image = "0.25.2"
log = "0.4.22"
tokio = "1.38.1"
vnc-rs = "0.5.1"
env_logger = { version= "0.10", optional=true }

[dev-dependencies]
mockito = "1.4.0"

[features]
# Feature to enable default logging configuration
default-logging = ["env_logger"]
4 changes: 4 additions & 0 deletions isototest/src/action/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
extern crate proc_macro;
use std::{thread::sleep, time::Duration};

use log::info;
use vnc::{client::VncClient, ClientKeyEvent, VncError, X11Event};

use crate::logging::LOG_TARGET;
use crate::types::{KeyCode, KeyEventType};

/// Sleep.
Expand Down Expand Up @@ -52,6 +54,7 @@ pub async fn write_to_console(
framerate: Option<f64>,
) -> Result<(), VncError> {
// Translate each character to a keycode
info!(target: LOG_TARGET, "Sending text '{}' with intervall of {}FPS....", text, framerate.unwrap_or(30 as f64));
let mut keycode: u32;

for ch in text.chars() {
Expand All @@ -72,6 +75,7 @@ pub async fn write_to_console(
press_button(client, modifier, KeyEventType::Release, framerate).await?;
}
}
info!(target: LOG_TARGET, "Text '{}' sent.", text);
Ok(())
}

Expand Down
18 changes: 13 additions & 5 deletions isototest/src/action/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ use image::ImageBuffer;
use image::DynamicImage::ImageRgba8;
use vnc::{Rect, VncClient, VncError, VncEvent, X11Event};

use log::{error, info, warn};

use crate::logging::LOG_TARGET;

/// Receive a screenshot of the remote machine.
///
/// # Parameters
Expand All @@ -36,6 +40,7 @@ pub async fn read_screen(
resolution: Option<(u32, u32)>,
timeout: Duration,
) -> Result<(u32, u32), VncError> {
info!(target: LOG_TARGET, "Requesting screenshot...");
// Request screen update.
client.input(X11Event::Refresh).await?;

Expand All @@ -47,21 +52,23 @@ pub async fn read_screen(
// **This will cause issues, if you try to use this functionality a second time.**
match resolution {
Some((x, y)) => {
info!(target: LOG_TARGET, "Resolution provided; proceeding...");
width = Some(x);
height = Some(y);
}
None => match client.recv_event().await? {
VncEvent::SetResolution(screen) => {
println!("Screen resolution: {}x{}", screen.width, screen.height);
info!(target: LOG_TARGET, "Resolution received. Screen resolution: {}x{}", screen.width, screen.height);
width = Some(screen.width as u32);
height = Some(screen.height as u32);

client.input(X11Event::Refresh).await?;
}
_ => {
error!(target: LOG_TARGET, "Failed to retrieve screen resolution. Aborting...");
return Err(VncError::General(
"[error] No resolution found!".to_string(),
))
));
}
},
}
Expand All @@ -88,15 +95,16 @@ pub async fn read_screen(
return Err(VncError::General(e));
}
x => {
println!(
"[warning] Function 'read_screen' got unexpected event '{:?}'.",
warn!(target: LOG_TARGET,
"Function 'read_screen' got unexpected event '{:?}'.",
x
);
break;
}
},
None => {
if idle_timer.elapsed() >= timeout {
warn!(target: LOG_TARGET, "Timeout while waiting for VNC Event.");
break;
}
}
Expand Down Expand Up @@ -135,6 +143,6 @@ pub async fn read_screen(
.save_with_format(path, ImageFormat::Png)
.unwrap();

println!("Screenshot saved to {}", file_path);
info!(target: LOG_TARGET, "Screenshot saved to '{}'", file_path);
Ok((width.unwrap(), height.unwrap()))
}
37 changes: 30 additions & 7 deletions isototest/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later

//! This module handles the VncClient and its connection to the VncServer.
use log::{debug, error, info};
use tokio::{self, net::TcpStream};
use vnc::{PixelFormat, VncClient, VncConnector, VncError};

use crate::logging::LOG_TARGET;

/// Create a new VNC client.
///
/// During the connection process the connection to the VNC server is
Expand All @@ -29,19 +32,23 @@ pub async fn create_vnc_client(
target_ip: String,
mut psw: Option<String>,
) -> Result<VncClient, VncError> {
info!(target: LOG_TARGET, "Creating VNC client for target IP: '{}'", target_ip);

if psw.is_none() {
debug!("No password provided; using empty password.");
psw = Some(String::new());
}

let tcp: TcpStream = match TcpStream::connect(target_ip).await {
Ok(tcp) => tcp,
Err(e) => {
error!(target: LOG_TARGET, "Failed to connect: {}", e);
let err = VncError::IoError(e);
return Err(err);
}
};

let vnc: VncClient = VncConnector::new(tcp)
let vnc: VncClient = match VncConnector::new(tcp)
.set_auth_method(async move { Ok(psw.unwrap()) })
.add_encoding(vnc::VncEncoding::Tight)
.add_encoding(vnc::VncEncoding::Zrle)
Expand All @@ -54,10 +61,19 @@ pub async fn create_vnc_client(
// NOTE: If the color encoding is changed in the following line, you must also change it in
// view.rs to avoid the saved screenshots from having swapped colors.
.set_pixel_format(PixelFormat::rgba())
.build()?
.try_start()
.await?
.finish()?;
.build()
{
Ok(vnc) => vnc,
Err(e) => {
error!(target: LOG_TARGET, "Failed to build VNC client: {}", e);
return Err(e);
}
}
.try_start()
.await?
.finish()?;

info!("VNC Client successfully built and started.");

Ok(vnc)
}
Expand All @@ -74,10 +90,17 @@ pub async fn create_vnc_client(
/// * `Err(VncError)` - Escalates the `VncError` upwards, if the `.close()` function of `vnc-rs`
/// returns an error.
pub async fn kill_client(client: VncClient) -> Result<(), VncError> {
info!(target: LOG_TARGET, "Closing connection...");
match client.close().await {
Ok(_) => {}
Err(e) => return Err(e),
Ok(_) => {
info!(target: LOG_TARGET, "Connection closed.");
}
Err(e) => {
error!(target: LOG_TARGET, "Unable to close connection: {}", e);
return Err(e);
}
};
drop(client);
info!(target: LOG_TARGET, "Client dropped.");
Ok(())
}
11 changes: 11 additions & 0 deletions isototest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,18 @@
//! Ok(())
//! }
//! ```
//!
//! ## Optional Features
//!
//! * `default-logging` - Provides you with a sensible logger configuration using the `env_logger`
//! crate.
pub mod action;
pub mod connection;
pub mod logging;
pub(crate) mod types;

#[cfg(feature = "default-logging")]
pub fn init_logging() {
logging::initialize_default_logging();
}
26 changes: 26 additions & 0 deletions isototest/src/logging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! This module provides a sensible default configuration of a logging system.
#[cfg(feature = "default-logging")]
use env_logger::Builder;
#[cfg(feature = "default-logging")]
use std::io::Write;

pub const LOG_TARGET: &str = "[isototest]";

#[cfg(feature = "default-logging")]
/// Initialize default logging configuration.
pub fn initialize_default_logging() {
Builder::new()
.filter_level(log::LevelFilter::Info)
.format(|bug, record| {
writeln!(
buf,
"{} [{}] {}: {}",
buf.timestamp,
record.level(),
record.target(),
record.args()
)
})
.init();
}

0 comments on commit 269cd52

Please sign in to comment.