forked from M-Labs/artiq
1
0
Fork 0

Revert "Upgrade smoltcp 0.6.0 -> 0.8.0"

This reverts commit c60de48a30.
This commit is contained in:
Sebastien Bourdeauducq 2022-07-08 17:58:13 +08:00
parent d622fb8db7
commit 2e05a1bd0d
7 changed files with 97 additions and 106 deletions

View File

@ -240,12 +240,6 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577" checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577"
[[package]]
name = "managed"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.4.1" version = "2.4.1"
@ -327,7 +321,7 @@ dependencies = [
"io", "io",
"log", "log",
"logger_artiq", "logger_artiq",
"managed 0.7.2", "managed",
"proto_artiq", "proto_artiq",
"riscv", "riscv",
"smoltcp", "smoltcp",
@ -371,13 +365,13 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]] [[package]]
name = "smoltcp" name = "smoltcp"
version = "0.8.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2308a1657c8db1f5b4993bab4e620bdbe5623bd81f254cf60326767bb243237" checksum = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"byteorder", "byteorder",
"managed 0.8.0", "managed",
] ]
[[package]] [[package]]

View File

@ -16,5 +16,5 @@ build_misoc = { path = "../libbuild_misoc" }
byteorder = { version = "1.0", default-features = false } byteorder = { version = "1.0", default-features = false }
crc = { version = "1.7", default-features = false } crc = { version = "1.7", default-features = false }
board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp"] } board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp"] }
smoltcp = { version = "0.8.0", default-features = false, features = ["medium-ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } smoltcp = { version = "0.6.0", default-features = false, features = ["ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] }
riscv = { version = "0.6.0", features = ["inline-asm"] } riscv = { version = "0.6.0", features = ["inline-asm"] }

View File

@ -18,8 +18,6 @@ use board_misoc::slave_fpga;
use board_misoc::{clock, ethmac, net_settings}; use board_misoc::{clock, ethmac, net_settings};
use board_misoc::uart_console::Console; use board_misoc::uart_console::Console;
use riscv::register::{mcause, mepc, mtval}; use riscv::register::{mcause, mepc, mtval};
use smoltcp::iface::SocketStorage;
use smoltcp::wire::HardwareAddress;
fn check_integrity() -> bool { fn check_integrity() -> bool {
extern { extern {
@ -398,9 +396,6 @@ fn network_boot() {
println!("Initializing network..."); println!("Initializing network...");
// Assuming only one socket is ever needed by the bootloader.
// The smoltcp reuses the listening socket when the connection is established.
let mut sockets = [SocketStorage::EMPTY];
let mut net_device = unsafe { ethmac::EthernetDevice::new() }; let mut net_device = unsafe { ethmac::EthernetDevice::new() };
net_device.reset_phy_if_any(); net_device.reset_phy_if_any();
@ -417,15 +412,15 @@ fn network_boot() {
let mut interface = match net_addresses.ipv6_addr { let mut interface = match net_addresses.ipv6_addr {
Some(addr) => { Some(addr) => {
ip_addrs[2] = IpCidr::new(addr, 0); ip_addrs[2] = IpCidr::new(addr, 0);
smoltcp::iface::InterfaceBuilder::new(net_device, &mut sockets[..]) smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) .ethernet_addr(net_addresses.hardware_addr)
.ip_addrs(&mut ip_addrs[..]) .ip_addrs(&mut ip_addrs[..])
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.finalize() .finalize()
} }
None => None =>
smoltcp::iface::InterfaceBuilder::new(net_device, &mut sockets[..]) smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) .ethernet_addr(net_addresses.hardware_addr)
.ip_addrs(&mut ip_addrs[..2]) .ip_addrs(&mut ip_addrs[..2])
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.finalize() .finalize()
@ -434,10 +429,14 @@ fn network_boot() {
let mut rx_storage = [0; 4096]; let mut rx_storage = [0; 4096];
let mut tx_storage = [0; 128]; let mut tx_storage = [0; 128];
let mut socket_set_entries: [_; 1] = Default::default();
let mut sockets =
smoltcp::socket::SocketSet::new(&mut socket_set_entries[..]);
let tcp_rx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut rx_storage[..]); let tcp_rx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut rx_storage[..]);
let tcp_tx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut tx_storage[..]); let tcp_tx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut tx_storage[..]);
let tcp_socket = smoltcp::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); let tcp_socket = smoltcp::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let tcp_handle = interface.add_socket(tcp_socket); let tcp_handle = sockets.add(tcp_socket);
let mut net_conn = NetConn::new(); let mut net_conn = NetConn::new();
let mut boot_time = None; let mut boot_time = None;
@ -447,7 +446,7 @@ fn network_boot() {
loop { loop {
let timestamp = clock::get_ms() as i64; let timestamp = clock::get_ms() as i64;
{ {
let socket = &mut *interface.get_socket::<smoltcp::socket::TcpSocket>(tcp_handle); let socket = &mut *sockets.get::<smoltcp::socket::TcpSocket>(tcp_handle);
match boot_time { match boot_time {
None => { None => {
@ -476,7 +475,7 @@ fn network_boot() {
} }
} }
match interface.poll(smoltcp::time::Instant::from_millis(timestamp)) { match interface.poll(&mut sockets, smoltcp::time::Instant::from_millis(timestamp)) {
Ok(_) => (), Ok(_) => (),
Err(smoltcp::Error::Unrecognized) => (), Err(smoltcp::Error::Unrecognized) => (),
Err(err) => println!("Network error: {}", err) Err(err) => println!("Network error: {}", err)

View File

@ -15,7 +15,7 @@ build_misoc = { path = "../libbuild_misoc" }
[dependencies] [dependencies]
byteorder = { version = "1.0", default-features = false } byteorder = { version = "1.0", default-features = false }
log = { version = "0.4", default-features = false, optional = true } log = { version = "0.4", default-features = false, optional = true }
smoltcp = { version = "0.8.0", default-features = false, optional = true } smoltcp = { version = "0.6.0", default-features = false, optional = true }
riscv = { version = "0.6.0", features = ["inline-asm"] } riscv = { version = "0.6.0", features = ["inline-asm"] }
[features] [features]

View File

@ -27,7 +27,7 @@ board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp
logger_artiq = { path = "../liblogger_artiq" } logger_artiq = { path = "../liblogger_artiq" }
board_artiq = { path = "../libboard_artiq" } board_artiq = { path = "../libboard_artiq" }
proto_artiq = { path = "../libproto_artiq", features = ["log", "alloc"] } proto_artiq = { path = "../libproto_artiq", features = ["log", "alloc"] }
smoltcp = { version = "0.8.0", default-features = false, features = ["alloc", "medium-ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } smoltcp = { version = "0.6.0", default-features = false, features = ["alloc", "ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] }
riscv = { version = "0.6.0", features = ["inline-asm"] } riscv = { version = "0.6.0", features = ["inline-asm"] }
[dependencies.fringe] [dependencies.fringe]

View File

@ -27,7 +27,7 @@ extern crate riscv;
use core::cell::RefCell; use core::cell::RefCell;
use core::convert::TryFrom; use core::convert::TryFrom;
use smoltcp::wire::{IpCidr, HardwareAddress}; use smoltcp::wire::IpCidr;
use board_misoc::{csr, ident, clock, spiflash, config, net_settings, pmp, boot}; use board_misoc::{csr, ident, clock, spiflash, config, net_settings, pmp, boot};
#[cfg(has_ethmac)] #[cfg(has_ethmac)]
@ -123,33 +123,38 @@ fn startup() {
net_device.reset_phy_if_any(); net_device.reset_phy_if_any();
let net_device = { let net_device = {
use smoltcp::phy::Tracer; use smoltcp::time::Instant;
use smoltcp::wire::PrettyPrinter;
use smoltcp::wire::EthernetFrame;
// We can't create the function pointer as a separate variable here because the type of fn net_trace_writer(timestamp: Instant, printer: PrettyPrinter<EthernetFrame<&[u8]>>) {
// the packet argument Packet isn't accessible and rust's type inference isn't sufficient
// to propagate in to a local var.
match config::read_str("net_trace", |r| r.map(|s| s == "1")) {
Ok(true) => Tracer::new(net_device, |timestamp, packet| {
print!("\x1b[37m[{:6}.{:03}s]\n{}\x1b[0m\n", print!("\x1b[37m[{:6}.{:03}s]\n{}\x1b[0m\n",
timestamp.secs(), timestamp.millis(), packet) timestamp.secs(), timestamp.millis(), printer)
}),
_ => Tracer::new(net_device, |_, _| {}),
} }
fn net_trace_silent(_timestamp: Instant, _printer: PrettyPrinter<EthernetFrame<&[u8]>>) {}
let net_trace_fn: fn(Instant, PrettyPrinter<EthernetFrame<&[u8]>>);
match config::read_str("net_trace", |r| r.map(|s| s == "1")) {
Ok(true) => net_trace_fn = net_trace_writer,
_ => net_trace_fn = net_trace_silent
}
smoltcp::phy::EthernetTracer::new(net_device, net_trace_fn)
}; };
let neighbor_cache = let neighbor_cache =
smoltcp::iface::NeighborCache::new(alloc::collections::btree_map::BTreeMap::new()); smoltcp::iface::NeighborCache::new(alloc::collections::btree_map::BTreeMap::new());
let net_addresses = net_settings::get_adresses(); let net_addresses = net_settings::get_adresses();
info!("network addresses: {}", net_addresses); info!("network addresses: {}", net_addresses);
let interface = match net_addresses.ipv6_addr { let mut interface = match net_addresses.ipv6_addr {
Some(addr) => { Some(addr) => {
let ip_addrs = [ let ip_addrs = [
IpCidr::new(net_addresses.ipv4_addr, 0), IpCidr::new(net_addresses.ipv4_addr, 0),
IpCidr::new(net_addresses.ipv6_ll_addr, 0), IpCidr::new(net_addresses.ipv6_ll_addr, 0),
IpCidr::new(addr, 0) IpCidr::new(addr, 0)
]; ];
smoltcp::iface::InterfaceBuilder::new(net_device, vec![]) smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) .ethernet_addr(net_addresses.hardware_addr)
.ip_addrs(ip_addrs) .ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.finalize() .finalize()
@ -159,8 +164,8 @@ fn startup() {
IpCidr::new(net_addresses.ipv4_addr, 0), IpCidr::new(net_addresses.ipv4_addr, 0),
IpCidr::new(net_addresses.ipv6_ll_addr, 0) IpCidr::new(net_addresses.ipv6_ll_addr, 0)
]; ];
smoltcp::iface::InterfaceBuilder::new(net_device, vec![]) smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) .ethernet_addr(net_addresses.hardware_addr)
.ip_addrs(ip_addrs) .ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.finalize() .finalize()
@ -179,7 +184,7 @@ fn startup() {
drtio_routing::interconnect_disable_all(); drtio_routing::interconnect_disable_all();
let aux_mutex = sched::Mutex::new(); let aux_mutex = sched::Mutex::new();
let mut scheduler = sched::Scheduler::new(interface); let mut scheduler = sched::Scheduler::new();
let io = scheduler.io(); let io = scheduler.io();
rtio_mgt::startup(&io, &aux_mutex, &drtio_routing_table, &up_destinations); rtio_mgt::startup(&io, &aux_mutex, &drtio_routing_table, &up_destinations);
@ -206,7 +211,19 @@ fn startup() {
let mut net_stats = ethmac::EthernetStatistics::new(); let mut net_stats = ethmac::EthernetStatistics::new();
loop { loop {
scheduler.run(); scheduler.run();
scheduler.run_network();
{
let sockets = &mut *scheduler.sockets().borrow_mut();
loop {
let timestamp = smoltcp::time::Instant::from_millis(clock::get_ms() as i64);
match interface.poll(sockets, timestamp) {
Ok(true) => (),
Ok(false) => break,
Err(smoltcp::Error::Unrecognized) => (),
Err(err) => debug!("network error: {}", err)
}
}
}
if let Some(_net_stats_diff) = net_stats.update() { if let Some(_net_stats_diff) = net_stats.update() {
debug!("ethernet mac:{}", ethmac::EthernetStatistics::new()); debug!("ethernet mac:{}", ethmac::EthernetStatistics::new());

View File

@ -9,13 +9,11 @@ use fringe::generator::{Generator, Yielder, State as GeneratorState};
use smoltcp::time::Duration; use smoltcp::time::Duration;
use smoltcp::Error as NetworkError; use smoltcp::Error as NetworkError;
use smoltcp::wire::IpEndpoint; use smoltcp::wire::IpEndpoint;
use smoltcp::iface::{Interface, SocketHandle}; use smoltcp::socket::{SocketHandle, SocketRef};
use io::{Read, Write}; use io::{Read, Write};
use board_misoc::clock; use board_misoc::clock;
use urc::Urc; use urc::Urc;
use board_misoc::ethmac::EthernetDevice;
use smoltcp::phy::Tracer;
#[derive(Fail, Debug)] #[derive(Fail, Debug)]
pub enum Error { pub enum Error {
@ -33,6 +31,8 @@ impl From<NetworkError> for Error {
} }
} }
type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>;
#[derive(Debug)] #[derive(Debug)]
struct WaitRequest { struct WaitRequest {
event: Option<*mut dyn FnMut() -> bool>, event: Option<*mut dyn FnMut() -> bool>,
@ -59,7 +59,7 @@ impl Thread {
unsafe fn new<F>(io: &Io, stack_size: usize, f: F) -> ThreadHandle unsafe fn new<F>(io: &Io, stack_size: usize, f: F) -> ThreadHandle
where F: 'static + FnOnce(Io) + Send { where F: 'static + FnOnce(Io) + Send {
let spawned = io.spawned.clone(); let spawned = io.spawned.clone();
let network = io.network.clone(); let sockets = io.sockets.clone();
// Add a 4k stack guard to the stack of any new threads // Add a 4k stack guard to the stack of any new threads
let stack = OwnedStack::new(stack_size + 4096); let stack = OwnedStack::new(stack_size + 4096);
@ -67,8 +67,8 @@ impl Thread {
generator: Generator::unsafe_new(stack, |yielder, _| { generator: Generator::unsafe_new(stack, |yielder, _| {
f(Io { f(Io {
yielder: Some(yielder), yielder: Some(yielder),
spawned, spawned: spawned,
network sockets: sockets
}) })
}), }),
waiting_for: WaitRequest { waiting_for: WaitRequest {
@ -115,21 +115,19 @@ impl ThreadHandle {
} }
} }
type Network = Interface<'static, Tracer<EthernetDevice>>;
pub struct Scheduler { pub struct Scheduler {
threads: Vec<ThreadHandle>, threads: Vec<ThreadHandle>,
spawned: Urc<RefCell<Vec<ThreadHandle>>>, spawned: Urc<RefCell<Vec<ThreadHandle>>>,
network: Urc<RefCell<Network>>, sockets: Urc<RefCell<SocketSet>>,
run_idx: usize, run_idx: usize,
} }
impl Scheduler { impl Scheduler {
pub fn new(network: Network) -> Scheduler { pub fn new() -> Scheduler {
Scheduler { Scheduler {
threads: Vec::new(), threads: Vec::new(),
spawned: Urc::new(RefCell::new(Vec::new())), spawned: Urc::new(RefCell::new(Vec::new())),
network: Urc::new(RefCell::new(network)), sockets: Urc::new(RefCell::new(SocketSet::new(Vec::new()))),
run_idx: 0, run_idx: 0,
} }
} }
@ -138,11 +136,13 @@ impl Scheduler {
Io { Io {
yielder: None, yielder: None,
spawned: self.spawned.clone(), spawned: self.spawned.clone(),
network: self.network.clone() sockets: self.sockets.clone()
} }
} }
pub fn run(&mut self) { pub fn run(&mut self) {
self.sockets.borrow_mut().prune();
self.threads.append(&mut *self.spawned.borrow_mut()); self.threads.append(&mut *self.spawned.borrow_mut());
if self.threads.len() == 0 { return } if self.threads.len() == 0 { return }
@ -188,17 +188,8 @@ impl Scheduler {
} }
} }
pub fn run_network(&mut self) { pub fn sockets(&self) -> &RefCell<SocketSet> {
let mut interface = self.network.borrow_mut(); &*self.sockets
loop {
let timestamp = smoltcp::time::Instant::from_millis(clock::get_ms() as i64);
match interface.poll(timestamp) {
Ok(true) => (),
Ok(false) => break,
Err(smoltcp::Error::Unrecognized) => (),
Err(err) => debug!("network error: {}", err)
}
}
} }
} }
@ -206,7 +197,7 @@ impl Scheduler {
pub struct Io<'a> { pub struct Io<'a> {
yielder: Option<&'a Yielder<WaitResult, WaitRequest>>, yielder: Option<&'a Yielder<WaitResult, WaitRequest>>,
spawned: Urc<RefCell<Vec<ThreadHandle>>>, spawned: Urc<RefCell<Vec<ThreadHandle>>>,
network: Urc<RefCell<Network>>, sockets: Urc<RefCell<SocketSet>>,
} }
impl<'a> Io<'a> { impl<'a> Io<'a> {
@ -300,10 +291,10 @@ impl<'a> Drop for MutexGuard<'a> {
macro_rules! until { macro_rules! until {
($socket:expr, $ty:ty, |$var:ident| $cond:expr) => ({ ($socket:expr, $ty:ty, |$var:ident| $cond:expr) => ({
let (network, handle) = ($socket.io.network.clone(), $socket.handle); let (sockets, handle) = ($socket.io.sockets.clone(), $socket.handle);
$socket.io.until(move || { $socket.io.until(move || {
let mut network = network.borrow_mut(); let mut sockets = sockets.borrow_mut();
let $var = network.get_socket::<$ty>(handle); let $var = sockets.get::<$ty>(handle);
$cond $cond
}) })
}) })
@ -325,9 +316,9 @@ impl<'a> TcpListener<'a> {
fn new_lower(io: &'a Io<'a>, buffer_size: usize) -> SocketHandle { fn new_lower(io: &'a Io<'a>, buffer_size: usize) -> SocketHandle {
let rx_buffer = vec![0; buffer_size]; let rx_buffer = vec![0; buffer_size];
let tx_buffer = vec![0; buffer_size]; let tx_buffer = vec![0; buffer_size];
io.network io.sockets
.borrow_mut() .borrow_mut()
.add_socket(TcpSocketLower::new( .add(TcpSocketLower::new(
TcpSocketBuffer::new(rx_buffer), TcpSocketBuffer::new(rx_buffer),
TcpSocketBuffer::new(tx_buffer))) TcpSocketBuffer::new(tx_buffer)))
} }
@ -342,9 +333,9 @@ impl<'a> TcpListener<'a> {
} }
fn with_lower<F, R>(&self, f: F) -> R fn with_lower<F, R>(&self, f: F) -> R
where F: FnOnce(&mut TcpSocketLower) -> R { where F: FnOnce(SocketRef<TcpSocketLower>) -> R {
let mut network = self.io.network.borrow_mut(); let mut sockets = self.io.sockets.borrow_mut();
let result = f(network.get_socket(self.handle.get())); let result = f(sockets.get(self.handle.get()));
result result
} }
@ -362,7 +353,7 @@ impl<'a> TcpListener<'a> {
pub fn listen<T: Into<IpEndpoint>>(&self, endpoint: T) -> Result<(), Error> { pub fn listen<T: Into<IpEndpoint>>(&self, endpoint: T) -> Result<(), Error> {
let endpoint = endpoint.into(); let endpoint = endpoint.into();
self.with_lower(|s| s.listen(endpoint)) self.with_lower(|mut s| s.listen(endpoint))
.map(|()| { .map(|()| {
self.endpoint.set(endpoint); self.endpoint.set(endpoint);
() ()
@ -374,10 +365,10 @@ impl<'a> TcpListener<'a> {
// We're waiting until at least one half of the connection becomes open. // We're waiting until at least one half of the connection becomes open.
// This handles the case where a remote socket immediately sends a FIN-- // This handles the case where a remote socket immediately sends a FIN--
// that still counts as accepting even though nothing may be sent. // that still counts as accepting even though nothing may be sent.
let (network, handle) = (self.io.network.clone(), self.handle.get()); let (sockets, handle) = (self.io.sockets.clone(), self.handle.get());
self.io.until(move || { self.io.until(move || {
let mut network = network.borrow_mut(); let mut sockets = sockets.borrow_mut();
let socket = network.get_socket::<TcpSocketLower>(handle); let socket = sockets.get::<TcpSocketLower>(handle);
socket.may_send() || socket.may_recv() socket.may_send() || socket.may_recv()
})?; })?;
@ -394,14 +385,14 @@ impl<'a> TcpListener<'a> {
} }
pub fn close(&self) { pub fn close(&self) {
self.with_lower(|s| s.close()) self.with_lower(|mut s| s.close())
} }
} }
impl<'a> Drop for TcpListener<'a> { impl<'a> Drop for TcpListener<'a> {
fn drop(&mut self) { fn drop(&mut self) {
self.with_lower(|s| s.close()); self.with_lower(|mut s| s.close());
self.io.network.borrow_mut().remove_socket(self.handle.get()); self.io.sockets.borrow_mut().release(self.handle.get())
} }
} }
@ -425,9 +416,9 @@ impl<'a> TcpStream<'a> {
} }
fn with_lower<F, R>(&self, f: F) -> R fn with_lower<F, R>(&self, f: F) -> R
where F: FnOnce(&mut TcpSocketLower) -> R { where F: FnOnce(SocketRef<TcpSocketLower>) -> R {
let mut network = self.io.network.borrow_mut(); let mut sockets = self.io.sockets.borrow_mut();
let result = f(network.get_socket(self.handle)); let result = f(sockets.get(self.handle));
result result
} }
@ -464,7 +455,7 @@ impl<'a> TcpStream<'a> {
} }
pub fn set_timeout(&self, value: Option<u64>) { pub fn set_timeout(&self, value: Option<u64>) {
self.with_lower(|s| s.set_timeout(value.map(Duration::from_millis))) self.with_lower(|mut s| s.set_timeout(value.map(Duration::from_millis)))
} }
pub fn keep_alive(&self) -> Option<u64> { pub fn keep_alive(&self) -> Option<u64> {
@ -472,11 +463,11 @@ impl<'a> TcpStream<'a> {
} }
pub fn set_keep_alive(&self, value: Option<u64>) { pub fn set_keep_alive(&self, value: Option<u64>) {
self.with_lower(|s| s.set_keep_alive(value.map(Duration::from_millis))) self.with_lower(|mut s| s.set_keep_alive(value.map(Duration::from_millis)))
} }
pub fn close(&self) -> Result<(), Error> { pub fn close(&self) -> Result<(), Error> {
self.with_lower(|s| s.close()); self.with_lower(|mut s| s.close());
until!(self, TcpSocketLower, |s| !s.is_open())?; until!(self, TcpSocketLower, |s| !s.is_open())?;
// right now the socket may be in TIME-WAIT state. if we don't give it a chance to send // right now the socket may be in TIME-WAIT state. if we don't give it a chance to send
// a packet, and the user code executes a loop { s.listen(); s.read(); s.close(); } // a packet, and the user code executes a loop { s.listen(); s.read(); s.close(); }
@ -490,33 +481,23 @@ impl<'a> Read for TcpStream<'a> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError> { fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError> {
// Only borrow the underlying socket for the span of the next statement. // Only borrow the underlying socket for the span of the next statement.
let result = self.with_lower(|s| s.recv_slice(buf)); let result = self.with_lower(|mut s| s.recv_slice(buf));
match result { match result {
// Slow path: we need to block until buffer is non-empty. // Slow path: we need to block until buffer is non-empty.
Ok(0) => { Ok(0) => {
until!(self, TcpSocketLower, |s| s.can_recv() || !s.may_recv())?; until!(self, TcpSocketLower, |s| s.can_recv() || !s.may_recv())?;
match self.with_lower(|s| s.recv_slice(buf)) { match self.with_lower(|mut s| s.recv_slice(buf)) {
Ok(length) => Ok(length), Ok(length) => Ok(length),
Err(NetworkError::Finished) |
Err(NetworkError::Illegal) => Ok(0), Err(NetworkError::Illegal) => Ok(0),
Err(e) => { _ => unreachable!()
panic!("Unexpected error from smoltcp: {}", e);
}
} }
} }
// Fast path: we had data in buffer. // Fast path: we had data in buffer.
Ok(length) => Ok(length), Ok(length) => Ok(length),
// We've received a fin.
Err(NetworkError::Finished) |
// Error path: the receive half of the socket is not open. // Error path: the receive half of the socket is not open.
Err(NetworkError::Illegal) => Ok(0), Err(NetworkError::Illegal) => Ok(0),
// No other error may be returned. // No other error may be returned.
Err(e) => { Err(_) => unreachable!()
// This could return Err(Error::Network(e)) rather than panic,
// but I expect that'll just cause a panic later perhaps with
// less interesting context.
panic!("Unexpected error from smoltcp: {}", e);
}
} }
} }
} }
@ -527,12 +508,12 @@ impl<'a> Write for TcpStream<'a> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> { fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
// Only borrow the underlying socket for the span of the next statement. // Only borrow the underlying socket for the span of the next statement.
let result = self.with_lower(|s| s.send_slice(buf)); let result = self.with_lower(|mut s| s.send_slice(buf));
match result { match result {
// Slow path: we need to block until buffer is non-full. // Slow path: we need to block until buffer is non-full.
Ok(0) => { Ok(0) => {
until!(self, TcpSocketLower, |s| s.can_send() || !s.may_send())?; until!(self, TcpSocketLower, |s| s.can_send() || !s.may_send())?;
match self.with_lower(|s| s.send_slice(buf)) { match self.with_lower(|mut s| s.send_slice(buf)) {
Ok(length) => Ok(length), Ok(length) => Ok(length),
Err(NetworkError::Illegal) => Ok(0), Err(NetworkError::Illegal) => Ok(0),
_ => unreachable!() _ => unreachable!()
@ -559,7 +540,7 @@ impl<'a> Write for TcpStream<'a> {
impl<'a> Drop for TcpStream<'a> { impl<'a> Drop for TcpStream<'a> {
fn drop(&mut self) { fn drop(&mut self) {
self.with_lower(|s| s.close()); self.with_lower(|mut s| s.close());
self.io.network.borrow_mut().remove_socket(self.handle); self.io.sockets.borrow_mut().release(self.handle)
} }
} }