From 61bc03f8c3756aa727fa73a49a76ac34787031dd Mon Sep 17 00:00:00 2001 From: Stone749990226 <749990226@qq.com> Date: Sun, 21 Jul 2024 17:09:10 +0800 Subject: [PATCH] feat(net): add more async fun to tcp and udp --- .vscode/settings.json | 7 +- Cargo.lock | 13 +- kernel/src/net/socket.rs | 5 +- kernel/src/net/tcp.rs | 4 +- kernel/src/net/udp.rs | 4 +- kernel/src/syscall/net.rs | 11 + kernel/src/task/tid.rs | 2 +- modules/net/Cargo.toml | 1 + modules/net/src/lib.rs | 30 ++- modules/net/src/tcp.rs | 79 ++++-- modules/net/src/udp.rs | 30 ++- modules/signal/src/action.rs | 2 +- modules/smoltcp/src/socket/tcp.rs | 408 +++++++++++++++++------------- modules/time/src/stat.rs | 8 +- modules/timer/src/lib.rs | 2 +- 15 files changed, 373 insertions(+), 233 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a7525811..36211f25 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,10 +7,11 @@ "./kernel/Cargo.toml", ], "rust-analyzer.checkOnSave": true, - "rust-analyzer.files.excludeDirs": [ - "third-party" - ], "files.watcherExclude": { "**/third-party": true }, + // not work + "rust-analyzer.files.excludeDirs": [ + "**/third-party/**" + ], } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 86f2e4ff..19f4e9de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -246,7 +246,7 @@ dependencies = [ "spin", "sync", "systype", - "virtio-drivers 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "virtio-drivers", ] [[package]] @@ -605,7 +605,7 @@ dependencies = [ "timer", "vfs", "vfs-core", - "virtio-drivers 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "virtio-drivers", "xmas-elf", ] @@ -1265,15 +1265,6 @@ dependencies = [ "time", ] -[[package]] -name = "virtio-drivers" -version = "0.7.3" -dependencies = [ - "bitflags 2.6.0", - "log", - "zerocopy", -] - [[package]] name = "virtio-drivers" version = "0.7.3" diff --git a/kernel/src/net/socket.rs b/kernel/src/net/socket.rs index 6aedb516..d0f646b0 100644 --- a/kernel/src/net/socket.rs +++ b/kernel/src/net/socket.rs @@ -38,7 +38,7 @@ pub trait ProtoOps: Sync + Send + Any + DowncastSync { async fn recvfrom(&self, _buf: &mut [u8]) -> SysResult<(usize, SockAddr)> { Err(SysError::EOPNOTSUPP) } - fn poll(&self) -> NetPollState { + async fn poll(&self) -> NetPollState { log::error!("[net poll] unimplemented"); NetPollState { readable: false, @@ -136,7 +136,8 @@ impl File for Socket { async fn base_poll(&self, events: PollEvents) -> PollEvents { let mut res = PollEvents::empty(); - let netstate = self.sk.poll(); + poll_interfaces(); + let netstate = self.sk.poll().await; if events.contains(PollEvents::IN) { if netstate.readable { res |= PollEvents::IN; diff --git a/kernel/src/net/tcp.rs b/kernel/src/net/tcp.rs index b0df93c2..8420119b 100644 --- a/kernel/src/net/tcp.rs +++ b/kernel/src/net/tcp.rs @@ -57,8 +57,8 @@ impl ProtoOps for TcpSock { Ok((bytes, peer_addr)) } - fn poll(&self) -> NetPollState { - self.tcp.poll() + async fn poll(&self) -> NetPollState { + self.tcp.poll().await } fn shutdown(&self, _how: SocketShutdownFlag) -> SysResult<()> { diff --git a/kernel/src/net/udp.rs b/kernel/src/net/udp.rs index c91504e1..78a4f779 100644 --- a/kernel/src/net/udp.rs +++ b/kernel/src/net/udp.rs @@ -51,8 +51,8 @@ impl ProtoOps for UdpSock { .map(|(len, addr)| (len, addr.into())) } - fn poll(&self) -> NetPollState { - self.udp.poll() + async fn poll(&self) -> NetPollState { + self.udp.poll().await } fn shutdown(&self, _how: SocketShutdownFlag) -> SysResult<()> { diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 2496e45d..c311aea1 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -338,6 +338,17 @@ impl Syscall<'_> { socket.sk.shutdown(how)?; Ok(0) } + + pub fn sys_socketpair( + &self, + domain: usize, + types: usize, + protocol: usize, + sv: UserWritePtr<[u32; 2]>, + ) -> SyscallResult { + log::error!("[sys_socketpair] unsupport syscall now"); + Ok(0) + } } impl Task { diff --git a/kernel/src/task/tid.rs b/kernel/src/task/tid.rs index de4f8ad6..b423f635 100644 --- a/kernel/src/task/tid.rs +++ b/kernel/src/task/tid.rs @@ -33,7 +33,7 @@ pub struct TidAddress { } impl TidAddress { - pub fn new() -> Self { + pub const fn new() -> Self { Self { set_child_tid: None, clear_child_tid: None, diff --git a/modules/net/Cargo.toml b/modules/net/Cargo.toml index 65110af6..bacff48c 100644 --- a/modules/net/Cargo.toml +++ b/modules/net/Cargo.toml @@ -34,6 +34,7 @@ features = [ "socket-tcp", "socket-dns", "proto-ipv6", + "async", # "fragmentation-buffer-size-65536", "proto-ipv4-fragmentation", # "reassembly-buffer-size-65536", "reassembly-buffer-count-32", # "assembler-max-segment-count-32", diff --git a/modules/net/src/lib.rs b/modules/net/src/lib.rs index e47c6a41..2950550d 100644 --- a/modules/net/src/lib.rs +++ b/modules/net/src/lib.rs @@ -3,7 +3,7 @@ #![feature(new_uninit)] extern crate alloc; use alloc::{boxed::Box, vec, vec::Vec}; -use core::{cell::RefCell, ops::DerefMut, panic}; +use core::{cell::RefCell, future::Future, ops::DerefMut, panic}; use arch::time::get_time_us; use device_core::{error::DevError, NetBufPtrOps, NetDriverOps}; @@ -122,6 +122,34 @@ impl<'a> SocketSetWrapper<'a> { f(socket) } + pub async fn with_socket_async, R, F, Fut>( + &self, + handle: SocketHandle, + f: F, + ) -> R + where + F: FnOnce(&T) -> Fut, + Fut: Future, + { + let set = self.0.lock(); + let socket = set.get(handle); + f(socket).await + } + + pub async fn with_socket_mut_async, R, F, Fut>( + &self, + handle: SocketHandle, + f: F, + ) -> R + where + F: FnOnce(&mut T) -> Fut, + Fut: Future, + { + let mut set = self.0.lock(); + let socket = set.get_mut(handle); + f(socket).await + } + pub fn with_socket_mut, R, F>(&self, handle: SocketHandle, f: F) -> R where F: FnOnce(&mut T) -> R, diff --git a/modules/net/src/tcp.rs b/modules/net/src/tcp.rs index c428974e..ddadce8a 100644 --- a/modules/net/src/tcp.rs +++ b/modules/net/src/tcp.rs @@ -1,10 +1,12 @@ +use alloc::boxed::Box; use core::{ cell::UnsafeCell, + future::Future, net::SocketAddr, sync::atomic::{AtomicBool, AtomicU8, Ordering}, }; -use async_utils::yield_now; +use async_utils::{get_waker, suspend_now, yield_now}; use log::*; use smoltcp::{ iface::SocketHandle, @@ -176,8 +178,8 @@ impl TcpSocket { if self.is_nonblocking() { Err(SysError::EINPROGRESS) } else { - self.block_on(|| { - let NetPollState { writable, .. } = self.poll_connect(); + self.block_on_async(|| async { + let NetPollState { writable, .. } = self.poll_connect().await; if !writable { warn!("socket connect() failed: invalid state"); Err(SysError::EAGAIN) @@ -255,6 +257,7 @@ impl TcpSocket { // SAFETY: `self.local_addr` should be initialized after `bind()`. let local_port = unsafe { self.local_addr.get().read().port }; self.block_on(|| { + // TODO: 这里waker还没有注册到Socket上,可能会丢失 waker let (handle, (local_addr, peer_addr)) = LISTEN_TABLE.accept(local_port)?; debug!("TCP socket accepted a new connection {}", peer_addr); Ok(TcpSocket::new_connected(handle, local_addr, peer_addr)) @@ -368,10 +371,10 @@ impl TcpSocket { } /// Whether the socket is readable or writable. - pub fn poll(&self) -> NetPollState { + pub async fn poll(&self) -> NetPollState { match self.get_state() { - STATE_CONNECTING => self.poll_connect(), - STATE_CONNECTED => self.poll_stream(), + STATE_CONNECTING => self.poll_connect().await, + STATE_CONNECTED => self.poll_stream().await, STATE_LISTENING => self.poll_listener(), _ => NetPollState { readable: false, @@ -464,12 +467,17 @@ impl TcpSocket { /// /// Returning `true` indicates that the socket has entered a stable /// state(connected or failed) and can proceed to the next step - fn poll_connect(&self) -> NetPollState { + async fn poll_connect(&self) -> NetPollState { // SAFETY: `self.handle` should be initialized above. let handle = unsafe { self.handle.get().read().unwrap() }; - let writable = - SOCKET_SET.with_socket::(handle, |socket| match socket.state() { - State::SynSent => false, // The connection request has been sent but no response + let waker = get_waker().await; + let writable = SOCKET_SET.with_socket_mut::(handle, |socket| { + match socket.state() { + State::SynSent => { + // The connection request has been sent but no response + socket.register_recv_waker(&waker); + false + } // has been received yet State::Established => { self.set_state(STATE_CONNECTED); // connected @@ -488,25 +496,32 @@ impl TcpSocket { self.set_state(STATE_CLOSED); // connection failed true } - }); + } + }); NetPollState { readable: false, writable, } } - fn poll_stream(&self) -> NetPollState { + async fn poll_stream(&self) -> NetPollState { // SAFETY: `self.handle` should be initialized in a connected socket. let handle = unsafe { self.handle.get().read().unwrap() }; - SOCKET_SET.with_socket::(handle, |socket| { - NetPollState { - // readable 本质上是是否应该继续阻塞,因此为 true 时的条件可以理解为: - // 1. 套接字已经关闭接收:在这种情况下,即使没有新数据到达,读取操作也不会阻塞, - // 因为读取会立即返回 - // 2. 套接字中有数据可读:这是最常见的可读情况,表示可以从套接字中读取到数据 - readable: !socket.may_recv() || socket.can_recv(), - writable: !socket.may_send() || socket.can_send(), + let waker = get_waker().await; + SOCKET_SET.with_socket_mut::(handle, |socket| { + // readable 本质上是是否应该继续阻塞,因此为 true 时的条件可以理解为: + // 1. 套接字已经关闭接收:在这种情况下,即使没有新数据到达,读取操作也不会阻塞, + // 因为读取会立即返回 + // 2. 套接字中有数据可读:这是最常见的可读情况,表示可以从套接字中读取到数据 + let readable = !socket.may_recv() || socket.can_recv(); + let writable = !socket.may_send() || socket.can_send(); + if !readable { + socket.register_recv_waker(&waker); } + if !writable { + socket.register_send_waker(&waker); + } + NetPollState { readable, writable } }) } @@ -538,7 +553,29 @@ impl TcpSocket { Err(SysError::EAGAIN) => { // TODO:判断是否有信号 - yield_now().await + suspend_now().await + } + Err(e) => return Err(e), + } + } + } + } + + async fn block_on_async(&self, mut f: F) -> SysResult + where + F: FnMut() -> Fut, + Fut: Future>, + { + if self.is_nonblocking() { + f().await + } else { + loop { + SOCKET_SET.poll_interfaces(); + match f().await { + Ok(t) => return Ok(t), + Err(SysError::EAGAIN) => { + // TODO:判断是否有信号 + suspend_now().await } Err(e) => return Err(e), } diff --git a/modules/net/src/udp.rs b/modules/net/src/udp.rs index 46a1e3ec..4c888c39 100644 --- a/modules/net/src/udp.rs +++ b/modules/net/src/udp.rs @@ -3,7 +3,7 @@ use core::{ sync::atomic::{AtomicBool, Ordering}, }; -use async_utils::yield_now; +use async_utils::{get_waker, suspend_now, yield_now}; use log::{debug, warn}; use smoltcp::{ iface::SocketHandle, @@ -114,7 +114,7 @@ impl UdpSocket { /// number of bytes written. pub async fn send_to(&self, buf: &[u8], remote_addr: SocketAddr) -> SysResult { if remote_addr.port() == 0 || remote_addr.ip().is_unspecified() { - warn!("socket send_to() failed: invalid address"); + warn!("socket send_to() failed: invalid remote address"); return Err(SysError::EINVAL); } self.send_impl(buf, from_core_sockaddr(remote_addr)).await @@ -203,16 +203,24 @@ impl UdpSocket { } /// Whether the socket is readable or writable. - pub fn poll(&self) -> NetPollState { + pub async fn poll(&self) -> NetPollState { if self.local_addr.read().is_none() { return NetPollState { readable: false, writable: false, }; } - SOCKET_SET.with_socket_mut::(self.handle, |socket| NetPollState { - readable: socket.can_recv(), - writable: socket.can_send(), + let waker = get_waker().await; + SOCKET_SET.with_socket_mut::(self.handle, |socket| { + let readable = socket.can_recv(); + let writable = socket.can_send(); + if !readable { + socket.register_recv_waker(&waker); + } + if !writable { + socket.register_send_waker(&waker); + } + NetPollState { readable, writable } }) } } @@ -235,7 +243,7 @@ impl UdpSocket { // TODO: UNSPECIFIED_ENDPOINT or LOCAL_ENDPOINT? self.bind(into_core_sockaddr(UNSPECIFIED_ENDPOINT))?; } - + let waker = get_waker().await; let bytes = self .block_on(|| { SOCKET_SET.with_socket_mut::(self.handle, |socket| { @@ -255,6 +263,8 @@ impl UdpSocket { Ok(buf.len()) } else { // tx buffer is full + socket.register_send_waker(&waker); + Err(SysError::EAGAIN) } }) @@ -272,7 +282,7 @@ impl UdpSocket { warn!("socket send() failed"); return Err(SysError::ENOTCONN); } - + let waker = get_waker().await; self.block_on(|| { SOCKET_SET.with_socket_mut::(self.handle, |socket| { if socket.can_recv() { @@ -285,6 +295,7 @@ impl UdpSocket { } else { // no more data log::info!("[recv_impl] no more data"); + socket.register_send_waker(&waker); Err(SysError::EAGAIN) } }) @@ -305,7 +316,8 @@ impl UdpSocket { Ok(t) => return Ok(t), Err(SysError::EAGAIN) => { // TODO:判断是否有信号 - yield_now().await + // yield_now().await + suspend_now().await; } Err(e) => return Err(e), } diff --git a/modules/signal/src/action.rs b/modules/signal/src/action.rs index a3b739cc..f3a35b1c 100644 --- a/modules/signal/src/action.rs +++ b/modules/signal/src/action.rs @@ -77,7 +77,7 @@ pub struct SigPending { } impl SigPending { - pub fn new() -> Self { + pub const fn new() -> Self { Self { queue: VecDeque::new(), bitmap: SigSet::empty(), diff --git a/modules/smoltcp/src/socket/tcp.rs b/modules/smoltcp/src/socket/tcp.rs index a5ced968..72cd7e82 100644 --- a/modules/smoltcp/src/socket/tcp.rs +++ b/modules/smoltcp/src/socket/tcp.rs @@ -2,19 +2,20 @@ // the parts of RFC 1122 that discuss TCP. Consult RFC 7414 when implementing // a new feature. -use core::fmt::Display; #[cfg(feature = "async")] use core::task::Waker; -use core::{cmp, fmt, mem}; +use core::{cmp, fmt, fmt::Display, mem}; #[cfg(feature = "async")] use crate::socket::WakerRegistration; -use crate::socket::{Context, PollAt}; -use crate::storage::{Assembler, RingBuffer}; -use crate::time::{Duration, Instant}; -use crate::wire::{ - IpAddress, IpEndpoint, IpListenEndpoint, IpProtocol, IpRepr, TcpControl, TcpRepr, TcpSeqNumber, - TCP_HEADER_LEN, +use crate::{ + socket::{Context, PollAt}, + storage::{Assembler, RingBuffer}, + time::{Duration, Instant}, + wire::{ + IpAddress, IpEndpoint, IpListenEndpoint, IpProtocol, IpRepr, TcpControl, TcpRepr, + TcpSeqNumber, TCP_HEADER_LEN, + }, }; macro_rules! tcp_trace { @@ -233,7 +234,8 @@ impl RttEstimator { // - The network conditions change, suddenly making the RTT much higher // In these cases, the estimator can get stuck, because it can't sample because // all packets sent would incur a retransmit. To avoid this, force an estimate - // increase if we see 3 consecutive retransmissions without any successful sample. + // increase if we see 3 consecutive retransmissions without any successful + // sample. self.rto_count = 0; self.rtt = RTTE_MAX_RTO.min(self.rtt * 2); let rto = self.retransmission_timeout().total_millis(); @@ -392,10 +394,10 @@ impl Display for Tuple { /// A Transmission Control Protocol socket. /// -/// A TCP socket may passively listen for connections or actively connect to another endpoint. -/// Note that, for listening sockets, there is no "backlog"; to be able to simultaneously -/// accept several connections, as many sockets must be allocated, or any new connection -/// attempts will be reset. +/// A TCP socket may passively listen for connections or actively connect to +/// another endpoint. Note that, for listening sockets, there is no "backlog"; +/// to be able to simultaneously accept several connections, as many sockets +/// must be allocated, or any new connection attempts will be reset. #[derive(Debug)] pub struct Socket<'a> { state: State, @@ -405,22 +407,26 @@ pub struct Socket<'a> { rx_buffer: SocketBuffer<'a>, rx_fin_received: bool, tx_buffer: SocketBuffer<'a>, - /// Interval after which, if no inbound packets are received, the connection is aborted. + /// Interval after which, if no inbound packets are received, the connection + /// is aborted. timeout: Option, /// Interval at which keep-alive packets will be sent. keep_alive: Option, - /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. + /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing + /// packets. hop_limit: Option, - /// Address passed to listen(). Listen address is set when listen() is called and - /// used every time the socket is reset back to the LISTEN state. + /// Address passed to listen(). Listen address is set when listen() is + /// called and used every time the socket is reset back to the LISTEN + /// state. listen_endpoint: IpListenEndpoint, /// Current 4-tuple (local and remote endpoints). tuple: Option, - /// The sequence number corresponding to the beginning of the transmit buffer. - /// I.e. an ACK(local_seq_no+n) packet removes n bytes from the transmit buffer. + /// The sequence number corresponding to the beginning of the transmit + /// buffer. I.e. an ACK(local_seq_no+n) packet removes n bytes from the + /// transmit buffer. local_seq_no: TcpSeqNumber, - /// The sequence number corresponding to the beginning of the receive buffer. - /// I.e. userspace reading n bytes adds n to remote_seq_no. + /// The sequence number corresponding to the beginning of the receive + /// buffer. I.e. userspace reading n bytes adds n to remote_seq_no. remote_seq_no: TcpSeqNumber, /// The last sequence number sent. /// I.e. in an idle socket, local_seq_no+tx_buffer.len(). @@ -430,15 +436,18 @@ pub struct Socket<'a> { remote_last_ack: Option, /// The last window length sent. remote_last_win: u16, - /// The sending window scaling factor advertised to remotes which support RFC 1323. - /// It is zero if the window <= 64KiB and/or the remote does not support it. + /// The sending window scaling factor advertised to remotes which support + /// RFC 1323. It is zero if the window <= 64KiB and/or the remote does + /// not support it. remote_win_shift: u8, /// The remote window size, relative to local_seq_no /// I.e. we're allowed to send octets until local_seq_no+remote_win_len remote_win_len: usize, - /// The receive window scaling factor for remotes which support RFC 1323, None if unsupported. + /// The receive window scaling factor for remotes which support RFC 1323, + /// None if unsupported. remote_win_scale: Option, - /// Whether or not the remote supports selective ACK as described in RFC 2018. + /// Whether or not the remote supports selective ACK as described in RFC + /// 2018. remote_has_sack: bool, /// The maximum number of data octets that the remote side may receive. remote_mss: usize, @@ -458,7 +467,8 @@ pub struct Socket<'a> { /// ACK or window updates (ie, no data) won't be sent until expiry. ack_delay_timer: AckDelayTimer, - /// Used for rate-limiting: No more challenge ACKs will be sent until this instant. + /// Used for rate-limiting: No more challenge ACKs will be sent until this + /// instant. challenge_ack_timer: Instant, /// Nagle's Algorithm enabled. @@ -537,11 +547,12 @@ impl<'a> Socket<'a> { /// /// Notes: /// - /// - Only one waker can be registered at a time. If another waker was previously registered, - /// it is overwritten and will no longer be woken. - /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. - /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `recv` has - /// necessarily changed. + /// - Only one waker can be registered at a time. If another waker was + /// previously registered, it is overwritten and will no longer be woken. + /// - The Waker is woken only once. Once woken, you must register it again + /// to receive more wakes. + /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of + /// `recv` has necessarily changed. #[cfg(feature = "async")] pub fn register_recv_waker(&mut self, waker: &Waker) { self.rx_waker.register(waker) @@ -555,11 +566,12 @@ impl<'a> Socket<'a> { /// /// Notes: /// - /// - Only one waker can be registered at a time. If another waker was previously registered, - /// it is overwritten and will no longer be woken. - /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. - /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `send` has - /// necessarily changed. + /// - Only one waker can be registered at a time. If another waker was + /// previously registered, it is overwritten and will no longer be woken. + /// - The Waker is woken only once. Once woken, you must register it again + /// to receive more wakes. + /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of + /// `send` has necessarily changed. #[cfg(feature = "async")] pub fn register_send_waker(&mut self, waker: &Waker) { self.tx_waker.register(waker) @@ -586,10 +598,10 @@ impl<'a> Socket<'a> { self.nagle } - /// Return the current window field value, including scaling according to RFC 1323. + /// Return the current window field value, including scaling according to + /// RFC 1323. /// /// Used in internal calculations as well as packet generation. - /// #[inline] fn scaled_window(&self) -> u16 { cmp::min( @@ -600,15 +612,17 @@ impl<'a> Socket<'a> { /// Set the timeout duration. /// - /// A socket with a timeout duration set will abort the connection if either of the following - /// occurs: + /// A socket with a timeout duration set will abort the connection if either + /// of the following occurs: /// - /// * After a [connect](#method.connect) call, the remote endpoint does not respond within - /// the specified duration; - /// * After establishing a connection, there is data in the transmit buffer and the remote - /// endpoint exceeds the specified duration between any two packets it sends; - /// * After enabling [keep-alive](#method.set_keep_alive), the remote endpoint exceeds - /// the specified duration between any two packets it sends. + /// * After a [connect](#method.connect) call, the remote endpoint does + /// not respond within the specified duration; + /// * After establishing a connection, there is data in the transmit + /// buffer and the remote endpoint exceeds the specified duration + /// between any two packets it sends; + /// * After enabling [keep-alive](#method.set_keep_alive), the remote + /// endpoint exceeds the specified duration between any two packets it + /// sends. pub fn set_timeout(&mut self, duration: Option) { self.timeout = duration } @@ -625,13 +639,14 @@ impl<'a> Socket<'a> { /// Also known as "tinygram prevention". By default, it is enabled. /// Disabling it is equivalent to Linux's TCP_NODELAY flag. /// - /// When enabled, Nagle's Algorithm prevents sending segments smaller than MSS if - /// there is data in flight (sent but not acknowledged). In other words, it ensures - /// at most only one segment smaller than MSS is in flight at a time. + /// When enabled, Nagle's Algorithm prevents sending segments smaller than + /// MSS if there is data in flight (sent but not acknowledged). In other + /// words, it ensures at most only one segment smaller than MSS is in + /// flight at a time. /// - /// It ensures better network utilization by preventing sending many very small packets, - /// at the cost of increased latency in some situations, particularly when the remote peer - /// has ACK delay enabled. + /// It ensures better network utilization by preventing sending many very + /// small packets, at the cost of increased latency in some situations, + /// particularly when the remote peer has ACK delay enabled. pub fn set_nagle_enabled(&mut self, enabled: bool) { self.nagle = enabled } @@ -645,40 +660,44 @@ impl<'a> Socket<'a> { /// Set the keep-alive interval. /// - /// An idle socket with a keep-alive interval set will transmit a "keep-alive ACK" packet - /// every time it receives no communication during that interval. As a result, three things - /// may happen: + /// An idle socket with a keep-alive interval set will transmit a + /// "keep-alive ACK" packet every time it receives no communication + /// during that interval. As a result, three things may happen: /// /// * The remote endpoint is fine and answers with an ACK packet. /// * The remote endpoint has rebooted and answers with an RST packet. /// * The remote endpoint has crashed and does not answer. /// - /// The keep-alive functionality together with the timeout functionality allows to react - /// to these error conditions. + /// The keep-alive functionality together with the timeout functionality + /// allows to react to these error conditions. pub fn set_keep_alive(&mut self, interval: Option) { self.keep_alive = interval; if self.keep_alive.is_some() { - // If the connection is idle and we've just set the option, it would not take effect - // until the next packet, unless we wind up the timer explicitly. + // If the connection is idle and we've just set the option, it would not take + // effect until the next packet, unless we wind up the timer + // explicitly. self.timer.set_keep_alive(); } } - /// Return the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. + /// Return the time-to-live (IPv4) or hop limit (IPv6) value used in + /// outgoing packets. /// /// See also the [set_hop_limit](#method.set_hop_limit) method pub fn hop_limit(&self) -> Option { self.hop_limit } - /// Set the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. + /// Set the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing + /// packets. /// - /// A socket without an explicitly set hop limit value uses the default [IANA recommended] - /// value (64). + /// A socket without an explicitly set hop limit value uses the default + /// [IANA recommended] value (64). /// /// # Panics /// - /// This function panics if a hop limit value of 0 is given. See [RFC 1122 § 3.2.1.7]. + /// This function panics if a hop limit value of 0 is given. See [RFC 1122 § + /// 3.2.1.7]. /// /// [IANA recommended]: https://www.iana.org/assignments/ip-parameters/ip-parameters.xhtml /// [RFC 1122 § 3.2.1.7]: https://tools.ietf.org/html/rfc1122#section-3.2.1.7 @@ -744,9 +763,10 @@ impl<'a> Socket<'a> { /// Start listening on the given endpoint. /// - /// This function returns `Err(Error::Illegal)` if the socket was already open - /// (see [is_open](#method.is_open)), and `Err(Error::Unaddressable)` - /// if the port in the given endpoint is zero. + /// This function returns `Err(Error::Illegal)` if the socket was already + /// open (see [is_open](#method.is_open)), and + /// `Err(Error::Unaddressable)` if the port in the given endpoint is + /// zero. pub fn listen(&mut self, local_endpoint: T) -> Result<(), ListenError> where T: Into, @@ -769,8 +789,9 @@ impl<'a> Socket<'a> { /// Connect to a given endpoint. /// - /// The local port must be provided explicitly. Assuming `fn get_ephemeral_port() -> u16` - /// allocates a port between 49152 and 65535, a connection may be established as follows: + /// The local port must be provided explicitly. Assuming `fn + /// get_ephemeral_port() -> u16` allocates a port between 49152 and + /// 65535, a connection may be established as follows: /// /// ```no_run /// # #[cfg(all( @@ -803,9 +824,9 @@ impl<'a> Socket<'a> { /// /// The local address may optionally be provided. /// - /// This function returns an error if the socket was open; see [is_open](#method.is_open). - /// It also returns an error if the local or remote port is zero, or if the remote address - /// is unspecified. + /// This function returns an error if the socket was open; see + /// [is_open](#method.is_open). It also returns an error if the local or + /// remote port is zero, or if the remote address is unspecified. pub fn connect( &mut self, cx: &mut Context, @@ -854,9 +875,11 @@ impl<'a> Socket<'a> { local: local_endpoint, remote: remote_endpoint, }); + // 将 socket 状态设置为 SynSent,表示已发送 SYN 包 self.set_state(State::SynSent); - + // 生成一个随机的初始序列号 let seq = Self::random_seq_no(cx); + // 设置本地和远程的序列号 self.local_seq_no = seq; self.remote_last_seq = seq; Ok(()) @@ -874,9 +897,10 @@ impl<'a> Socket<'a> { /// Close the transmit half of the full-duplex connection. /// - /// Note that there is no corresponding function for the receive half of the full-duplex - /// connection; only the remote end can close it. If you no longer wish to receive any - /// data and would like to reuse the socket right away, use [abort](#method.abort). + /// Note that there is no corresponding function for the receive half of the + /// full-duplex connection; only the remote end can close it. If you no + /// longer wish to receive any data and would like to reuse the socket + /// right away, use [abort](#method.abort). pub fn close(&mut self) { match self.state { // In the LISTEN state there is no established connection. @@ -902,18 +926,20 @@ impl<'a> Socket<'a> { /// Aborts the connection, if any. /// - /// This function instantly closes the socket. One reset packet will be sent to the remote - /// endpoint. + /// This function instantly closes the socket. One reset packet will be sent + /// to the remote endpoint. /// - /// In terms of the TCP state machine, the socket may be in any state and is moved to - /// the `CLOSED` state. + /// In terms of the TCP state machine, the socket may be in any state and is + /// moved to the `CLOSED` state. pub fn abort(&mut self) { self.set_state(State::Closed); } - /// Return whether the socket is passively listening for incoming connections. + /// Return whether the socket is passively listening for incoming + /// connections. /// - /// In terms of the TCP state machine, the socket must be in the `LISTEN` state. + /// In terms of the TCP state machine, the socket must be in the `LISTEN` + /// state. #[inline] pub fn is_listening(&self) -> bool { match self.state { @@ -924,12 +950,13 @@ impl<'a> Socket<'a> { /// Return whether the socket is open. /// - /// This function returns true if the socket will process incoming or dispatch outgoing - /// packets. Note that this does not mean that it is possible to send or receive data through - /// the socket; for that, use [can_send](#method.can_send) or [can_recv](#method.can_recv). + /// This function returns true if the socket will process incoming or + /// dispatch outgoing packets. Note that this does not mean that it is + /// possible to send or receive data through the socket; for that, use + /// [can_send](#method.can_send) or [can_recv](#method.can_recv). /// - /// In terms of the TCP state machine, the socket must not be in the `CLOSED` - /// or `TIME-WAIT` states. + /// In terms of the TCP state machine, the socket must not be in the + /// `CLOSED` or `TIME-WAIT` states. #[inline] pub fn is_open(&self) -> bool { match self.state { @@ -941,16 +968,16 @@ impl<'a> Socket<'a> { /// Return whether a connection is active. /// - /// This function returns true if the socket is actively exchanging packets with - /// a remote endpoint. Note that this does not mean that it is possible to send or receive - /// data through the socket; for that, use [can_send](#method.can_send) or - /// [can_recv](#method.can_recv). + /// This function returns true if the socket is actively exchanging packets + /// with a remote endpoint. Note that this does not mean that it is + /// possible to send or receive data through the socket; for that, use + /// [can_send](#method.can_send) or [can_recv](#method.can_recv). /// - /// If a connection is established, [abort](#method.close) will send a reset to - /// the remote endpoint. + /// If a connection is established, [abort](#method.close) will send a reset + /// to the remote endpoint. /// - /// In terms of the TCP state machine, the socket must not be in the `CLOSED`, `TIME-WAIT`, - /// or `LISTEN` state. + /// In terms of the TCP state machine, the socket must not be in the + /// `CLOSED`, `TIME-WAIT`, or `LISTEN` state. #[inline] pub fn is_active(&self) -> bool { match self.state { @@ -963,13 +990,14 @@ impl<'a> Socket<'a> { /// Return whether the transmit half of the full-duplex connection is open. /// - /// This function returns true if it's possible to send data and have it arrive - /// to the remote endpoint. However, it does not make any guarantees about the state - /// of the transmit buffer, and even if it returns true, [send](#method.send) may - /// not be able to enqueue any octets. + /// This function returns true if it's possible to send data and have it + /// arrive to the remote endpoint. However, it does not make any + /// guarantees about the state of the transmit buffer, and even if it + /// returns true, [send](#method.send) may not be able to enqueue any + /// octets. /// - /// In terms of the TCP state machine, the socket must be in the `ESTABLISHED` or - /// `CLOSE-WAIT` state. + /// In terms of the TCP state machine, the socket must be in the + /// `ESTABLISHED` or `CLOSE-WAIT` state. #[inline] pub fn may_send(&self) -> bool { match self.state { @@ -983,12 +1011,14 @@ impl<'a> Socket<'a> { /// Return whether the receive half of the full-duplex connection is open. /// - /// This function returns true if it's possible to receive data from the remote endpoint. - /// It will return true while there is data in the receive buffer, and if there isn't, - /// as long as the remote endpoint has not closed the connection. + /// This function returns true if it's possible to receive data from the + /// remote endpoint. It will return true while there is data in the + /// receive buffer, and if there isn't, as long as the remote endpoint + /// has not closed the connection. /// - /// In terms of the TCP state machine, the socket must be in the `ESTABLISHED`, - /// `FIN-WAIT-1`, or `FIN-WAIT-2` state, or have data in the receive buffer instead. + /// In terms of the TCP state machine, the socket must be in the + /// `ESTABLISHED`, `FIN-WAIT-1`, or `FIN-WAIT-2` state, or have data in + /// the receive buffer instead. #[inline] pub fn may_recv(&self) -> bool { match self.state { @@ -1025,8 +1055,9 @@ impl<'a> Socket<'a> { self.tx_buffer.capacity() } - /// Check whether the receive half of the full-duplex connection buffer is open - /// (see [may_recv](#method.may_recv)), and the receive buffer is not empty. + /// Check whether the receive half of the full-duplex connection buffer is + /// open (see [may_recv](#method.may_recv)), and the receive buffer is + /// not empty. #[inline] pub fn can_recv(&self) -> bool { if !self.may_recv() { @@ -1064,8 +1095,8 @@ impl<'a> Socket<'a> { Ok(result) } - /// Call `f` with the largest contiguous slice of octets in the transmit buffer, - /// and enqueue the amount of elements returned by `f`. + /// Call `f` with the largest contiguous slice of octets in the transmit + /// buffer, and enqueue the amount of elements returned by `f`. /// /// This function returns `Err(Error::Illegal)` if the transmit half of /// the connection is not open; see [may_send](#method.may_send). @@ -1078,8 +1109,9 @@ impl<'a> Socket<'a> { /// Enqueue a sequence of octets to be sent, and fill it from a slice. /// - /// This function returns the amount of octets actually enqueued, which is limited - /// by the amount of free space in the transmit buffer; down to zero. + /// This function returns the amount of octets actually enqueued, which is + /// limited by the amount of free space in the transmit buffer; down to + /// zero. /// /// See also [send](#method.send). pub fn send_slice(&mut self, data: &[u8]) -> Result { @@ -1090,9 +1122,10 @@ impl<'a> Socket<'a> { } fn recv_error_check(&mut self) -> Result<(), RecvError> { - // We may have received some data inside the initial SYN, but until the connection - // is fully open we must not dequeue any data, as it may be overwritten by e.g. - // another (stale) SYN. (We do not support TCP Fast Open.) + // We may have received some data inside the initial SYN, but until the + // connection is fully open we must not dequeue any data, as it may be + // overwritten by e.g. another (stale) SYN. (We do not support TCP Fast + // Open.) if !self.may_recv() { if self.rx_fin_received { return Err(RecvError::Finished); @@ -1123,16 +1156,17 @@ impl<'a> Socket<'a> { Ok(result) } - /// Call `f` with the largest contiguous slice of octets in the receive buffer, - /// and dequeue the amount of elements returned by `f`. + /// Call `f` with the largest contiguous slice of octets in the receive + /// buffer, and dequeue the amount of elements returned by `f`. /// /// This function errors if the receive half of the connection is not open. /// - /// If the receive half has been gracefully closed (with a FIN packet), `Err(Error::Finished)` - /// is returned. In this case, the previously received data is guaranteed to be complete. + /// If the receive half has been gracefully closed (with a FIN packet), + /// `Err(Error::Finished)` is returned. In this case, the previously + /// received data is guaranteed to be complete. /// - /// In all other cases, `Err(Error::Illegal)` is returned and previously received data (if any) - /// may be incomplete (truncated). + /// In all other cases, `Err(Error::Illegal)` is returned and previously + /// received data (if any) may be incomplete (truncated). pub fn recv<'b, F, R>(&'b mut self, f: F) -> Result where F: FnOnce(&'b mut [u8]) -> (usize, R), @@ -1142,8 +1176,9 @@ impl<'a> Socket<'a> { /// Dequeue a sequence of received octets, and fill a slice from it. /// - /// This function returns the amount of octets actually dequeued, which is limited - /// by the amount of occupied space in the receive buffer; down to zero. + /// This function returns the amount of octets actually dequeued, which is + /// limited by the amount of occupied space in the receive buffer; down + /// to zero. /// /// See also [recv](#method.recv). pub fn recv_slice(&mut self, data: &mut [u8]) -> Result { @@ -1171,7 +1206,8 @@ impl<'a> Socket<'a> { /// Peek at a sequence of received octets without removing them from /// the receive buffer, and fill a slice from it. /// - /// This function otherwise behaves identically to [recv_slice](#method.recv_slice). + /// This function otherwise behaves identically to + /// [recv_slice](#method.recv_slice). pub fn peek_slice(&mut self, data: &mut [u8]) -> Result { let buffer = self.peek(data.len())?; let data = &mut data[..buffer.len()]; @@ -1181,16 +1217,19 @@ impl<'a> Socket<'a> { /// Return the amount of octets queued in the transmit buffer. /// - /// Note that the Berkeley sockets interface does not have an equivalent of this API. + /// Note that the Berkeley sockets interface does not have an equivalent of + /// this API. pub fn send_queue(&self) -> usize { self.tx_buffer.len() } - /// Return the amount of octets queued in the receive buffer. This value can be larger than - /// the slice read by the next `recv` or `peek` call because it includes all queued octets, - /// and not only the octets that may be returned as a contiguous slice. + /// Return the amount of octets queued in the receive buffer. This value can + /// be larger than the slice read by the next `recv` or `peek` call + /// because it includes all queued octets, and not only the octets that + /// may be returned as a contiguous slice. /// - /// Note that the Berkeley sockets interface does not have an equivalent of this API. + /// Note that the Berkeley sockets interface does not have an equivalent of + /// this API. pub fn recv_queue(&self) -> usize { self.rx_buffer.len() } @@ -1205,8 +1244,9 @@ impl<'a> Socket<'a> { #[cfg(feature = "async")] { // Wake all tasks waiting. Even if we haven't received/sent data, this - // is needed because return values of functions may change depending on the state. - // For example, a pending read has to fail with an error if the socket is closed. + // is needed because return values of functions may change depending on the + // state. For example, a pending read has to fail with an error if + // the socket is closed. self.rx_waker.wake(); self.tx_waker.wake(); } @@ -1256,9 +1296,9 @@ impl<'a> Socket<'a> { let (mut ip_reply_repr, mut reply_repr) = Self::reply(ip_repr, repr); // From RFC 793: - // [...] an empty acknowledgment segment containing the current send-sequence number - // and an acknowledgment indicating the next sequence number expected - // to be received. + // [...] an empty acknowledgment segment containing the current send-sequence + // number and an acknowledgment indicating the next sequence number + // expected to be received. reply_repr.seq_number = self.remote_last_seq; reply_repr.ack_number = Some(self.remote_seq_no + self.rx_buffer.len()); self.remote_last_ack = reply_repr.ack_number; @@ -1269,15 +1309,16 @@ impl<'a> Socket<'a> { reply_repr.window_len = self.scaled_window(); self.remote_last_win = reply_repr.window_len; - // If the remote supports selective acknowledgement, add the option to the outgoing - // segment. + // If the remote supports selective acknowledgement, add the option to the + // outgoing segment. if self.remote_has_sack { net_debug!("sending sACK option with current assembler ranges"); - // RFC 2018: The first SACK block (i.e., the one immediately following the kind and - // length fields in the option) MUST specify the contiguous block of data containing - // the segment which triggered this ACK, unless that segment advanced the - // Acknowledgment Number field in the header. + // RFC 2018: The first SACK block (i.e., the one immediately following the kind + // and length fields in the option) MUST specify the contiguous + // block of data containing the segment which triggered this ACK, + // unless that segment advanced the Acknowledgment Number field in + // the header. reply_repr.sack_ranges[0] = None; if let Some(last_seg_seq) = self.local_rx_last_seq.map(|s| s.0 as u32) { @@ -1289,8 +1330,9 @@ impl<'a> Socket<'a> { } if reply_repr.sack_ranges[0].is_none() { - // The matching segment was removed from the assembler, meaning the acknowledgement - // number has advanced, or there was no previous sACK. + // The matching segment was removed from the assembler, meaning the + // acknowledgement number has advanced, or there was no previous + // sACK. // // While the RFC says we SHOULD keep a list of reported sACK ranges, and iterate // through those, that is currently infeasible. Instead, we offer the range with @@ -1304,7 +1346,8 @@ impl<'a> Socket<'a> { } } - // Since the sACK option may have changed the length of the payload, update that. + // Since the sACK option may have changed the length of the payload, update + // that. ip_reply_repr.set_payload_len(reply_repr.buffer_len()); (ip_reply_repr, reply_repr) } @@ -1361,7 +1404,8 @@ impl<'a> Socket<'a> { ) -> Option<(IpRepr, TcpRepr<'static>)> { debug_assert!(self.accepts(cx, ip_repr, repr)); - // Consider how much the sequence number space differs from the transmit buffer space. + // Consider how much the sequence number space differs from the transmit buffer + // space. let (sent_syn, sent_fin) = match self.state { // In SYN-SENT or SYN-RECEIVED, we've just sent a SYN. State::SynSent | State::SynReceived => (true, false), @@ -1424,7 +1468,7 @@ impl<'a> Socket<'a> { return Some(Self::rst_reply(ip_repr, repr)); } // Anything else in the SYN-SENT state is invalid. - (State::SynSent, _, _) => { + (State::SynSent, ..) => { net_debug!("expecting a SYN|ACK"); return None; } @@ -1592,8 +1636,9 @@ impl<'a> Socket<'a> { let mut control = repr.control; control = control.quash_psh(); - // If a FIN is received at the end of the current segment but the start of the segment - // is not at the start of the receive window, disregard this FIN. + // If a FIN is received at the end of the current segment but the start of the + // segment is not at the start of the receive window, disregard this + // FIN. if control == TcpControl::Fin && window_start != segment_start { control = TcpControl::None; } @@ -1776,8 +1821,9 @@ impl<'a> Socket<'a> { // Update remote state. self.remote_last_ts = Some(cx.now()); - // RFC 1323: The window field (SEG.WND) in the header of every incoming segment, with the - // exception of SYN segments, is left-shifted by Snd.Wind.Scale bits before updating SND.WND. + // RFC 1323: The window field (SEG.WND) in the header of every incoming segment, + // with the exception of SYN segments, is left-shifted by Snd.Wind.Scale + // bits before updating SND.WND. let scale = match repr.control { TcpControl::Syn => 0, _ => self.remote_win_scale.unwrap_or(0), @@ -1868,7 +1914,10 @@ impl<'a> Socket<'a> { let assembler_was_empty = self.assembler.is_empty(); // Try adding payload octets to the assembler. - let Ok(contig_len) = self.assembler.add_then_remove_front(payload_offset, payload_len) else { + let Ok(contig_len) = self + .assembler + .add_then_remove_front(payload_offset, payload_len) + else { net_debug!( "assembler: too many holes to add {} octets at offset {}", payload_len, @@ -1946,7 +1995,7 @@ impl<'a> Socket<'a> { fn timed_out(&self, timestamp: Instant) -> bool { match (self.remote_last_ts, self.timeout) { (Some(remote_last_ts), Some(timeout)) => timestamp >= remote_last_ts + timeout, - (_, _) => false, + (..) => false, } } @@ -2008,7 +2057,8 @@ impl<'a> Socket<'a> { // Can we actually send the FIN? We can send it if: // 1. We have unsent data that fits in the remote window. // 2. We have no unsent data. - // This condition matches only if #2, because #1 is already covered by can_data and we're ORing them. + // This condition matches only if #2, because #1 is already covered by can_data + // and we're ORing them. let can_fin = want_fin && self.remote_last_seq == self.local_seq_no + self.tx_buffer.len(); can_send || can_fin @@ -2067,7 +2117,8 @@ impl<'a> Socket<'a> { self.set_state(State::Closed); } else if !self.seq_to_transmit(cx) { if let Some(retransmit_delta) = self.timer.should_retransmit(cx.now()) { - // If a retransmit timer expired, we should resend data starting at the last ACK. + // If a retransmit timer expired, we should resend data starting at the last + // ACK. net_debug!("retransmitting at t+{}", retransmit_delta); // Rewind "last sequence number sent", as if we never @@ -2221,10 +2272,11 @@ impl<'a> Socket<'a> { State::FinWait2 | State::TimeWait => {} } - // There might be more than one reason to send a packet. E.g. the keep-alive timer - // has expired, and we also have data in transmit buffer. Since any packet that occupies - // sequence space will elicit an ACK, we only need to send an explicit packet if we - // couldn't fill the sequence space with anything. + // There might be more than one reason to send a packet. E.g. the keep-alive + // timer has expired, and we also have data in transmit buffer. Since + // any packet that occupies sequence space will elicit an ACK, we only + // need to send an explicit packet if we couldn't fill the sequence + // space with anything. let is_keep_alive; if self.timer.should_keep_alive(cx.now()) && repr.is_empty() { repr.seq_number = repr.seq_number - 1; @@ -2289,8 +2341,8 @@ impl<'a> Socket<'a> { } self.ack_delay_timer = AckDelayTimer::Idle; - // Leave the rest of the state intact if sending a keep-alive packet, since those - // carry a fake segment. + // Leave the rest of the state intact if sending a keep-alive packet, since + // those carry a fake segment. if is_keep_alive { return Ok(()); } @@ -2313,7 +2365,8 @@ impl<'a> Socket<'a> { } if self.state == State::Closed { - // When aborting a connection, forget about it after sending a single RST packet. + // When aborting a connection, forget about it after sending a single RST + // packet. self.tuple = None; #[cfg(feature = "async")] { @@ -2355,7 +2408,7 @@ impl<'a> Socket<'a> { // when the timeout would expire. (Some(remote_last_ts), Some(timeout)) => PollAt::Time(remote_last_ts + timeout), // Otherwise we have no timeout. - (_, _) => PollAt::Ingress, + (..) => PollAt::Ingress, }; // We wait for the earliest of our timers to fire. @@ -2380,11 +2433,14 @@ impl<'a> fmt::Write for Socket<'a> { #[cfg(test)] mod test { + use core::i32; + use std::{ + ops::{Deref, DerefMut}, + vec::Vec, + }; + use super::*; use crate::wire::IpRepr; - use core::i32; - use std::ops::{Deref, DerefMut}; - use std::vec::Vec; // =========================================================================================// // Constants @@ -3661,11 +3717,11 @@ mod test { } fn setup_rfc2018_cases() -> (TestSocket, Vec) { - // This is a utility function used by the tests for RFC 2018 cases. It configures a socket - // in a particular way suitable for those cases. + // This is a utility function used by the tests for RFC 2018 cases. It + // configures a socket in a particular way suitable for those cases. // - // RFC 2018: Assume the left window edge is 5000 and that the data transmitter sends [...] - // segments, each containing 500 data bytes. + // RFC 2018: Assume the left window edge is 5000 and that the data transmitter + // sends [...] segments, each containing 500 data bytes. let mut s = socket_established_with_buffer_sizes(4000, 4000); s.remote_has_sack = true; @@ -3708,17 +3764,18 @@ mod test { #[test] fn test_established_rfc2018_cases() { - // This test case verifies the exact scenarios described on pages 8-9 of RFC 2018. Please - // ensure its behavior does not deviate from those scenarios. + // This test case verifies the exact scenarios described on pages 8-9 of RFC + // 2018. Please ensure its behavior does not deviate from those + // scenarios. let (mut s, segment) = setup_rfc2018_cases(); // RFC 2018: // // Case 2: The first segment is dropped but the remaining 7 are received. // - // Upon receiving each of the last seven packets, the data receiver will return a TCP ACK - // segment that acknowledges sequence number 5000 and contains a SACK option specifying one - // block of queued data: + // Upon receiving each of the last seven packets, the data receiver will return + // a TCP ACK segment that acknowledges sequence number 5000 and contains + // a SACK option specifying one block of queued data: // // Triggering ACK Left Edge Right Edge // Segment @@ -3917,8 +3974,9 @@ mod test { // - Peer doesn't ack them yet // - Sends data so we need to reply with an ACK - // - ...AND and sends a window announcement that SHRINKS the window, so data we've - // previously sent is now outside the window. Yes, this is allowed by TCP. + // - ...AND and sends a window announcement that SHRINKS the window, so data + // we've previously sent is now outside the window. Yes, this is allowed by + // TCP. send!( s, TcpRepr { diff --git a/modules/time/src/stat.rs b/modules/time/src/stat.rs index 392c7f6e..3a911d4f 100644 --- a/modules/time/src/stat.rs +++ b/modules/time/src/stat.rs @@ -12,7 +12,7 @@ pub struct TaskTimeStat { user_time: Duration, system_time: Duration, - task_start: Duration, + // task_start: Duration, system_time_start: Duration, user_time_start: Duration, schedule_time_start: Duration, @@ -22,10 +22,10 @@ pub struct TaskTimeStat { } impl TaskTimeStat { - pub fn new() -> Self { - let start = get_time_duration(); + pub const fn new() -> Self { + // let start = get_time_duration(); Self { - task_start: start, + // task_start: start, user_time: Duration::ZERO, system_time: Duration::ZERO, child_user_time: Duration::ZERO, diff --git a/modules/timer/src/lib.rs b/modules/timer/src/lib.rs index 71562404..c8229eac 100644 --- a/modules/timer/src/lib.rs +++ b/modules/timer/src/lib.rs @@ -101,7 +101,7 @@ impl TimerManager { current, timer.0.expire ); - let mut timer = timers.pop().unwrap().0; + let timer = timers.pop().unwrap().0; if let Some(new_timer) = timer.callback() { timers.push(Reverse(new_timer)); }