feat: Update netstack to use redox-scheme.
This commit is contained in:
committed by
Jeremy Soller
parent
3363174937
commit
4f3cba2cd0
+1
-2
@@ -14,8 +14,7 @@ redox_syscall = { version = "0.5", features = ["std"] }
|
||||
redox-log = "0.1"
|
||||
libredox = { version = "0.1.3", features = ["mkns"] }
|
||||
anyhow = "1.0.81"
|
||||
#redox-scheme = "0.5.0"
|
||||
redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" }
|
||||
redox-scheme = "0.8"
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4"
|
||||
|
||||
+36
-18
@@ -4,9 +4,10 @@ use std::process;
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use event::{EventFlags, EventQueue};
|
||||
use libredox::flag::{O_CREAT, O_NONBLOCK, O_RDWR};
|
||||
use libredox::flag::{O_NONBLOCK, O_RDWR};
|
||||
use libredox::Fd;
|
||||
|
||||
use redox_scheme::Socket;
|
||||
use scheme::Smolnetd;
|
||||
use smoltcp::wire::EthernetAddress;
|
||||
|
||||
@@ -61,24 +62,25 @@ fn run(daemon: daemon::Daemon) -> Result<()> {
|
||||
.map(|mac_address| EthernetAddress::from_bytes(&mac_address))
|
||||
.context("failed to get mac address from network adapter")?;
|
||||
|
||||
trace!("opening :ip");
|
||||
let ip_fd = Fd::open(":ip", O_RDWR | O_CREAT | O_NONBLOCK, 0).context("failed to open :ip")?;
|
||||
trace!("opening ip scheme socket");
|
||||
let ip_fd = Socket::nonblock("ip")
|
||||
.map_err(|e| anyhow!("failed to open create ip scheme socket: {}", e))?;
|
||||
|
||||
trace!("opening :udp");
|
||||
trace!("opening udp scheme socket");
|
||||
let udp_fd =
|
||||
Fd::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK, 0).context("failed to open :udp")?;
|
||||
Socket::nonblock("udp").map_err(|e| anyhow!("failed to open udp scheme socket: {}", e))?;
|
||||
|
||||
trace!("opening :tcp");
|
||||
trace!("opening tcp scheme socket");
|
||||
let tcp_fd =
|
||||
Fd::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK, 0).context("failed to open :tcp")?;
|
||||
Socket::nonblock("tcp").map_err(|e| anyhow!("failed to open tcp scheme socket: {}", e))?;
|
||||
|
||||
trace!("opening :icmp");
|
||||
let icmp_fd =
|
||||
Fd::open(":icmp", O_RDWR | O_CREAT | O_NONBLOCK, 0).context("failed to open :icmp")?;
|
||||
trace!("opening icmp scheme socket");
|
||||
let icmp_fd = Socket::nonblock("icmp")
|
||||
.map_err(|e| anyhow!("failed to open icmp scheme socket: {}", e))?;
|
||||
|
||||
trace!("opening :netcfg");
|
||||
let netcfg_fd =
|
||||
Fd::open(":netcfg", O_RDWR | O_CREAT | O_NONBLOCK, 0).context("failed to open :netcfg")?;
|
||||
trace!("opening netcfg scheme socket");
|
||||
let netcfg_fd = Socket::nonblock("netcfg")
|
||||
.map_err(|e| anyhow!("failed to open netcfg scheme socket {}", e))?;
|
||||
|
||||
let time_path = format!("/scheme/time/{}", syscall::CLOCK_MONOTONIC);
|
||||
let time_fd = Fd::open(&time_path, O_RDWR, 0).context("failed to open /scheme/time")?;
|
||||
@@ -108,23 +110,39 @@ fn run(daemon: daemon::Daemon) -> Result<()> {
|
||||
.context("failed to listen to timer events")?;
|
||||
|
||||
event_queue
|
||||
.subscribe(ip_fd.raw(), EventSource::IpScheme, EventFlags::READ)
|
||||
.subscribe(ip_fd.inner().raw(), EventSource::IpScheme, EventFlags::READ)
|
||||
.context("failed to listen to ip scheme events")?;
|
||||
|
||||
event_queue
|
||||
.subscribe(udp_fd.raw(), EventSource::UdpScheme, EventFlags::READ)
|
||||
.subscribe(
|
||||
udp_fd.inner().raw(),
|
||||
EventSource::UdpScheme,
|
||||
EventFlags::READ,
|
||||
)
|
||||
.context("failed to listen to udp scheme events")?;
|
||||
|
||||
event_queue
|
||||
.subscribe(tcp_fd.raw(), EventSource::TcpScheme, EventFlags::READ)
|
||||
.subscribe(
|
||||
tcp_fd.inner().raw(),
|
||||
EventSource::TcpScheme,
|
||||
EventFlags::READ,
|
||||
)
|
||||
.context("failed to listen to tcp scheme events")?;
|
||||
|
||||
event_queue
|
||||
.subscribe(icmp_fd.raw(), EventSource::IcmpScheme, EventFlags::READ)
|
||||
.subscribe(
|
||||
icmp_fd.inner().raw(),
|
||||
EventSource::IcmpScheme,
|
||||
EventFlags::READ,
|
||||
)
|
||||
.context("failed to listen to icmp scheme events")?;
|
||||
|
||||
event_queue
|
||||
.subscribe(netcfg_fd.raw(), EventSource::NetcfgScheme, EventFlags::READ)
|
||||
.subscribe(
|
||||
netcfg_fd.inner().raw(),
|
||||
EventSource::NetcfgScheme,
|
||||
EventFlags::READ,
|
||||
)
|
||||
.context("failed to listen to netcfg scheme events")?;
|
||||
|
||||
let mut smolnetd = Smolnetd::new(
|
||||
|
||||
@@ -9,12 +9,12 @@ use std::str;
|
||||
use syscall;
|
||||
use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
use super::{Smolnetd, SocketSet};
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile};
|
||||
use super::{SchemeWrapper, Smolnetd, SocketSet};
|
||||
use crate::port_set::PortSet;
|
||||
use crate::router::Router;
|
||||
|
||||
pub type IcmpScheme = SocketScheme<IcmpSocket<'static>>;
|
||||
pub type IcmpScheme = SchemeWrapper<IcmpSocket<'static>>;
|
||||
|
||||
enum IcmpSocketType {
|
||||
Echo,
|
||||
@@ -170,7 +170,7 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
if self.can_send() {
|
||||
match file.data.socket_type {
|
||||
IcmpSocketType::Echo => {
|
||||
@@ -191,14 +191,14 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
|
||||
let mut icmp_packet = Icmpv4Packet::new_unchecked(icmp_payload);
|
||||
//TODO: replace Default with actual caps
|
||||
icmp_repr.emit(&mut icmp_packet, &Default::default());
|
||||
Ok(Some(buf.len()))
|
||||
Ok(buf.len())
|
||||
}
|
||||
IcmpSocketType::Udp => Err(SyscallError::new(syscall::EINVAL)),
|
||||
}
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-read
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
while self.can_recv() {
|
||||
let (payload, _) = self.recv().expect("Can't recv icmp packet");
|
||||
let icmp_packet = Icmpv4Packet::new_unchecked(&payload);
|
||||
@@ -223,14 +223,14 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
|
||||
buf[mem::size_of::<u16>() + i] = data[i];
|
||||
}
|
||||
|
||||
return Ok(Some(mem::size_of::<u16>() + data.len()));
|
||||
return Ok(mem::size_of::<u16>() + data.len());
|
||||
}
|
||||
}
|
||||
|
||||
if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-read
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
|
||||
use crate::router::Router;
|
||||
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
use super::{Smolnetd, SocketSet};
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile};
|
||||
use super::{SchemeWrapper, Smolnetd, SocketSet};
|
||||
|
||||
pub type IpScheme = SocketScheme<RawSocket<'static>>;
|
||||
pub type IpScheme = SchemeWrapper<RawSocket<'static>>;
|
||||
|
||||
impl<'a> SchemeSocket for RawSocket<'a> {
|
||||
type SchemeDataT = ();
|
||||
@@ -97,14 +97,14 @@ impl<'a> SchemeSocket for RawSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
if self.can_send() {
|
||||
self.send_slice(buf).expect("Can't send slice");
|
||||
Ok(Some(buf.len()))
|
||||
Ok(buf.len())
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-read
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,14 +112,14 @@ impl<'a> SchemeSocket for RawSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
if self.can_recv() {
|
||||
let length = self.recv_slice(buf).expect("Can't receive slice");
|
||||
Ok(Some(length))
|
||||
Ok(length)
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-read
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+253
-24
@@ -4,10 +4,17 @@ 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 crate::scheme::socket::{SchemeSocket, SocketScheme};
|
||||
use libredox::flag;
|
||||
use libredox::Fd;
|
||||
use redox_scheme::{
|
||||
scheme::{IntoTag, Op, SchemeResponse, SchemeSync},
|
||||
CallerCtx, RequestKind, Response, SignalBehavior, Socket,
|
||||
};
|
||||
use smoltcp;
|
||||
use smoltcp::iface::{Config, Interface as SmoltcpInterface};
|
||||
use smoltcp::phy::Tracer;
|
||||
use smoltcp::socket::AnySocket;
|
||||
use smoltcp::time::{Duration, Instant};
|
||||
use smoltcp::wire::{
|
||||
EthernetAddress, HardwareAddress, IpAddress, IpCidr, IpListenEndpoint, Ipv4Address,
|
||||
@@ -21,6 +28,7 @@ use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use syscall;
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::Error as SyscallError;
|
||||
|
||||
use self::icmp::IcmpScheme;
|
||||
use self::ip::IpScheme;
|
||||
@@ -73,12 +81,12 @@ impl Smolnetd {
|
||||
pub fn new(
|
||||
network_file: Fd,
|
||||
hardware_addr: EthernetAddress,
|
||||
ip_file: Fd,
|
||||
udp_file: Fd,
|
||||
tcp_file: Fd,
|
||||
icmp_file: Fd,
|
||||
ip_file: Socket,
|
||||
udp_file: Socket,
|
||||
tcp_file: Socket,
|
||||
icmp_file: Socket,
|
||||
time_file: Fd,
|
||||
netcfg_file: Fd,
|
||||
netcfg_file: Socket,
|
||||
) -> Smolnetd {
|
||||
let protocol_addrs = vec![
|
||||
//This is a placeholder IP for DHCP
|
||||
@@ -133,29 +141,29 @@ impl Smolnetd {
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
unsafe { File::from_raw_fd(ip_file.into_raw() as RawFd) },
|
||||
ip_file,
|
||||
),
|
||||
udp_scheme: UdpScheme::new(
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
unsafe { File::from_raw_fd(udp_file.into_raw() as RawFd) },
|
||||
udp_file,
|
||||
),
|
||||
tcp_scheme: TcpScheme::new(
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
unsafe { File::from_raw_fd(tcp_file.into_raw() as RawFd) },
|
||||
tcp_file,
|
||||
),
|
||||
icmp_scheme: IcmpScheme::new(
|
||||
Rc::clone(&iface),
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&socket_set),
|
||||
unsafe { File::from_raw_fd(icmp_file.into_raw() as RawFd) },
|
||||
icmp_file,
|
||||
),
|
||||
netcfg_scheme: NetCfgScheme::new(
|
||||
Rc::clone(&iface),
|
||||
unsafe { File::from_raw_fd(netcfg_file.into_raw() as RawFd) },
|
||||
netcfg_file,
|
||||
Rc::clone(&route_table),
|
||||
Rc::clone(&devices),
|
||||
),
|
||||
@@ -267,20 +275,13 @@ impl Smolnetd {
|
||||
}
|
||||
}
|
||||
|
||||
fn post_fevent(scheme_file: &mut File, fd: usize, event: usize, data_len: usize) -> Result<()> {
|
||||
scheme_file
|
||||
.write(&syscall::Packet {
|
||||
id: 0,
|
||||
pid: 0,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
a: syscall::number::SYS_FEVENT,
|
||||
b: fd,
|
||||
c: event,
|
||||
d: data_len,
|
||||
})
|
||||
.map(|_| ())
|
||||
.map_err(|e| Error::from_io_error(e, "failed to post fevent"))
|
||||
fn post_fevent(socket: &Socket, id: usize, flags: usize) -> syscall::error::Result<()> {
|
||||
let fevent_response = Response::post_fevent(id, flags);
|
||||
match socket.write_response(fevent_response, SignalBehavior::Restart) {
|
||||
Ok(true) => Ok(()), // Write response success
|
||||
Ok(false) => Err(syscall::error::Error::new(syscall::EAGAIN)), // Write response failed, retry.
|
||||
Err(err) => Err(err), // Error writing response
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_endpoint(socket: &str) -> IpListenEndpoint {
|
||||
@@ -297,3 +298,231 @@ fn parse_endpoint(socket: &str) -> IpListenEndpoint {
|
||||
.unwrap_or(0);
|
||||
IpListenEndpoint { addr: host, port }
|
||||
}
|
||||
|
||||
struct WaitHandle {
|
||||
until: Option<TimeSpec>,
|
||||
cancelling: bool,
|
||||
packet: (Op, CallerCtx),
|
||||
}
|
||||
|
||||
type WaitQueue = Vec<WaitHandle>;
|
||||
|
||||
pub struct SchemeWrapper<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static>,
|
||||
{
|
||||
scheme: socket::SocketScheme<SocketT>,
|
||||
wait_queue: WaitQueue,
|
||||
}
|
||||
impl<SocketT> SchemeWrapper<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static>,
|
||||
{
|
||||
pub fn new(
|
||||
iface: Interface,
|
||||
route_table: Rc<RefCell<RouteTable>>,
|
||||
socket_set: Rc<RefCell<SocketSet>>,
|
||||
scheme_file: Socket,
|
||||
) -> Self {
|
||||
Self {
|
||||
scheme: SocketScheme::<SocketT>::new(iface, route_table, socket_set, scheme_file),
|
||||
wait_queue: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn on_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
let result = loop {
|
||||
let request = match self
|
||||
.scheme
|
||||
.scheme_file
|
||||
.next_request(SignalBehavior::Restart)
|
||||
{
|
||||
Ok(Some(req)) => req,
|
||||
Ok(None) => {
|
||||
break Some(());
|
||||
}
|
||||
Err(error)
|
||||
if error.errno == syscall::EWOULDBLOCK || error.errno == syscall::EAGAIN =>
|
||||
{
|
||||
break None;
|
||||
}
|
||||
Err(other) => {
|
||||
return Err(Error::from_syscall_error(
|
||||
other,
|
||||
"failed to receive new request",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let req = match request.kind() {
|
||||
RequestKind::Call(c) => c,
|
||||
RequestKind::OnClose { id } => {
|
||||
self.scheme.on_close(id);
|
||||
continue;
|
||||
}
|
||||
RequestKind::Cancellation(req) => {
|
||||
if let Some(idx) = self
|
||||
.wait_queue
|
||||
.iter()
|
||||
.position(|q| q.packet.0.req_id() == req.id)
|
||||
{
|
||||
self.wait_queue[idx].cancelling = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let caller = req.caller();
|
||||
let mut op = match req.op() {
|
||||
Ok(op) => op,
|
||||
Err(req) => {
|
||||
self.scheme
|
||||
.scheme_file
|
||||
.write_response(
|
||||
Response::err(syscall::EOPNOTSUPP, req),
|
||||
SignalBehavior::Restart,
|
||||
)
|
||||
.map_err(|e| {
|
||||
Error::from_syscall_error(e.into(), "failed to write response")
|
||||
})?;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let resp = match op.handle_sync_dont_consume(&caller, &mut self.scheme) {
|
||||
SchemeResponse::Opened(Err(SyscallError {
|
||||
errno: syscall::EWOULDBLOCK,
|
||||
}))
|
||||
| SchemeResponse::Regular(Err(SyscallError {
|
||||
errno: syscall::EWOULDBLOCK,
|
||||
})) if !op.is_explicitly_nonblock() => {
|
||||
match self.scheme.handle_block(&op) {
|
||||
Ok(timeout) => {
|
||||
self.wait_queue.push(WaitHandle {
|
||||
until: timeout,
|
||||
cancelling: false,
|
||||
packet: (op, caller),
|
||||
});
|
||||
}
|
||||
Err(err) => {
|
||||
let _ = self
|
||||
.scheme
|
||||
.scheme_file
|
||||
.write_response(
|
||||
Response::err(err.errno, op),
|
||||
SignalBehavior::Restart,
|
||||
)
|
||||
.map_err(|e| {
|
||||
Error::from_syscall_error(e.into(), "failed to write response")
|
||||
})?;
|
||||
return Err(Error::from_syscall_error(
|
||||
err,
|
||||
"Can't handle blocked socket",
|
||||
));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
SchemeResponse::Regular(r) => Response::new(r, op),
|
||||
SchemeResponse::Opened(o) => Response::open_dup_like(o, op),
|
||||
};
|
||||
let _ = self
|
||||
.scheme
|
||||
.scheme_file
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
.map_err(|e| Error::from_syscall_error(e.into(), "failed to write response"))?;
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn notify_sockets(&mut self) -> Result<()> {
|
||||
let cur_time = libredox::call::clock_gettime(flag::CLOCK_MONOTONIC)
|
||||
.map_err(|e| Error::from_syscall_error(e.into(), "Can't get time"))?;
|
||||
|
||||
// Notify non-blocking sockets
|
||||
let scheme = &mut self.scheme;
|
||||
|
||||
for (&fd, ref mut file) in &mut scheme.files {
|
||||
let events = {
|
||||
let mut socket_set = scheme.socket_set.borrow_mut();
|
||||
file.events(&mut socket_set)
|
||||
};
|
||||
if events > 0 {
|
||||
post_fevent(&scheme.scheme_file, fd, events)
|
||||
.map_err(|e| Error::from_syscall_error(e.into(), "failed to post fevent"))?;
|
||||
}
|
||||
}
|
||||
// Wake up blocking queue
|
||||
let queue = &mut self.wait_queue;
|
||||
let mut i = 0;
|
||||
while i < queue.len() {
|
||||
let handle = &mut queue[i];
|
||||
let (op, caller) = &mut handle.packet;
|
||||
let res = op.handle_sync_dont_consume(caller, scheme);
|
||||
|
||||
match res {
|
||||
SchemeResponse::Opened(Err(SyscallError {
|
||||
errno: syscall::EWOULDBLOCK,
|
||||
}))
|
||||
| SchemeResponse::Regular(Err(SyscallError {
|
||||
errno: syscall::EWOULDBLOCK,
|
||||
})) if !op.is_explicitly_nonblock() => {
|
||||
if handle.cancelling {
|
||||
let (op, _) = queue.swap_remove(i).packet;
|
||||
scheme
|
||||
.scheme_file
|
||||
.write_response(
|
||||
Response::err(syscall::ECANCELED, op),
|
||||
SignalBehavior::Restart,
|
||||
)
|
||||
.map_err(|e| {
|
||||
Error::from_syscall_error(e.into(), "failed to write response")
|
||||
})?;
|
||||
continue;
|
||||
}
|
||||
match handle.until {
|
||||
Some(until)
|
||||
if (until.tv_sec < cur_time.tv_sec
|
||||
|| (until.tv_sec == cur_time.tv_sec
|
||||
&& i64::from(until.tv_nsec) < i64::from(cur_time.tv_nsec))) =>
|
||||
{
|
||||
let (op, _) = queue.swap_remove(i).packet;
|
||||
let _ = scheme
|
||||
.scheme_file
|
||||
.write_response(
|
||||
Response::err(syscall::ETIMEDOUT, op),
|
||||
SignalBehavior::Restart,
|
||||
)
|
||||
.map_err(|e| {
|
||||
Error::from_syscall_error(e.into(), "failed to write response")
|
||||
})?;
|
||||
}
|
||||
_ => {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
SchemeResponse::Regular(r) => {
|
||||
let (op, _) = queue.swap_remove(i).packet;
|
||||
let _ = scheme
|
||||
.scheme_file
|
||||
.write_response(Response::new(r, op), SignalBehavior::Restart)
|
||||
.map_err(|e| {
|
||||
Error::from_syscall_error(e.into(), "failed to write response")
|
||||
})?;
|
||||
}
|
||||
SchemeResponse::Opened(o) => {
|
||||
let (op, _) = queue.swap_remove(i).packet;
|
||||
let _ = scheme
|
||||
.scheme_file
|
||||
.write_response(Response::open_dup_like(o, op), SignalBehavior::Restart)
|
||||
.map_err(|e| {
|
||||
Error::from_syscall_error(e.into(), "failed to write response")
|
||||
})?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
mod nodes;
|
||||
mod notifier;
|
||||
|
||||
use redox_scheme::{
|
||||
scheme::SchemeSync, CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket,
|
||||
};
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read, Write};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
@@ -14,10 +15,8 @@ use std::str::FromStr;
|
||||
use syscall;
|
||||
use syscall::data::Stat;
|
||||
use syscall::flag::{MODE_DIR, MODE_FILE};
|
||||
use syscall::{
|
||||
Error as SyscallError, EventFlags as SyscallEventFlags, Packet as SyscallPacket,
|
||||
Result as SyscallResult, SchemeMut,
|
||||
};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{Error as SyscallError, EventFlags as SyscallEventFlags, Result as SyscallResult};
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::link::DeviceList;
|
||||
@@ -326,7 +325,7 @@ impl NetCfgFile {
|
||||
}
|
||||
|
||||
pub struct NetCfgScheme {
|
||||
scheme_file: File,
|
||||
scheme_file: Socket,
|
||||
next_fd: usize,
|
||||
files: BTreeMap<usize, NetCfgFile>,
|
||||
root_node: CfgNodeRef,
|
||||
@@ -336,7 +335,7 @@ pub struct NetCfgScheme {
|
||||
impl NetCfgScheme {
|
||||
pub fn new(
|
||||
iface: Interface,
|
||||
scheme_file: File,
|
||||
scheme_file: Socket,
|
||||
route_table: Rc<RefCell<RouteTable>>,
|
||||
devices: Rc<RefCell<DeviceList>>,
|
||||
) -> NetCfgScheme {
|
||||
@@ -361,23 +360,50 @@ impl NetCfgScheme {
|
||||
|
||||
pub fn on_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
let result = loop {
|
||||
let mut packet = SyscallPacket::default();
|
||||
match self.scheme_file.read(&mut packet) {
|
||||
Ok(0) => {
|
||||
//TODO: Cleanup must occur
|
||||
let request = match self.scheme_file.next_request(SignalBehavior::Restart) {
|
||||
Ok(Some(req)) => req,
|
||||
Ok(None) => {
|
||||
break Some(());
|
||||
}
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
if err.kind() == ErrorKind::WouldBlock {
|
||||
break None;
|
||||
} else {
|
||||
return Err(Error::from(err));
|
||||
}
|
||||
Err(error)
|
||||
if error.errno == syscall::EWOULDBLOCK || error.errno == syscall::EAGAIN =>
|
||||
{
|
||||
break None;
|
||||
}
|
||||
}
|
||||
self.handle(&mut packet);
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
Err(other) => {
|
||||
return Err(Error::from_syscall_error(
|
||||
other,
|
||||
"failed to receive new request",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let req = match request.kind() {
|
||||
RequestKind::Call(c) => c,
|
||||
RequestKind::OnClose { id } => {
|
||||
self.on_close(id);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let caller = req.caller();
|
||||
let op = match req.op() {
|
||||
Ok(op) => op,
|
||||
Err(req) => {
|
||||
self.scheme_file.write_response(
|
||||
Response::err(syscall::EOPNOTSUPP, req),
|
||||
SignalBehavior::Restart,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let resp = op.handle_sync(caller, self);
|
||||
let _ = self
|
||||
.scheme_file
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
.map_err(|e| Error::from_syscall_error(e.into(), "failed to write response"))?;
|
||||
};
|
||||
self.notify_scheduled_fds();
|
||||
Ok(result)
|
||||
@@ -386,13 +412,13 @@ impl NetCfgScheme {
|
||||
fn notify_scheduled_fds(&mut self) {
|
||||
let fds_to_notify = self.notifier.borrow_mut().get_notified_fds();
|
||||
for fd in fds_to_notify {
|
||||
let _ = post_fevent(&mut self.scheme_file, fd, syscall::EVENT_READ.bits(), 1);
|
||||
let _ = post_fevent(&self.scheme_file, fd, syscall::EVENT_READ.bits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeMut for NetCfgScheme {
|
||||
fn open(&mut self, path: &str, _flags: usize, uid: u32, _gid: u32) -> SyscallResult<usize> {
|
||||
impl SchemeSync for NetCfgScheme {
|
||||
fn open(&mut self, path: &str, _flags: usize, ctx: &CallerCtx) -> SyscallResult<OpenResult> {
|
||||
let mut current_node = Rc::clone(&self.root_node);
|
||||
for part in path.split('/') {
|
||||
if part.is_empty() {
|
||||
@@ -421,31 +447,37 @@ impl SchemeMut for NetCfgScheme {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
uid,
|
||||
uid: ctx.uid,
|
||||
pos: 0,
|
||||
read_buf,
|
||||
write_buf: vec![],
|
||||
done: false,
|
||||
},
|
||||
);
|
||||
Ok(fd)
|
||||
Ok(OpenResult::ThisScheme {
|
||||
number: fd,
|
||||
flags: NewFdFlags::empty(),
|
||||
})
|
||||
}
|
||||
|
||||
fn close(&mut self, fd: usize) -> SyscallResult<usize> {
|
||||
fn on_close(&mut self, fd: usize) {
|
||||
trace!("close {}", fd);
|
||||
if let Some(mut file) = self.files.remove(&fd) {
|
||||
self.notifier.borrow_mut().unsubscribe(&file.path, fd);
|
||||
if !file.done {
|
||||
file.commit().map(|_| 0)
|
||||
} else {
|
||||
Ok(0)
|
||||
let _ = file.commit().map(|_| 0);
|
||||
}
|
||||
} else {
|
||||
Err(SyscallError::new(syscall::EBADF))
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<usize> {
|
||||
fn write(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
buf: &[u8],
|
||||
_offset: u64,
|
||||
_fcntl_flags: u32,
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<usize> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
@@ -474,7 +506,14 @@ impl SchemeMut for NetCfgScheme {
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn read(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
fn read(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
buf: &mut [u8],
|
||||
_offset: u64,
|
||||
_fcntl_flags: u32,
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<usize> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
@@ -489,7 +528,7 @@ impl SchemeMut for NetCfgScheme {
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
fn fstat(&mut self, fd: usize, stat: &mut Stat) -> SyscallResult<usize> {
|
||||
fn fstat(&mut self, fd: usize, stat: &mut Stat, _ctx: &CallerCtx) -> SyscallResult<()> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
@@ -506,10 +545,15 @@ impl SchemeMut for NetCfgScheme {
|
||||
stat.st_gid = 0;
|
||||
stat.st_size = file.read_buf.len() as u64;
|
||||
|
||||
Ok(0)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fevent(&mut self, fd: usize, events: SyscallEventFlags) -> SyscallResult<SyscallEventFlags> {
|
||||
fn fevent(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
events: SyscallEventFlags,
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<SyscallEventFlags> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
@@ -522,14 +566,14 @@ impl SchemeMut for NetCfgScheme {
|
||||
Ok(SyscallEventFlags::empty())
|
||||
}
|
||||
|
||||
fn fsync(&mut self, fd: usize) -> SyscallResult<usize> {
|
||||
fn fsync(&mut self, fd: usize, _ctx: &CallerCtx) -> SyscallResult<()> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
if !file.done {
|
||||
let res = file.commit().map(|_| 0);
|
||||
let res = file.commit();
|
||||
file.done = true;
|
||||
res
|
||||
} else {
|
||||
|
||||
+95
-183
@@ -1,8 +1,7 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::btree_map::Entry;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read, Write};
|
||||
use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
@@ -10,22 +9,22 @@ use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
|
||||
use libredox::flag::{self, CLOCK_MONOTONIC};
|
||||
use libredox::flag::CLOCK_MONOTONIC;
|
||||
use redox_scheme::{
|
||||
scheme::{Op, SchemeSync},
|
||||
CallerCtx, OpenResult, Socket,
|
||||
};
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::flag::{EVENT_READ, EVENT_WRITE};
|
||||
use syscall::{self, KSMSG_CANCEL};
|
||||
use syscall::{
|
||||
Error as SyscallError, EventFlags as SyscallEventFlags, Packet as SyscallPacket,
|
||||
Result as SyscallResult, SchemeBlockMut,
|
||||
};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{Error as SyscallError, EventFlags as SyscallEventFlags, Result as SyscallResult};
|
||||
|
||||
use super::Interface;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::router::route_table::RouteTable;
|
||||
use crate::scheme::smoltcp::iface::SocketHandle;
|
||||
use smoltcp::socket::AnySocket;
|
||||
|
||||
use super::{post_fevent, SocketSet};
|
||||
use super::SocketSet;
|
||||
|
||||
pub struct Context {
|
||||
pub iface: Interface,
|
||||
@@ -153,15 +152,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct WaitHandle {
|
||||
until: Option<TimeSpec>,
|
||||
cancelling: bool,
|
||||
packet: SyscallPacket,
|
||||
}
|
||||
|
||||
type WaitQueue = Vec<WaitHandle>;
|
||||
|
||||
pub type DupResult<T> = Option<(
|
||||
SchemeFile<T>,
|
||||
Option<(SocketHandle, <T as SchemeSocket>::DataT)>,
|
||||
@@ -209,17 +199,14 @@ where
|
||||
data: &mut Self::SchemeDataT,
|
||||
) -> SyscallResult<()>;
|
||||
|
||||
fn write_buf(
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<Option<usize>>;
|
||||
fn write_buf(&mut self, file: &mut SocketFile<Self::DataT>, buf: &[u8])
|
||||
-> SyscallResult<usize>;
|
||||
|
||||
fn read_buf(
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<Option<usize>>;
|
||||
) -> SyscallResult<usize>;
|
||||
|
||||
fn fpath(&self, file: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize>;
|
||||
|
||||
@@ -237,12 +224,11 @@ where
|
||||
{
|
||||
next_fd: usize,
|
||||
nulls: BTreeMap<usize, NullFile>,
|
||||
files: BTreeMap<usize, SchemeFile<SocketT>>,
|
||||
pub files: BTreeMap<usize, SchemeFile<SocketT>>,
|
||||
ref_counts: BTreeMap<SocketHandle, usize>,
|
||||
context: Context,
|
||||
socket_set: Rc<RefCell<SocketSet>>,
|
||||
scheme_file: File,
|
||||
wait_queue: WaitQueue,
|
||||
pub socket_set: Rc<RefCell<SocketSet>>,
|
||||
pub scheme_file: Socket,
|
||||
scheme_data: SocketT::SchemeDataT,
|
||||
_phantom_socket: PhantomData<SocketT>,
|
||||
}
|
||||
@@ -255,7 +241,7 @@ where
|
||||
iface: Interface,
|
||||
route_table: Rc<RefCell<RouteTable>>,
|
||||
socket_set: Rc<RefCell<SocketSet>>,
|
||||
scheme_file: File,
|
||||
scheme_file: Socket,
|
||||
) -> SocketScheme<SocketT> {
|
||||
SocketScheme {
|
||||
next_fd: 1,
|
||||
@@ -265,117 +251,13 @@ where
|
||||
socket_set,
|
||||
scheme_data: SocketT::new_scheme_data(),
|
||||
scheme_file,
|
||||
wait_queue: Vec::new(),
|
||||
_phantom_socket: PhantomData,
|
||||
context: Context { iface, route_table },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
let result = loop {
|
||||
let mut packet = SyscallPacket::default();
|
||||
match self.scheme_file.read(&mut packet) {
|
||||
Ok(0) => {
|
||||
//TODO: Cleanup must occur
|
||||
break Some(());
|
||||
}
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
if err.kind() == ErrorKind::WouldBlock {
|
||||
break None;
|
||||
} else {
|
||||
return Err(Error::from(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
if packet.a == KSMSG_CANCEL {
|
||||
if let Some(idx) = self
|
||||
.wait_queue
|
||||
.iter()
|
||||
.position(|q| q.packet.id == packet.b as u64)
|
||||
{
|
||||
self.wait_queue[idx].cancelling = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if let Some(a) = self.handle(&mut packet) {
|
||||
packet.a = a;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
} else {
|
||||
match self.handle_block(&mut packet) {
|
||||
Ok(timeout) => {
|
||||
self.wait_queue.push(WaitHandle {
|
||||
until: timeout,
|
||||
cancelling: false,
|
||||
packet,
|
||||
});
|
||||
}
|
||||
Err(err) => {
|
||||
packet.a = (-err.errno) as usize;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
return Err(Error::from_syscall_error(
|
||||
err,
|
||||
"Can't handle blocked socket",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn notify_sockets(&mut self) -> Result<()> {
|
||||
let cur_time = libredox::call::clock_gettime(flag::CLOCK_MONOTONIC)
|
||||
.map_err(|e| Error::from_syscall_error(e.into(), "Can't get time"))?;
|
||||
|
||||
// Notify non-blocking sockets
|
||||
for (&fd, ref mut file) in &mut self.files {
|
||||
let events = {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
file.events(&mut socket_set)
|
||||
};
|
||||
if events > 0 {
|
||||
post_fevent(&mut self.scheme_file, fd, events, 1)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Wake up blocking queue
|
||||
let mut i = 0;
|
||||
while i < self.wait_queue.len() {
|
||||
let mut packet = self.wait_queue[i].packet;
|
||||
if let Some(a) = self.handle(&packet) {
|
||||
self.wait_queue.remove(i);
|
||||
packet.a = a;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
} else {
|
||||
if self.wait_queue[i].cancelling {
|
||||
self.wait_queue.remove(i);
|
||||
packet.a = (-syscall::ECANCELED) as usize;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
continue;
|
||||
}
|
||||
match self.wait_queue[i].until {
|
||||
Some(until)
|
||||
if (until.tv_sec < cur_time.tv_sec
|
||||
|| (until.tv_sec == cur_time.tv_sec
|
||||
&& i64::from(until.tv_nsec) < i64::from(cur_time.tv_nsec))) =>
|
||||
{
|
||||
self.wait_queue.remove(i);
|
||||
packet.a = (-syscall::ETIMEDOUT) as usize;
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
}
|
||||
_ => {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_block(&mut self, packet: &mut SyscallPacket) -> SyscallResult<Option<TimeSpec>> {
|
||||
let fd = packet.b;
|
||||
pub fn handle_block(&mut self, op: &Op) -> SyscallResult<Option<TimeSpec>> {
|
||||
let fd = op.file_id().expect("op is not fd based request");
|
||||
let (read_timeout, write_timeout) = {
|
||||
let file = self
|
||||
.files
|
||||
@@ -389,9 +271,9 @@ where
|
||||
}
|
||||
}?;
|
||||
|
||||
let mut timeout = match packet.a {
|
||||
syscall::SYS_WRITE => write_timeout,
|
||||
syscall::SYS_READ => read_timeout,
|
||||
let mut timeout = match op {
|
||||
Op::Read(_) => write_timeout,
|
||||
Op::Write(_) => read_timeout,
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@@ -512,32 +394,26 @@ where
|
||||
Setting::Other(setting) => SocketT::set_setting(file, setting, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<SocketT> syscall::SchemeBlockMut for SocketScheme<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static>,
|
||||
{
|
||||
fn open(
|
||||
fn open_inner(
|
||||
&mut self,
|
||||
path: &str,
|
||||
flags: usize,
|
||||
uid: u32,
|
||||
_gid: u32,
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
gid: u32,
|
||||
) -> SyscallResult<OpenResult> {
|
||||
if path.is_empty() {
|
||||
let null = NullFile {
|
||||
flags,
|
||||
uid,
|
||||
gid: _gid,
|
||||
};
|
||||
let null = NullFile { flags, uid, gid };
|
||||
|
||||
let id = self.next_fd;
|
||||
self.next_fd += 1;
|
||||
|
||||
self.nulls.insert(id, null);
|
||||
|
||||
Ok(Some(id))
|
||||
Ok(OpenResult::ThisScheme {
|
||||
number: id,
|
||||
flags: NewFdFlags::empty(),
|
||||
})
|
||||
} else {
|
||||
let (socket_handle, data) = SocketT::new_socket(
|
||||
&mut self.socket_set.borrow_mut(),
|
||||
@@ -564,27 +440,38 @@ where
|
||||
self.ref_counts.insert(socket_handle, 1);
|
||||
self.files.insert(id, file);
|
||||
|
||||
Ok(Some(id))
|
||||
Ok(OpenResult::ThisScheme {
|
||||
number: id,
|
||||
flags: NewFdFlags::empty(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn close(&mut self, fd: usize) -> SyscallResult<Option<usize>> {
|
||||
impl<SocketT> SchemeSync for SocketScheme<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static>,
|
||||
{
|
||||
fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> SyscallResult<OpenResult> {
|
||||
self.open_inner(path, flags, ctx.uid, ctx.gid)
|
||||
}
|
||||
|
||||
fn on_close(&mut self, fd: usize) {
|
||||
if let Some(_null) = self.nulls.remove(&fd) {
|
||||
return Ok(Some(0));
|
||||
return;
|
||||
}
|
||||
|
||||
let socket_handle = {
|
||||
let file = self
|
||||
.files
|
||||
.get(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
let Some(file) = self.files.get(&fd) else {
|
||||
return;
|
||||
};
|
||||
file.socket_handle()
|
||||
};
|
||||
let scheme_file = self.files.remove(&fd);
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
if let Some(scheme_file) = scheme_file {
|
||||
let socket = socket_set.get::<SocketT>(socket_handle);
|
||||
socket.close_file(&scheme_file, &mut self.scheme_data)?;
|
||||
let _ = socket.close_file(&scheme_file, &mut self.scheme_data);
|
||||
}
|
||||
|
||||
// incorrect, and kernel can't send close until all references are gone
|
||||
@@ -620,10 +507,16 @@ where
|
||||
if remove {
|
||||
socket_set.remove(socket_handle);
|
||||
}
|
||||
Ok(Some(0))
|
||||
}
|
||||
|
||||
fn write(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<Option<usize>> {
|
||||
fn write(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
buf: &[u8],
|
||||
_offset: u64,
|
||||
_fcntl_flags: u32,
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<usize> {
|
||||
let (fd, setting) = {
|
||||
let file = self
|
||||
.files
|
||||
@@ -639,17 +532,25 @@ where
|
||||
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
|
||||
let ret = SocketT::write_buf(socket, file, buf);
|
||||
match ret {
|
||||
Ok(None) => {}
|
||||
Err(e) if e.errno == syscall::EWOULDBLOCK || e.errno == syscall::EAGAIN => {
|
||||
}
|
||||
_ => file.write_notified = false,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
};
|
||||
self.update_setting(fd, setting, buf).map(Some)
|
||||
self.update_setting(fd, setting, buf)
|
||||
}
|
||||
|
||||
fn read(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult<Option<usize>> {
|
||||
fn read(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
buf: &mut [u8],
|
||||
_offset: u64,
|
||||
_fcntl_flags: u32,
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<usize> {
|
||||
let (fd, setting) = {
|
||||
let file = self
|
||||
.files
|
||||
@@ -665,7 +566,8 @@ where
|
||||
|
||||
let ret = SocketT::read_buf(socket, file, buf);
|
||||
match ret {
|
||||
Ok(None) => {}
|
||||
Err(e) if e.errno == syscall::EWOULDBLOCK || e.errno == syscall::EAGAIN => {
|
||||
}
|
||||
_ => file.read_notified = false,
|
||||
}
|
||||
|
||||
@@ -673,10 +575,10 @@ where
|
||||
}
|
||||
}
|
||||
};
|
||||
self.get_setting(fd, setting, buf).map(Some)
|
||||
self.get_setting(fd, setting, buf)
|
||||
}
|
||||
|
||||
fn dup(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<Option<usize>> {
|
||||
fn dup(&mut self, fd: usize, buf: &[u8], _ctx: &CallerCtx) -> SyscallResult<OpenResult> {
|
||||
let path = str::from_utf8(buf).or_else(|_| Err(SyscallError::new(syscall::EINVAL)))?;
|
||||
|
||||
if let Some((flags, uid, gid)) = self
|
||||
@@ -684,7 +586,7 @@ where
|
||||
.get(&fd)
|
||||
.map(|null| (null.flags, null.uid, null.gid))
|
||||
{
|
||||
return self.open(path, flags, uid, gid);
|
||||
return self.open_inner(path, flags, uid, gid);
|
||||
}
|
||||
|
||||
let new_file = {
|
||||
@@ -727,7 +629,7 @@ where
|
||||
&mut self.scheme_data,
|
||||
)? {
|
||||
Some(some) => some,
|
||||
None => return Ok(None),
|
||||
None => return Err(SyscallError::new(syscall::EWOULDBLOCK)),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -757,14 +659,18 @@ where
|
||||
self.files.insert(id, new_file);
|
||||
self.next_fd += 1;
|
||||
|
||||
Ok(Some(id))
|
||||
Ok(OpenResult::ThisScheme {
|
||||
number: id,
|
||||
flags: NewFdFlags::empty(),
|
||||
})
|
||||
}
|
||||
|
||||
fn fevent(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
events: SyscallEventFlags,
|
||||
) -> SyscallResult<Option<SyscallEventFlags>> {
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<SyscallEventFlags> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
@@ -779,22 +685,22 @@ where
|
||||
}
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let revents = SyscallEventFlags::from_bits_truncate(file.events(&mut socket_set));
|
||||
Ok(Some(revents))
|
||||
Ok(revents)
|
||||
}
|
||||
|
||||
fn fsync(&mut self, fd: usize) -> SyscallResult<Option<usize>> {
|
||||
fn fsync(&mut self, fd: usize, _ctx: &CallerCtx) -> SyscallResult<()> {
|
||||
{
|
||||
let _file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
}
|
||||
Ok(Some(0))
|
||||
Ok(())
|
||||
// TODO Implement fsyncing
|
||||
// self.0.network_fsync()
|
||||
}
|
||||
|
||||
fn fpath(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult<Option<usize>> {
|
||||
fn fpath(&mut self, fd: usize, buf: &mut [u8], _ctx: &CallerCtx) -> SyscallResult<usize> {
|
||||
let file = self
|
||||
.files
|
||||
.get_mut(&fd)
|
||||
@@ -803,16 +709,22 @@ where
|
||||
let socket_set = self.socket_set.borrow();
|
||||
let socket = socket_set.get::<SocketT>(file.socket_handle());
|
||||
|
||||
socket.fpath(file, buf).map(Some)
|
||||
socket.fpath(file, buf)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> SyscallResult<Option<usize>> {
|
||||
fn fcntl(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
cmd: usize,
|
||||
arg: usize,
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<usize> {
|
||||
if let Some(ref mut null) = self.nulls.get_mut(&fd) {
|
||||
match cmd {
|
||||
syscall::F_GETFL => Ok(Some(null.flags)),
|
||||
syscall::F_GETFL => Ok(null.flags),
|
||||
syscall::F_SETFL => {
|
||||
null.flags = arg & !syscall::O_ACCMODE;
|
||||
Ok(Some(0))
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(SyscallError::new(syscall::EINVAL)),
|
||||
}
|
||||
@@ -824,10 +736,10 @@ where
|
||||
|
||||
if let SchemeFile::Socket(ref mut socket_file) = *file {
|
||||
match cmd {
|
||||
syscall::F_GETFL => Ok(Some(socket_file.flags)),
|
||||
syscall::F_GETFL => Ok(socket_file.flags),
|
||||
syscall::F_SETFL => {
|
||||
socket_file.flags = arg & !syscall::O_ACCMODE;
|
||||
Ok(Some(0))
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(SyscallError::new(syscall::EINVAL)),
|
||||
}
|
||||
|
||||
+10
-10
@@ -6,11 +6,11 @@ use std::str;
|
||||
use syscall;
|
||||
use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
use super::{parse_endpoint, SocketSet};
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile};
|
||||
use super::{parse_endpoint, SchemeWrapper, SocketSet};
|
||||
use crate::port_set::PortSet;
|
||||
|
||||
pub type TcpScheme = SocketScheme<TcpSocket<'static>>;
|
||||
pub type TcpScheme = SchemeWrapper<TcpSocket<'static>>;
|
||||
|
||||
impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
type SchemeDataT = PortSet;
|
||||
@@ -150,16 +150,16 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
if !self.is_active() {
|
||||
Err(SyscallError::new(syscall::ENOTCONN))
|
||||
} else if self.can_send() {
|
||||
self.send_slice(buf).expect("Can't send slice");
|
||||
Ok(Some(buf.len()))
|
||||
Ok(buf.len())
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-write
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-write
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,18 +167,18 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
if !self.is_active() {
|
||||
Err(SyscallError::new(syscall::ENOTCONN))
|
||||
} else if self.can_recv() {
|
||||
let length = self.recv_slice(buf).expect("Can't receive slice");
|
||||
Ok(Some(length))
|
||||
Ok(length)
|
||||
} else if !self.may_recv() {
|
||||
Ok(Some(0))
|
||||
Ok(0)
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-read
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ use std::str;
|
||||
use syscall;
|
||||
use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
use super::{parse_endpoint, Smolnetd, SocketSet};
|
||||
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile};
|
||||
use super::{parse_endpoint, SchemeWrapper, Smolnetd, SocketSet};
|
||||
use crate::port_set::PortSet;
|
||||
use crate::router::Router;
|
||||
|
||||
pub type UdpScheme = SocketScheme<UdpSocket<'static>>;
|
||||
pub type UdpScheme = SchemeWrapper<UdpSocket<'static>>;
|
||||
|
||||
impl<'a> SchemeSocket for UdpSocket<'a> {
|
||||
type SchemeDataT = PortSet;
|
||||
@@ -117,7 +117,7 @@ impl<'a> SchemeSocket for UdpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
if !file.data.is_specified() {
|
||||
return Err(SyscallError::new(syscall::EADDRNOTAVAIL));
|
||||
}
|
||||
@@ -130,11 +130,11 @@ impl<'a> SchemeSocket for UdpSocket<'a> {
|
||||
endpoint.port,
|
||||
);
|
||||
self.send_slice(buf, endpoint).expect("Can't send slice");
|
||||
Ok(Some(buf.len()))
|
||||
Ok(buf.len())
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-read
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,14 +142,14 @@ impl<'a> SchemeSocket for UdpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<Option<usize>> {
|
||||
) -> SyscallResult<usize> {
|
||||
if self.can_recv() {
|
||||
let (length, _) = self.recv_slice(buf).expect("Can't receive slice");
|
||||
Ok(Some(length))
|
||||
Ok(length)
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Err(SyscallError::new(syscall::EAGAIN))
|
||||
} else {
|
||||
Ok(None) // internally scheduled to re-read
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user