mirror of
https://github.com/GyulyVGC/sniffnet.git
synced 2025-12-23 22:29:01 -05:00
use an iced stream to update newer_release_available instead of using a mutex
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -4071,7 +4071,6 @@ dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
@@ -4715,6 +4714,7 @@ dependencies = [
|
||||
"serde_test",
|
||||
"serial_test",
|
||||
"splines",
|
||||
"tokio",
|
||||
"toml 0.8.22",
|
||||
"winres",
|
||||
]
|
||||
|
||||
@@ -55,15 +55,16 @@ phf = "0.11.3"
|
||||
phf_shared = "0.11.3"
|
||||
splines = "4.4.2"
|
||||
clap = { version = "4.5.37", features = ["derive"] }
|
||||
tokio = "1.44.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
gag = "1.0.0"
|
||||
|
||||
[target.'cfg(not(target_arch = "powerpc64"))'.dependencies]
|
||||
reqwest = { version = "0.12.15", default-features = false, features = ["json", "blocking", "rustls-tls"] }
|
||||
reqwest = { version = "0.12.15", default-features = false, features = ["json", "rustls-tls"] }
|
||||
|
||||
[target.'cfg(target_arch = "powerpc64")'.dependencies]
|
||||
reqwest = { version = "0.12.15", features = ["json", "blocking"] }
|
||||
reqwest = { version = "0.12.15", features = ["json"] }
|
||||
|
||||
#───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -123,9 +123,6 @@ fn test_restore_default_configs() {
|
||||
assert_eq!(Configs::load(), Configs::default());
|
||||
|
||||
// only needed because it will delete config files via its Drop implementation
|
||||
Sniffer::new(
|
||||
&Arc::new(Mutex::new(Configs::default())),
|
||||
Arc::new(Mutex::new(Some(true))),
|
||||
);
|
||||
Sniffer::new(&Arc::new(Mutex::new(Configs::default())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
//! GUI bottom footer
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
use iced::widget::text::LineHeight;
|
||||
use iced::widget::tooltip::Position;
|
||||
use iced::widget::{Column, Container, Row, Text, Tooltip, button, rich_text, span};
|
||||
@@ -29,7 +27,7 @@ pub fn footer<'a>(
|
||||
color_gradient: GradientType,
|
||||
font: Font,
|
||||
font_footer: Font,
|
||||
newer_release_available: &Mutex<Option<bool>>,
|
||||
newer_release_available: Option<bool>,
|
||||
) -> Container<'a, Message, StyleType> {
|
||||
if thumbnail {
|
||||
return thumbnail_footer();
|
||||
@@ -188,7 +186,7 @@ fn get_release_details<'a>(
|
||||
language: Language,
|
||||
font: Font,
|
||||
font_footer: Font,
|
||||
newer_release_available: &Mutex<Option<bool>>,
|
||||
newer_release_available: Option<bool>,
|
||||
) -> Row<'a, Message, StyleType> {
|
||||
let mut ret_val = Row::new()
|
||||
.align_y(Alignment::Center)
|
||||
@@ -199,7 +197,7 @@ fn get_release_details<'a>(
|
||||
.size(FONT_SIZE_FOOTER)
|
||||
.font(font_footer),
|
||||
);
|
||||
if let Some(boolean_response) = *newer_release_available.lock().unwrap() {
|
||||
if let Some(boolean_response) = newer_release_available {
|
||||
if boolean_response {
|
||||
// a newer release is available on GitHub
|
||||
let button = button(
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use iced::Event::{Keyboard, Window};
|
||||
use iced::futures::Stream;
|
||||
use iced::keyboard::key::Named;
|
||||
use iced::keyboard::{Event, Key, Modifiers};
|
||||
use iced::mouse::Event::ButtonPressed;
|
||||
use iced::widget::Column;
|
||||
use iced::window::{Id, Level};
|
||||
use iced::{Element, Point, Size, Subscription, Task, window};
|
||||
use iced::{Element, Point, Size, Subscription, Task, stream, window};
|
||||
use pcap::Device;
|
||||
use rfd::FileHandle;
|
||||
|
||||
@@ -58,6 +59,7 @@
|
||||
use crate::report::types::report_sort_type::ReportSortType;
|
||||
use crate::report::types::search_parameters::SearchParameters;
|
||||
use crate::report::types::sort_type::SortType;
|
||||
use crate::secondary_threads::check_updates::set_newer_release_status;
|
||||
use crate::secondary_threads::parse_packets::parse_packets;
|
||||
use crate::translations::types::language::Language;
|
||||
use crate::utils::error_logger::{ErrorLogger, Location};
|
||||
@@ -82,7 +84,7 @@ pub struct Sniffer {
|
||||
/// Capture data updated by thread parsing packets
|
||||
pub info_traffic: Arc<Mutex<InfoTraffic>>,
|
||||
/// Reports if a newer release of the software is available on GitHub
|
||||
pub newer_release_available: Arc<Mutex<Option<bool>>>,
|
||||
pub newer_release_available: Option<bool>,
|
||||
/// Traffic data displayed in GUI
|
||||
pub runtime_data: RunTimeData,
|
||||
/// Network adapter to be analyzed
|
||||
@@ -130,10 +132,7 @@ pub struct Sniffer {
|
||||
}
|
||||
|
||||
impl Sniffer {
|
||||
pub fn new(
|
||||
configs: &Arc<Mutex<Configs>>,
|
||||
newer_release_available: Arc<Mutex<Option<bool>>>,
|
||||
) -> Self {
|
||||
pub fn new(configs: &Arc<Mutex<Configs>>) -> Self {
|
||||
let ConfigSettings {
|
||||
style,
|
||||
language,
|
||||
@@ -146,7 +145,7 @@ pub fn new(
|
||||
configs: configs.clone(),
|
||||
current_capture_id: Arc::new(Mutex::new(0)),
|
||||
info_traffic: Arc::new(Mutex::new(InfoTraffic::new())),
|
||||
newer_release_available,
|
||||
newer_release_available: None,
|
||||
runtime_data: RunTimeData::new(),
|
||||
device,
|
||||
filters: Filters::default(),
|
||||
@@ -254,6 +253,10 @@ fn window_subscription() -> Subscription<Message> {
|
||||
})
|
||||
}
|
||||
|
||||
fn check_updates_stream() -> impl Stream<Item = Message> {
|
||||
stream::channel(1, set_newer_release_status)
|
||||
}
|
||||
|
||||
pub fn update(&mut self, message: Message) -> Task<Message> {
|
||||
match message {
|
||||
Message::TickRun => return self.refresh_data(),
|
||||
@@ -536,6 +539,7 @@ pub fn update(&mut self, message: Message) -> Task<Message> {
|
||||
}
|
||||
}
|
||||
Message::WindowId(id) => self.id = id,
|
||||
Message::SetNewerReleaseStatus(status) => self.newer_release_available = status,
|
||||
Message::TickInit => {}
|
||||
}
|
||||
Task::none()
|
||||
@@ -570,7 +574,7 @@ pub fn view(&self) -> Element<Message, StyleType> {
|
||||
color_gradient,
|
||||
font,
|
||||
font_headers,
|
||||
&self.newer_release_available,
|
||||
self.newer_release_available,
|
||||
);
|
||||
|
||||
let content: Element<Message, StyleType> =
|
||||
@@ -625,6 +629,7 @@ pub fn subscription(&self) -> Subscription<Message> {
|
||||
self.mouse_subscription(),
|
||||
self.time_subscription(),
|
||||
Sniffer::window_subscription(),
|
||||
Subscription::run(Sniffer::check_updates_stream),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -998,15 +1003,12 @@ mod tests {
|
||||
|
||||
// tests using this will require the #[parallel] annotation
|
||||
fn new_sniffer() -> Sniffer {
|
||||
Sniffer::new(
|
||||
&Arc::new(Mutex::new(Configs::default())),
|
||||
Arc::new(Mutex::new(None)),
|
||||
)
|
||||
Sniffer::new(&Arc::new(Mutex::new(Configs::default())))
|
||||
}
|
||||
|
||||
// tests using this will require the #[serial] annotation
|
||||
fn new_sniffer_with_configs(configs: Configs) -> Sniffer {
|
||||
Sniffer::new(&Arc::new(Mutex::new(configs)), Arc::new(Mutex::new(None)))
|
||||
Sniffer::new(&Arc::new(Mutex::new(configs)))
|
||||
}
|
||||
|
||||
// helpful to clean up files generated from tests
|
||||
|
||||
@@ -126,4 +126,6 @@ pub enum Message {
|
||||
ScaleFactorShortcut(bool),
|
||||
/// Set the window ID
|
||||
WindowId(Option<window::Id>),
|
||||
/// Set new release status
|
||||
SetNewerReleaseStatus(Option<bool>),
|
||||
}
|
||||
|
||||
20
src/main.rs
20
src/main.rs
@@ -4,7 +4,7 @@
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{panic, process, thread};
|
||||
use std::{panic, process};
|
||||
|
||||
use iced::advanced::graphics::image::image_rs::ImageFormat;
|
||||
#[cfg(target_os = "linux")]
|
||||
@@ -34,7 +34,6 @@
|
||||
use crate::configs::types::configs::{CONFIGS, Configs};
|
||||
use crate::gui::sniffer::FONT_FAMILY_NAME;
|
||||
use crate::gui::styles::style_constants::{ICONS_BYTES, SARASA_MONO_BOLD_BYTES, SARASA_MONO_BYTES};
|
||||
use crate::secondary_threads::check_updates::set_newer_release_status;
|
||||
use crate::utils::error_logger::{ErrorLogger, Location};
|
||||
|
||||
mod chart;
|
||||
@@ -75,9 +74,6 @@ pub fn main() -> iced::Result {
|
||||
let configs1 = Arc::new(Mutex::new(configs));
|
||||
let configs2 = configs1.clone();
|
||||
|
||||
let newer_release_available1 = Arc::new(Mutex::new(None));
|
||||
let newer_release_available2 = newer_release_available1.clone();
|
||||
|
||||
// kill the main thread as soon as a secondary thread panics
|
||||
let orig_hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |panic_info| {
|
||||
@@ -93,13 +89,6 @@ pub fn main() -> iced::Result {
|
||||
})
|
||||
.log_err(location!());
|
||||
|
||||
let _ = thread::Builder::new()
|
||||
.name("thread_check_updates".to_string())
|
||||
.spawn(move || {
|
||||
set_newer_release_status(&newer_release_available2);
|
||||
})
|
||||
.log_err(location!());
|
||||
|
||||
print_cli_welcome_message();
|
||||
|
||||
let ConfigWindow { size, position, .. } = configs1.lock().unwrap().window;
|
||||
@@ -138,10 +127,5 @@ pub fn main() -> iced::Result {
|
||||
.subscription(Sniffer::subscription)
|
||||
.theme(Sniffer::theme)
|
||||
.scale_factor(Sniffer::scale_factor)
|
||||
.run_with(move || {
|
||||
(
|
||||
Sniffer::new(&configs1, newer_release_available1),
|
||||
boot_task_chain,
|
||||
)
|
||||
})
|
||||
.run_with(move || (Sniffer::new(&configs1), boot_task_chain))
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::sync::Mutex;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::SNIFFNET_LOWERCASE;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::utils::error_logger::ErrorLogger;
|
||||
use crate::utils::formatted_strings::APP_VERSION;
|
||||
use crate::{Location, SNIFFNET_LOWERCASE, location};
|
||||
use iced::futures::SinkExt;
|
||||
use iced::futures::channel::mpsc::Sender;
|
||||
use serde::Deserialize;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct AppVersion {
|
||||
@@ -14,23 +14,27 @@ struct AppVersion {
|
||||
|
||||
/// Calls a method to check if a newer release of Sniffnet is available on GitHub
|
||||
/// and updates application status accordingly
|
||||
pub fn set_newer_release_status(newer_release_available: &Mutex<Option<bool>>) {
|
||||
let result = is_newer_release_available(6, 30);
|
||||
*newer_release_available.lock().unwrap() = result;
|
||||
pub async fn set_newer_release_status(mut sender: Sender<Message>) {
|
||||
let result = is_newer_release_available(6, 30).await;
|
||||
let _ = sender
|
||||
.send(Message::SetNewerReleaseStatus(result))
|
||||
.await
|
||||
.log_err(location!());
|
||||
}
|
||||
|
||||
/// Checks if a newer release of Sniffnet is available on GitHub
|
||||
fn is_newer_release_available(max_retries: u8, seconds_between_retries: u8) -> Option<bool> {
|
||||
let client = reqwest::blocking::Client::new();
|
||||
async fn is_newer_release_available(max_retries: u8, seconds_between_retries: u8) -> Option<bool> {
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.get("https://api.github.com/repos/GyulyVGC/sniffnet/releases/latest")
|
||||
.header("User-agent", format!("{SNIFFNET_LOWERCASE}-{APP_VERSION}"))
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.header("X-GitHub-Api-Version", "2022-11-28")
|
||||
.send();
|
||||
.send()
|
||||
.await;
|
||||
|
||||
if let Ok(result) = response {
|
||||
let result_json = result.json::<AppVersion>();
|
||||
let result_json = result.json::<AppVersion>().await;
|
||||
|
||||
#[cfg(test)]
|
||||
if result_json.is_err() {
|
||||
@@ -39,7 +43,8 @@ fn is_newer_release_available(max_retries: u8, seconds_between_retries: u8) -> O
|
||||
.header("User-agent", format!("{SNIFFNET_LOWERCASE}-{APP_VERSION}"))
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.header("X-GitHub-Api-Version", "2022-11-28")
|
||||
.send();
|
||||
.send()
|
||||
.await;
|
||||
println!("\nResponse text: {:?}", response2.unwrap());
|
||||
println!("JSON result: {result_json:?}\n");
|
||||
}
|
||||
@@ -52,6 +57,7 @@ fn is_newer_release_available(max_retries: u8, seconds_between_retries: u8) -> O
|
||||
latest_version = latest_version.trim().to_string();
|
||||
|
||||
// release name sample: v1.1.2
|
||||
// TODO: support versions with numbers of more than 1 digit
|
||||
let latest_version_as_bytes = latest_version.as_bytes();
|
||||
if latest_version.len() == 6
|
||||
&& latest_version.starts_with('v')
|
||||
@@ -72,8 +78,12 @@ fn is_newer_release_available(max_retries: u8, seconds_between_retries: u8) -> O
|
||||
let retries_left = max_retries - 1;
|
||||
if retries_left > 0 {
|
||||
// sleep seconds_between_retries and retries the request
|
||||
thread::sleep(Duration::from_secs(u64::from(seconds_between_retries)));
|
||||
is_newer_release_available(retries_left, seconds_between_retries)
|
||||
tokio::time::sleep(Duration::from_secs(u64::from(seconds_between_retries))).await;
|
||||
Box::pin(is_newer_release_available(
|
||||
retries_left,
|
||||
seconds_between_retries,
|
||||
))
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user