UDP settings.

This commit is contained in:
Egor Karavaev
2017-09-26 23:51:04 +03:00
parent c62eca07d9
commit 3198a8eb69
7 changed files with 192 additions and 78 deletions
+1 -1
View File
@@ -86,7 +86,7 @@ impl BufferPool {
Buffer {
buffer,
stack: self.stack.clone(),
stack: Rc::clone(&self.stack),
}
}
}
+1 -1
View File
@@ -69,7 +69,7 @@ impl smoltcp::phy::Device for NetworkDevice {
fn transmit(&mut self, _timestamp: u64, length: usize) -> smoltcp::Result<Self::TxBuffer> {
Ok(TxBuffer {
network_file: self.network_file.clone(),
network_file: Rc::clone(&self.network_file),
buffer: vec![0; length],
})
}
+9 -9
View File
@@ -33,8 +33,8 @@ fn run() -> Result<()> {
trace!("opening network:");
let network_fd = syscall::open("network:", O_RDWR | O_NONBLOCK)
.map_err(|e| Error::from_syscall_error(e, "failed to open network:"))? as
RawFd;
.map_err(|e| Error::from_syscall_error(e, "failed to open network:"))?
as RawFd;
trace!("opening :ip");
let ip_fd = syscall::open(":ip", O_RDWR | O_CREAT | O_NONBLOCK)
@@ -42,13 +42,13 @@ fn run() -> Result<()> {
trace!("opening :udp");
let udp_fd = syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK)
.map_err(|e| Error::from_syscall_error(e, "failed to open :udp"))? as
RawFd;
.map_err(|e| Error::from_syscall_error(e, "failed to open :udp"))?
as RawFd;
let time_path = format!("time:{}", syscall::CLOCK_MONOTONIC);
let time_fd = syscall::open(&time_path, syscall::O_RDWR)
.map_err(|e| Error::from_syscall_error(e, "failed to open time:"))? as
RawFd;
.map_err(|e| Error::from_syscall_error(e, "failed to open time:"))?
as RawFd;
let (network_file, ip_file, time_file, udp_file) = unsafe {
(
@@ -66,7 +66,7 @@ fn run() -> Result<()> {
let mut event_queue = EventQueue::<(), Error>::new()
.map_err(|e| Error::from_io_error(e, "failed to create event queue"))?;
let smolnetd_ = smolnetd.clone();
let smolnetd_ = Rc::clone(&smolnetd);
event_queue
.add(network_fd, move |_| {
@@ -76,13 +76,13 @@ fn run() -> Result<()> {
Error::from_io_error(e, "failed to listen to network events")
})?;
let smolnetd_ = smolnetd.clone();
let smolnetd_ = Rc::clone(&smolnetd);
event_queue
.add(ip_fd, move |_| smolnetd_.borrow_mut().on_ip_scheme_event())
.map_err(|e| Error::from_io_error(e, "failed to listen to ip events"))?;
let smolnetd_ = smolnetd.clone();
let smolnetd_ = Rc::clone(&smolnetd);
event_queue
.add(
+1 -1
View File
@@ -35,7 +35,7 @@ impl PortSet {
self.next = self.next.wrapping_add(1);
};
return Some(port);
Some(port)
}
pub fn claim_port(&mut self, port: u16) -> bool {
+3 -2
View File
@@ -47,7 +47,7 @@ impl IpScheme {
}
pub fn notify_sockets(&mut self) -> Result<()> {
for (&fd, ref handle) in &self.raw_sockets {
for (&fd, handle) in &self.raw_sockets {
let mut socket_set = self.socket_set.borrow_mut();
let socket: &mut RawSocket = socket_set.get_mut(handle.socket_handle).as_socket();
if socket.can_send() {
@@ -66,7 +66,8 @@ impl<'a> syscall::SchemeMut for IpScheme {
return Err(syscall::Error::new(syscall::EACCES));
}
let path = str::from_utf8(url).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?;
let proto = u8::from_str_radix(path, 16).or(Err(syscall::Error::new(syscall::ENOENT)))?;
let proto =
u8::from_str_radix(path, 16).or_else(|_| Err(syscall::Error::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);
+11 -13
View File
@@ -44,18 +44,17 @@ impl Smolnetd {
pub fn new(network_file: File, ip_file: File, udp_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(),
).expect("Can't parse the 'mac' cfg");
let local_ip = smoltcp::wire::IpAddress::from_str(&getcfg("ip").unwrap().trim())
let hardware_addr = smoltcp::wire::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).unwrap()];
let default_gw = smoltcp::wire::IpAddress::from_str(&getcfg("ip_router").unwrap().trim())
let default_gw = smoltcp::wire::IpAddress::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(network_file.clone(), input_queue.clone());
let network_device = NetworkDevice::new(Rc::clone(&network_file), Rc::clone(&input_queue));
let iface = smoltcp::iface::EthernetInterface::new(
Box::new(network_device),
Box::new(arp_cache) as Box<smoltcp::iface::ArpCache>,
@@ -66,11 +65,11 @@ impl Smolnetd {
let socket_set = Rc::new(RefCell::new(smoltcp::socket::SocketSet::new(vec![])));
Smolnetd {
iface,
socket_set: socket_set.clone(),
socket_set: Rc::clone(&socket_set),
startup_time: Instant::now(),
time_file,
ip_scheme: IpScheme::new(socket_set.clone(), ip_file),
udp_scheme: UdpScheme::new(socket_set.clone(), udp_file),
ip_scheme: IpScheme::new(Rc::clone(&socket_set), ip_file),
udp_scheme: UdpScheme::new(Rc::clone(&socket_set), udp_file),
input_queue,
network_file,
input_buffer_pool: BufferPool::new(Self::INGRESS_PACKET_SIZE),
@@ -97,10 +96,10 @@ impl Smolnetd {
if self.time_file.read(&mut time)? < mem::size_of::<syscall::data::TimeSpec>() {
panic!();
}
let mut time_ms = time.tv_sec * 1000i64 + (time.tv_nsec as i64) / 1_000_000i64;
let mut time_ms = time.tv_sec * 1000i64 + i64::from(time.tv_nsec) / 1_000_000i64;
time_ms += Smolnetd::CHECK_TIMEOUT_MS;
time.tv_sec = time_ms / 1000;
time.tv_nsec = ((time_ms % 1000) * 1_000_00) as i32;
time.tv_nsec = ((time_ms % 1000) * 1_000_000) as i32;
self.time_file
.write_all(&time)
.map_err(|e| Error::from_io_error(e, "Failed to write to time file"))?;
@@ -140,8 +139,7 @@ impl Smolnetd {
fn get_timestamp(&self) -> u64 {
let duration = Instant::now().duration_since(self.startup_time);
let duration_ms = (duration.as_secs() * 1000) + (duration.subsec_nanos() / 1000000) as u64;
duration_ms
(duration.as_secs() * 1000) + u64::from(duration.subsec_nanos() / 1_000_000)
}
fn network_fsync(&mut self) -> syscall::Result<usize> {
+166 -51
View File
@@ -5,7 +5,11 @@ use std::fs::File;
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::SchemeMut;
use syscall::data::TimeSpec;
use syscall;
use device::NetworkDevice;
@@ -14,6 +18,7 @@ use super::{Smolnetd, SocketSet};
use port_set::PortSet;
use super::post_fevent;
#[derive(Copy, Clone, Eq, PartialEq)]
enum Setting {
Ttl,
ReadTimeout,
@@ -24,19 +29,27 @@ struct UdpHandle {
flags: usize,
events: usize,
remote_endpoint: IpEndpoint,
read_timeout: Option<TimeSpec>,
write_timeout: Option<TimeSpec>,
socket_handle: SocketHandle,
}
struct SettingHandle {
fd: usize,
socket_handle: SocketHandle,
setting: Setting,
}
enum FdHandle {
Setting(SocketHandle, Setting),
Setting(SettingHandle),
Socket(UdpHandle),
}
impl FdHandle {
fn socket_handle(&self) -> SocketHandle {
match *self {
FdHandle::Socket(UdpHandle { socket_handle, .. }) => socket_handle,
FdHandle::Setting(socket_handle, _) => socket_handle,
FdHandle::Socket(UdpHandle { socket_handle, .. }) |
FdHandle::Setting(SettingHandle { socket_handle, .. }) => socket_handle,
}
}
}
@@ -56,7 +69,7 @@ impl UdpScheme {
udp_fds: BTreeMap::new(),
socket_set,
// 49152..65535 is the suggested range for dynamic private ports
port_set: PortSet::new(49152u16, 65535u16).expect("Wrong UDP port numbers"),
port_set: PortSet::new(49_152u16, 65_535u16).expect("Wrong UDP port numbers"),
udp_file,
}
}
@@ -75,7 +88,7 @@ impl UdpScheme {
pub fn notify_sockets(&mut self) -> Result<()> {
for (&fd, handle) in &self.udp_fds {
if let &FdHandle::Socket(UdpHandle { socket_handle, .. }) = handle {
if let FdHandle::Socket(UdpHandle { socket_handle, .. }) = *handle {
let mut socket_set = self.socket_set.borrow_mut();
let socket: &mut UdpSocket = socket_set.get_mut(socket_handle).as_socket();
if socket.can_send() {
@@ -85,6 +98,83 @@ impl UdpScheme {
}
Ok(())
}
fn get_setting(
&mut self,
fd: usize,
setting: Setting,
buf: &mut [u8],
) -> syscall::Result<usize> {
let handle = self.udp_fds
.get_mut(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
let handle = match *handle {
FdHandle::Socket(ref mut handle) => handle,
_ => {
return Err(syscall::Error::new(syscall::EBADF));
}
};
let timespec = match (setting, handle.read_timeout, handle.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)
}
}
fn update_setting(
&mut self,
fd: usize,
setting: Setting,
buf: &[u8],
) -> syscall::Result<usize> {
let handle = self.udp_fds
.get_mut(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
let handle = match *handle {
FdHandle::Socket(ref mut handle) => handle,
_ => {
return Err(syscall::Error::new(syscall::EBADF));
}
};
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 => {
handle.read_timeout = timeout;
}
Setting::WriteTimeout => {
handle.write_timeout = timeout;
}
_ => {}
};
return Ok(count);
}
Setting::Ttl => {}
}
Ok(0)
}
}
impl syscall::SchemeMut for UdpScheme {
@@ -93,7 +183,7 @@ impl syscall::SchemeMut for UdpScheme {
trace!("Udp open {} ", path);
let mut parts = path.split("/");
let mut parts = path.split('/');
let remote_endpoint = parse_endpoint(parts.next().unwrap_or(""));
let mut local_endpoint = parse_endpoint(parts.next().unwrap_or(""));
@@ -135,6 +225,8 @@ impl syscall::SchemeMut for UdpScheme {
flags,
events: 0,
socket_handle,
write_timeout: None,
read_timeout: None,
remote_endpoint: remote_endpoint,
}),
);
@@ -169,53 +261,60 @@ impl syscall::SchemeMut for UdpScheme {
fn write(&mut self, fd: usize, buf: &[u8]) -> syscall::Result<usize> {
trace!("Upd write {} len {}", fd, buf.len());
let handle = self.udp_fds
.get(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
match *handle {
FdHandle::Setting(_, _) => {
//TODO: udp settings
// pretend we've accepted
}
FdHandle::Socket(ref handle) => {
if !handle.remote_endpoint.is_specified() {
return Err(syscall::Error::new(syscall::EADDRNOTAVAIL));
let (fd, setting) = {
let handle = self.udp_fds
.get(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
match *handle {
FdHandle::Setting(ref setting_handle) => {
(setting_handle.fd, setting_handle.setting)
}
FdHandle::Socket(ref handle) => {
if !handle.remote_endpoint.is_specified() {
return Err(syscall::Error::new(syscall::EADDRNOTAVAIL));
}
let mut socket_set = self.socket_set.borrow_mut();
let socket: &mut UdpSocket =
socket_set.get_mut(handle.socket_handle).as_socket();
socket
.send_slice(buf, handle.remote_endpoint)
.expect("Can't send slice");
return Ok(buf.len());
}
let mut socket_set = self.socket_set.borrow_mut();
let socket: &mut UdpSocket = socket_set.get_mut(handle.socket_handle).as_socket();
socket
.send_slice(buf, handle.remote_endpoint)
.expect("Can't send slice");
}
}
Ok(buf.len())
};
self.update_setting(fd, setting, buf)
}
fn read(&mut self, fd: usize, buf: &mut [u8]) -> syscall::Result<usize> {
trace!("udp read {} {}", fd, buf.len());
let handle = self.udp_fds.get(&fd).ok_or_else(|| {
trace!("UDP read EBADF {}", fd);
syscall::Error::new(syscall::EBADF)
})?;
match *handle {
FdHandle::Setting(_, _) => {
//TODO: udp settings
Ok(buf.len())
}
FdHandle::Socket(ref handle) => {
let mut socket_set = self.socket_set.borrow_mut();
let socket: &mut UdpSocket = socket_set.get_mut(handle.socket_handle).as_socket();
if socket.can_recv() {
let (length, _) = socket.recv_slice(buf).expect("Can't receive slice");
trace!("Upd read {}", fd);
Ok(length)
} else if handle.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
Ok(0)
} else {
Err(syscall::Error::new(syscall::EWOULDBLOCK))
let (fd, setting) = {
let handle = self.udp_fds.get(&fd).ok_or_else(|| {
trace!("UDP read EBADF {}", fd);
syscall::Error::new(syscall::EBADF)
})?;
match *handle {
FdHandle::Setting(ref setting_handle) => {
(setting_handle.fd, setting_handle.setting)
}
FdHandle::Socket(ref handle) => {
let mut socket_set = self.socket_set.borrow_mut();
let socket: &mut UdpSocket =
socket_set.get_mut(handle.socket_handle).as_socket();
return if socket.can_recv() {
let (length, _) = socket.recv_slice(buf).expect("Can't receive slice");
trace!("Upd read {}", fd);
Ok(length)
} else if handle.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
Ok(0)
} else {
Err(syscall::Error::new(syscall::EWOULDBLOCK))
};
}
}
}
};
self.get_setting(fd, setting, buf)
}
fn dup(&mut self, fd: usize, buf: &[u8]) -> syscall::Result<usize> {
@@ -230,15 +329,29 @@ impl syscall::SchemeMut for UdpScheme {
let socket_handle = handle.socket_handle();
match path {
"ttl" => FdHandle::Setting(socket_handle, Setting::Ttl),
"read_timeout" => FdHandle::Setting(socket_handle, Setting::ReadTimeout),
"write_timeout" => FdHandle::Setting(socket_handle, Setting::WriteTimeout),
"ttl" => FdHandle::Setting(SettingHandle {
socket_handle,
fd,
setting: Setting::Ttl,
}),
"read_timeout" => FdHandle::Setting(SettingHandle {
socket_handle,
fd,
setting: Setting::ReadTimeout,
}),
"write_timeout" => FdHandle::Setting(SettingHandle {
socket_handle,
fd,
setting: Setting::WriteTimeout,
}),
_ => {
let remote_endpoint = parse_endpoint(path);
if let &mut FdHandle::Socket(ref udp_handle) = handle {
if let FdHandle::Socket(ref udp_handle) = *handle {
FdHandle::Socket(UdpHandle {
flags: udp_handle.flags,
events: udp_handle.events,
read_timeout: udp_handle.read_timeout,
write_timeout: udp_handle.write_timeout,
remote_endpoint: if remote_endpoint.is_specified() {
remote_endpoint
} else {
@@ -250,6 +363,8 @@ impl syscall::SchemeMut for UdpScheme {
FdHandle::Socket(UdpHandle {
flags: 0,
events: 0,
read_timeout: None,
write_timeout: None,
remote_endpoint: remote_endpoint,
socket_handle,
})
@@ -279,7 +394,7 @@ impl syscall::SchemeMut for UdpScheme {
.get_mut(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
match *handle {
FdHandle::Setting(_, _) => Err(syscall::Error::new(syscall::EBADF)),
FdHandle::Setting(_) => Err(syscall::Error::new(syscall::EBADF)),
FdHandle::Socket(ref mut handle) => {
handle.events = events;
Ok(fd)
@@ -301,7 +416,7 @@ impl syscall::SchemeMut for UdpScheme {
}
fn parse_endpoint(socket: &str) -> IpEndpoint {
let mut socket_parts = socket.split(":");
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)),