Skip to content

Commit

Permalink
Move Event and Overlapped to talpid-windows crate
Browse files Browse the repository at this point in the history
  • Loading branch information
dlon committed Oct 20, 2023
1 parent f2c6041 commit ca98809
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 112 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions talpid-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ winreg = { version = "0.51", features = ["transactions"] }
memoffset = "0.6"
windows-service = "0.6.0"
talpid-windows-net = { path = "../talpid-windows-net" }
talpid-windows = { path = "../talpid-windows" }

[target.'cfg(windows)'.dependencies.windows-sys]
workspace = true
Expand Down
7 changes: 4 additions & 3 deletions talpid-core/src/split_tunnel/windows/driver.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::windows::{
get_device_path, get_process_creation_time, get_process_device_path, open_process, Event,
Overlapped, ProcessAccess, ProcessSnapshot,
get_device_path, get_process_creation_time, get_process_device_path, open_process,
ProcessAccess, ProcessSnapshot,
};
use bitflags::bitflags;
use memoffset::offset_of;
Expand All @@ -22,6 +22,7 @@ use std::{
time::Duration,
};
use talpid_types::ErrorExt;
use talpid_windows::{io::Overlapped, sync::Event};
use windows_sys::Win32::{
Foundation::{
ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND, ERROR_INVALID_PARAMETER, ERROR_IO_PENDING,
Expand Down Expand Up @@ -877,7 +878,7 @@ pub fn get_overlapped_result(
let event = overlapped.get_event().unwrap();

// SAFETY: This is a valid event object.
unsafe { wait_for_single_object(event.as_handle(), None) }?;
unsafe { wait_for_single_object(event.as_raw(), None) }?;

// SAFETY: The handle and overlapped object are valid.
let mut returned_bytes = 0u32;
Expand Down
31 changes: 19 additions & 12 deletions talpid-core/src/split_tunnel/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub struct SplitTunnel {
runtime: tokio::runtime::Handle,
request_tx: RequestTx,
event_thread: Option<std::thread::JoinHandle<()>>,
quit_event: Arc<windows::Event>,
quit_event: Arc<talpid_windows::sync::Event>,
excluded_processes: Arc<RwLock<HashMap<usize, ExcludedProcess>>>,
_route_change_callback: Option<CallbackHandle>,
daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>,
Expand Down Expand Up @@ -191,14 +191,21 @@ impl SplitTunnel {
fn spawn_event_listener(
handle: Arc<driver::DeviceHandle>,
excluded_processes: Arc<RwLock<HashMap<usize, ExcludedProcess>>>,
) -> Result<(std::thread::JoinHandle<()>, Arc<windows::Event>), Error> {
let mut event_overlapped = windows::Overlapped::new(Some(
windows::Event::new(true, false).map_err(Error::EventThreadError)?,
) -> Result<
(
std::thread::JoinHandle<()>,
Arc<talpid_windows::sync::Event>,
),
Error,
> {
let mut event_overlapped = talpid_windows::io::Overlapped::new(Some(
talpid_windows::sync::Event::new(true, false).map_err(Error::EventThreadError)?,
))
.map_err(Error::EventThreadError)?;

let quit_event =
Arc::new(windows::Event::new(true, false).map_err(Error::EventThreadError)?);
let quit_event = Arc::new(
talpid_windows::sync::Event::new(true, false).map_err(Error::EventThreadError)?,
);
let quit_event_copy = quit_event.clone();

let event_thread = std::thread::spawn(move || {
Expand Down Expand Up @@ -237,11 +244,11 @@ impl SplitTunnel {

fn fetch_next_event(
device: &Arc<driver::DeviceHandle>,
quit_event: &windows::Event,
overlapped: &mut windows::Overlapped,
quit_event: &talpid_windows::sync::Event,
overlapped: &mut talpid_windows::io::Overlapped,
data_buffer: &mut Vec<u8>,
) -> io::Result<EventResult> {
if unsafe { driver::wait_for_single_object(quit_event.as_handle(), Some(Duration::ZERO)) }
if unsafe { driver::wait_for_single_object(quit_event.as_raw(), Some(Duration::ZERO)) }
.is_ok()
{
return Ok(EventResult::Quit);
Expand All @@ -268,8 +275,8 @@ impl SplitTunnel {
})?;

let event_objects = [
overlapped.get_event().unwrap().as_handle(),
quit_event.as_handle(),
overlapped.get_event().unwrap().as_raw(),
quit_event.as_raw(),
];

let signaled_object =
Expand All @@ -283,7 +290,7 @@ impl SplitTunnel {
},
)?;

if signaled_object == quit_event.as_handle() {
if signaled_object == quit_event.as_raw() {
// Quit event was signaled
return Ok(EventResult::Quit);
}
Expand Down
99 changes: 2 additions & 97 deletions talpid-core/src/split_tunnel/windows/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::{
};
use windows_sys::Win32::{
Foundation::{
CloseHandle, BOOL, ERROR_INSUFFICIENT_BUFFER, ERROR_NO_MORE_FILES, FILETIME, HANDLE,
CloseHandle, ERROR_INSUFFICIENT_BUFFER, ERROR_NO_MORE_FILES, FILETIME, HANDLE,
INVALID_HANDLE_VALUE,
},
Storage::FileSystem::{GetFinalPathNameByHandleW, QueryDosDeviceW},
Expand All @@ -22,11 +22,8 @@ use windows_sys::Win32::{
CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W,
},
ProcessStatus::GetProcessImageFileNameW,
Threading::{
CreateEventW, GetProcessTimes, OpenProcess, SetEvent, PROCESS_QUERY_LIMITED_INFORMATION,
},
Threading::{GetProcessTimes, OpenProcess, PROCESS_QUERY_LIMITED_INFORMATION},
WindowsProgramming::VOLUME_NAME_NT,
IO::OVERLAPPED,
},
};

Expand Down Expand Up @@ -299,95 +296,3 @@ fn get_process_device_path_inner(

Ok(OsStringExt::from_wide(&buffer))
}

/// Abstraction over `OVERLAPPED`, which is used for async I/O.
pub struct Overlapped {
overlapped: OVERLAPPED,
event: Option<Event>,
}

unsafe impl Send for Overlapped {}
unsafe impl Sync for Overlapped {}

impl Overlapped {
/// Creates an `OVERLAPPED` object with `hEvent` set.
pub fn new(event: Option<Event>) -> io::Result<Self> {
let mut overlapped = Overlapped {
overlapped: unsafe { mem::zeroed() },
event: None,
};
overlapped.set_event(event);
Ok(overlapped)
}

/// Borrows the underlying `OVERLAPPED` object.
pub fn as_mut_ptr(&mut self) -> *mut OVERLAPPED {
&mut self.overlapped
}

/// Returns a reference to the associated event.
pub fn get_event(&self) -> Option<&Event> {
self.event.as_ref()
}

/// Sets the event object for the underlying `OVERLAPPED` object (i.e., `hEvent`)
fn set_event(&mut self, event: Option<Event>) {
match event {
Some(event) => {
self.overlapped.hEvent = event.0;
self.event = Some(event);
}
None => {
self.overlapped.hEvent = 0;
self.event = None;
}
}
}
}

/// Abstraction over a Windows event object.
pub struct Event(HANDLE);

unsafe impl Send for Event {}
unsafe impl Sync for Event {}

impl Event {
pub fn new(manual_reset: bool, initial_state: bool) -> io::Result<Self> {
let event = unsafe {
CreateEventW(
ptr::null_mut(),
bool_to_winbool(manual_reset),
bool_to_winbool(initial_state),
ptr::null(),
)
};
if event == 0 {
return Err(io::Error::last_os_error());
}
Ok(Self(event))
}

pub fn set(&self) -> io::Result<()> {
if unsafe { SetEvent(self.0) } == 0 {
return Err(io::Error::last_os_error());
}
Ok(())
}

pub fn as_handle(&self) -> HANDLE {
self.0
}
}

impl Drop for Event {
fn drop(&mut self) {
unsafe { CloseHandle(self.0) };
}
}

const fn bool_to_winbool(val: bool) -> BOOL {
match val {
true => 1,
false => 0,
}
}
21 changes: 21 additions & 0 deletions talpid-windows/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "talpid-windows"
description = "Nice abstractions for Windows"
version.workspace = true
authors.workspace = true
repository.workspace = true
license.workspace = true
edition.workspace = true
publish.workspace = true

[target.'cfg(windows)'.dependencies.windows-sys]
workspace = true
features = [
"Win32_Foundation",
"Win32_Globalization",
"Win32_System_Com",
"Win32_System_IO",
"Win32_Networking_WinSock",
"Win32_NetworkManagement_IpHelper",
"Win32_NetworkManagement_Ndis",
]
49 changes: 49 additions & 0 deletions talpid-windows/src/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::{io, mem};
use windows_sys::Win32::System::IO::OVERLAPPED;

use crate::sync::Event;

/// Abstraction over `OVERLAPPED`.
pub struct Overlapped {
overlapped: OVERLAPPED,
event: Option<Event>,
}

unsafe impl Send for Overlapped {}
unsafe impl Sync for Overlapped {}

impl Overlapped {
/// Creates an `OVERLAPPED` object with `hEvent` set.
pub fn new(event: Option<Event>) -> io::Result<Self> {
let mut overlapped = Overlapped {
overlapped: unsafe { mem::zeroed() },
event: None,
};
overlapped.set_event(event);
Ok(overlapped)
}

/// Borrows the underlying `OVERLAPPED` object.
pub fn as_mut_ptr(&mut self) -> *mut OVERLAPPED {
&mut self.overlapped
}

/// Returns a reference to the associated event.
pub fn get_event(&self) -> Option<&Event> {
self.event.as_ref()
}

/// Sets the event object for the underlying `OVERLAPPED` object (i.e., `hEvent`)
fn set_event(&mut self, event: Option<Event>) {
match event {
Some(event) => {
self.overlapped.hEvent = event.as_raw();
self.event = Some(event);
}
None => {
self.overlapped.hEvent = 0;
self.event = None;
}
}
}
}
12 changes: 12 additions & 0 deletions talpid-windows/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Interface with low-level windows specific bits.
#![deny(missing_docs)]
#![deny(rust_2018_idioms)]

/// Windows I/O
#[cfg(windows)]
pub mod io;

/// Synchronization (event objects, etc.)
#[cfg(windows)]
pub mod sync;
Loading

0 comments on commit ca98809

Please sign in to comment.