Switch to libredox and redox-event.
This commit is contained in:
+76
-97
@@ -13,12 +13,14 @@ use std::os::unix::io::{FromRawFd, RawFd};
|
||||
use std::process;
|
||||
use std::rc::Rc;
|
||||
|
||||
use event::EventQueue;
|
||||
use redox_netstack::error::{Error, Result};
|
||||
use event::{EventQueue, EventFlags};
|
||||
use libredox::Fd;
|
||||
use libredox::flag::{O_RDWR, O_NONBLOCK, O_CREAT};
|
||||
use anyhow::{Result, anyhow, bail, Context};
|
||||
|
||||
use redox_netstack::logger;
|
||||
use scheme::Smolnetd;
|
||||
use smoltcp::wire::EthernetAddress;
|
||||
use syscall::flag::*;
|
||||
|
||||
mod buffer_pool;
|
||||
mod link;
|
||||
@@ -48,7 +50,7 @@ fn get_network_adapter() -> Result<String> {
|
||||
}
|
||||
|
||||
if adapters.is_empty() {
|
||||
Err(Error::other_error("no network adapter found"))
|
||||
bail!("no network adapter found");
|
||||
} else {
|
||||
let adapter = adapters.remove(0);
|
||||
if !adapters.is_empty() {
|
||||
@@ -62,129 +64,106 @@ fn get_network_adapter() -> Result<String> {
|
||||
fn run(daemon: redox_daemon::Daemon) -> Result<()> {
|
||||
let adapter = get_network_adapter()?;
|
||||
trace!("opening {adapter}:");
|
||||
let network_fd = syscall::open(format!("{adapter}:"), O_RDWR | O_NONBLOCK)
|
||||
.map_err(|e| Error::from_syscall_error(e, format!("failed to open {adapter}:")))?
|
||||
as RawFd;
|
||||
let network_fd = Fd::open(&format!("{adapter}:"), O_RDWR | O_NONBLOCK, 0)
|
||||
.map_err(|e| anyhow!("failed to open {adapter}: {e}"))?;
|
||||
|
||||
let hardware_addr = std::fs::read(format!("{adapter}:mac"))
|
||||
.map(|mac_address| EthernetAddress::from_bytes(&mac_address))
|
||||
.expect("failed to get mac address from network adapter");
|
||||
.context("failed to get mac address from network adapter")?;
|
||||
|
||||
trace!("opening :ip");
|
||||
let ip_fd = syscall::open(":ip", O_RDWR | O_CREAT | O_NONBLOCK)
|
||||
.map_err(|e| Error::from_syscall_error(e, "failed to open :ip"))? as RawFd;
|
||||
let ip_fd = Fd::open(":ip", O_RDWR | O_CREAT | O_NONBLOCK, 0)
|
||||
.context("failed to open :ip")?;
|
||||
|
||||
trace!("opening :udp");
|
||||
let udp_fd = syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK)
|
||||
.map_err(|e| Error::from_syscall_error(e, "failed to open :udp"))?
|
||||
as RawFd;
|
||||
let udp_fd = Fd::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK, 0)
|
||||
.context("failed to open :udp")?;
|
||||
|
||||
trace!("opening :tcp");
|
||||
let tcp_fd = syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK)
|
||||
.map_err(|e| Error::from_syscall_error(e, "failed to open :tcp"))?
|
||||
as RawFd;
|
||||
let tcp_fd = Fd::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK, 0)
|
||||
.context("failed to open :tcp")?;
|
||||
|
||||
trace!("opening :icmp");
|
||||
let icmp_fd = syscall::open(":icmp", O_RDWR | O_CREAT | O_NONBLOCK)
|
||||
.map_err(|e| Error::from_syscall_error(e, "failed to open :icmp"))?
|
||||
as RawFd;
|
||||
let icmp_fd = Fd::open(":icmp", O_RDWR | O_CREAT | O_NONBLOCK, 0)
|
||||
.context("failed to open :icmp")?;
|
||||
|
||||
trace!("opening :netcfg");
|
||||
let netcfg_fd = syscall::open(":netcfg", O_RDWR | O_CREAT | O_NONBLOCK)
|
||||
.map_err(|e| Error::from_syscall_error(e, "failed to open :netcfg"))?
|
||||
as RawFd;
|
||||
let netcfg_fd = Fd::open(":netcfg", O_RDWR | O_CREAT | O_NONBLOCK, 0)
|
||||
.context("failed to open :netcfg")?;
|
||||
|
||||
let time_path = format!("time:{}", syscall::CLOCK_MONOTONIC);
|
||||
let time_fd = syscall::open(&time_path, syscall::O_RDWR)
|
||||
.map_err(|e| Error::from_syscall_error(e, "failed to open time:"))?
|
||||
as RawFd;
|
||||
let time_fd = Fd::open(&time_path, O_RDWR, 0)
|
||||
.context("failed to open time:")?;
|
||||
|
||||
let (network_file, ip_file, time_file, udp_file, tcp_file, icmp_file, netcfg_file) = unsafe {
|
||||
(
|
||||
File::from_raw_fd(network_fd),
|
||||
File::from_raw_fd(ip_fd),
|
||||
File::from_raw_fd(time_fd),
|
||||
File::from_raw_fd(udp_fd),
|
||||
File::from_raw_fd(tcp_fd),
|
||||
File::from_raw_fd(icmp_fd),
|
||||
File::from_raw_fd(netcfg_fd),
|
||||
)
|
||||
};
|
||||
event::user_data! {
|
||||
enum EventSource {
|
||||
Network,
|
||||
Time,
|
||||
IpScheme,
|
||||
UdpScheme,
|
||||
TcpScheme,
|
||||
IcmpScheme,
|
||||
NetcfgScheme,
|
||||
}
|
||||
}
|
||||
|
||||
let smolnetd = Rc::new(RefCell::new(Smolnetd::new(
|
||||
network_file,
|
||||
hardware_addr,
|
||||
ip_file,
|
||||
udp_file,
|
||||
tcp_file,
|
||||
icmp_file,
|
||||
time_file,
|
||||
netcfg_file,
|
||||
)));
|
||||
|
||||
let mut event_queue = EventQueue::<(), Error>::new()
|
||||
.map_err(|e| Error::from_io_error(e, "failed to create event queue"))?;
|
||||
|
||||
syscall::setrens(0, 0).expect("smolnetd: failed to enter null namespace");
|
||||
let event_queue = EventQueue::<EventSource>::new()
|
||||
.context("failed to create event queue")?;
|
||||
|
||||
daemon.ready().expect("smolnetd: failed to notify parent");
|
||||
|
||||
let smolnetd_ = Rc::clone(&smolnetd);
|
||||
event_queue.subscribe(network_fd.raw(), EventSource::Network, EventFlags::READ)
|
||||
.context("failed to listen to network events")?;
|
||||
|
||||
event_queue
|
||||
.add(network_fd, move |_| {
|
||||
smolnetd_.borrow_mut().on_network_scheme_event()
|
||||
})
|
||||
.map_err(|e| Error::from_io_error(e, "failed to listen to network events"))?;
|
||||
event_queue.subscribe(time_fd.raw(), EventSource::Time, EventFlags::READ)
|
||||
.context("failed to listen to timer events")?;
|
||||
|
||||
let smolnetd_ = Rc::clone(&smolnetd);
|
||||
event_queue.subscribe(ip_fd.raw(), EventSource::IpScheme, EventFlags::READ)
|
||||
.context("failed to listen to ip scheme events")?;
|
||||
|
||||
event_queue
|
||||
.add(ip_fd, move |_| smolnetd_.borrow_mut().on_ip_scheme_event())
|
||||
.map_err(|e| Error::from_io_error(e, "failed to listen to ip events"))?;
|
||||
event_queue.subscribe(udp_fd.raw(), EventSource::UdpScheme, EventFlags::READ)
|
||||
.context("failed to listen to udp scheme events")?;
|
||||
|
||||
let smolnetd_ = Rc::clone(&smolnetd);
|
||||
event_queue.subscribe(tcp_fd.raw(), EventSource::TcpScheme, EventFlags::READ)
|
||||
.context("failed to listen to tcp scheme events")?;
|
||||
|
||||
event_queue
|
||||
.add(udp_fd, move |_| {
|
||||
smolnetd_.borrow_mut().on_udp_scheme_event()
|
||||
})
|
||||
.map_err(|e| Error::from_io_error(e, "failed to listen to udp events"))?;
|
||||
event_queue.subscribe(icmp_fd.raw(), EventSource::IcmpScheme, EventFlags::READ)
|
||||
.context("failed to listen to icmp scheme events")?;
|
||||
|
||||
let smolnetd_ = Rc::clone(&smolnetd);
|
||||
event_queue.subscribe(netcfg_fd.raw(), EventSource::NetcfgScheme, EventFlags::READ)
|
||||
.context("failed to listen to netcfg scheme events")?;
|
||||
|
||||
event_queue
|
||||
.add(tcp_fd, move |_| {
|
||||
smolnetd_.borrow_mut().on_tcp_scheme_event()
|
||||
})
|
||||
.map_err(|e| Error::from_io_error(e, "failed to listen to tcp events"))?;
|
||||
let mut smolnetd = Smolnetd::new(
|
||||
network_fd,
|
||||
hardware_addr,
|
||||
ip_fd,
|
||||
udp_fd,
|
||||
tcp_fd,
|
||||
icmp_fd,
|
||||
time_fd,
|
||||
netcfg_fd,
|
||||
);
|
||||
|
||||
let smolnetd_ = Rc::clone(&smolnetd);
|
||||
libredox::call::setrens(0, 0)
|
||||
.context("smolnetd: failed to enter null namespace")?;
|
||||
|
||||
event_queue
|
||||
.add(icmp_fd, move |_| {
|
||||
smolnetd_.borrow_mut().on_icmp_scheme_event()
|
||||
})
|
||||
.map_err(|e| Error::from_io_error(e, "failed to listen to icmp events"))?;
|
||||
let all = {
|
||||
use EventSource::*;
|
||||
[Network, Time, IpScheme, UdpScheme, IcmpScheme, NetcfgScheme].map(Ok)
|
||||
};
|
||||
|
||||
let smolnetd_ = Rc::clone(&smolnetd);
|
||||
|
||||
event_queue
|
||||
.add(time_fd, move |_| smolnetd_.borrow_mut().on_time_event())
|
||||
.map_err(|e| Error::from_io_error(e, "failed to listen to time events"))?;
|
||||
|
||||
event_queue
|
||||
.add(netcfg_fd, move |_| {
|
||||
smolnetd.borrow_mut().on_netcfg_scheme_event()
|
||||
})
|
||||
.map_err(|e| Error::from_io_error(e, "failed to listen to netcfg events"))?;
|
||||
|
||||
event_queue.trigger_all(event::Event {
|
||||
fd: 0,
|
||||
flags: EventFlags::empty(),
|
||||
})?;
|
||||
|
||||
event_queue.run()
|
||||
for event_res in all.into_iter().chain(event_queue.map(|r| r.map(|e| e.user_data))) {
|
||||
match event_res? {
|
||||
EventSource::Network => smolnetd.on_network_scheme_event()?,
|
||||
EventSource::Time => smolnetd.on_time_event()?,
|
||||
EventSource::IpScheme => smolnetd.on_ip_scheme_event()?,
|
||||
EventSource::UdpScheme => smolnetd.on_udp_scheme_event()?,
|
||||
EventSource::TcpScheme => smolnetd.on_tcp_scheme_event()?,
|
||||
EventSource::IcmpScheme => smolnetd.on_icmp_scheme_event()?,
|
||||
EventSource::NetcfgScheme => smolnetd.on_netcfg_scheme_event()?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
+29
-27
@@ -4,6 +4,7 @@ use crate::link::{loopback::LoopbackDevice, DeviceList};
|
||||
use crate::router::route_table::{RouteTable, Rule};
|
||||
use crate::router::Router;
|
||||
use crate::scheme::smoltcp::iface::SocketSet as SmoltcpSocketSet;
|
||||
use libredox::Fd;
|
||||
use netutils::getcfg;
|
||||
use smoltcp;
|
||||
use smoltcp::iface::{Config, Interface as SmoltcpInterface};
|
||||
@@ -16,6 +17,7 @@ use std::cell::RefCell;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::mem::size_of;
|
||||
use std::os::fd::{FromRawFd, RawFd};
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use syscall;
|
||||
@@ -63,14 +65,14 @@ impl Smolnetd {
|
||||
pub const MAX_CHECK_TIMEOUT: Duration = Duration::from_millis(500);
|
||||
|
||||
pub fn new(
|
||||
network_file: File,
|
||||
network_file: Fd,
|
||||
hardware_addr: EthernetAddress,
|
||||
ip_file: File,
|
||||
udp_file: File,
|
||||
tcp_file: File,
|
||||
icmp_file: File,
|
||||
time_file: File,
|
||||
netcfg_file: File,
|
||||
ip_file: Fd,
|
||||
udp_file: Fd,
|
||||
tcp_file: Fd,
|
||||
icmp_file: Fd,
|
||||
time_file: Fd,
|
||||
netcfg_file: Fd,
|
||||
) -> Smolnetd {
|
||||
let protocol_addrs = vec![
|
||||
IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8),
|
||||
@@ -108,7 +110,7 @@ impl Smolnetd {
|
||||
|
||||
let mut eth0 = EthernetLink::new(
|
||||
"eth0",
|
||||
network_file,
|
||||
unsafe { File::from_raw_fd(network_file.into_raw() as RawFd) },
|
||||
);
|
||||
eth0.set_mac_address(hardware_addr);
|
||||
|
||||
@@ -120,79 +122,79 @@ impl Smolnetd {
|
||||
router_device: network_device,
|
||||
socket_set: Rc::clone(&socket_set),
|
||||
timer: ::std::time::Instant::now(),
|
||||
time_file,
|
||||
time_file: unsafe { File::from_raw_fd(time_file.into_raw() as RawFd) },
|
||||
ip_scheme: IpScheme::new(
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
ip_file,
|
||||
unsafe { File::from_raw_fd(ip_file.into_raw() as RawFd) },
|
||||
),
|
||||
udp_scheme: UdpScheme::new(
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
udp_file,
|
||||
unsafe { File::from_raw_fd(udp_file.into_raw() as RawFd) },
|
||||
),
|
||||
tcp_scheme: TcpScheme::new(
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
tcp_file,
|
||||
unsafe { File::from_raw_fd(tcp_file.into_raw() as RawFd) },
|
||||
),
|
||||
icmp_scheme: IcmpScheme::new(
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
icmp_file,
|
||||
unsafe { File::from_raw_fd(icmp_file.into_raw() as RawFd) },
|
||||
),
|
||||
netcfg_scheme: NetCfgScheme::new(
|
||||
Rc::clone(&iface),
|
||||
netcfg_file,
|
||||
unsafe { File::from_raw_fd(netcfg_file.into_raw() as RawFd) },
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&devices),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_network_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
pub fn on_network_scheme_event(&mut self) -> Result<()> {
|
||||
self.poll()?;
|
||||
Ok(None)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_ip_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
pub fn on_ip_scheme_event(&mut self) -> Result<()> {
|
||||
self.ip_scheme.on_scheme_event()?;
|
||||
let _ = self.poll()?;
|
||||
Ok(None)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_udp_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
pub fn on_udp_scheme_event(&mut self) -> Result<()> {
|
||||
self.udp_scheme.on_scheme_event()?;
|
||||
let _ = self.poll()?;
|
||||
Ok(None)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_tcp_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
pub fn on_tcp_scheme_event(&mut self) -> Result<()> {
|
||||
self.tcp_scheme.on_scheme_event()?;
|
||||
let _ = self.poll()?;
|
||||
Ok(None)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_icmp_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
pub fn on_icmp_scheme_event(&mut self) -> Result<()> {
|
||||
self.icmp_scheme.on_scheme_event()?;
|
||||
let _ = self.poll()?;
|
||||
Ok(None)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_time_event(&mut self) -> Result<Option<()>> {
|
||||
pub fn on_time_event(&mut self) -> Result<()> {
|
||||
let timeout = self.poll()?;
|
||||
self.schedule_time_event(timeout)?;
|
||||
//TODO: Fix network scheme to ensure events are not missed
|
||||
self.on_network_scheme_event()
|
||||
}
|
||||
|
||||
pub fn on_netcfg_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
pub fn on_netcfg_scheme_event(&mut self) -> Result<()> {
|
||||
self.netcfg_scheme.on_scheme_event()?;
|
||||
Ok(None)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn schedule_time_event(&mut self, timeout: Duration) -> Result<()> {
|
||||
|
||||
@@ -10,7 +10,8 @@ use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
|
||||
use syscall;
|
||||
use libredox::flag::CLOCK_MONOTONIC;
|
||||
use syscall::{self, KSMSG_CANCEL};
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::flag::{EVENT_READ, EVENT_WRITE};
|
||||
use syscall::{
|
||||
@@ -286,6 +287,10 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
if packet.a == KSMSG_CANCEL {
|
||||
println!("smolnetd: todo: handle cancellation");
|
||||
continue;
|
||||
}
|
||||
if let Some(a) = self.handle(&mut packet) {
|
||||
packet.a = a;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
@@ -372,15 +377,14 @@ where
|
||||
}?;
|
||||
|
||||
let mut timeout = match packet.a {
|
||||
syscall::SYS_WRITE => Ok(write_timeout),
|
||||
syscall::SYS_READ => Ok(read_timeout),
|
||||
_ => Ok(None),
|
||||
}?;
|
||||
syscall::SYS_WRITE => write_timeout,
|
||||
syscall::SYS_READ => read_timeout,
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(ref mut timeout) = timeout {
|
||||
let mut cur_time = TimeSpec::default();
|
||||
syscall::clock_gettime(syscall::CLOCK_MONOTONIC, &mut cur_time)?;
|
||||
*timeout = add_time(timeout, &cur_time)
|
||||
let cur_time = libredox::call::clock_gettime(CLOCK_MONOTONIC)?;
|
||||
*timeout = add_time(timeout, &TimeSpec { tv_sec: cur_time.tv_sec, tv_nsec: cur_time.tv_nsec as i32 })
|
||||
}
|
||||
|
||||
Ok(timeout)
|
||||
|
||||
Reference in New Issue
Block a user