diff --git a/app/Cargo.toml b/app/Cargo.toml index ddf4e0b..dc6ccc7 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -8,6 +8,7 @@ workspace = true [dependencies] bgtu-networks-2-network-abstract = { path = "../network/abstract" } +bgtu-networks-2-gui-abstract = { path = "../gui/abstract" } bgtu-networks-2-gui-egui = { path = "../gui/egui" } bgtu-networks-2-data = { path = "../data" } diff --git a/app/src/main.rs b/app/src/main.rs index 22d4406..046bf5e 100644 --- a/app/src/main.rs +++ b/app/src/main.rs @@ -4,6 +4,7 @@ use bgtu_networks_2_network_windows::winsocks_scope_2_2; use std::sync::Arc; use std::thread; use bgtu_networks_2_gui_egui::run_eframe_gui; +use bgtu_networks_2_gui_abstract::ServersStorage as ServersGuiCtx; fn main() { winsocks_scope_2_2(NetworkMain {}); @@ -21,10 +22,21 @@ impl NetworkScope for NetworkMain { s.spawn(|| { Ctx::run_ping_eventloop(&mut storage.as_ref().new_network_ctx()); }); - - run_eframe_gui(&mut storage.new_gui_ctx()); + + let network_thread_terminator = NetworkThreadTerminator { ctx: &mut storage.new_gui_ctx() }; + let _ = run_eframe_gui(&mut storage.new_gui_ctx()); + drop(network_thread_terminator); }); - - } } + + +struct NetworkThreadTerminator<'ctx, Ctx: ServersGuiCtx> { + ctx: &'ctx mut Ctx, +} + +impl<'ctx, Ctx: ServersGuiCtx> Drop for NetworkThreadTerminator<'ctx, Ctx> { + fn drop(&mut self) { + self.ctx.terminate(); + } +} \ No newline at end of file diff --git a/data/src/synchronized/mod.rs b/data/src/synchronized/mod.rs index 325bf93..ad97d35 100644 --- a/data/src/synchronized/mod.rs +++ b/data/src/synchronized/mod.rs @@ -61,6 +61,10 @@ impl ServersNetworkCtx for _Impl<'_, A> { let lock_scope = self.data.mutex.read(); unsafe { self.get_unprotected() }.report_error(addr, id); } + + fn is_running(&self) -> bool { + return unsafe { self.get_unprotected() }.is_running(); + } } impl ServersGuiCtx for _Impl<'_, A> { @@ -94,4 +98,8 @@ impl ServersGuiCtx for _Impl<'_, A> { fn graph_sections_count(&self) -> usize { return unsafe { self.get_unprotected() }.graph_sections_count(); } + + fn terminate(&mut self) { + unsafe { self.get_unprotected() }.terminate(); + } } diff --git a/data/src/unprotected.rs b/data/src/unprotected.rs index 16c9a1d..e82d70c 100644 --- a/data/src/unprotected.rs +++ b/data/src/unprotected.rs @@ -3,11 +3,13 @@ use bgtu_networks_2_gui_abstract::ServersStorage as ServersGuiCtx; use bgtu_networks_2_network_abstract::{Address, ServersContext as ServersNetworkCtx}; use std::collections::HashMap; use std::hash::Hash; +use std::sync::atomic::{AtomicBool, Ordering}; pub struct ServersStorage { history_capacity: usize, last_stored_req_id: u64, map: HashMap>)>, + is_running: AtomicBool } impl ServersStorage { @@ -16,6 +18,7 @@ impl ServersStorage { history_capacity, last_stored_req_id: 0, map: HashMap::new(), + is_running: AtomicBool::new(true) }; } @@ -42,6 +45,10 @@ impl ServersNetworkCtx for ServersStorage { } fn report_error(&mut self, _addr: A, _id: u64) {} + + fn is_running(&self) -> bool { + return self.is_running.load(Ordering::Relaxed); + } } impl ServersGuiCtx for ServersStorage { @@ -78,4 +85,8 @@ impl ServersGuiCtx for ServersStorage { fn graph_sections_count(&self) -> usize { return self.history_capacity; } + + fn terminate(&mut self) { + self.is_running.store(false, Ordering::Relaxed) + } } diff --git a/gui/abstract/src/lib.rs b/gui/abstract/src/lib.rs index 835e334..e9aca85 100644 --- a/gui/abstract/src/lib.rs +++ b/gui/abstract/src/lib.rs @@ -4,9 +4,9 @@ pub trait ServersStorage { type Address: Address; fn add_server(&mut self, addr: Self::Address, memo: String); - + fn remove_server(&mut self, addr: &Self::Address); - + fn edit_memo(&mut self, addr: &Self::Address, new_memo: String); // type TimeIterator: Iterator>; @@ -15,4 +15,6 @@ pub trait ServersStorage { ) -> impl Iterator>)>; fn graph_sections_count(&self) -> usize; + + fn terminate(&mut self); } diff --git a/network/abstract/src/lib.rs b/network/abstract/src/lib.rs index 7846f9e..d0613c7 100644 --- a/network/abstract/src/lib.rs +++ b/network/abstract/src/lib.rs @@ -17,6 +17,8 @@ pub trait ServersContext { fn report_ping(&mut self, addr: A, id: u64, ping_ms: u128); fn report_error(&mut self, addr: A, id: u64); + + fn is_running(&self) -> bool; } pub trait NetworkScope { diff --git a/network/windows/src/eventloop/mod.rs b/network/windows/src/eventloop/mod.rs index ddd1cba..e976135 100644 --- a/network/windows/src/eventloop/mod.rs +++ b/network/windows/src/eventloop/mod.rs @@ -30,7 +30,7 @@ pub unsafe fn run_eventloop>(ctx: *mut let mut seq_no = 0u16; - loop { + while (*ctx).is_running() { let (round_id, addrs_it) = (*ctx).start_measuring(); let mut should_recv_being_enabled = false; @@ -50,7 +50,7 @@ pub unsafe fn run_eventloop>(ctx: *mut let delayStart = GetTickCount(); let delayEnd = delayStart.wrapping_add(1000); - loop { + while (*ctx).is_running() { let current = GetTickCount(); if delayStart < delayEnd { if current < delayEnd { diff --git a/network/windows/src/eventloop/socket.rs b/network/windows/src/eventloop/socket.rs index 1dac417..ec8d9db 100644 --- a/network/windows/src/eventloop/socket.rs +++ b/network/windows/src/eventloop/socket.rs @@ -13,7 +13,7 @@ use windows::Win32::Networking::WinSock::{ WSAECONNRESET, WSAEDESTADDRREQ, WSAEFAULT, WSAEHOSTUNREACH, WSAEINPROGRESS, WSAEINTR, WSAEINVAL, WSAEMSGSIZE, WSAENETDOWN, WSAENETRESET, WSAENETUNREACH, WSAENOBUFS, WSAENOTCONN, WSAENOTSOCK, WSAESHUTDOWN, WSAEWOULDBLOCK, WSAGetLastError, WSANOTINITIALISED, WSARecvFrom, - WSASendTo, WSASocketW, + WSASendTo, WSASocketW, closesocket, }; use windows::Win32::System::IO::OVERLAPPED; @@ -184,3 +184,13 @@ impl<'a> WindowsOverlappingIcmpSocket<'a> { } } } + +impl Drop for WindowsOverlappingIcmpSocket<'_> { + fn drop(&mut self) { + unsafe { + if closesocket(self.socket) == SOCKET_ERROR { + throw_from_windows_err_code(WSAGetLastError()) + } + } + } +}