Migrating to smoltcp 0.10

This commit is contained in:
Gartox
2023-08-28 18:11:08 +02:00
parent 2f1443b925
commit 035bcf1d69
12 changed files with 217 additions and 163 deletions
+6 -4
View File
@@ -20,22 +20,24 @@ netutils = { git = "https://gitlab.redox-os.org/redox-os/netutils.git" }
redox_event = { git = "https://gitlab.redox-os.org/redox-os/event.git" }
redox-daemon = "0.1.1"
redox_syscall = "0.3"
redox-log = "0.1"
byteorder = { version = "1.0", default-features = false }
dns-parser = "0.7.1"
[dependencies.log]
version = "0.3"
version = "0.4"
default-features = false
features = ["release_max_level_warn"]
[dependencies.smoltcp]
path = "smoltcp"
version = "0.10.0"
default-features = false
features = [
"std",
"ethernet",
"medium-ethernet",
"proto-ipv4",
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp"
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp",
"log"
]
#For debugging: "log", "verbose"
+1 -1
View File
@@ -81,7 +81,7 @@ fn run(daemon: redox_daemon::Daemon) -> Result<()> {
fn main() {
redox_daemon::Daemon::new(move |daemon| {
logger::init_logger();
logger::init_logger("dnsd");
if let Err(err) = run(daemon) {
error!("dnsd: {}", err);
process::exit(1);
+13 -19
View File
@@ -1,22 +1,16 @@
use log::{set_logger_raw, Log, LogLevelFilter, LogMetadata, LogRecord};
use redox_log::{OutputBuilder, RedoxLogger};
struct Logger;
impl Log for Logger {
fn enabled(&self, _: &LogMetadata) -> bool {
true
}
fn log(&self, record: &LogRecord) {
println!("{}: {}", record.target(), record.args());
}
}
pub fn init_logger() {
unsafe {
set_logger_raw(|max_log_level| {
max_log_level.set(LogLevelFilter::Trace);
&Logger
}).expect("Can't initialize logger");
pub fn init_logger(process_name: &str) {
if let Err(_) = RedoxLogger::new()
.with_output(
OutputBuilder::stdout()
.with_ansi_escape_codes()
.flush_on_newline(true)
.with_filter(log::LevelFilter::Trace)
.build(),
)
.with_process_name(process_name.into())
.enable() {
eprintln!("{process_name}: Failed to init logger")
}
}
+13 -13
View File
@@ -45,9 +45,9 @@ pub struct RxToken {
}
impl smoltcp::phy::RxToken for RxToken {
fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> smoltcp::Result<R>
fn consume<R, F>(mut self, f: F) -> R
where
F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
F: FnOnce(&mut [u8]) -> R,
{
f(&mut self.buffer)
}
@@ -58,14 +58,14 @@ pub struct TxToken {
}
impl smoltcp::phy::TxToken for TxToken {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result<R>
fn consume<R, F>(self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
F: FnOnce(&mut [u8]) -> R,
{
let data = self.data.borrow_mut();
let mut buffer = data.buffer_pool.borrow_mut().get_buffer();
buffer.resize(len);
let res = f(&mut buffer)?;
let res = f(&mut buffer);
let mut loopback = false;
if let Ok(mut frame) = smoltcp::wire::EthernetFrame::new_checked(&mut buffer) {
@@ -78,19 +78,19 @@ impl smoltcp::phy::TxToken for TxToken {
if loopback {
data.input_queue.borrow_mut().push_back(buffer.move_out());
} else {
// TODO: Handle error
data.network_file
.borrow_mut()
.write(&buffer)
.map_err(|_| smoltcp::Error::Dropped)?;
.write(&buffer);
}
Ok(res)
res
}
}
impl<'a> smoltcp::phy::Device<'a> for NetworkDevice {
type RxToken = RxToken;
type TxToken = TxToken;
impl smoltcp::phy::Device for NetworkDevice {
type RxToken<'a> = RxToken;
type TxToken<'a> = TxToken;
fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities {
let mut limits = smoltcp::phy::DeviceCapabilities::default();
@@ -99,7 +99,7 @@ impl<'a> smoltcp::phy::Device<'a> for NetworkDevice {
limits
}
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
let data = self.data.borrow_mut();
let buffer = data.input_queue.borrow_mut().pop_front();
@@ -115,7 +115,7 @@ impl<'a> smoltcp::phy::Device<'a> for NetworkDevice {
}
}
fn transmit(&'a mut self) -> Option<Self::TxToken> {
fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
Some(TxToken {
data: Rc::clone(&self.data),
})
+1 -1
View File
@@ -151,7 +151,7 @@ fn run(daemon: redox_daemon::Daemon) -> Result<()> {
fn main() {
redox_daemon::Daemon::new(move |daemon| {
logger::init_logger();
logger::init_logger("smolnetd");
if let Err(err) = run(daemon) {
error!("smoltcpd: {}", err);
+10 -8
View File
@@ -1,5 +1,6 @@
use smoltcp::socket::{IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer, SocketHandle};
use smoltcp::wire::{Icmpv4Packet, Icmpv4Repr, IpAddress, IpEndpoint};
use smoltcp::socket::icmp::{Endpoint as IcmpEndpoint, PacketMetadata as IcmpPacketMetadata, Socket as IcmpSocket, PacketBuffer as IcmpSocketBuffer};
use smoltcp::iface::SocketHandle;
use smoltcp::wire::{Icmpv4Packet, Icmpv4Repr, IpAddress, IpListenEndpoint};
use std::mem;
use std::str;
use syscall::{Error as SyscallError, Result as SyscallResult};
@@ -9,9 +10,9 @@ use byteorder::{ByteOrder, NetworkEndian};
use crate::device::NetworkDevice;
use crate::port_set::PortSet;
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use super::{Smolnetd, SocketSet};
use super::{Smolnetd, SocketSet, Interface};
pub type IcmpScheme = SocketScheme<IcmpSocket<'static, 'static>>;
pub type IcmpScheme = SocketScheme<IcmpSocket<'static>>;
enum IcmpSocketType {
Echo,
@@ -24,7 +25,7 @@ pub struct IcmpData {
ident: u16,
}
impl<'a, 'b> SchemeSocket for IcmpSocket<'a, 'b> {
impl<'a> SchemeSocket for IcmpSocket<'a> {
type SchemeDataT = PortSet;
type DataT = IcmpData;
type SettingT = ();
@@ -74,6 +75,7 @@ impl<'a, 'b> SchemeSocket for IcmpSocket<'a, 'b> {
path: &str,
_uid: u32,
ident_set: &mut Self::SchemeDataT,
iface: &Interface
) -> SyscallResult<(SocketHandle, Self::DataT)> {
use std::str::FromStr;
@@ -101,7 +103,7 @@ impl<'a, 'b> SchemeSocket for IcmpSocket<'a, 'b> {
)
);
let handle = socket_set.add(socket);
let mut icmp_socket = socket_set.get::<IcmpSocket>(handle);
let icmp_socket = socket_set.get_mut::<IcmpSocket>(handle);
let ident = ident_set
.get_port()
.ok_or_else(|| SyscallError::new(syscall::EINVAL))?;
@@ -133,12 +135,12 @@ impl<'a, 'b> SchemeSocket for IcmpSocket<'a, 'b> {
)
);
let handle = socket_set.add(socket);
let mut icmp_socket = socket_set.get::<IcmpSocket>(handle);
let icmp_socket = socket_set.get_mut::<IcmpSocket>(handle);
let ident = ident_set
.get_port()
.ok_or_else(|| SyscallError::new(syscall::EINVAL))?;
icmp_socket
.bind(IcmpEndpoint::Udp(IpEndpoint::from(ident)))
.bind(IcmpEndpoint::Udp(IpListenEndpoint::from(ident)))
.map_err(|_| syscall::Error::new(syscall::EINVAL))?;
let socket_data = IcmpData {
socket_type: IcmpSocketType::Udp,
+6 -4
View File
@@ -1,16 +1,17 @@
use smoltcp::socket::{RawPacketMetadata, RawSocket, RawSocketBuffer, SocketHandle};
use smoltcp::socket::raw::{PacketMetadata as RawPacketMetadata, Socket as RawSocket, PacketBuffer as RawSocketBuffer};
use smoltcp::iface::SocketHandle;
use smoltcp::wire::{IpProtocol, IpVersion};
use std::str;
use syscall::{Error as SyscallError, Result as SyscallResult};
use syscall;
use crate::device::NetworkDevice;
use super::{Smolnetd, SocketSet};
use super::{Smolnetd, SocketSet, Interface};
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
pub type IpScheme = SocketScheme<RawSocket<'static, 'static>>;
pub type IpScheme = SocketScheme<RawSocket<'static>>;
impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> {
impl<'a> SchemeSocket for RawSocket<'a> {
type SchemeDataT = ();
type DataT = ();
type SettingT = ();
@@ -58,6 +59,7 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> {
path: &str,
uid: u32,
_: &mut Self::SchemeDataT,
iface: &Interface
) -> SyscallResult<(SocketHandle, Self::DataT)> {
if uid != 0 {
return Err(SyscallError::new(syscall::EACCES));
+37 -40
View File
@@ -1,12 +1,12 @@
use netutils::getcfg;
use smoltcp;
use smoltcp::iface::{EthernetInterface, EthernetInterfaceBuilder, NeighborCache, Routes};
use smoltcp::phy::EthernetTracer;
use smoltcp::socket::SocketSet as SmoltcpSocketSet;
use smoltcp::iface::{Interface as SmoltcpInterface, Routes, Config};
use smoltcp::phy::Tracer;
use crate::scheme::smoltcp::iface::SocketSet as SmoltcpSocketSet;
use smoltcp::time::{Duration, Instant};
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, IpEndpoint, Ipv4Address};
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, IpListenEndpoint, HardwareAddress};
use std::cell::RefCell;
use std::collections::{BTreeMap, VecDeque};
use std::collections::VecDeque;
use std::fs::File;
use std::io::{self, Read, Write};
use std::mem::size_of;
@@ -31,14 +31,15 @@ mod udp;
mod icmp;
mod netcfg;
type SocketSet = SmoltcpSocketSet<'static, 'static, 'static>;
type Interface = Rc<RefCell<EthernetInterface<'static, 'static, 'static, EthernetTracer<NetworkDevice>>>>;
type SocketSet = SmoltcpSocketSet<'static>;
type Interface = Rc<RefCell<SmoltcpInterface>>;
const MAX_DURATION: Duration = Duration { millis: ::std::u64::MAX };
const MIN_DURATION: Duration = Duration { millis: 0 };
const MAX_DURATION: Duration = Duration::from_millis(u64::MAX);
const MIN_DURATION: Duration = Duration::from_millis(0);
pub struct Smolnetd {
network_file: Rc<RefCell<File>>,
network_device: Tracer<NetworkDevice>,
time_file: File,
iface: Interface,
@@ -58,8 +59,8 @@ pub struct Smolnetd {
impl Smolnetd {
const MAX_PACKET_SIZE: usize = 2048;
const SOCKET_BUFFER_SIZE: usize = 128; //packets
const MIN_CHECK_TIMEOUT: Duration = Duration { millis: 10 };
const MAX_CHECK_TIMEOUT: Duration = Duration { millis: 500 };
const MIN_CHECK_TIMEOUT: Duration = Duration::from_millis(10);
const MAX_CHECK_TIMEOUT: Duration = Duration::from_millis(500);
pub fn new(
network_file: File,
@@ -84,7 +85,7 @@ impl Smolnetd {
let buffer_pool = Rc::new(RefCell::new(BufferPool::new(Self::MAX_PACKET_SIZE)));
let input_queue = Rc::new(RefCell::new(VecDeque::new()));
let network_file = Rc::new(RefCell::new(network_file));
let network_device = EthernetTracer::new(NetworkDevice::new(
let mut network_device = Tracer::new(NetworkDevice::new(
Rc::clone(&network_file),
Rc::clone(&input_queue),
hardware_addr,
@@ -92,25 +93,23 @@ impl Smolnetd {
), |_timestamp, printer| {
trace!("{}", printer)
});
let mut routes = Routes::new(BTreeMap::new());
routes.add_default_ipv4_route(default_gw).expect("Failed to add default gateway");
let iface = EthernetInterfaceBuilder::new(network_device)
.neighbor_cache(NeighborCache::new(BTreeMap::new()))
.ethernet_addr(hardware_addr)
.ip_addrs(protocol_addrs)
.routes(routes)
.finalize();
let config = Config::new(HardwareAddress::Ethernet(hardware_addr));
let mut iface = SmoltcpInterface::new(config, &mut network_device, Instant::now());
iface.update_ip_addrs(|ip_addrs| ip_addrs.extend(protocol_addrs));
iface.routes_mut().add_default_ipv4_route(default_gw).expect("Failed to add default gateway");
let iface = Rc::new(RefCell::new(iface));
let socket_set = Rc::new(RefCell::new(SocketSet::new(vec![])));
Smolnetd {
iface: Rc::clone(&iface),
network_device,
socket_set: Rc::clone(&socket_set),
timer: ::std::time::Instant::now(),
time_file,
ip_scheme: IpScheme::new(Rc::clone(&socket_set), ip_file),
udp_scheme: UdpScheme::new(Rc::clone(&socket_set), udp_file),
tcp_scheme: TcpScheme::new(Rc::clone(&socket_set), tcp_file),
icmp_scheme: IcmpScheme::new(Rc::clone(&socket_set), icmp_file),
ip_scheme: IpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), ip_file),
udp_scheme: UdpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), udp_file),
tcp_scheme: TcpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), tcp_file),
icmp_scheme: IcmpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), icmp_file),
netcfg_scheme: NetCfgScheme::new(Rc::clone(&iface), netcfg_file),
input_queue,
network_file,
@@ -190,23 +189,22 @@ impl Smolnetd {
break MIN_DURATION;
}
iter_limit -= 1;
match iface.poll(&mut socket_set, timestamp) {
Ok(_) | Err(smoltcp::Error::Unrecognized) => (),
Err(e) => {
error!("poll error: {}", e);
break MIN_DURATION;
}
}
match iface.poll_delay(&socket_set, timestamp) {
Some(Duration { millis: 0 }) => { }
// TODO: Check what if the bool returned by poll can be useful
iface.poll(timestamp, &mut self.network_device, &mut socket_set);
match iface.poll_delay(timestamp, &socket_set) {
Some(delay) if delay == Duration::ZERO => { }
Some(delay) => {
break ::std::cmp::min(MAX_DURATION, delay)
}
None => break MAX_DURATION
}
};
}
};
self.notify_sockets()?;
Ok(::std::cmp::min(
::std::cmp::max(Smolnetd::MIN_CHECK_TIMEOUT, timeout),
Smolnetd::MAX_CHECK_TIMEOUT,
@@ -257,17 +255,16 @@ fn post_fevent(scheme_file: &mut File, fd: usize, event: usize, data_len: usize)
.map_err(|e| Error::from_io_error(e, "failed to post fevent"))
}
fn parse_endpoint(socket: &str) -> IpEndpoint {
fn parse_endpoint(socket: &str) -> IpListenEndpoint {
let mut socket_parts = socket.split(':');
let host = IpAddress::Ipv4(
Ipv4Address::from_str(socket_parts.next().unwrap_or(""))
.unwrap_or_else(|_| Ipv4Address::new(0, 0, 0, 0)),
);
let host =
Ipv4Address::from_str(socket_parts.next().unwrap_or("")).ok().filter(|addr| !addr.is_unspecified()).map(IpAddress::Ipv4);
let port = socket_parts
.next()
.unwrap_or("")
.parse::<u16>()
.unwrap_or(0);
IpEndpoint::new(host, port)
IpListenEndpoint{ addr: host, port}
}
+15 -14
View File
@@ -82,7 +82,7 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
ro [iface] || {
let mut gateway = None;
iface.borrow_mut().routes_mut().update(|map| {
gateway = map.get(&gateway_cidr()).map(|route| route.via_router);
gateway = map.iter().find(|route| route.cidr == gateway_cidr()).map(|route| route.via_router)
});
if let Some(ip) = gateway {
format!("default via {}\n", ip)
@@ -136,16 +136,17 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
let mut iface = iface.borrow_mut();
let mut gateway = None;
iface.routes_mut().update(|map| {
gateway = map.get(&gateway_cidr()).map(|route| route.via_router);
gateway = map.iter().find(|route| route.cidr == gateway_cidr()).map(|route| route.via_router)
});
if gateway != Some(IpAddress::Ipv4(default_gw)) {
return Err(SyscallError::new(syscall::EINVAL));
match gateway {
None => Err(SyscallError::new(syscall::EINVAL)),
Some(addr) if addr != IpAddress::Ipv4(default_gw) => Err(SyscallError::new(syscall::EINVAL)),
Some(_) => {
iface.routes_mut().remove_default_ipv4_route();
notifier.borrow_mut().schedule_notify("route/list");
Ok(())
}
}
iface.routes_mut().update(|map| {
map.remove(&gateway_cidr());
});
notifier.borrow_mut().schedule_notify("route/list");
Ok(())
} else {
Err(SyscallError::new(syscall::EINVAL))
}
@@ -157,7 +158,7 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
"mac" => {
rw [iface, notifier] (Option<EthernetAddress>, None)
|| {
format!("{}\n", iface.borrow().ethernet_addr())
format!("{}\n", iface.borrow().hardware_addr())
}
|cur_value, line| {
if cur_value.is_none() {
@@ -174,7 +175,7 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
}
|cur_value| {
if let Some(mac) = *cur_value {
iface.borrow_mut().set_ethernet_addr(mac);
iface.borrow_mut().set_hardware_addr(smoltcp::wire::HardwareAddress::Ethernet(mac));
notifier.borrow_mut().schedule_notify("ifaces/eth0/mac");
}
Ok(())
@@ -208,7 +209,7 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
let mut cidrs = vec![];
mem::swap(cur_value, &mut cidrs);
iface.update_ip_addrs(|s| {
*s = From::from(cidrs);
*s = cidrs.into_iter().collect();
});
notifier.borrow_mut().schedule_notify("ifaces/eth0/addr/list");
}
@@ -233,7 +234,7 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
cidrs.insert(0, *cidr);
}
iface.update_ip_addrs(|s| {
*s = From::from(cidrs);
*s = cidrs.into_iter().collect();
});
notifier.borrow_mut().schedule_notify("ifaces/eth0/addr/list");
Ok(())
@@ -261,7 +262,7 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
}
}
iface.update_ip_addrs(|s| {
*s = From::from(cidrs);
*s = cidrs.into_iter().collect();
});
notifier.borrow_mut().schedule_notify("ifaces/eth0/addr/list");
Ok(())
+47 -17
View File
@@ -1,10 +1,11 @@
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::fs::File;
use std::io::{ErrorKind, Read, Write};
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::ops::{Deref, SubAssign};
use std::ops::DerefMut;
use std::rc::Rc;
use std::str;
@@ -15,7 +16,9 @@ use syscall::data::TimeSpec;
use syscall::flag::{EVENT_READ, EVENT_WRITE};
use redox_netstack::error::{Error, Result};
use smoltcp::socket::{AnySocket, SocketHandle};
use smoltcp::socket::AnySocket;
use crate::scheme::smoltcp::iface::SocketHandle;
use super::Interface;
use super::{post_fevent, SocketSet};
@@ -98,7 +101,7 @@ where
}
}
pub fn events(&mut self, socket_set: &mut SocketSet) -> usize where SocketT: AnySocket<'static, 'static> {
pub fn events(&mut self, socket_set: &mut SocketSet) -> usize where SocketT: AnySocket<'static> {
let mut revents = 0;
if let &mut SchemeFile::Socket(SocketFile {
socket_handle,
@@ -170,6 +173,7 @@ where
path: &str,
uid: u32,
data: &mut Self::SchemeDataT,
iface: &Interface
) -> SyscallResult<(SocketHandle, Self::DataT)>;
fn close_file(&self, file: &SchemeFile<Self>, data: &mut Self::SchemeDataT) -> SyscallResult<()>;
@@ -190,11 +194,13 @@ where
pub struct SocketScheme<SocketT>
where
SocketT: SchemeSocket + AnySocket<'static, 'static>,
SocketT: SchemeSocket + AnySocket<'static>,
{
next_fd: usize,
nulls: BTreeMap<usize, NullFile>,
files: BTreeMap<usize, SchemeFile<SocketT>>,
ref_counts: BTreeMap<SocketHandle, usize>,
iface: Interface,
socket_set: Rc<RefCell<SocketSet>>,
scheme_file: File,
wait_queue: WaitQueue,
@@ -204,13 +210,15 @@ where
impl<SocketT> SocketScheme<SocketT>
where
SocketT: SchemeSocket + AnySocket<'static, 'static>,
SocketT: SchemeSocket + AnySocket<'static>,
{
pub fn new(socket_set: Rc<RefCell<SocketSet>>, scheme_file: File) -> SocketScheme<SocketT> {
pub fn new(iface: Interface, socket_set: Rc<RefCell<SocketSet>>, scheme_file: File) -> SocketScheme<SocketT> {
SocketScheme {
next_fd: 1,
nulls: BTreeMap::new(),
iface,
files: BTreeMap::new(),
ref_counts: BTreeMap::new(),
socket_set,
scheme_data: SocketT::new_scheme_data(),
scheme_file,
@@ -424,7 +432,7 @@ where
}
Setting::Ttl => if let Some(hop_limit) = buf.get(0) {
let mut socket_set = self.socket_set.borrow_mut();
let mut socket = socket_set.get::<SocketT>(file.socket_handle);
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
socket.set_hop_limit(*hop_limit);
Ok(1)
} else {
@@ -437,7 +445,7 @@ where
impl<SocketT> syscall::SchemeBlockMut for SocketScheme<SocketT>
where
SocketT: SchemeSocket + AnySocket<'static, 'static>,
SocketT: SchemeSocket + AnySocket<'static>,
{
fn open(&mut self, path: &str, flags: usize, uid: u32, _gid: u32) -> SyscallResult<Option<usize>> {
if path.is_empty() {
@@ -459,6 +467,7 @@ where
path,
uid,
&mut self.scheme_data,
&self.iface
)?;
let file = SchemeFile::Socket(SocketFile {
@@ -475,6 +484,7 @@ where
let id = self.next_fd;
self.next_fd += 1;
self.ref_counts.insert(socket_handle, 1);
self.files.insert(id, file);
Ok(Some(id))
@@ -506,9 +516,29 @@ where
}| a != fd,
);
socket_set.release(socket_handle);
//TODO: removing sockets in release should make prune unnecessary
socket_set.prune();
let remove = match self.ref_counts.entry(socket_handle) {
Entry::Vacant(_) => {
warn!("Closing a socket_handle with no ref");
true
},
Entry::Occupied(mut e) => if *e.get() == 0 {
warn!("Closing a socket_handle with no ref");
e.remove();
true
} else {
*e.get_mut() -= 1;
if *e.get() == 0 {
e.remove();
true
} else {
false
}
},
};
if remove {
socket_set.remove(socket_handle);
}
Ok(Some(0))
}
@@ -524,8 +554,8 @@ where
}
SchemeFile::Socket(ref mut file) => {
let mut socket_set = self.socket_set.borrow_mut();
let mut socket = socket_set.get::<SocketT>(file.socket_handle);
return SocketT::write_buf(&mut socket, file, buf);
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
return SocketT::write_buf(socket, file, buf);
}
}
};
@@ -543,8 +573,8 @@ where
}
SchemeFile::Socket(ref mut file) => {
let mut socket_set = self.socket_set.borrow_mut();
let mut socket = socket_set.get::<SocketT>(file.socket_handle);
return SocketT::read_buf(&mut socket, file, buf);
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
return SocketT::read_buf(socket, file, buf);
}
}
};
@@ -609,10 +639,10 @@ where
file.socket_handle = socket_handle;
file.data = data;
} else {
self.socket_set.borrow_mut().retain(file.socket_handle());
*self.ref_counts.entry(file.socket_handle()).or_insert(0) += 1;
}
} else {
self.socket_set.borrow_mut().retain(file.socket_handle());
*self.ref_counts.entry(file.socket_handle()).or_insert(0) += 1;
}
new_handle
};
+55 -34
View File
@@ -1,11 +1,13 @@
use smoltcp::socket::{SocketHandle, TcpSocket, TcpSocketBuffer};
use smoltcp::iface::SocketHandle;
use smoltcp::socket::tcp::{Socket as TcpSocket, SocketBuffer as TcpSocketBuffer};
use smoltcp::wire::IpEndpoint;
use std::str;
use syscall::{Error as SyscallError, Result as SyscallResult};
use syscall;
use syscall::{Error as SyscallError, Result as SyscallResult};
use crate::port_set::PortSet;
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use super::{parse_endpoint, SocketSet};
use super::{parse_endpoint, SocketSet, Interface};
use crate::port_set::PortSet;
pub type TcpScheme = SocketScheme<TcpSocket<'static>>;
@@ -59,6 +61,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
path: &str,
uid: u32,
port_set: &mut Self::SchemeDataT,
iface: &Interface
) -> SyscallResult<(SocketHandle, Self::DataT)> {
trace!("TCP open {}", path);
let mut parts = path.split('/');
@@ -85,12 +88,12 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
let socket_handle = socket_set.add(socket);
let mut tcp_socket = socket_set.get::<TcpSocket>(socket_handle);
let tcp_socket = socket_set.get_mut::<TcpSocket>(socket_handle);
if remote_endpoint.is_specified() {
trace!("Connecting tcp {} {}", local_endpoint, remote_endpoint);
tcp_socket
.connect(remote_endpoint, local_endpoint)
.connect(iface.borrow_mut().context(), IpEndpoint::new(remote_endpoint.addr.unwrap(), remote_endpoint.port), local_endpoint)
.expect("Can't connect tcp socket ");
} else {
trace!("Listening tcp {}", local_endpoint);
@@ -108,7 +111,9 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
port_set: &mut Self::SchemeDataT,
) -> SyscallResult<()> {
if let SchemeFile::Socket(_) = *file {
port_set.release_port(self.local_endpoint().port);
if let Some(endpoint) = self.local_endpoint() {
port_set.release_port(endpoint.port);
}
}
Ok(())
}
@@ -163,34 +168,43 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
};
let file = match path {
"listen" => if let SchemeFile::Socket(ref tcp_handle) = *file {
if !is_active {
if tcp_handle.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
return Err(SyscallError::new(syscall::EAGAIN));
} else {
return Ok(None);
"listen" => {
if let SchemeFile::Socket(ref tcp_handle) = *file {
if !is_active {
if tcp_handle.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
return Err(SyscallError::new(syscall::EAGAIN));
} else {
return Ok(None);
}
}
}
trace!("TCP creating new listening socket");
let new_handle = SchemeFile::Socket(tcp_handle.clone_with_data(()));
trace!("TCP creating new listening socket");
let new_handle = SchemeFile::Socket(tcp_handle.clone_with_data(()));
let rx_packets = vec![0; 0xffff];
let tx_packets = vec![0; 0xffff];
let rx_buffer = TcpSocketBuffer::new(rx_packets);
let tx_buffer = TcpSocketBuffer::new(tx_packets);
let socket = TcpSocket::new(rx_buffer, tx_buffer);
let new_socket_handle = socket_set.add(socket);
{
let mut tcp_socket = socket_set.get::<TcpSocket>(new_socket_handle);
tcp_socket
.listen(local_endpoint)
.expect("Can't listen on local endpoint");
let rx_packets = vec![0; 0xffff];
let tx_packets = vec![0; 0xffff];
let rx_buffer = TcpSocketBuffer::new(rx_packets);
let tx_buffer = TcpSocketBuffer::new(tx_packets);
let socket = TcpSocket::new(rx_buffer, tx_buffer);
let new_socket_handle = socket_set.add(socket);
{
let tcp_socket = socket_set.get_mut::<TcpSocket>(new_socket_handle);
tcp_socket
.listen(
local_endpoint
.expect("Socket was active so local endpoint must be set"),
)
.expect("Can't listen on local endpoint");
}
port_set.acquire_port(
local_endpoint
.expect("Socket was active so local endpoint must be set")
.port,
);
return Ok(Some((new_handle, Some((new_socket_handle, ())))));
} else {
return Err(SyscallError::new(syscall::EBADF));
}
port_set.acquire_port(local_endpoint.port);
return Ok(Some((new_handle, Some((new_socket_handle, ())))));
} else {
return Err(SyscallError::new(syscall::EBADF));
},
}
_ => {
trace!("TCP dup unknown {}", path);
if let SchemeFile::Socket(ref tcp_handle) = *file {
@@ -202,14 +216,21 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
};
if let SchemeFile::Socket(_) = file {
port_set.acquire_port(local_endpoint.port);
if let Some(local_endpoint) = local_endpoint {
port_set.acquire_port(local_endpoint.port);
}
}
Ok(Some((file, None)))
}
fn fpath(&self, _: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize> {
let path = format!("tcp:{}/{}", self.remote_endpoint(), self.local_endpoint());
let path = match (self.remote_endpoint(), self.local_endpoint()) {
(Some(remote_endpoint), Some(local_endpoint)) => format!("tcp:{}/{}", remote_endpoint, local_endpoint),
(Some(remote_endpoint), None) => format!("tcp:{}/none", remote_endpoint),
(None, Some(local_endpoint)) => format!("tcp:none/{}", local_endpoint),
(None, None) => "tcp:none/none".into(),
};
let path = path.as_bytes();
let mut i = 0;
+13 -8
View File
@@ -1,5 +1,6 @@
use smoltcp::socket::{SocketHandle, UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
use smoltcp::wire::IpEndpoint;
use smoltcp::socket::udp::{PacketMetadata as UdpPacketMetadata, Socket as UdpSocket, PacketBuffer as UdpSocketBuffer};
use smoltcp::iface::SocketHandle;
use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
use std::str;
use syscall::{Error as SyscallError, Result as SyscallResult};
use syscall;
@@ -7,13 +8,13 @@ use syscall;
use crate::device::NetworkDevice;
use crate::port_set::PortSet;
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use super::{parse_endpoint, Smolnetd, SocketSet};
use super::{parse_endpoint, Smolnetd, SocketSet, Interface};
pub type UdpScheme = SocketScheme<UdpSocket<'static, 'static>>;
pub type UdpScheme = SocketScheme<UdpSocket<'static>>;
impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
impl<'a> SchemeSocket for UdpSocket<'a> {
type SchemeDataT = PortSet;
type DataT = IpEndpoint;
type DataT = IpListenEndpoint;
type SettingT = ();
fn new_scheme_data() -> Self::SchemeDataT {
@@ -61,6 +62,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
path: &str,
uid: u32,
port_set: &mut Self::SchemeDataT,
_iface: &Interface
) -> SyscallResult<(SocketHandle, Self::DataT)> {
let mut parts = path.split('/');
let remote_endpoint = parse_endpoint(parts.next().unwrap_or(""));
@@ -90,11 +92,12 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
let socket_handle = socket_set.add(udp_socket);
let mut udp_socket = socket_set.get::<UdpSocket>(socket_handle);
let udp_socket = socket_set.get_mut::<UdpSocket>(socket_handle);
udp_socket
.bind(local_endpoint)
.expect("Can't bind udp socket to local endpoint");
Ok((socket_handle, remote_endpoint))
}
@@ -118,7 +121,9 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
return Err(SyscallError::new(syscall::EADDRNOTAVAIL));
}
if self.can_send() {
self.send_slice(buf, file.data).expect("Can't send slice");
let endpoint = file.data;
let endpoint = IpEndpoint::new(endpoint.addr.expect("If we can send, this should be specified"), endpoint.port);
self.send_slice(buf, endpoint).expect("Can't send slice");
Ok(Some(buf.len()))
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
Err(SyscallError::new(syscall::EAGAIN))