diff --git a/src/smolnetd/scheme/mod.rs b/src/smolnetd/scheme/mod.rs index 03ed2e3a3c..5efed421ab 100644 --- a/src/smolnetd/scheme/mod.rs +++ b/src/smolnetd/scheme/mod.rs @@ -14,13 +14,13 @@ use buffer_pool::{Buffer, BufferPool}; use device::NetworkDevice; use error::{Error, Result}; use self::ip::IpScheme; -use self::udp_socket::UdpScheme; -use self::tcp_socket::TcpScheme; +use self::udp::UdpScheme; +use self::tcp::TcpScheme; mod ip; mod socket; -mod udp_socket; -mod tcp_socket; +mod udp; +mod tcp; type SocketSet = Rc>>; @@ -44,7 +44,8 @@ pub struct Smolnetd { impl Smolnetd { const INGRESS_PACKET_SIZE: usize = 2048; const SOCKET_BUFFER_SIZE: usize = 128; //packets - const CHECK_TIMEOUT_MS: i64 = 10; + const MIN_CHECK_TIMEOUT_MS: i64 = 10; + const MAX_CHECK_TIMEOUT_MS: i64 = 500; pub fn new( network_file: File, @@ -95,41 +96,76 @@ impl Smolnetd { } pub fn on_ip_scheme_event(&mut self) -> Result> { - self.ip_scheme.on_scheme_event() + self.ip_scheme.on_scheme_event()?; + self.poll()?; + Ok(None) } pub fn on_udp_scheme_event(&mut self) -> Result> { - self.udp_scheme.on_scheme_event() + self.udp_scheme.on_scheme_event()?; + self.poll()?; + Ok(None) } pub fn on_tcp_scheme_event(&mut self) -> Result> { - self.tcp_scheme.on_scheme_event() + self.tcp_scheme.on_scheme_event()?; + self.poll()?; + Ok(None) } pub fn on_time_event(&mut self) -> Result> { + let timeout = self.poll()?; + self.schedule_timeout(timeout)?; + Ok(None) + } + + fn schedule_timeout(&mut self, timeout: i64) -> Result<()> { let mut time = syscall::data::TimeSpec::default(); if self.time_file.read(&mut time)? < mem::size_of::() { - panic!(); + return Err(Error::from_syscall_error( + syscall::Error::new(syscall::EBADF), + "Can't read current time", + )); } let mut time_ms = time.tv_sec * 1000i64 + i64::from(time.tv_nsec) / 1_000_000i64; - time_ms += Smolnetd::CHECK_TIMEOUT_MS; + time_ms += timeout; time.tv_sec = time_ms / 1000; time.tv_nsec = ((time_ms % 1000) * 1_000_000) as i32; self.time_file .write_all(&time) .map_err(|e| Error::from_io_error(e, "Failed to write to time file"))?; - - self.poll().map(Some)?; - Ok(None) + Ok(()) } - fn poll(&mut self) -> Result<()> { - let timestamp = self.get_timestamp(); - // trace!("Poll {}", timestamp); - if let Err(err) = self.iface.poll(&mut *self.socket_set.borrow_mut(), timestamp) { - error!("poll error: {}", err); - } - self.notify_sockets() + fn poll(&mut self) -> Result { + let mut iter_limit = 10usize; + let timeout = loop { + iter_limit -= 1; + if iter_limit == 0 { + break 0; + } + let timestamp = self.get_timestamp(); + match self.iface + .poll(&mut *self.socket_set.borrow_mut(), timestamp) + { + Err(err) => { + error!("poll error: {}", err); + break 0; + } + Ok(None) => { + break ::std::u64::MAX; + } + Ok(Some(n)) if n > 0 => { + break n; + } + _ => {} + } + }; + self.notify_sockets()?; + Ok(::std::cmp::min( + ::std::cmp::max(Smolnetd::MIN_CHECK_TIMEOUT_MS, timeout as i64), + Smolnetd::MAX_CHECK_TIMEOUT_MS, + )) } fn read_frames(&mut self) -> Result { @@ -158,11 +194,6 @@ impl Smolnetd { (duration.as_secs() * 1000) + u64::from(duration.subsec_nanos() / 1_000_000) } - fn network_fsync(&mut self) -> syscall::Result { - use std::os::unix::io::AsRawFd; - syscall::fsync(self.network_file.borrow_mut().as_raw_fd() as usize) - } - fn notify_sockets(&mut self) -> Result<()> { self.ip_scheme.notify_sockets()?; self.udp_scheme.notify_sockets()?; diff --git a/src/smolnetd/scheme/socket.rs b/src/smolnetd/scheme/socket.rs index 75ab6a49cc..9b26c1eb07 100644 --- a/src/smolnetd/scheme/socket.rs +++ b/src/smolnetd/scheme/socket.rs @@ -320,7 +320,7 @@ where trace!("Adding {} to wait queie", fd); let wait_queues = self.wait_queue_map .entry(socket_handle) - .or_insert_with(|| WaitQueues::default()); + .or_insert_with(WaitQueues::default); let queue = match packet.a { syscall::SYS_READ => Ok(&mut wait_queues.read_queue), diff --git a/src/smolnetd/scheme/tcp_socket.rs b/src/smolnetd/scheme/tcp.rs similarity index 96% rename from src/smolnetd/scheme/tcp_socket.rs rename to src/smolnetd/scheme/tcp.rs index dbb4d1d7f8..1a26e01f39 100644 --- a/src/smolnetd/scheme/tcp_socket.rs +++ b/src/smolnetd/scheme/tcp.rs @@ -112,8 +112,8 @@ impl<'a> SchemeSocket for TcpSocket<'a> { return Err(syscall::Error::new(syscall::EACCES)); } - let rx_packets = vec![0; 65535]; - let tx_packets = vec![0; 65535]; + let rx_packets = vec![0; 65_535]; + let tx_packets = vec![0; 65_535]; let rx_buffer = TcpSocketBuffer::new(rx_packets); let tx_buffer = TcpSocketBuffer::new(tx_packets); let mut tcp_socket = TcpSocket::new(rx_buffer, tx_buffer); @@ -142,7 +142,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { file: &SchemeFile, port_set: &mut Self::SchemeDataT, ) -> syscall::Result<()> { - if let &SchemeFile::Socket(_) = file { + if let SchemeFile::Socket(_) = *file { port_set.release_port(self.local_endpoint().port); } Ok(()) @@ -156,14 +156,14 @@ impl<'a> SchemeSocket for TcpSocket<'a> { if !self.is_open() { return Err(syscall::Error::new(syscall::EADDRNOTAVAIL)); } - return if self.can_send() { + if self.can_send() { self.send_slice(buf).expect("Can't send slice"); Ok(buf.len()) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { Ok(0) } else { Err(syscall::Error::new(syscall::EWOULDBLOCK)) - }; + } } fn read_buf( @@ -171,14 +171,14 @@ impl<'a> SchemeSocket for TcpSocket<'a> { file: &mut SocketFile, buf: &mut [u8], ) -> syscall::Result { - return if self.can_recv() { + if self.can_recv() { 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) } else { Err(syscall::Error::new(syscall::EWOULDBLOCK)) - }; + } } fn dup( diff --git a/src/smolnetd/scheme/udp_socket.rs b/src/smolnetd/scheme/udp.rs similarity index 98% rename from src/smolnetd/scheme/udp_socket.rs rename to src/smolnetd/scheme/udp.rs index a9c40cf066..030d53c495 100644 --- a/src/smolnetd/scheme/udp_socket.rs +++ b/src/smolnetd/scheme/udp.rs @@ -144,7 +144,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { file: &SchemeFile, port_set: &mut Self::SchemeDataT, ) -> syscall::Result<()> { - if let &SchemeFile::Socket(_) = file { + if let SchemeFile::Socket(_) = *file { port_set.release_port(self.endpoint().port); } Ok(()) @@ -158,14 +158,14 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { if !file.data.is_specified() { return Err(syscall::Error::new(syscall::EADDRNOTAVAIL)); } - return if self.can_send() { + if self.can_send() { 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) } else { Err(syscall::Error::new(syscall::EWOULDBLOCK)) - }; + } } fn read_buf( @@ -173,14 +173,14 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { file: &mut SocketFile, buf: &mut [u8], ) -> syscall::Result { - return if self.can_recv() { + if self.can_recv() { 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) } else { Err(syscall::Error::new(syscall::EWOULDBLOCK)) - }; + } } fn dup(