diff --git a/.idea/kvm.iml b/.idea/kvm.iml index ff5191c..0db8344 100644 --- a/.idea/kvm.iml +++ b/.idea/kvm.iml @@ -7,6 +7,7 @@ + diff --git a/Cargo.lock b/Cargo.lock index a98c398..ed0d39f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "client" version = "0.1.0" @@ -10,19 +22,170 @@ dependencies = [ ] [[package]] -name = "libc" -version = "0.2.140" +name = "hermit-abi" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "input" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeb3afdf1f8137428002b354eaf87aa629178995683941d94b04c6d145ec8937" +dependencies = [ + "bitflags", + "input-sys", + "io-lifetimes", + "libc", + "log", + "udev", +] + +[[package]] +name = "input-sys" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f6c2a17e8aba7217660e32863af87b0febad811d4b8620ef76b386603fddc2" +dependencies = [ + "libc", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "libc" +version = "0.2.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" + +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "linux" +version = "0.1.0" +dependencies = [ + "libc", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] [[package]] name = "messages" version = "0.1.0" +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + [[package]] name = "server" version = "0.1.0" dependencies = [ + "input", "libc", + "linux", "messages", ] + +[[package]] +name = "udev" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebdbbd670373442a12fe9ef7aeb53aec4147a5a27a00bbc3ab639f08f48191a" +dependencies = [ + "libc", + "libudev-sys", + "pkg-config", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/linux/Cargo.toml b/linux/Cargo.toml new file mode 100644 index 0000000..0692338 --- /dev/null +++ b/linux/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "linux" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2.140" diff --git a/linux/src/buf_utils.rs b/linux/src/buf_utils.rs new file mode 100644 index 0000000..5f6c4ae --- /dev/null +++ b/linux/src/buf_utils.rs @@ -0,0 +1,13 @@ +pub fn read_i32(buf: &[u8]) -> i32 { + (buf[3] as i32) << 24 | + (buf[2] as i32) << 16 | + (buf[1] as i32) << 8 | + buf[0] as i32 +} + +pub fn read_u32(buf: &[u8]) -> u32 { + (buf[3] as u32) << 24 | + (buf[2] as u32) << 16 | + (buf[1] as u32) << 8 | + buf[0] as u32 +} diff --git a/linux/src/epoll.rs b/linux/src/epoll.rs new file mode 100644 index 0000000..845c51c --- /dev/null +++ b/linux/src/epoll.rs @@ -0,0 +1,140 @@ +use std::io; +use std::os::fd::RawFd; + +use libc::epoll_event; + +use crate::syscall; + +const EVENTS_CAPACITY: usize = 1024; +const WAIT_MAX_EVENTS: i32 = 1024; +const WAIT_TIMEOUT: i32 = 1000; + +#[repr(i32)] +#[derive(Copy, Clone)] +pub enum EpollFlags { + // Events + In = libc::EPOLLIN, + Err = libc::EPOLLERR, + Hup = libc::EPOLLHUP, + Out = libc::EPOLLOUT, + Pri = libc::EPOLLPRI, + RdHup = libc::EPOLLRDHUP, + + // Flags + Et = libc::EPOLLET, + Exclusive = libc::EPOLLEXCLUSIVE, + OneShot = libc::EPOLLONESHOT, + WakeUp = libc::EPOLLWAKEUP, +} + +#[repr(i32)] +pub enum EpollOp { + Add = libc::EPOLL_CTL_ADD, + Modify = libc::EPOLL_CTL_MOD, + Delete = libc::EPOLL_CTL_DEL, +} + +pub struct Epoll { + fd: RawFd, + flag: u32, + pub events: Vec, +} + +impl Epoll { + pub fn new() -> io::Result { + Self::with_flags(&[]) + } + + pub fn with_flags(flags: &[EpollFlags]) -> io::Result { + let flag = epoll_flags_as_u32(flags); + + match epoll_create() { + Ok(fd) => Ok(Epoll { + fd, + flag, + events: Vec::with_capacity(EVENTS_CAPACITY), + }), + Err(e) => Err(e), + } + } + + pub fn add_interest(&self, fd: RawFd, key: u64, flags: &[EpollFlags]) -> io::Result<()> { + epoll_add_interest(self.fd, fd, self.create_epoll_event(key, flags)) + } + + pub fn modify_interest(&self, fd: RawFd, key: u64, flags: &[EpollFlags]) -> io::Result<()> { + epoll_modify_interest(self.fd, fd, self.create_epoll_event(key, flags)) + } + + fn create_epoll_event(&self, key: u64, flags: &[EpollFlags]) -> epoll_event { + epoll_event { + events: self.flag | epoll_flags_as_u32(flags), + u64: key as u64, + } + } + + pub fn wait(&mut self) -> io::Result<()> { + self.events.clear(); + match epoll_wait(self.fd, &mut self.events, WAIT_MAX_EVENTS, WAIT_TIMEOUT) { + Ok(res) => { + // safe as long as the kernel does nothing wrong - copied from mio + unsafe { self.events.set_len(res) } + Ok(()) + } + Err(e) => Err(e) + } + } +} + +impl EpollFlags { + pub fn flag_match(&self, event: u32) -> bool { + let expected_flag = *self as i32; + event as i32 & expected_flag == expected_flag + } +} + +fn epoll_create() -> io::Result { + let fd = syscall!(epoll_create1(0))?; + if let Ok(flags) = syscall!(fcntl(fd, libc::F_GETFD)) { + let _ = syscall!(fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC)); + } + + Ok(fd) +} + +fn epoll_wait(epoll_fd: RawFd, events: &mut Vec, max_events: i32, timeout: i32) -> io::Result { + match syscall!(epoll_wait( + epoll_fd, + events.as_mut_ptr() as *mut libc::epoll_event, + max_events, + timeout as libc::c_int + )) { + Ok(v) => Ok(v as usize), + Err(e) => Err(e) + } +} + +fn epoll_add_interest(epoll_fd: RawFd, fd: RawFd, event: epoll_event) -> io::Result<()> { + epoll_ctl(epoll_fd, fd, event, EpollOp::Add) +} + +fn epoll_modify_interest(epoll_fd: RawFd, fd: RawFd, event: epoll_event) -> io::Result<()> { + epoll_ctl(epoll_fd, fd, event, EpollOp::Modify) +} + +fn epoll_delete_interest(epoll_fd: RawFd, fd: RawFd) -> io::Result<()> { + let event = epoll_event { events: 0, u64: 0 }; // event will be ignored + epoll_ctl(epoll_fd, fd, event, EpollOp::Delete) +} + +fn epoll_ctl(epoll_fd: RawFd, fd: RawFd, mut event: epoll_event, op: EpollOp) -> io::Result<()> { + syscall!(epoll_ctl(epoll_fd, op as i32, fd, &mut event))?; + Ok(()) +} + +fn epoll_flags_as_u32(flags: &[EpollFlags]) -> u32 { + let mut val = 0i32; + flags.into_iter().for_each(|flag| val |= *flag as i32); + val as u32 +} + diff --git a/linux/src/inotify.rs b/linux/src/inotify.rs new file mode 100644 index 0000000..53fba50 --- /dev/null +++ b/linux/src/inotify.rs @@ -0,0 +1,131 @@ +use std::ffi::{CStr, CString}; +use std::fs::File; +use std::io; +use std::io::Read; +use std::os::fd::{AsRawFd, FromRawFd, RawFd}; + +use libc::inotify_event; + +use crate::buf_utils::{read_i32, read_u32}; +use crate::syscall; + +const INOTIFY_EVENT_BUFFER_CAPACITY: usize = 4096; +const INOTIFY_EVENT_SIZE: usize = std::mem::size_of::(); + +#[derive(Copy, Clone, Debug)] +#[repr(u32)] +pub enum InotifyEvent { + Access = libc::IN_ACCESS, + Attrib = libc::IN_ATTRIB, + CloseWrite = libc::IN_CLOSE_WRITE, + CloseNoWrite = libc::IN_CLOSE_NOWRITE, + Create = libc::IN_CREATE, + Delete = libc::IN_DELETE, + DeleteSelf = libc::IN_DELETE_SELF, + Modify = libc::IN_MODIFY, + MoveSelf = libc::IN_MOVE_SELF, + MovedFrom = libc::IN_MOVED_FROM, + MovedTo = libc::IN_MOVED_TO, + Open = libc::IN_OPEN, +} + +const IN_ALL_EVENTS: [InotifyEvent; 12] = [ + InotifyEvent::Access, + InotifyEvent::Attrib, + InotifyEvent::CloseWrite, + InotifyEvent::CloseNoWrite, + InotifyEvent::Create, + InotifyEvent::Delete, + InotifyEvent::DeleteSelf, + InotifyEvent::Modify, + InotifyEvent::MoveSelf, + InotifyEvent::MovedFrom, + InotifyEvent::MovedTo, + InotifyEvent::Open, +]; + +pub struct Inotify { + file: File, + pub events: Vec, +} + +pub struct Watch { + wd: RawFd, +} + +impl Inotify { + pub fn new() -> io::Result { + let fd = inotify_init()?; + let file = unsafe { File::from_raw_fd(fd) }; + + Ok(Inotify { + file, + events: Vec::new(), + }) + } + + pub fn watch(&self, path: &str, events: &[InotifyEvent]) -> io::Result { + let wd = inotify_add_watch(self.file.as_raw_fd(), path, events)?; + Ok(Watch { wd }) + } + + pub fn wait(&mut self) -> io::Result<()> { + let mut buf = [0u8; INOTIFY_EVENT_BUFFER_CAPACITY]; + let read_size = self.file.read(&mut buf)?; // Should block + + self.events.clear(); + + // Read events + for i in 0..(read_size / INOTIFY_EVENT_SIZE) { + let offset = INOTIFY_EVENT_SIZE * i; + let event_buf = &buf[offset..offset + INOTIFY_EVENT_SIZE]; + + self.events.push(inotify_event { + wd: read_i32(&event_buf), + mask: read_u32(&event_buf[4..]), + cookie: read_u32(&event_buf[8..]), + len: read_u32(&event_buf[12..]), + }); + } + + Ok(()) + } +} + +impl Watch {} + +fn inotify_init() -> io::Result { + syscall!(inotify_init()) +} + +fn inotify_add_watch(fd: RawFd, path: &str, events: &[InotifyEvent]) -> io::Result { + let c_path = CString::new(path).unwrap(); + let mask = events_as_mask(events); + + let wd = syscall!(inotify_add_watch(fd, c_path.as_ptr(), mask))?; + Ok(wd) +} + +fn inotify_rm_watch(fd: RawFd, wd: RawFd) -> io::Result<()> { + syscall!(inotify_rm_watch(fd, wd))?; + Ok(()) +} + +fn events_as_mask(events: &[InotifyEvent]) -> u32 { + let mut mask = 0; + events.into_iter().for_each(|event| mask |= *event as u32); + mask +} + +pub fn mask_as_events(mask: u32) -> Vec { + let mut events = Vec::new(); + + for event in IN_ALL_EVENTS { + let event_u32 = event as u32; + if mask & event_u32 == event_u32 { + events.push(event); + } + } + + events +} diff --git a/linux/src/lib.rs b/linux/src/lib.rs new file mode 100644 index 0000000..4a9b552 --- /dev/null +++ b/linux/src/lib.rs @@ -0,0 +1,15 @@ +pub mod epoll; +pub mod inotify; +mod buf_utils; + +#[macro_export] +macro_rules! syscall { + ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{ + let res = unsafe { libc::$fn($($arg, )*) }; + if res == -1 { + Err(std::io::Error::last_os_error()) + } else { + Ok(res) + } + }}; +} diff --git a/server/Cargo.toml b/server/Cargo.toml index 6b9d405..fb45b89 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -4,5 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -libc = "0.2.140" -messages = { path = "../messages" } \ No newline at end of file +messages = { path = "../messages" } +linux = { path = "../linux" } +input = "0.8.2" +libc = "0.2.141" diff --git a/server/src/input/events/mod.rs b/server/src/input/events/mod.rs new file mode 100644 index 0000000..9e96c5b --- /dev/null +++ b/server/src/input/events/mod.rs @@ -0,0 +1 @@ +pub mod pointer; diff --git a/server/src/input/events/pointer.rs b/server/src/input/events/pointer.rs new file mode 100644 index 0000000..282f288 --- /dev/null +++ b/server/src/input/events/pointer.rs @@ -0,0 +1,29 @@ +pub enum PointerEvent { + Motion(PointerMotionEvent), + Button(PointerButtonEvent), + Scroll(PointerScrollEvent), +} + +pub enum Axis { + Horizontal = 0, + Vertical = 1, +} + +pub struct PointerButtonEvent { + pub button: u32, + pub seat_button_count: u32, + pub button_state: u32, +} + +pub struct PointerMotionEvent { + pub dx: f64, + pub dx_unaccelerated: f64, + pub dy: f64, + pub dy_unaccelerated: f64, +} + +pub struct PointerScrollEvent { + pub axis: Axis, + pub scroll_value: f64, + pub scroll_value_v120: f64, +} diff --git a/server/src/input/mod.rs b/server/src/input/mod.rs new file mode 100644 index 0000000..9b6e42d --- /dev/null +++ b/server/src/input/mod.rs @@ -0,0 +1,42 @@ +mod events; + +use std::fs::{File, OpenOptions}; +use std::io; +use std::os::fd::OwnedFd; +use std::os::unix::fs::OpenOptionsExt; +use std::path::Path; + +use input::{Libinput, LibinputInterface}; +use libc::{O_RDONLY, O_RDWR, O_WRONLY}; + +const UDEV_SEAT: &str = "seat0"; + +struct Interface; + +impl LibinputInterface for Interface { + fn open_restricted(&mut self, path: &Path, flags: i32) -> Result { + OpenOptions::new() + .custom_flags(flags) + .read((flags & O_RDONLY == O_RDONLY) | (flags & O_RDWR == O_RDWR)) + .write((flags & O_WRONLY == O_WRONLY) | (flags & O_RDWR == O_RDWR)) + .open(path) + .map(|file| file.into()) + .map_err(|err| err.raw_os_error().unwrap()) + } + + fn close_restricted(&mut self, fd: OwnedFd) { + File::from(fd); + } +} + +pub(crate) fn read_inputs() -> io::Result<()> { + let mut input = Libinput::new_with_udev(Interface); + input.udev_assign_seat(UDEV_SEAT).unwrap(); + loop { + input.dispatch().unwrap(); + for event in &mut input { + // event. + println!("Got event: {:?}", event); + } + } +} diff --git a/server/src/main.rs b/server/src/main.rs index 264531d..28fb3d1 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,16 +5,20 @@ use std::net::SocketAddr; use messages::client_registration::ClientRegistration; use messages::serialization::{DeserializeMessage, read_message_data, SerializeMessage}; +use crate::input::read_inputs; use crate::net::tcp_server::{NextIntent, TcpClient, TcpServer}; mod net; +mod input; mod client; fn main() -> io::Result<()> { - let addr = SocketAddr::from(([127, 0, 0, 1], 4433)); - let mut server: TcpServer = TcpServer::new(addr)?; + // let addr = SocketAddr::from(([127, 0, 0, 1], 4433)); + // let mut server: TcpServer = TcpServer::new(addr)?; + // + // server.listen()?; - server.listen()?; + read_inputs()?; Ok(()) } diff --git a/server/src/net/epoll.rs b/server/src/net/epoll.rs deleted file mode 100644 index c7ff9b2..0000000 --- a/server/src/net/epoll.rs +++ /dev/null @@ -1,113 +0,0 @@ -use std::io; -use std::os::fd::RawFd; - -use libc::{epoll_event}; - -const EVENTS_CAPACITY: usize = 1024; -const WAIT_MAX_EVENTS: i32 = 1024; -const WAIT_TIMEOUT: i32 = 1000; - -pub struct Epoll { - fd: RawFd, - pub events: Vec, -} - -#[derive(Copy, Clone)] -#[repr(i32)] -pub enum EpollEvent { - Read = libc::EPOLLIN, - Write = libc::EPOLLOUT, - Disconnect = libc::EPOLLRDHUP, -} - -impl Epoll { - pub fn create() -> io::Result { - match epoll_create() { - Ok(fd) => Ok(Epoll { - fd, - events: Vec::with_capacity(EVENTS_CAPACITY), - }), - Err(e) => Err(e), - } - } - - pub fn add_interest(&self, fd: RawFd, key: u16, events: &[EpollEvent]) -> io::Result<()> { - add_interest(self.fd, fd, create_oneshot_epoll_event(key, events)) - } - - pub fn modify_interest(&self, fd: RawFd, key: u16, events: &[EpollEvent]) -> io::Result<()> { - modify_interest(self.fd, fd, create_oneshot_epoll_event(key, events)) - } - - pub fn wait(&mut self) -> io::Result<()> { - self.events.clear(); - match epoll_wait(self.fd, &mut self.events, WAIT_MAX_EVENTS, WAIT_TIMEOUT) { - Ok(res) => { - // safe as long as the kernel does nothing wrong - copied from mio - unsafe { self.events.set_len(res) } - Ok(()) - } - Err(e) => Err(e) - } - } -} - -pub fn match_epoll_event(event: u32, expected_event: EpollEvent) -> bool { - let expected_event = expected_event as i32; - event as i32 & expected_event == expected_event -} - -macro_rules! syscall { - ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{ - let res = unsafe { libc::$fn($($arg, )*) }; - if res == -1 { - Err(std::io::Error::last_os_error()) - } else { - Ok(res) - } - }}; -} - -fn epoll_create() -> io::Result { - let fd = syscall!(epoll_create1(0))?; - if let Ok(flags) = syscall!(fcntl(fd, libc::F_GETFD)) { - let _ = syscall!(fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC)); - } - - Ok(fd) -} - -fn epoll_wait(epoll_fd: RawFd, events: &mut Vec, max_events: i32, timeout: i32) -> io::Result { - match syscall!(epoll_wait( - epoll_fd, - events.as_mut_ptr() as *mut libc::epoll_event, - max_events, - timeout as libc::c_int - )) { - Ok(v) => Ok(v as usize), - Err(e) => Err(e) - } -} - -fn add_interest(epoll_fd: RawFd, fd: RawFd, mut event: epoll_event) -> io::Result<()> { - syscall!(epoll_ctl(epoll_fd, libc::EPOLL_CTL_ADD, fd, &mut event))?; - Ok(()) -} - -fn modify_interest(epoll_fd: RawFd, fd: RawFd, mut event: epoll_event) -> io::Result<()> { - syscall!(epoll_ctl(epoll_fd, libc::EPOLL_CTL_MOD, fd, &mut event))?; - Ok(()) -} - -fn create_oneshot_epoll_event(key: u16, events: &[EpollEvent]) -> epoll_event { - epoll_event { - events: get_oneshot_events_flag(events), - u64: key as u64, - } -} - -fn get_oneshot_events_flag(events: &[EpollEvent]) -> u32 { - let mut flag: i32 = libc::EPOLLONESHOT; - events.into_iter().for_each(|e| flag = flag | *e as i32); - flag as u32 -} diff --git a/server/src/net/mod.rs b/server/src/net/mod.rs index 07adc27..1a1017e 100644 --- a/server/src/net/mod.rs +++ b/server/src/net/mod.rs @@ -1,3 +1,2 @@ pub mod tcp_server; -mod epoll; diff --git a/server/src/net/tcp_server.rs b/server/src/net/tcp_server.rs index c39c262..c171d41 100644 --- a/server/src/net/tcp_server.rs +++ b/server/src/net/tcp_server.rs @@ -4,11 +4,11 @@ use std::io::{Read, Write}; use std::net::{SocketAddr, TcpListener, TcpStream}; use std::os::fd::{AsRawFd, RawFd}; -use crate::net::epoll::{Epoll, EpollEvent, match_epoll_event}; +use linux::epoll::{Epoll, EpollFlags}; // Based on: https://www.zupzup.org/epoll-with-rust/index.html -const KEY_NEW_CONNECTION: u16 = 0; +const KEY_NEW_CONNECTION: u64 = 0; pub trait TcpClient { fn new() -> Self; @@ -28,13 +28,13 @@ pub struct TcpServer listener: TcpListener, listener_fd: RawFd, epoll: Epoll, - key: u16, - request_contexts: HashMap>, + key: u64, + request_contexts: HashMap>, } struct TcpContext where T: TcpClient { - key: u16, + key: u64, stream: TcpStream, client: T, } @@ -47,8 +47,8 @@ impl TcpServer let listener_fd = listener.as_raw_fd(); - let epoll = Epoll::create()?; - epoll.add_interest(listener_fd, KEY_NEW_CONNECTION, &[EpollEvent::Read])?; + let epoll = Epoll::with_flags(&[EpollFlags::OneShot])?; + epoll.add_interest(listener_fd, KEY_NEW_CONNECTION, &[EpollFlags::In])?; Ok(TcpServer { addr, @@ -73,7 +73,7 @@ impl TcpServer let mut to_remove = Vec::new(); for (events, u64) in events { - match *u64 as u16 { + match *u64 { KEY_NEW_CONNECTION => self.accept_connection()?, key => { if let Some(context) = self.request_contexts.get_mut(&key) { @@ -104,16 +104,16 @@ impl TcpServer let context = TcpContext { key, stream, client }; - self.epoll.add_interest(fd, key, &[EpollEvent::Read, EpollEvent::Disconnect])?; + self.epoll.add_interest(fd, key, &[EpollFlags::In, EpollFlags::RdHup])?; self.request_contexts.insert(key, context); } Err(e) => eprintln!("Couldn't accept: {e}") }; - self.epoll.modify_interest(self.listener_fd, KEY_NEW_CONNECTION, &[EpollEvent::Read]) + self.epoll.modify_interest(self.listener_fd, KEY_NEW_CONNECTION, &[EpollFlags::In]) } - fn get_next_key(&mut self) -> u16 { + fn get_next_key(&mut self) -> u64 { self.key += 1; self.key } @@ -122,15 +122,15 @@ impl TcpServer fn handle_event(epoll: &Epoll, context: &mut TcpContext, event: u32) -> bool where T: TcpClient { match event { - v if match_epoll_event(v, EpollEvent::Read) => { + v if EpollFlags::In.flag_match(v) => { println!("Read"); return handle_read_event(epoll, context); } - v if match_epoll_event(v, EpollEvent::Write) => { + v if EpollFlags::Out.flag_match(v) => { println!("Write"); return handle_write_event(epoll, context); } - v if match_epoll_event(v, EpollEvent::Disconnect) => { + v if EpollFlags::RdHup.flag_match(v) => { println!("Disconnect"); return true; } @@ -171,14 +171,14 @@ fn handle_write_event(epoll: &Epoll, context: &mut TcpContext) -> bool fn set_interest(epoll: &Epoll, context: &TcpContext, next_intent: &NextIntent) where T: TcpClient { let event = match next_intent { - NextIntent::Read => EpollEvent::Read, - NextIntent::Write => EpollEvent::Write, + NextIntent::Read => EpollFlags::In, + NextIntent::Write => EpollFlags::Out, }; epoll.modify_interest( context.stream.as_raw_fd(), context.key, - &[event, EpollEvent::Disconnect]) + &[event, EpollFlags::RdHup]) .unwrap(); }