Code cleanup.
This commit is contained in:
@@ -21,8 +21,8 @@ mod buffer_pool;
|
||||
mod device;
|
||||
mod error;
|
||||
mod logger;
|
||||
mod scheme;
|
||||
mod port_set;
|
||||
mod scheme;
|
||||
|
||||
fn run() -> Result<()> {
|
||||
use syscall::flag::*;
|
||||
|
||||
+28
-98
@@ -1,31 +1,19 @@
|
||||
use super::socket::*;
|
||||
|
||||
use smoltcp::socket::{RawPacketBuffer, RawSocket, RawSocketBuffer, SocketHandle};
|
||||
use smoltcp::wire::{IpProtocol, IpVersion};
|
||||
use smoltcp;
|
||||
use std::io::{Read, Write};
|
||||
use std::str;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
use syscall;
|
||||
|
||||
use device::NetworkDevice;
|
||||
use super::Smolnetd;
|
||||
use super::{Smolnetd, SocketSet};
|
||||
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
|
||||
pub type IpScheme = SocketScheme<RawSocket<'static, 'static>>;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum Setting {
|
||||
ReadTimeout,
|
||||
WriteTimeout,
|
||||
}
|
||||
|
||||
impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> {
|
||||
type SchemeDataT = ();
|
||||
type DataT = ();
|
||||
type SettingT = Setting;
|
||||
type SettingT = ();
|
||||
|
||||
fn new_scheme_data() -> Self::SchemeDataT {
|
||||
()
|
||||
@@ -40,70 +28,32 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> {
|
||||
}
|
||||
|
||||
fn get_setting(
|
||||
file: &SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &mut [u8],
|
||||
) -> syscall::Result<usize> {
|
||||
let timespec = match (setting, file.read_timeout, file.write_timeout) {
|
||||
(Setting::ReadTimeout, Some(read_timeout), _) => read_timeout,
|
||||
(Setting::WriteTimeout, _, Some(write_timeout)) => write_timeout,
|
||||
_ => {
|
||||
return Ok(0);
|
||||
}
|
||||
};
|
||||
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
Ok(0)
|
||||
} else {
|
||||
let count = timespec.deref().read(buf).map_err(|err| {
|
||||
syscall::Error::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
Ok(count)
|
||||
}
|
||||
_file: &SocketFile<Self::DataT>,
|
||||
_setting: Self::SettingT,
|
||||
_buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn set_setting(
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &[u8],
|
||||
) -> syscall::Result<usize> {
|
||||
match setting {
|
||||
Setting::ReadTimeout | Setting::WriteTimeout => {
|
||||
let (timeout, count) = {
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
(None, 0)
|
||||
} else {
|
||||
let mut timespec = TimeSpec::default();
|
||||
let count = timespec.deref_mut().write(buf).map_err(|err| {
|
||||
syscall::Error::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
(Some(timespec), count)
|
||||
}
|
||||
};
|
||||
match setting {
|
||||
Setting::ReadTimeout => {
|
||||
file.read_timeout = timeout;
|
||||
}
|
||||
Setting::WriteTimeout => {
|
||||
file.write_timeout = timeout;
|
||||
}
|
||||
};
|
||||
return Ok(count);
|
||||
}
|
||||
}
|
||||
_file: &mut SocketFile<Self::DataT>,
|
||||
_setting: Self::SettingT,
|
||||
_buf: &[u8],
|
||||
) -> SyscallResult<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn new_socket(
|
||||
socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>,
|
||||
socket_set: &mut SocketSet,
|
||||
path: &str,
|
||||
uid: u32,
|
||||
_: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<(SocketHandle, Self::DataT)> {
|
||||
) -> SyscallResult<(SocketHandle, Self::DataT)> {
|
||||
if uid != 0 {
|
||||
return Err(syscall::Error::new(syscall::EACCES));
|
||||
return Err(SyscallError::new(syscall::EACCES));
|
||||
}
|
||||
let proto =
|
||||
u8::from_str_radix(path, 16).or_else(|_| Err(syscall::Error::new(syscall::ENOENT)))?;
|
||||
u8::from_str_radix(path, 16).or_else(|_| Err(SyscallError::new(syscall::ENOENT)))?;
|
||||
|
||||
let mut rx_packets = Vec::with_capacity(Smolnetd::SOCKET_BUFFER_SIZE);
|
||||
let mut tx_packets = Vec::with_capacity(Smolnetd::SOCKET_BUFFER_SIZE);
|
||||
@@ -124,7 +74,7 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> {
|
||||
Ok((socket_handle, ()))
|
||||
}
|
||||
|
||||
fn close_file(&self, _: &SchemeFile<Self>, _: &mut Self::SchemeDataT) -> syscall::Result<()> {
|
||||
fn close_file(&self, _: &SchemeFile<Self>, _: &mut Self::SchemeDataT) -> SyscallResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -132,14 +82,14 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> syscall::Result<usize> {
|
||||
) -> SyscallResult<usize> {
|
||||
if self.can_send() {
|
||||
self.send_slice(buf).expect("Can't send slice");
|
||||
Ok(buf.len())
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EWOULDBLOCK))
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,47 +97,27 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> syscall::Result<usize> {
|
||||
) -> SyscallResult<usize> {
|
||||
if self.can_recv() {
|
||||
let length = self.recv_slice(buf).expect("Can't receive slice");
|
||||
Ok(length)
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EWOULDBLOCK))
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
fn dup(
|
||||
_socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>,
|
||||
socket_handle: SocketHandle,
|
||||
_socket_set: &mut SocketSet,
|
||||
_file: &mut SchemeFile<Self>,
|
||||
fd: usize,
|
||||
path: &str,
|
||||
_path: &str,
|
||||
_: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<DupResult<Self>> {
|
||||
match path {
|
||||
"write_timeout" => Ok((
|
||||
SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::WriteTimeout,
|
||||
}),
|
||||
None,
|
||||
)),
|
||||
"read_timeout" => Ok((
|
||||
SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::ReadTimeout,
|
||||
}),
|
||||
None,
|
||||
)),
|
||||
_ => Err(syscall::Error::new(syscall::EBADF)),
|
||||
}
|
||||
) -> SyscallResult<DupResult<Self>> {
|
||||
Err(SyscallError::new(syscall::EBADF))
|
||||
}
|
||||
|
||||
fn fpath(&self, _file: &SchemeFile<Self>, buf: &mut [u8]) -> syscall::Result<usize> {
|
||||
fn fpath(&self, _file: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
let path = format!("ip:{}", self.ip_protocol());
|
||||
let path = path.as_bytes();
|
||||
|
||||
|
||||
+41
-24
@@ -1,35 +1,38 @@
|
||||
use netutils::getcfg;
|
||||
use smoltcp;
|
||||
use smoltcp::iface::{ArpCache, EthernetInterface, SliceArpCache};
|
||||
use smoltcp::socket::SocketSet as SmoltcpSocketSet;
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, IpEndpoint, Ipv4Address};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::mem;
|
||||
use std::mem::size_of;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall;
|
||||
|
||||
use buffer_pool::{Buffer, BufferPool};
|
||||
use device::NetworkDevice;
|
||||
use error::{Error, Result};
|
||||
use self::ip::IpScheme;
|
||||
use self::udp::UdpScheme;
|
||||
use self::tcp::TcpScheme;
|
||||
use self::udp::UdpScheme;
|
||||
|
||||
mod ip;
|
||||
mod socket;
|
||||
mod udp;
|
||||
mod tcp;
|
||||
mod udp;
|
||||
|
||||
type SocketSet = Rc<RefCell<smoltcp::socket::SocketSet<'static, 'static, 'static>>>;
|
||||
type SocketSet = SmoltcpSocketSet<'static, 'static, 'static>;
|
||||
|
||||
pub struct Smolnetd {
|
||||
network_file: Rc<RefCell<File>>,
|
||||
time_file: File,
|
||||
|
||||
iface: smoltcp::iface::EthernetInterface<'static, 'static, 'static, NetworkDevice>,
|
||||
socket_set: SocketSet,
|
||||
iface: EthernetInterface<'static, 'static, 'static, NetworkDevice>,
|
||||
socket_set: Rc<RefCell<SocketSet>>,
|
||||
|
||||
startup_time: Instant,
|
||||
|
||||
@@ -54,26 +57,25 @@ impl Smolnetd {
|
||||
tcp_file: File,
|
||||
time_file: File,
|
||||
) -> Smolnetd {
|
||||
let arp_cache = smoltcp::iface::SliceArpCache::new(vec![Default::default(); 8]);
|
||||
let hardware_addr = smoltcp::wire::EthernetAddress::from_str(getcfg("mac").unwrap().trim())
|
||||
let arp_cache = SliceArpCache::new(vec![Default::default(); 8]);
|
||||
let hardware_addr = EthernetAddress::from_str(getcfg("mac").unwrap().trim())
|
||||
.expect("Can't parse the 'mac' cfg");
|
||||
let local_ip = smoltcp::wire::IpAddress::from_str(getcfg("ip").unwrap().trim())
|
||||
.expect("Can't parse the 'ip' cfg.");
|
||||
let protocol_addrs = [smoltcp::wire::IpCidr::new(local_ip, 24)];
|
||||
let default_gw = smoltcp::wire::Ipv4Address::from_str(getcfg("ip_router").unwrap().trim())
|
||||
let local_ip =
|
||||
IpAddress::from_str(getcfg("ip").unwrap().trim()).expect("Can't parse the 'ip' cfg.");
|
||||
let protocol_addrs = [IpCidr::new(local_ip, 24)];
|
||||
let default_gw = Ipv4Address::from_str(getcfg("ip_router").unwrap().trim())
|
||||
.expect("Can't parse the 'ip_router' cfg.");
|
||||
// trace!("mac {:?} ip {}", hardware_addr, protocol_addrs);
|
||||
let input_queue = Rc::new(RefCell::new(VecDeque::new()));
|
||||
let network_file = Rc::new(RefCell::new(network_file));
|
||||
let network_device = NetworkDevice::new(Rc::clone(&network_file), Rc::clone(&input_queue));
|
||||
let iface = smoltcp::iface::EthernetInterface::new(
|
||||
let iface = EthernetInterface::new(
|
||||
Box::new(network_device),
|
||||
Box::new(arp_cache) as Box<smoltcp::iface::ArpCache>,
|
||||
Box::new(arp_cache) as Box<ArpCache>,
|
||||
hardware_addr,
|
||||
protocol_addrs,
|
||||
Some(default_gw),
|
||||
);
|
||||
let socket_set = Rc::new(RefCell::new(smoltcp::socket::SocketSet::new(vec![])));
|
||||
let socket_set = Rc::new(RefCell::new(SocketSet::new(vec![])));
|
||||
Smolnetd {
|
||||
iface,
|
||||
socket_set: Rc::clone(&socket_set),
|
||||
@@ -97,31 +99,31 @@ impl Smolnetd {
|
||||
|
||||
pub fn on_ip_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
self.ip_scheme.on_scheme_event()?;
|
||||
self.poll()?;
|
||||
let _ = self.poll()?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn on_udp_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
self.udp_scheme.on_scheme_event()?;
|
||||
self.poll()?;
|
||||
let _ = self.poll()?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn on_tcp_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
self.tcp_scheme.on_scheme_event()?;
|
||||
self.poll()?;
|
||||
let _ = self.poll()?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn on_time_event(&mut self) -> Result<Option<()>> {
|
||||
let timeout = self.poll()?;
|
||||
self.schedule_timeout(timeout)?;
|
||||
self.schedule_time_event(timeout)?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn schedule_timeout(&mut self, timeout: i64) -> Result<()> {
|
||||
let mut time = syscall::data::TimeSpec::default();
|
||||
if self.time_file.read(&mut time)? < mem::size_of::<syscall::data::TimeSpec>() {
|
||||
fn schedule_time_event(&mut self, timeout: i64) -> Result<()> {
|
||||
let mut time = TimeSpec::default();
|
||||
if self.time_file.read(&mut time)? < size_of::<TimeSpec>() {
|
||||
return Err(Error::from_syscall_error(
|
||||
syscall::Error::new(syscall::EBADF),
|
||||
"Can't read current time",
|
||||
@@ -215,3 +217,18 @@ fn post_fevent(scheme_file: &mut File, fd: usize, event: usize, data_len: usize)
|
||||
.map(|_| ())
|
||||
.map_err(|e| Error::from_io_error(e, "failed to post fevent"))
|
||||
}
|
||||
|
||||
fn parse_endpoint(socket: &str) -> IpEndpoint {
|
||||
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 port = socket_parts
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.parse::<u16>()
|
||||
.unwrap_or(0);
|
||||
IpEndpoint::new(host, port)
|
||||
}
|
||||
|
||||
+207
-129
@@ -1,25 +1,29 @@
|
||||
use smoltcp::socket::{AnySocket, SocketHandle};
|
||||
use smoltcp;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::str;
|
||||
use std::marker::PhantomData;
|
||||
use syscall::SchemeMut;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::{Error as SyscallError, Packet as SyscallPacket, Result as SyscallResult, SchemeMut};
|
||||
use syscall;
|
||||
|
||||
use error::{Error, Result};
|
||||
use super::SocketSet;
|
||||
use super::post_fevent;
|
||||
use super::{SocketSet, post_fevent};
|
||||
|
||||
pub struct SocketFile<DataT> {
|
||||
pub flags: usize,
|
||||
pub data: DataT,
|
||||
|
||||
events: usize,
|
||||
socket_handle: SocketHandle,
|
||||
pub data: DataT,
|
||||
pub read_timeout: Option<TimeSpec>,
|
||||
pub write_timeout: Option<TimeSpec>,
|
||||
read_timeout: Option<TimeSpec>,
|
||||
write_timeout: Option<TimeSpec>,
|
||||
}
|
||||
|
||||
impl<DataT> SocketFile<DataT> {
|
||||
@@ -46,10 +50,18 @@ impl<DataT> SocketFile<DataT> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SettingFile<SettingT> {
|
||||
pub fd: usize,
|
||||
pub socket_handle: SocketHandle,
|
||||
pub setting: SettingT,
|
||||
#[derive(Copy, Clone)]
|
||||
enum Setting<SettingT: Copy> {
|
||||
Ttl,
|
||||
ReadTimeout,
|
||||
WriteTimeout,
|
||||
#[allow(dead_code)] Other(SettingT),
|
||||
}
|
||||
|
||||
pub struct SettingFile<SettingT: Copy> {
|
||||
fd: usize,
|
||||
socket_handle: SocketHandle,
|
||||
setting: Setting<SettingT>,
|
||||
}
|
||||
|
||||
pub enum SchemeFile<SocketT>
|
||||
@@ -64,7 +76,7 @@ impl<SocketT> SchemeFile<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket,
|
||||
{
|
||||
fn socket_handle(&self) -> SocketHandle {
|
||||
pub fn socket_handle(&self) -> SocketHandle {
|
||||
match *self {
|
||||
SchemeFile::Socket(SocketFile { socket_handle, .. }) |
|
||||
SchemeFile::Setting(SettingFile { socket_handle, .. }) => socket_handle,
|
||||
@@ -75,14 +87,17 @@ where
|
||||
#[derive(Default, Clone)]
|
||||
struct WaitHandle {
|
||||
until: Option<TimeSpec>,
|
||||
packet: syscall::Packet,
|
||||
packet: SyscallPacket,
|
||||
}
|
||||
|
||||
type WaitQueue = Vec<WaitHandle>;
|
||||
|
||||
type WaitQueueMap = BTreeMap<SocketHandle, WaitQueue>;
|
||||
|
||||
pub type DupResult<T: SchemeSocket> = (SchemeFile<T>, Option<(SocketHandle, T::DataT)>);
|
||||
pub type DupResult<T> = (
|
||||
SchemeFile<T>,
|
||||
Option<(SocketHandle, <T as SchemeSocket>::DataT)>,
|
||||
);
|
||||
|
||||
pub trait SchemeSocket
|
||||
where
|
||||
@@ -97,30 +112,30 @@ where
|
||||
fn can_send(&self) -> bool;
|
||||
fn can_recv(&self) -> bool;
|
||||
|
||||
fn get_setting(&SocketFile<Self::DataT>, Self::SettingT, &mut [u8]) -> syscall::Result<usize>;
|
||||
fn set_setting(&mut SocketFile<Self::DataT>, Self::SettingT, &[u8]) -> syscall::Result<usize>;
|
||||
fn get_setting(&SocketFile<Self::DataT>, Self::SettingT, &mut [u8]) -> SyscallResult<usize>;
|
||||
fn set_setting(&mut SocketFile<Self::DataT>, Self::SettingT, &[u8]) -> SyscallResult<usize>;
|
||||
|
||||
fn new_socket(
|
||||
&mut smoltcp::socket::SocketSet<'static, 'static, 'static>,
|
||||
&mut SocketSet,
|
||||
&str,
|
||||
u32,
|
||||
&mut Self::SchemeDataT,
|
||||
) -> syscall::Result<(SocketHandle, Self::DataT)>;
|
||||
fn close_file(&self, &SchemeFile<Self>, &mut Self::SchemeDataT) -> syscall::Result<()>;
|
||||
) -> SyscallResult<(SocketHandle, Self::DataT)>;
|
||||
|
||||
fn write_buf(&mut self, &mut SocketFile<Self::DataT>, buf: &[u8]) -> syscall::Result<usize>;
|
||||
fn read_buf(&mut self, &mut SocketFile<Self::DataT>, buf: &mut [u8]) -> syscall::Result<usize>;
|
||||
fn close_file(&self, &SchemeFile<Self>, &mut Self::SchemeDataT) -> SyscallResult<()>;
|
||||
|
||||
fn fpath(&self, &SchemeFile<Self>, &mut [u8]) -> syscall::Result<usize>;
|
||||
fn write_buf(&mut self, &mut SocketFile<Self::DataT>, buf: &[u8]) -> SyscallResult<usize>;
|
||||
|
||||
fn read_buf(&mut self, &mut SocketFile<Self::DataT>, buf: &mut [u8]) -> SyscallResult<usize>;
|
||||
|
||||
fn fpath(&self, &SchemeFile<Self>, &mut [u8]) -> SyscallResult<usize>;
|
||||
|
||||
fn dup(
|
||||
&mut smoltcp::socket::SocketSet<'static, 'static, 'static>,
|
||||
SocketHandle,
|
||||
&mut SocketSet,
|
||||
&mut SchemeFile<Self>,
|
||||
usize,
|
||||
&str,
|
||||
&mut Self::SchemeDataT,
|
||||
) -> syscall::Result<DupResult<Self>>;
|
||||
) -> SyscallResult<DupResult<Self>>;
|
||||
}
|
||||
|
||||
pub struct SocketScheme<SocketT>
|
||||
@@ -128,8 +143,8 @@ where
|
||||
SocketT: SchemeSocket + AnySocket<'static, 'static>,
|
||||
{
|
||||
next_fd: usize,
|
||||
fds: BTreeMap<usize, SchemeFile<SocketT>>,
|
||||
socket_set: SocketSet,
|
||||
files: BTreeMap<usize, SchemeFile<SocketT>>,
|
||||
socket_set: Rc<RefCell<SocketSet>>,
|
||||
scheme_file: File,
|
||||
wait_queue_map: WaitQueueMap,
|
||||
scheme_data: SocketT::SchemeDataT,
|
||||
@@ -140,10 +155,10 @@ impl<SocketT> SocketScheme<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static, 'static>,
|
||||
{
|
||||
pub fn new(socket_set: SocketSet, scheme_file: File) -> SocketScheme<SocketT> {
|
||||
pub fn new(socket_set: Rc<RefCell<SocketSet>>, scheme_file: File) -> SocketScheme<SocketT> {
|
||||
SocketScheme {
|
||||
next_fd: 1,
|
||||
fds: BTreeMap::new(),
|
||||
files: BTreeMap::new(),
|
||||
socket_set,
|
||||
scheme_data: SocketT::new_scheme_data(),
|
||||
scheme_file,
|
||||
@@ -154,7 +169,7 @@ where
|
||||
|
||||
pub fn on_scheme_event(&mut self) -> Result<Option<()>> {
|
||||
loop {
|
||||
let mut packet = syscall::Packet::default();
|
||||
let mut packet = SyscallPacket::default();
|
||||
if self.scheme_file.read(&mut packet)? == 0 {
|
||||
break;
|
||||
}
|
||||
@@ -172,12 +187,12 @@ where
|
||||
|
||||
pub fn notify_sockets(&mut self) -> Result<()> {
|
||||
// Notify non-blocking sockets
|
||||
for (&fd, handle) in &self.fds {
|
||||
for (&fd, file) in &self.files {
|
||||
if let SchemeFile::Socket(SocketFile {
|
||||
socket_handle,
|
||||
events,
|
||||
..
|
||||
}) = *handle
|
||||
}) = *file
|
||||
{
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get::<SocketT>(socket_handle);
|
||||
@@ -243,7 +258,6 @@ where
|
||||
}
|
||||
}
|
||||
} else {
|
||||
trace!("Waking up {} with {}", packet.b, packet.a);
|
||||
self.scheme_file.write_all(&packet)?;
|
||||
}
|
||||
}
|
||||
@@ -255,13 +269,12 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn move_handle_to_new_socket_handle(
|
||||
fn move_file_to_new_socket_handle(
|
||||
wait_queue_map: &mut WaitQueueMap,
|
||||
fd: usize,
|
||||
from: SocketHandle,
|
||||
to: SocketHandle,
|
||||
) -> syscall::Result<()> {
|
||||
trace!("Moving {} from {:?} to {:?}", fd, from, to);
|
||||
) -> SyscallResult<()> {
|
||||
let mut to_move = vec![];
|
||||
|
||||
if let Some(wait_queue) = wait_queue_map.get_mut(&from) {
|
||||
@@ -277,7 +290,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_block(&mut self, mut packet: syscall::Packet) -> Result<()> {
|
||||
fn handle_block(&mut self, mut packet: SyscallPacket) -> Result<()> {
|
||||
let syscall_result = self.try_handle_block(&mut packet);
|
||||
if let Err(syscall_error) = syscall_result {
|
||||
packet.a = (-syscall_error.errno) as usize;
|
||||
@@ -291,21 +304,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn try_handle_block(&mut self, packet: &mut syscall::Packet) -> syscall::Result<()> {
|
||||
fn try_handle_block(&mut self, packet: &mut SyscallPacket) -> SyscallResult<()> {
|
||||
let fd = packet.b;
|
||||
let (socket_handle, read_timeout, write_timeout) = {
|
||||
let handle = self.fds
|
||||
let file = self.files
|
||||
.get(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
if let SchemeFile::Socket(ref scheme_file) = *handle {
|
||||
if let SchemeFile::Socket(ref scheme_file) = *file {
|
||||
Ok((
|
||||
scheme_file.socket_handle,
|
||||
scheme_file.read_timeout,
|
||||
scheme_file.write_timeout,
|
||||
))
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EBADF))
|
||||
Err(SyscallError::new(syscall::EBADF))
|
||||
}
|
||||
}?;
|
||||
|
||||
@@ -336,38 +349,83 @@ where
|
||||
fn get_setting(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
setting: SocketT::SettingT,
|
||||
setting: Setting<SocketT::SettingT>,
|
||||
buf: &mut [u8],
|
||||
) -> syscall::Result<usize> {
|
||||
let handle = self.fds
|
||||
) -> SyscallResult<usize> {
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
let handle = match *handle {
|
||||
SchemeFile::Socket(ref mut handle) => handle,
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
let file = match *file {
|
||||
SchemeFile::Socket(ref mut file) => file,
|
||||
_ => {
|
||||
return Err(syscall::Error::new(syscall::EBADF));
|
||||
return Err(SyscallError::new(syscall::EBADF));
|
||||
}
|
||||
};
|
||||
|
||||
SocketT::get_setting(handle, setting, buf)
|
||||
if let Setting::Other(setting) = setting {
|
||||
SocketT::get_setting(file, setting, buf)
|
||||
} else {
|
||||
let timespec = match (setting, file.read_timeout, file.write_timeout) {
|
||||
(Setting::ReadTimeout, Some(read_timeout), _) => read_timeout,
|
||||
(Setting::WriteTimeout, _, Some(write_timeout)) => write_timeout,
|
||||
_ => {
|
||||
return Ok(0);
|
||||
}
|
||||
};
|
||||
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
Ok(0)
|
||||
} else {
|
||||
let count = timespec.deref().read(buf).map_err(|err| {
|
||||
SyscallError::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
Ok(count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_setting(
|
||||
&mut self,
|
||||
fd: usize,
|
||||
setting: SocketT::SettingT,
|
||||
setting: Setting<SocketT::SettingT>,
|
||||
buf: &[u8],
|
||||
) -> syscall::Result<usize> {
|
||||
let handle = self.fds
|
||||
) -> SyscallResult<usize> {
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
let handle = match *handle {
|
||||
SchemeFile::Socket(ref mut handle) => handle,
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
let file = match *file {
|
||||
SchemeFile::Socket(ref mut file) => file,
|
||||
_ => {
|
||||
return Err(syscall::Error::new(syscall::EBADF));
|
||||
return Err(SyscallError::new(syscall::EBADF));
|
||||
}
|
||||
};
|
||||
SocketT::set_setting(handle, setting, buf)
|
||||
match setting {
|
||||
Setting::ReadTimeout | Setting::WriteTimeout => {
|
||||
let (timeout, count) = {
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
(None, 0)
|
||||
} else {
|
||||
let mut timespec = TimeSpec::default();
|
||||
let count = timespec.deref_mut().write(buf).map_err(|err| {
|
||||
SyscallError::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
(Some(timespec), count)
|
||||
}
|
||||
};
|
||||
match setting {
|
||||
Setting::ReadTimeout => {
|
||||
file.read_timeout = timeout;
|
||||
}
|
||||
Setting::WriteTimeout => {
|
||||
file.write_timeout = timeout;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Ok(count)
|
||||
}
|
||||
Setting::Ttl => Ok(0),
|
||||
Setting::Other(setting) => SocketT::set_setting(file, setting, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,9 +433,8 @@ impl<SocketT> syscall::SchemeMut for SocketScheme<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket + AnySocket<'static, 'static>,
|
||||
{
|
||||
fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> syscall::Result<usize> {
|
||||
let path = str::from_utf8(url).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?;
|
||||
trace!("open {}", path);
|
||||
fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> SyscallResult<usize> {
|
||||
let path = str::from_utf8(url).or_else(|_| Err(SyscallError::new(syscall::EINVAL)))?;
|
||||
|
||||
let (socket_handle, data) = SocketT::new_socket(
|
||||
&mut self.socket_set.borrow_mut(),
|
||||
@@ -388,7 +445,7 @@ where
|
||||
|
||||
let id = self.next_fd;
|
||||
|
||||
self.fds.insert(
|
||||
self.files.insert(
|
||||
id,
|
||||
SchemeFile::Socket(SocketFile {
|
||||
flags,
|
||||
@@ -403,15 +460,14 @@ where
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn close(&mut self, fd: usize) -> syscall::Result<usize> {
|
||||
trace!("close {}", fd);
|
||||
fn close(&mut self, fd: usize) -> SyscallResult<usize> {
|
||||
let socket_handle = {
|
||||
let handle = self.fds
|
||||
let file = self.files
|
||||
.get(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
handle.socket_handle()
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
file.socket_handle()
|
||||
};
|
||||
let scheme_file = self.fds.remove(&fd);
|
||||
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);
|
||||
@@ -421,7 +477,7 @@ where
|
||||
if let Some(ref mut wait_queue) = self.wait_queue_map.get_mut(&socket_handle) {
|
||||
wait_queue.retain(
|
||||
|&WaitHandle {
|
||||
packet: syscall::Packet { a, .. },
|
||||
packet: SyscallPacket { a, .. },
|
||||
..
|
||||
}| a != fd,
|
||||
);
|
||||
@@ -438,143 +494,165 @@ where
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn write(&mut self, fd: usize, buf: &[u8]) -> syscall::Result<usize> {
|
||||
fn write(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<usize> {
|
||||
let (fd, setting) = {
|
||||
let handle = self.fds
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
match *handle {
|
||||
match *file {
|
||||
SchemeFile::Setting(ref setting_handle) => {
|
||||
(setting_handle.fd, setting_handle.setting)
|
||||
}
|
||||
SchemeFile::Socket(ref mut handle) => {
|
||||
SchemeFile::Socket(ref mut file) => {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let mut socket = socket_set.get::<SocketT>(handle.socket_handle);
|
||||
|
||||
return <SocketT as SchemeSocket>::write_buf(&mut socket, handle, buf);
|
||||
let mut socket = socket_set.get::<SocketT>(file.socket_handle);
|
||||
return SocketT::write_buf(&mut socket, file, buf);
|
||||
}
|
||||
}
|
||||
};
|
||||
self.update_setting(fd, setting, buf)
|
||||
}
|
||||
|
||||
fn read(&mut self, fd: usize, buf: &mut [u8]) -> syscall::Result<usize> {
|
||||
fn read(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
let (fd, setting) = {
|
||||
let handle = self.fds
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
match *handle {
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
match *file {
|
||||
SchemeFile::Setting(ref setting_handle) => {
|
||||
(setting_handle.fd, setting_handle.setting)
|
||||
}
|
||||
SchemeFile::Socket(ref mut handle) => {
|
||||
SchemeFile::Socket(ref mut file) => {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let mut socket = socket_set.get::<SocketT>(handle.socket_handle);
|
||||
return <SocketT as SchemeSocket>::read_buf(&mut socket, handle, buf);
|
||||
let mut socket = socket_set.get::<SocketT>(file.socket_handle);
|
||||
return SocketT::read_buf(&mut socket, file, buf);
|
||||
}
|
||||
}
|
||||
};
|
||||
self.get_setting(fd, setting, buf)
|
||||
}
|
||||
|
||||
fn dup(&mut self, fd: usize, buf: &[u8]) -> syscall::Result<usize> {
|
||||
let path = str::from_utf8(buf).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?;
|
||||
fn dup(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<usize> {
|
||||
let path = str::from_utf8(buf).or_else(|_| Err(SyscallError::new(syscall::EINVAL)))?;
|
||||
|
||||
let new_file = {
|
||||
let handle = self.fds
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
let socket_handle = handle.socket_handle();
|
||||
let socket_handle = file.socket_handle();
|
||||
|
||||
let (new_handle, update_with) = SocketT::dup(
|
||||
&mut self.socket_set.borrow_mut(),
|
||||
socket_handle,
|
||||
handle,
|
||||
fd,
|
||||
path,
|
||||
&mut self.scheme_data,
|
||||
)?;
|
||||
let (new_handle, update_with) = match path {
|
||||
"ttl" => (
|
||||
SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::Ttl,
|
||||
}),
|
||||
None,
|
||||
),
|
||||
"read_timeout" => (
|
||||
SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::ReadTimeout,
|
||||
}),
|
||||
None,
|
||||
),
|
||||
"write_timeout" => (
|
||||
SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::WriteTimeout,
|
||||
}),
|
||||
None,
|
||||
),
|
||||
_ => SocketT::dup(
|
||||
&mut self.socket_set.borrow_mut(),
|
||||
file,
|
||||
path,
|
||||
&mut self.scheme_data,
|
||||
)?,
|
||||
};
|
||||
|
||||
if let Some((socket_handle, data)) = update_with {
|
||||
if let SchemeFile::Socket(ref mut handle) = *handle {
|
||||
trace!("Updating {} to a new socket handle {:?}", fd, socket_handle);
|
||||
Self::move_handle_to_new_socket_handle(
|
||||
if let SchemeFile::Socket(ref mut file) = *file {
|
||||
Self::move_file_to_new_socket_handle(
|
||||
&mut self.wait_queue_map,
|
||||
fd,
|
||||
handle.socket_handle,
|
||||
file.socket_handle,
|
||||
socket_handle,
|
||||
)?;
|
||||
handle.socket_handle = socket_handle;
|
||||
handle.data = data;
|
||||
file.socket_handle = socket_handle;
|
||||
file.data = data;
|
||||
} else {
|
||||
self.socket_set.borrow_mut().retain(handle.socket_handle());
|
||||
self.socket_set.borrow_mut().retain(file.socket_handle());
|
||||
}
|
||||
} else {
|
||||
self.socket_set.borrow_mut().retain(handle.socket_handle());
|
||||
self.socket_set.borrow_mut().retain(file.socket_handle());
|
||||
}
|
||||
new_handle
|
||||
};
|
||||
|
||||
let id = self.next_fd;
|
||||
self.fds.insert(id, new_file);
|
||||
self.files.insert(id, new_file);
|
||||
self.next_fd += 1;
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn fevent(&mut self, fd: usize, events: usize) -> syscall::Result<usize> {
|
||||
let handle = self.fds
|
||||
fn fevent(&mut self, fd: usize, events: usize) -> SyscallResult<usize> {
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
match *handle {
|
||||
SchemeFile::Setting(_) => Err(syscall::Error::new(syscall::EBADF)),
|
||||
SchemeFile::Socket(ref mut handle) => {
|
||||
handle.events = events;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
match *file {
|
||||
SchemeFile::Setting(_) => Err(SyscallError::new(syscall::EBADF)),
|
||||
SchemeFile::Socket(ref mut file) => {
|
||||
file.events = events;
|
||||
Ok(fd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fsync(&mut self, fd: usize) -> syscall::Result<usize> {
|
||||
fn fsync(&mut self, fd: usize) -> SyscallResult<usize> {
|
||||
{
|
||||
let _handle = self.fds
|
||||
let _file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
}
|
||||
Ok(0)
|
||||
// TODO Implement fsyncing
|
||||
// self.0.network_fsync()
|
||||
}
|
||||
|
||||
fn fpath(&mut self, fd: usize, buf: &mut [u8]) -> syscall::Result<usize> {
|
||||
let handle = self.fds
|
||||
fn fpath(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get::<SocketT>(handle.socket_handle());
|
||||
let socket = socket_set.get::<SocketT>(file.socket_handle());
|
||||
|
||||
socket.fpath(handle, buf)
|
||||
socket.fpath(file, buf)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> syscall::Result<usize> {
|
||||
let handle = self.fds
|
||||
fn fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> SyscallResult<usize> {
|
||||
let file = self.files
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
if let SchemeFile::Socket(ref mut socket_file) = *handle {
|
||||
if let SchemeFile::Socket(ref mut socket_file) = *file {
|
||||
match cmd {
|
||||
syscall::F_GETFL => Ok(socket_file.flags),
|
||||
syscall::F_SETFL => {
|
||||
socket_file.flags = arg & !syscall::O_ACCMODE;
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(syscall::Error::new(syscall::EINVAL)),
|
||||
_ => Err(SyscallError::new(syscall::EINVAL)),
|
||||
}
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EBADF))
|
||||
Err(SyscallError::new(syscall::EBADF))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
-122
@@ -1,32 +1,18 @@
|
||||
use super::socket::*;
|
||||
|
||||
use smoltcp::socket::{SocketHandle, TcpSocket, TcpSocketBuffer};
|
||||
use smoltcp::wire::{IpAddress, IpEndpoint, Ipv4Address};
|
||||
use smoltcp;
|
||||
use std::io::{Read, Write};
|
||||
use std::str::FromStr;
|
||||
use std::str;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
use syscall;
|
||||
|
||||
use port_set::PortSet;
|
||||
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
use super::{parse_endpoint, SocketSet};
|
||||
|
||||
pub type TcpScheme = SocketScheme<TcpSocket<'static>>;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum Setting {
|
||||
Ttl,
|
||||
ReadTimeout,
|
||||
WriteTimeout,
|
||||
}
|
||||
|
||||
impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
type SchemeDataT = PortSet;
|
||||
type DataT = ();
|
||||
type SettingT = Setting;
|
||||
type SettingT = ();
|
||||
|
||||
fn new_scheme_data() -> Self::SchemeDataT {
|
||||
PortSet::new(49_152u16, 65_535u16).expect("Wrong TCP port numbers")
|
||||
@@ -41,77 +27,34 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
}
|
||||
|
||||
fn get_setting(
|
||||
file: &SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &mut [u8],
|
||||
) -> syscall::Result<usize> {
|
||||
trace!("TCP get setting {:?}", setting);
|
||||
let timespec = match (setting, file.read_timeout, file.write_timeout) {
|
||||
(Setting::ReadTimeout, Some(read_timeout), _) => read_timeout,
|
||||
(Setting::WriteTimeout, _, Some(write_timeout)) => write_timeout,
|
||||
_ => {
|
||||
return Ok(0);
|
||||
}
|
||||
};
|
||||
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
Ok(0)
|
||||
} else {
|
||||
let count = timespec.deref().read(buf).map_err(|err| {
|
||||
syscall::Error::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
Ok(count)
|
||||
}
|
||||
_file: &SocketFile<Self::DataT>,
|
||||
_setting: Self::SettingT,
|
||||
_buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn set_setting(
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &[u8],
|
||||
) -> syscall::Result<usize> {
|
||||
trace!("TCP set setting {:?}", setting);
|
||||
match setting {
|
||||
Setting::ReadTimeout | Setting::WriteTimeout => {
|
||||
let (timeout, count) = {
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
(None, 0)
|
||||
} else {
|
||||
let mut timespec = TimeSpec::default();
|
||||
let count = timespec.deref_mut().write(buf).map_err(|err| {
|
||||
syscall::Error::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
(Some(timespec), count)
|
||||
}
|
||||
};
|
||||
match setting {
|
||||
Setting::ReadTimeout => {
|
||||
file.read_timeout = timeout;
|
||||
}
|
||||
Setting::WriteTimeout => {
|
||||
file.write_timeout = timeout;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
return Ok(count);
|
||||
}
|
||||
Setting::Ttl => {}
|
||||
}
|
||||
_file: &mut SocketFile<Self::DataT>,
|
||||
_setting: Self::SettingT,
|
||||
_buf: &[u8],
|
||||
) -> SyscallResult<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn new_socket(
|
||||
socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>,
|
||||
socket_set: &mut SocketSet,
|
||||
path: &str,
|
||||
uid: u32,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<(SocketHandle, Self::DataT)> {
|
||||
) -> SyscallResult<(SocketHandle, Self::DataT)> {
|
||||
trace!("TCP open {}", path);
|
||||
let mut parts = path.split('/');
|
||||
let remote_endpoint = parse_endpoint(parts.next().unwrap_or(""));
|
||||
let mut local_endpoint = parse_endpoint(parts.next().unwrap_or(""));
|
||||
|
||||
if local_endpoint.port > 0 && local_endpoint.port <= 1024 && uid != 0 {
|
||||
return Err(syscall::Error::new(syscall::EACCES));
|
||||
return Err(SyscallError::new(syscall::EACCES));
|
||||
}
|
||||
|
||||
let rx_packets = vec![0; 65_535];
|
||||
@@ -123,9 +66,9 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
if local_endpoint.port == 0 {
|
||||
local_endpoint.port = port_set
|
||||
.get_port()
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EINVAL))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EINVAL))?;
|
||||
} else if !port_set.claim_port(local_endpoint.port) {
|
||||
return Err(syscall::Error::new(syscall::EADDRINUSE));
|
||||
return Err(SyscallError::new(syscall::EADDRINUSE));
|
||||
}
|
||||
|
||||
let socket_handle = socket_set.add(socket);
|
||||
@@ -151,7 +94,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
&self,
|
||||
file: &SchemeFile<Self>,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<()> {
|
||||
) -> SyscallResult<()> {
|
||||
if let SchemeFile::Socket(_) = *file {
|
||||
port_set.release_port(self.local_endpoint().port);
|
||||
}
|
||||
@@ -162,16 +105,16 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> syscall::Result<usize> {
|
||||
) -> SyscallResult<usize> {
|
||||
if !self.is_active() {
|
||||
Err(syscall::Error::new(syscall::ENOTCONN))
|
||||
Err(SyscallError::new(syscall::ENOTCONN))
|
||||
} else if self.can_send() {
|
||||
self.send_slice(buf).expect("Can't send slice");
|
||||
Ok(buf.len())
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EWOULDBLOCK))
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,51 +122,36 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> syscall::Result<usize> {
|
||||
) -> SyscallResult<usize> {
|
||||
if !self.is_active() {
|
||||
Err(syscall::Error::new(syscall::ENOTCONN))
|
||||
Err(SyscallError::new(syscall::ENOTCONN))
|
||||
} else if self.can_recv() {
|
||||
let length = self.recv_slice(buf).expect("Can't receive slice");
|
||||
Ok(length)
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EWOULDBLOCK))
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
fn dup(
|
||||
socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>,
|
||||
socket_handle: SocketHandle,
|
||||
socket_set: &mut SocketSet,
|
||||
file: &mut SchemeFile<Self>,
|
||||
fd: usize,
|
||||
path: &str,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<DupResult<Self>> {
|
||||
) -> SyscallResult<DupResult<Self>> {
|
||||
let socket_handle = file.socket_handle();
|
||||
|
||||
let (is_active, local_endpoint) = {
|
||||
let socket = socket_set.get::<TcpSocket>(socket_handle);
|
||||
(socket.is_active(), socket.local_endpoint())
|
||||
};
|
||||
|
||||
let handle = match path {
|
||||
"ttl" => SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::Ttl,
|
||||
}),
|
||||
"read_timeout" => SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::ReadTimeout,
|
||||
}),
|
||||
"write_timeout" => SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::WriteTimeout,
|
||||
}),
|
||||
let file = match path {
|
||||
"listen" => if let SchemeFile::Socket(ref tcp_handle) = *file {
|
||||
if !is_active {
|
||||
return Err(syscall::Error::new(syscall::EWOULDBLOCK));
|
||||
return Err(SyscallError::new(syscall::EWOULDBLOCK));
|
||||
}
|
||||
trace!("TCP creating new listening socket");
|
||||
let new_handle = SchemeFile::Socket(tcp_handle.clone_with_data(()));
|
||||
@@ -243,7 +171,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
port_set.acquire_port(local_endpoint.port);
|
||||
return Ok((new_handle, Some((new_socket_handle, ()))));
|
||||
} else {
|
||||
return Err(syscall::Error::new(syscall::EBADF));
|
||||
return Err(SyscallError::new(syscall::EBADF));
|
||||
},
|
||||
_ => {
|
||||
trace!("TCP dup unknown {}", path);
|
||||
@@ -255,14 +183,14 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
if let SchemeFile::Socket(_) = handle {
|
||||
if let SchemeFile::Socket(_) = file {
|
||||
port_set.acquire_port(local_endpoint.port);
|
||||
}
|
||||
|
||||
Ok((handle, None))
|
||||
Ok((file, None))
|
||||
}
|
||||
|
||||
fn fpath(&self, _: &SchemeFile<Self>, buf: &mut [u8]) -> syscall::Result<usize> {
|
||||
fn fpath(&self, _: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
let path = format!("tcp:{}/{}", self.remote_endpoint(), self.local_endpoint());
|
||||
let path = path.as_bytes();
|
||||
|
||||
@@ -275,18 +203,3 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
Ok(i)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_endpoint(socket: &str) -> IpEndpoint {
|
||||
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 port = socket_parts
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.parse::<u16>()
|
||||
.unwrap_or(0);
|
||||
IpEndpoint::new(host, port)
|
||||
}
|
||||
|
||||
+34
-121
@@ -1,34 +1,20 @@
|
||||
use super::socket::*;
|
||||
|
||||
use smoltcp::socket::{SocketHandle, UdpPacketBuffer, UdpSocket, UdpSocketBuffer};
|
||||
use smoltcp::wire::{IpAddress, IpEndpoint, Ipv4Address};
|
||||
use smoltcp;
|
||||
use std::io::{Read, Write};
|
||||
use std::str::FromStr;
|
||||
use smoltcp::wire::IpEndpoint;
|
||||
use std::str;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use syscall::data::TimeSpec;
|
||||
use syscall::{Error as SyscallError, Result as SyscallResult};
|
||||
use syscall;
|
||||
|
||||
use device::NetworkDevice;
|
||||
use super::Smolnetd;
|
||||
use port_set::PortSet;
|
||||
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
|
||||
use super::{parse_endpoint, Smolnetd, SocketSet};
|
||||
|
||||
pub type UdpScheme = SocketScheme<UdpSocket<'static, 'static>>;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum Setting {
|
||||
Ttl,
|
||||
ReadTimeout,
|
||||
WriteTimeout,
|
||||
}
|
||||
|
||||
impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
type SchemeDataT = PortSet;
|
||||
type DataT = IpEndpoint;
|
||||
type SettingT = Setting;
|
||||
type SettingT = ();
|
||||
|
||||
fn new_scheme_data() -> Self::SchemeDataT {
|
||||
PortSet::new(49_152u16, 65_535u16).expect("Wrong UDP port numbers")
|
||||
@@ -43,75 +29,33 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
}
|
||||
|
||||
fn get_setting(
|
||||
file: &SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &mut [u8],
|
||||
) -> syscall::Result<usize> {
|
||||
let timespec = match (setting, file.read_timeout, file.write_timeout) {
|
||||
(Setting::ReadTimeout, Some(read_timeout), _) => read_timeout,
|
||||
(Setting::WriteTimeout, _, Some(write_timeout)) => write_timeout,
|
||||
_ => {
|
||||
return Ok(0);
|
||||
}
|
||||
};
|
||||
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
Ok(0)
|
||||
} else {
|
||||
let count = timespec.deref().read(buf).map_err(|err| {
|
||||
syscall::Error::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
Ok(count)
|
||||
}
|
||||
_file: &SocketFile<Self::DataT>,
|
||||
_setting: Self::SettingT,
|
||||
_buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn set_setting(
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
setting: Self::SettingT,
|
||||
buf: &[u8],
|
||||
) -> syscall::Result<usize> {
|
||||
match setting {
|
||||
Setting::ReadTimeout | Setting::WriteTimeout => {
|
||||
let (timeout, count) = {
|
||||
if buf.len() < mem::size_of::<TimeSpec>() {
|
||||
(None, 0)
|
||||
} else {
|
||||
let mut timespec = TimeSpec::default();
|
||||
let count = timespec.deref_mut().write(buf).map_err(|err| {
|
||||
syscall::Error::new(err.raw_os_error().unwrap_or(syscall::EIO))
|
||||
})?;
|
||||
(Some(timespec), count)
|
||||
}
|
||||
};
|
||||
trace!("Setting {:?} to {:?}", setting, timeout);
|
||||
match setting {
|
||||
Setting::ReadTimeout => {
|
||||
file.read_timeout = timeout;
|
||||
}
|
||||
Setting::WriteTimeout => {
|
||||
file.write_timeout = timeout;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
return Ok(count);
|
||||
}
|
||||
Setting::Ttl => {}
|
||||
}
|
||||
_file: &mut SocketFile<Self::DataT>,
|
||||
_setting: Self::SettingT,
|
||||
_buf: &[u8],
|
||||
) -> SyscallResult<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn new_socket(
|
||||
socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>,
|
||||
socket_set: &mut SocketSet,
|
||||
path: &str,
|
||||
uid: u32,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<(SocketHandle, Self::DataT)> {
|
||||
) -> SyscallResult<(SocketHandle, Self::DataT)> {
|
||||
let mut parts = path.split('/');
|
||||
let remote_endpoint = parse_endpoint(parts.next().unwrap_or(""));
|
||||
let mut local_endpoint = parse_endpoint(parts.next().unwrap_or(""));
|
||||
|
||||
if local_endpoint.port > 0 && local_endpoint.port <= 1024 && uid != 0 {
|
||||
return Err(syscall::Error::new(syscall::EACCES));
|
||||
return Err(SyscallError::new(syscall::EACCES));
|
||||
}
|
||||
|
||||
let mut rx_packets = Vec::with_capacity(Smolnetd::SOCKET_BUFFER_SIZE);
|
||||
@@ -127,9 +71,9 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
if local_endpoint.port == 0 {
|
||||
local_endpoint.port = port_set
|
||||
.get_port()
|
||||
.ok_or_else(|| syscall::Error::new(syscall::EINVAL))?;
|
||||
.ok_or_else(|| SyscallError::new(syscall::EINVAL))?;
|
||||
} else if !port_set.claim_port(local_endpoint.port) {
|
||||
return Err(syscall::Error::new(syscall::EADDRINUSE));
|
||||
return Err(SyscallError::new(syscall::EADDRINUSE));
|
||||
}
|
||||
|
||||
let socket_handle = socket_set.add(udp_socket);
|
||||
@@ -146,7 +90,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
&self,
|
||||
file: &SchemeFile<Self>,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<()> {
|
||||
) -> SyscallResult<()> {
|
||||
if let SchemeFile::Socket(_) = *file {
|
||||
port_set.release_port(self.endpoint().port);
|
||||
}
|
||||
@@ -157,9 +101,9 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &[u8],
|
||||
) -> syscall::Result<usize> {
|
||||
) -> SyscallResult<usize> {
|
||||
if !file.data.is_specified() {
|
||||
return Err(syscall::Error::new(syscall::EADDRNOTAVAIL));
|
||||
return Err(SyscallError::new(syscall::EADDRNOTAVAIL));
|
||||
}
|
||||
if self.can_send() {
|
||||
self.send_slice(buf, file.data).expect("Can't send slice");
|
||||
@@ -167,7 +111,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EWOULDBLOCK))
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,41 +119,25 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
&mut self,
|
||||
file: &mut SocketFile<Self::DataT>,
|
||||
buf: &mut [u8],
|
||||
) -> syscall::Result<usize> {
|
||||
) -> SyscallResult<usize> {
|
||||
if self.can_recv() {
|
||||
let (length, _) = self.recv_slice(buf).expect("Can't receive slice");
|
||||
Ok(length)
|
||||
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EWOULDBLOCK))
|
||||
Err(SyscallError::new(syscall::EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
fn dup(
|
||||
socket_set: &mut smoltcp::socket::SocketSet,
|
||||
socket_handle: SocketHandle,
|
||||
socket_set: &mut SocketSet,
|
||||
file: &mut SchemeFile<Self>,
|
||||
fd: usize,
|
||||
path: &str,
|
||||
port_set: &mut Self::SchemeDataT,
|
||||
) -> syscall::Result<DupResult<Self>> {
|
||||
let handle = match path {
|
||||
"ttl" => SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::Ttl,
|
||||
}),
|
||||
"read_timeout" => SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::ReadTimeout,
|
||||
}),
|
||||
"write_timeout" => SchemeFile::Setting(SettingFile {
|
||||
socket_handle,
|
||||
fd,
|
||||
setting: Setting::WriteTimeout,
|
||||
}),
|
||||
) -> SyscallResult<DupResult<Self>> {
|
||||
let socket_handle = file.socket_handle();
|
||||
let file = match path {
|
||||
_ => {
|
||||
let remote_endpoint = parse_endpoint(path);
|
||||
if let SchemeFile::Socket(ref udp_handle) = *file {
|
||||
@@ -231,15 +159,15 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
socket.endpoint()
|
||||
};
|
||||
|
||||
if let SchemeFile::Socket(_) = handle {
|
||||
if let SchemeFile::Socket(_) = file {
|
||||
port_set.acquire_port(endpoint.port);
|
||||
}
|
||||
|
||||
Ok((handle, None))
|
||||
Ok((file, None))
|
||||
}
|
||||
|
||||
fn fpath(&self, file: &SchemeFile<Self>, buf: &mut [u8]) -> syscall::Result<usize> {
|
||||
if let &SchemeFile::Socket(ref socket_file) = file {
|
||||
fn fpath(&self, file: &SchemeFile<Self>, buf: &mut [u8]) -> SyscallResult<usize> {
|
||||
if let SchemeFile::Socket(ref socket_file) = *file {
|
||||
let path = format!("udp:{}/{}", socket_file.data, self.endpoint());
|
||||
let path = path.as_bytes();
|
||||
|
||||
@@ -251,22 +179,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> {
|
||||
|
||||
Ok(i)
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::EBADF))
|
||||
Err(SyscallError::new(syscall::EBADF))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_endpoint(socket: &str) -> IpEndpoint {
|
||||
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 port = socket_parts
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.parse::<u16>()
|
||||
.unwrap_or(0);
|
||||
IpEndpoint::new(host, port)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user