diff --git a/network/windows/Cargo.toml b/network/windows/Cargo.toml index 9630935..8279b34 100644 --- a/network/windows/Cargo.toml +++ b/network/windows/Cargo.toml @@ -12,4 +12,4 @@ bgtu-networks-2-network-abstract = { path = "../abstract" } [dependencies.windows] version = ">=0.41.0, <=0.62.2" registry = "crates-io" -features = ["Win32_System_IO", "Win32_Networking", "Win32_Networking_WinSock", "Win32_System_Diagnostics", "Win32_System_Diagnostics_Debug", "Win32_System_Threading"] \ No newline at end of file +features = ["Win32_System_IO", "Win32_Networking", "Win32_Networking_WinSock", "Win32_System_Diagnostics", "Win32_System_Diagnostics_Debug", "Win32_System_Threading", "Win32_System_Memory"] \ No newline at end of file diff --git a/network/windows/src/errors.rs b/network/windows/src/errors.rs index 7abba52..bcab8df 100644 --- a/network/windows/src/errors.rs +++ b/network/windows/src/errors.rs @@ -2,7 +2,7 @@ use std::ffi::{CStr, CString, c_char}; use std::ptr; use std::ptr::null_mut; use std::slice::from_raw_parts_mut; -use windows::Win32::Foundation::{HLOCAL, LocalFree}; +use windows::Win32::Foundation::{HLOCAL, LocalFree, WIN32_ERROR}; use windows::Win32::Networking::WinSock::WSA_ERROR; use windows::Win32::System::Diagnostics::Debug::{ FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS, @@ -39,6 +39,12 @@ impl ErrCode for HRESULT { } } +impl ErrCode for WIN32_ERROR { + fn to_dword(&self) -> u32 { + return self.0 + } +} + pub(super) fn throw_from_windows_err_code(code: impl ErrCode) -> ! { panic!( "Windows error [{:X}]: {}", diff --git a/network/windows/src/eventloop/allocator.rs b/network/windows/src/eventloop/allocator.rs index ecee487..3a4dc53 100644 --- a/network/windows/src/eventloop/allocator.rs +++ b/network/windows/src/eventloop/allocator.rs @@ -1,30 +1,95 @@ -use std::collections::HashMap; -use std::mem::uninitialized; +use crate::errors::throw_from_windows_err_code; +use std::mem::{offset_of, uninitialized}; use std::pin::Pin; use std::ptr; +use std::ptr::{NonNull, null_mut}; +use windows::Win32::Foundation::{GetLastError, HANDLE}; +use windows::Win32::System::Memory::{HEAP_FLAGS, HEAP_NO_SERIALIZE, HeapAlloc, HeapCreate}; -pub(crate) struct Allocator { - map: HashMap>>, +pub(crate) struct Allocator { + win_heap: HANDLE, + last: Option>, } -impl Allocator { +trait Cell { + fn get_prev(&self) -> Option>; + fn set_prev(&mut self, p: Option>); + fn get_next(&self) -> Option>; + fn set_next(&mut self, p: Option>); +} + +struct CellImpl { + prev: Option>, + next: Option>, + value: T, +} + +impl Cell for CellImpl { + fn get_prev(&self) -> Option> { + return self.prev; + } + + fn set_prev(&mut self, p: Option>) { + self.prev = p; + } + + fn get_next(&self) -> Option> { + return self.next; + } + + fn set_next(&mut self, p: Option>) { + self.next = p; + } +} + +impl Allocator { pub fn new() -> Self { - return Self { - map: HashMap::new(), - }; + unsafe { + let h; + match HeapCreate(HEAP_NO_SERIALIZE, 0, 0) { + Ok(hh) => h = hh, + Err(err) => throw_from_windows_err_code(err.code()), + } + return Allocator { + win_heap: h, + last: None, + }; + } } - pub unsafe fn alloc<'s>(&'s mut self) -> Pin<&'s mut T> { - let ptr = Box::pin(uninitialized::()); - let addr = ptr::from_ref(ptr.as_ref().get_ref()).addr(); - self.map.insert(addr, ptr); - return self - .map - .get_mut(&addr) - .unwrap_or_else(|| unreachable!()) - .as_mut(); + pub unsafe fn alloc<'s, T: Drop + 'static>( + &'s mut self, + init: impl FnOnce(Pin<&mut T>), + ) -> Pin<&'s mut T> { + let mut p = NonNull::new( + HeapAlloc( + self.win_heap, + HEAP_FLAGS::default(), + size_of::>(), + ) + .cast::>(), + ) + .unwrap_or_else(|| throw_from_windows_err_code(GetLastError())); + + if let Some(mut last) = self.last { + last.as_mut().set_next(Some(p)); + } + p.as_mut().prev = self.last; + p.as_mut().next = None; + self.last = Some(p); + + init(Pin::new_unchecked(&mut p.as_mut().value)); + + return Pin::new_unchecked(&mut p.as_mut().value); } - pub unsafe fn free(&mut self, p: Pin<&mut T>) { + pub unsafe fn free(&mut self, p: Pin<&mut T>) { + let p = Pin::into_inner_unchecked(p); + let c = NonNull::new_unchecked( + NonNull::new_unchecked(p) + .as_ptr() + .map_addr(|a| a - offset_of!(CellImpl, value)) + .cast::>(), + ); } } diff --git a/network/windows/src/eventloop/mod.rs b/network/windows/src/eventloop/mod.rs index 127bb9b..53e3111 100644 --- a/network/windows/src/eventloop/mod.rs +++ b/network/windows/src/eventloop/mod.rs @@ -15,16 +15,16 @@ use windows::Win32::System::IO::OVERLAPPED; use windows::Win32::System::Threading::SleepEx; pub unsafe fn run_eventloop>(ctx: *mut Ctx) { - let mut heap = Allocator::>>::new(); + let mut heap = Allocator::new(); let mut socket = WindowsOverlappingIcmpSocket::new(); - let mut recv_task = NonNull::from_mut(&mut heap).as_mut().alloc(); - CallbackData::init_recv( - &mut recv_task, + let mut recv_task = NonNull::from_mut(&mut heap).as_mut().alloc(|mut p| CallbackData::init_recv( + &mut p, NonNull::new_unchecked(ctx), NonNull::from_mut(&mut heap), - ); + )); + let mut is_receive_enabled = false; @@ -33,13 +33,13 @@ pub unsafe fn run_eventloop>(ctx: *mut let mut should_recv_being_enabled = false; for address in it { - let mut task = NonNull::from_mut(&mut heap).as_mut().alloc(); - CallbackData::init_send( - &mut task, + let mut task = NonNull::from_mut(&mut heap).as_mut().alloc(|mut p| CallbackData::init_send( + &mut p, NonNull::new_unchecked(ctx), NonNull::from_mut(&mut heap), address, - ); + )); + socket.send(&mut task, Some(sending_done::)); should_recv_being_enabled = true; @@ -56,7 +56,7 @@ pub unsafe fn run_eventloop>(ctx: *mut struct CallbackData> { ctx: NonNull, - allocator: NonNull>>, + allocator: NonNull, address: WindowsAddressKnown, __flags: u32, __addrs_size: i32, @@ -66,7 +66,7 @@ impl> CallbackData { fn init_send( task: &mut Pin<&mut IoTask>>, ctx: NonNull, - allocator: NonNull>>, + allocator: NonNull, address: WindowsAddressKnown, ) { task.init(Self { @@ -80,7 +80,7 @@ impl> CallbackData { fn init_recv( task: &mut Pin<&mut IoTask>>, ctx: NonNull, - allocator: NonNull>>, + allocator: NonNull, ) { task.init(Self { ctx, diff --git a/network/windows/src/eventloop/task.rs b/network/windows/src/eventloop/task.rs index 42bc9c2..a95ac6f 100644 --- a/network/windows/src/eventloop/task.rs +++ b/network/windows/src/eventloop/task.rs @@ -46,3 +46,9 @@ impl IoTask { return &mut unsafe { Pin::into_inner_unchecked(NonNull::from_mut(self).read()) }.sys; } } + +impl Drop for IoTask { + fn drop(&mut self) { + todo!() + } +} \ No newline at end of file