From 6ffe32798968bcdef2b0da866e2f76aab32d829c Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 30 May 2018 17:25:57 +0200 Subject: [PATCH] Switch to an edge-triggered event system (#28) --- src/smolnetd/scheme/socket.rs | 30 ++++++++++++++++++++++++++---- src/smolnetd/scheme/tcp.rs | 10 +++++++--- src/smolnetd/scheme/udp.rs | 4 ++-- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/smolnetd/scheme/socket.rs b/src/smolnetd/scheme/socket.rs index d6723964ab..0f20037095 100644 --- a/src/smolnetd/scheme/socket.rs +++ b/src/smolnetd/scheme/socket.rs @@ -28,6 +28,8 @@ pub struct SocketFile { events: usize, socket_handle: SocketHandle, + read_notified: bool, + write_notified: bool, read_timeout: Option, write_timeout: Option, } @@ -37,6 +39,8 @@ impl SocketFile { SocketFile { flags: self.flags, events: self.events, + read_notified: false, // we still want to notify about this new socket + write_notified: false, read_timeout: self.read_timeout, write_timeout: self.write_timeout, socket_handle: self.socket_handle, @@ -48,6 +52,8 @@ impl SocketFile { SocketFile { flags: 0, events: 0, + read_notified: false, + write_notified: false, read_timeout: None, write_timeout: None, socket_handle, @@ -198,10 +204,12 @@ where pub fn notify_sockets(&mut self) -> Result<()> { // Notify non-blocking sockets - for (&fd, file) in &self.files { - if let SchemeFile::Socket(SocketFile { + for (&fd, ref mut file) in &mut self.files { + if let &mut SchemeFile::Socket(SocketFile { socket_handle, events, + ref mut read_notified, + ref mut write_notified, .. }) = *file { @@ -209,11 +217,21 @@ where let socket = socket_set.get::(socket_handle); if events & syscall::EVENT_READ == syscall::EVENT_READ && socket.can_recv() { - post_fevent(&mut self.scheme_file, fd, syscall::EVENT_READ, 1)?; + if !*read_notified { + post_fevent(&mut self.scheme_file, fd, syscall::EVENT_READ, 1)?; + *read_notified = true; + } + } else { + *read_notified = false; } if events & syscall::EVENT_WRITE == syscall::EVENT_WRITE && socket.can_send() { - post_fevent(&mut self.scheme_file, fd, syscall::EVENT_WRITE, 1)?; + if !*write_notified { + post_fevent(&mut self.scheme_file, fd, syscall::EVENT_WRITE, 1)?; + *write_notified = true; + } + } else { + *write_notified = false; } } } @@ -488,6 +506,8 @@ where flags, events: 0, socket_handle, + read_notified: false, + write_notified: false, write_timeout: None, read_timeout: None, data, @@ -663,6 +683,8 @@ where SchemeFile::Setting(_) => Err(SyscallError::new(syscall::EBADF)), SchemeFile::Socket(ref mut file) => { file.events = events; + file.read_notified = false; // resend missed events + file.write_notified = false; Ok(fd) } } diff --git a/src/smolnetd/scheme/tcp.rs b/src/smolnetd/scheme/tcp.rs index a7cbf99c35..72dfca25fd 100644 --- a/src/smolnetd/scheme/tcp.rs +++ b/src/smolnetd/scheme/tcp.rs @@ -120,7 +120,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { self.send_slice(buf).expect("Can't send slice"); Ok(buf.len()) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { - Ok(0) + Err(SyscallError::new(syscall::EAGAIN)) } else { Err(SyscallError::new(syscall::EWOULDBLOCK)) } @@ -137,7 +137,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { let length = self.recv_slice(buf).expect("Can't receive slice"); Ok(length) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { - Ok(0) + Err(SyscallError::new(syscall::EAGAIN)) } else { Err(SyscallError::new(syscall::EWOULDBLOCK)) } @@ -159,7 +159,11 @@ impl<'a> SchemeSocket for TcpSocket<'a> { let file = match path { "listen" => if let SchemeFile::Socket(ref tcp_handle) = *file { if !is_active { - return Err(SyscallError::new(syscall::EWOULDBLOCK)); + if tcp_handle.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { + return Err(SyscallError::new(syscall::EAGAIN)); + } else { + return Err(SyscallError::new(syscall::EWOULDBLOCK)); + } } trace!("TCP creating new listening socket"); let new_handle = SchemeFile::Socket(tcp_handle.clone_with_data(())); diff --git a/src/smolnetd/scheme/udp.rs b/src/smolnetd/scheme/udp.rs index fcf4d03936..a59089bd0d 100644 --- a/src/smolnetd/scheme/udp.rs +++ b/src/smolnetd/scheme/udp.rs @@ -117,7 +117,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { self.send_slice(buf, file.data).expect("Can't send slice"); Ok(buf.len()) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { - Ok(0) + Err(SyscallError::new(syscall::EAGAIN)) } else { Err(SyscallError::new(syscall::EWOULDBLOCK)) } @@ -132,7 +132,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { let (length, _) = self.recv_slice(buf).expect("Can't receive slice"); Ok(length) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { - Ok(0) + Err(SyscallError::new(syscall::EAGAIN)) } else { Err(SyscallError::new(syscall::EWOULDBLOCK)) }