Migrating to smoltcp 0.10
This commit is contained in:
+6
-4
@@ -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
@@ -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
@@ -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
@@ -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),
|
||||
})
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user