From 454dfd9a39c59f357f2de59a834781c94040748e Mon Sep 17 00:00:00 2001 From: Egor Karavaev Date: Wed, 4 Oct 2017 18:43:07 +0300 Subject: [PATCH 1/3] Support for tcp listen. --- src/smolnetd/buffer_pool.rs | 4 +- src/smolnetd/main.rs | 2 + src/smolnetd/scheme/ip.rs | 41 +++++--- src/smolnetd/scheme/mod.rs | 1 - src/smolnetd/scheme/socket.rs | 175 +++++++++++++++++++++------------- src/smolnetd/scheme/tcp.rs | 83 ++++++++++++---- src/smolnetd/scheme/udp.rs | 22 ++++- 7 files changed, 227 insertions(+), 101 deletions(-) diff --git a/src/smolnetd/buffer_pool.rs b/src/smolnetd/buffer_pool.rs index f3248c1958..c96baea781 100644 --- a/src/smolnetd/buffer_pool.rs +++ b/src/smolnetd/buffer_pool.rs @@ -68,9 +68,7 @@ impl BufferPool { pub fn get_buffer(&mut self) -> Buffer { let buffer = match self.stack.borrow_mut().pop() { - None => { - vec![0u8; self.buffers_size] - } + None => vec![0u8; self.buffers_size], Some(mut v) => { // memsetting the buffer with `resize` would be a waste of time let capacity = v.capacity(); diff --git a/src/smolnetd/main.rs b/src/smolnetd/main.rs index 2ac8cc8095..1f78c09590 100644 --- a/src/smolnetd/main.rs +++ b/src/smolnetd/main.rs @@ -1,3 +1,5 @@ +#![feature(drain_filter)] + extern crate event; #[macro_use] extern crate log; diff --git a/src/smolnetd/scheme/ip.rs b/src/smolnetd/scheme/ip.rs index 6c8c74a2c8..d48fd52f4f 100644 --- a/src/smolnetd/scheme/ip.rs +++ b/src/smolnetd/scheme/ip.rs @@ -161,19 +161,38 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> { socket_handle: SocketHandle, path: &str, _: &mut Self::SchemeDataT, - ) -> syscall::Result> { + ) -> syscall::Result> { match path { - "write_timeout" => Ok(SchemeFile::Setting(SettingFile { - socket_handle, - fd, - setting: Setting::WriteTimeout, - })), - "read_timeout" => Ok(SchemeFile::Setting(SettingFile { - socket_handle, - fd, - setting: Setting::ReadTimeout, - })), + "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)), } } + + fn fpath(&self, _file: &SchemeFile, buf: &mut [u8]) -> syscall::Result { + let path = format!("ip:{}", self.ip_protocol()); + let path = path.as_bytes(); + + let mut i = 0; + while i < buf.len() && i < path.len() { + buf[i] = path[i]; + i += 1; + } + + Ok(i) + } } diff --git a/src/smolnetd/scheme/mod.rs b/src/smolnetd/scheme/mod.rs index 5efed421ab..39f3977ac5 100644 --- a/src/smolnetd/scheme/mod.rs +++ b/src/smolnetd/scheme/mod.rs @@ -181,7 +181,6 @@ impl Smolnetd { if count == 0 { break; } - trace!("got frame {}", count); buffer.resize(count); self.input_queue.borrow_mut().push_back(buffer); total_frames += 1; diff --git a/src/smolnetd/scheme/socket.rs b/src/smolnetd/scheme/socket.rs index 9b26c1eb07..586e4501a0 100644 --- a/src/smolnetd/scheme/socket.rs +++ b/src/smolnetd/scheme/socket.rs @@ -29,7 +29,7 @@ impl SocketFile { read_timeout: self.read_timeout, write_timeout: self.write_timeout, socket_handle: self.socket_handle, - data + data, } } @@ -40,7 +40,7 @@ impl SocketFile { read_timeout: None, write_timeout: None, socket_handle, - data + data, } } } @@ -77,11 +77,11 @@ struct WaitHandle { packet: syscall::Packet, } -#[derive(Default)] -struct WaitQueues { - read_queue: Vec, - write_queue: Vec, -} +type WaitQueue = Vec; + +type WaitQueueMap = BTreeMap; + +pub type DupResult = (SchemeFile, Option<(Socket<'static, 'static>, T::DataT)>); pub trait SchemeSocket where @@ -109,6 +109,8 @@ where fn write_buf(&mut self, &mut SocketFile, buf: &[u8]) -> syscall::Result; fn read_buf(&mut self, &mut SocketFile, buf: &mut [u8]) -> syscall::Result; + fn fpath(&self, &SchemeFile, &mut [u8]) -> syscall::Result; + fn dup( &self, &mut SchemeFile, @@ -116,11 +118,9 @@ where SocketHandle, &str, &mut Self::SchemeDataT, - ) -> syscall::Result>; + ) -> syscall::Result>; } -type WaitQueueMap = BTreeMap; - pub struct SocketScheme where SocketT: SchemeSocket, @@ -206,35 +206,19 @@ where let socket_handles: Vec<_> = self.wait_queue_map.keys().cloned().collect(); for socket_handle in socket_handles { - let (can_recv, can_send) = { - let mut socket_set = self.socket_set.borrow_mut(); - let socket: &mut SocketT = socket_set.get_mut(socket_handle).as_socket(); - (socket.can_recv(), socket.can_send()) - }; - - if can_recv { - self.wake_up_wait_queue(socket_handle, cur_time, |wq| &mut wq.read_queue)?; - } - - if can_send { - self.wake_up_wait_queue(socket_handle, cur_time, |wq| &mut wq.write_queue)?; - } + self.wake_up_wait_queue(socket_handle, cur_time)?; } Ok(()) } - fn wake_up_wait_queue( + fn wake_up_wait_queue( &mut self, socket_handle: SocketHandle, cur_time: syscall::TimeSpec, - f: F, - ) -> Result<()> - where - F: Fn(&mut WaitQueues) -> &mut Vec, - { - let mut input_queue = if let Some(wait_queues) = self.wait_queue_map.get_mut(&socket_handle) + ) -> Result<()> { + let mut input_queue = if let Some(wait_queue) = self.wait_queue_map.get_mut(&socket_handle) { - ::std::mem::replace(f(wait_queues), vec![]) + ::std::mem::replace(wait_queue, vec![]) } else { vec![] }; @@ -247,11 +231,10 @@ where if packet.a == (-syscall::EWOULDBLOCK) as usize { match wait_handle.until { Some(until) - if (until.tv_sec >= cur_time.tv_sec + if (until.tv_sec < cur_time.tv_sec || (until.tv_sec == cur_time.tv_sec - && until.tv_nsec >= cur_time.tv_nsec)) => + && until.tv_nsec < cur_time.tv_nsec)) => { - trace!("Timeouting fd {}", packet.b); packet.a = (-syscall::ETIMEDOUT) as usize; self.scheme_file.write_all(&packet)?; } @@ -260,20 +243,41 @@ where } } } else { - trace!("Waking up fd {}", packet.b); + trace!("Waking up {} with {}", packet.b, packet.a); self.scheme_file.write_all(&packet)?; } } - if let Some(wait_queues) = self.wait_queue_map.get_mut(&socket_handle) { - f(wait_queues).extend(to_retain); + if let Some(wait_queue) = self.wait_queue_map.get_mut(&socket_handle) { + wait_queue.extend(to_retain); } Ok(()) } + fn move_handle_to_new_socket_handle( + wait_queue_map: &mut WaitQueueMap, + fd: usize, + from: SocketHandle, + to: SocketHandle, + ) -> syscall::Result<()> { + trace!("Moving {} from {:?} to {:?}", fd, from, to); + let mut to_move = vec![]; + + if let Some(wait_queue) = wait_queue_map.get_mut(&from) { + to_move = wait_queue + .drain_filter(|wh| wh.packet.b == fd) + .collect::>(); + } + + wait_queue_map + .entry(to) + .or_insert_with(|| vec![]) + .extend(to_move); + Ok(()) + } + fn handle_block(&mut self, mut packet: syscall::Packet) -> Result<()> { - trace!("Handling blocking call"); let syscall_result = self.try_handle_block(&mut packet); if let Err(syscall_error) = syscall_result { packet.a = (-syscall_error.errno) as usize; @@ -306,9 +310,9 @@ where }?; let mut timeout = match packet.a { - syscall::SYS_READ => Ok(read_timeout), syscall::SYS_WRITE => Ok(write_timeout), - _ => Err(syscall::Error::new(syscall::EBADF)), + syscall::SYS_READ => Ok(read_timeout), + _ => Ok(None), }?; if let Some(ref mut timeout) = timeout { @@ -317,18 +321,11 @@ where *timeout = add_time(timeout, &cur_time) } - trace!("Adding {} to wait queie", fd); - let wait_queues = self.wait_queue_map + let wait_queue = self.wait_queue_map .entry(socket_handle) - .or_insert_with(WaitQueues::default); + .or_insert_with(|| vec![]); - let queue = match packet.a { - syscall::SYS_READ => Ok(&mut wait_queues.read_queue), - syscall::SYS_WRITE => Ok(&mut wait_queues.write_queue), - _ => Err(syscall::Error::new(syscall::EBADF)), - }?; - - queue.push(WaitHandle { + wait_queue.push(WaitHandle { until: timeout, packet: *packet, }); @@ -381,6 +378,7 @@ where { fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> syscall::Result { let path = str::from_utf8(url).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?; + trace!("open {}", path); let (socket, data) = SocketT::new_socket(path, uid, &mut self.scheme_data)?; @@ -403,6 +401,7 @@ where } fn close(&mut self, fd: usize) -> syscall::Result { + trace!("close {}", fd); let socket_handle = { let handle = self.fds .get(&fd) @@ -416,20 +415,14 @@ where socket.close_file(&scheme_file, &mut self.scheme_data)?; } let remove_wq = - if let Some(ref mut wait_queues) = self.wait_queue_map.get_mut(&socket_handle) { - wait_queues.read_queue.retain( + if let Some(ref mut wait_queue) = self.wait_queue_map.get_mut(&socket_handle) { + wait_queue.retain( |&WaitHandle { packet: syscall::Packet { a, .. }, .. }| a != fd, ); - wait_queues.write_queue.retain( - |&WaitHandle { - packet: syscall::Packet { a, .. }, - .. - }| a != fd, - ); - wait_queues.read_queue.is_empty() && wait_queues.write_queue.is_empty() + wait_queue.is_empty() } else { false }; @@ -485,22 +478,42 @@ where fn dup(&mut self, fd: usize, buf: &[u8]) -> syscall::Result { let path = str::from_utf8(buf).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?; - let handle = { + let new_file = { let handle = self.fds .get_mut(&fd) .ok_or_else(|| syscall::Error::new(syscall::EBADF))?; let socket_handle = handle.socket_handle(); - let mut socket_set = self.socket_set.borrow_mut(); - let socket: &mut SocketT = socket_set.get_mut(handle.socket_handle()).as_socket(); - socket.dup(handle, fd, socket_handle, path, &mut self.scheme_data) - }?; + let (new_handle, update_with) = { + let mut socket_set = self.socket_set.borrow_mut(); + let socket: &mut SocketT = socket_set.get_mut(handle.socket_handle()).as_socket(); + socket.dup(handle, fd, socket_handle, path, &mut self.scheme_data)? + }; - self.socket_set.borrow_mut().retain(handle.socket_handle()); + if let Some((socket, data)) = update_with { + if let SchemeFile::Socket(ref mut handle) = *handle { + let socket_handle = self.socket_set.borrow_mut().add(socket); + trace!("Updating {} to a new socket handle {:?}", fd, socket_handle); + Self::move_handle_to_new_socket_handle( + &mut self.wait_queue_map, + fd, + handle.socket_handle, + socket_handle, + )?; + handle.socket_handle = socket_handle; + handle.data = data; + } else { + self.socket_set.borrow_mut().retain(handle.socket_handle()); + } + } else { + self.socket_set.borrow_mut().retain(handle.socket_handle()); + } + new_handle + }; let id = self.next_fd; - self.fds.insert(id, handle); + self.fds.insert(id, new_file); self.next_fd += 1; Ok(id) @@ -529,6 +542,36 @@ where // TODO Implement fsyncing // self.0.network_fsync() } + + fn fpath(&mut self, fd: usize, buf: &mut [u8]) -> syscall::Result { + let handle = self.fds + .get_mut(&fd) + .ok_or_else(|| syscall::Error::new(syscall::EBADF))?; + + let mut socket_set = self.socket_set.borrow_mut(); + let socket: &mut SocketT = socket_set.get_mut(handle.socket_handle()).as_socket(); + + socket.fpath(handle, buf) + } + + fn fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> syscall::Result { + let handle = self.fds + .get_mut(&fd) + .ok_or_else(|| syscall::Error::new(syscall::EBADF))?; + + if let SchemeFile::Socket(ref mut socket_file) = *handle { + 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)), + } + } else { + Err(syscall::Error::new(syscall::EBADF)) + } + } } fn add_time(a: &TimeSpec, b: &TimeSpec) -> TimeSpec { diff --git a/src/smolnetd/scheme/tcp.rs b/src/smolnetd/scheme/tcp.rs index 1a26e01f39..0889ac7de9 100644 --- a/src/smolnetd/scheme/tcp.rs +++ b/src/smolnetd/scheme/tcp.rs @@ -116,7 +116,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { let tx_packets = vec![0; 65_535]; let rx_buffer = TcpSocketBuffer::new(rx_packets); let tx_buffer = TcpSocketBuffer::new(tx_packets); - let mut tcp_socket = TcpSocket::new(rx_buffer, tx_buffer); + let mut socket = TcpSocket::new(rx_buffer, tx_buffer); if local_endpoint.port == 0 { local_endpoint.port = port_set @@ -127,14 +127,22 @@ impl<'a> SchemeSocket for TcpSocket<'a> { } { - let tcp_socket: &mut TcpSocket = tcp_socket.as_socket(); - trace!("Connecting tcp {} {}", local_endpoint, remote_endpoint); - tcp_socket - .connect(remote_endpoint, local_endpoint) - .expect("Can't connect tcp socket "); + let tcp_socket: &mut TcpSocket = socket.as_socket(); + + if remote_endpoint.is_specified() { + trace!("Connecting tcp {} {}", local_endpoint, remote_endpoint); + tcp_socket + .connect(remote_endpoint, local_endpoint) + .expect("Can't connect tcp socket "); + } else { + trace!("Listening tcp {}", local_endpoint); + tcp_socket + .listen(local_endpoint) + .expect("Can't listen on local endpoint"); + } } - Ok((tcp_socket, ())) + Ok((socket, ())) } fn close_file( @@ -153,10 +161,9 @@ impl<'a> SchemeSocket for TcpSocket<'a> { file: &mut SocketFile, buf: &[u8], ) -> syscall::Result { - if !self.is_open() { - return Err(syscall::Error::new(syscall::EADDRNOTAVAIL)); - } - if self.can_send() { + if !self.is_active() { + Err(syscall::Error::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 { @@ -171,7 +178,9 @@ impl<'a> SchemeSocket for TcpSocket<'a> { file: &mut SocketFile, buf: &mut [u8], ) -> syscall::Result { - if self.can_recv() { + if !self.is_active() { + Err(syscall::Error::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 { @@ -188,8 +197,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { socket_handle: SocketHandle, path: &str, port_set: &mut Self::SchemeDataT, - ) -> syscall::Result> { - trace!("TCP dup {}", path); + ) -> syscall::Result> { let handle = match path { "ttl" => SchemeFile::Setting(SettingFile { socket_handle, @@ -206,18 +214,57 @@ impl<'a> SchemeSocket for TcpSocket<'a> { fd, setting: Setting::WriteTimeout, }), - _ => if let SchemeFile::Socket(ref tcp_handle) = *file { - SchemeFile::Socket(tcp_handle.clone_with_data(())) + "listen" => if let SchemeFile::Socket(ref tcp_handle) = *file { + if !self.is_active() { + return Err(syscall::Error::new(syscall::EWOULDBLOCK)); + } + trace!("TCP creating new listening socket"); + let new_handle = SchemeFile::Socket(tcp_handle.clone_with_data(())); + + let rx_packets = vec![0; 65_535]; + let tx_packets = vec![0; 65_535]; + let rx_buffer = TcpSocketBuffer::new(rx_packets); + let tx_buffer = TcpSocketBuffer::new(tx_packets); + let mut socket = TcpSocket::new(rx_buffer, tx_buffer); + { + let tcp_socket: &mut TcpSocket = socket.as_socket(); + tcp_socket + .listen(self.local_endpoint()) + .expect("Can't listen on local endpoint"); + } + port_set.acquire_port(self.local_endpoint().port); + return Ok((new_handle, Some((socket, ())))); } else { - SchemeFile::Socket(SocketFile::new_with_data(socket_handle, ())) + return Err(syscall::Error::new(syscall::EBADF)); }, + _ => { + trace!("TCP dup unknown {}", path); + if let SchemeFile::Socket(ref tcp_handle) = *file { + SchemeFile::Socket(tcp_handle.clone_with_data(())) + } else { + SchemeFile::Socket(SocketFile::new_with_data(socket_handle, ())) + } + } }; if let SchemeFile::Socket(_) = handle { port_set.acquire_port(self.local_endpoint().port); } - Ok(handle) + Ok((handle, None)) + } + + fn fpath(&self, _: &SchemeFile, buf: &mut [u8]) -> syscall::Result { + let path = format!("tcp:{}/{}", self.remote_endpoint(), self.local_endpoint()); + let path = path.as_bytes(); + + let mut i = 0; + while i < buf.len() && i < path.len() { + buf[i] = path[i]; + i += 1; + } + + Ok(i) } } diff --git a/src/smolnetd/scheme/udp.rs b/src/smolnetd/scheme/udp.rs index 030d53c495..93203e4bca 100644 --- a/src/smolnetd/scheme/udp.rs +++ b/src/smolnetd/scheme/udp.rs @@ -82,6 +82,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { (Some(timespec), count) } }; + trace!("Setting {:?} to {:?}", setting, timeout); match setting { Setting::ReadTimeout => { file.read_timeout = timeout; @@ -190,7 +191,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { socket_handle: SocketHandle, path: &str, port_set: &mut Self::SchemeDataT, - ) -> syscall::Result> { + ) -> syscall::Result> { let handle = match path { "ttl" => SchemeFile::Setting(SettingFile { socket_handle, @@ -227,7 +228,24 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { port_set.acquire_port(self.endpoint().port); } - Ok(handle) + Ok((handle, None)) + } + + fn fpath(&self, file: &SchemeFile, buf: &mut [u8]) -> syscall::Result { + if let &SchemeFile::Socket(ref socket_file) = file { + let path = format!("udp:{}/{}", socket_file.data, self.endpoint()); + let path = path.as_bytes(); + + let mut i = 0; + while i < buf.len() && i < path.len() { + buf[i] = path[i]; + i += 1; + } + + Ok(i) + } else { + Err(syscall::Error::new(syscall::EBADF)) + } } } From 0584743789b459b77a33dad238a2bb092cc94d8b Mon Sep 17 00:00:00 2001 From: Egor Karavaev Date: Sat, 7 Oct 2017 00:18:10 +0300 Subject: [PATCH 2/3] Updating upstream smoltcp. --- Cargo.lock | 4 +-- src/smolnetd/scheme/ip.rs | 16 ++++++---- src/smolnetd/scheme/socket.rs | 59 ++++++++++++++++++---------------- src/smolnetd/scheme/tcp.rs | 60 ++++++++++++++++++++--------------- src/smolnetd/scheme/udp.rs | 33 +++++++++++-------- 5 files changed, 98 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87c44fa9ff..bc0ed2071e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,7 +191,7 @@ dependencies = [ [[package]] name = "netutils" version = "0.1.0" -source = "git+https://github.com/redox-os/netutils.git#ec1a835a9d4a95a8e41c4e994a540d298d897cd4" +source = "git+https://github.com/redox-os/netutils.git#29b8efd41d8c56b33c619db78e5b019934dbb7a3" dependencies = [ "arg_parser 0.1.0 (git+https://github.com/redox-os/arg-parser.git)", "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", @@ -328,7 +328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smoltcp" version = "0.4.0" -source = "git+https://github.com/m-labs/smoltcp.git#b0fc1d9542ef3b8e7add3b90dcf2d6f1fc4c633e" +source = "git+https://github.com/m-labs/smoltcp.git#096ce02ac4c935c4df485a79107fb26b5897065d" dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/smolnetd/scheme/ip.rs b/src/smolnetd/scheme/ip.rs index d48fd52f4f..4edb53b5f9 100644 --- a/src/smolnetd/scheme/ip.rs +++ b/src/smolnetd/scheme/ip.rs @@ -1,7 +1,8 @@ use super::socket::*; -use smoltcp::socket::{RawPacketBuffer, RawSocket, RawSocketBuffer, Socket, SocketHandle}; +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; @@ -93,10 +94,11 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> { } fn new_socket( + socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, path: &str, uid: u32, _: &mut Self::SchemeDataT, - ) -> syscall::Result<(Socket<'static, 'static>, Self::DataT)> { + ) -> syscall::Result<(SocketHandle, Self::DataT)> { if uid != 0 { return Err(syscall::Error::new(syscall::EACCES)); } @@ -117,7 +119,9 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> { rx_buffer, tx_buffer, ); - Ok((ip_socket, ())) + + let socket_handle = socket_set.add(ip_socket); + Ok((socket_handle, ())) } fn close_file(&self, _: &SchemeFile, _: &mut Self::SchemeDataT) -> syscall::Result<()> { @@ -155,10 +159,10 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> { } fn dup( - &self, - _: &mut SchemeFile, - fd: usize, + _socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, socket_handle: SocketHandle, + _file: &mut SchemeFile, + fd: usize, path: &str, _: &mut Self::SchemeDataT, ) -> syscall::Result> { diff --git a/src/smolnetd/scheme/socket.rs b/src/smolnetd/scheme/socket.rs index 586e4501a0..7d5b3ec05e 100644 --- a/src/smolnetd/scheme/socket.rs +++ b/src/smolnetd/scheme/socket.rs @@ -1,4 +1,5 @@ -use smoltcp::socket::{AsSocket, Socket, SocketHandle}; +use smoltcp::socket::{AnySocket, SocketHandle}; +use smoltcp; use std::collections::BTreeMap; use std::fs::File; use std::io::{Read, Write}; @@ -81,7 +82,7 @@ type WaitQueue = Vec; type WaitQueueMap = BTreeMap; -pub type DupResult = (SchemeFile, Option<(Socket<'static, 'static>, T::DataT)>); +pub type DupResult = (SchemeFile, Option<(SocketHandle, T::DataT)>); pub trait SchemeSocket where @@ -100,10 +101,11 @@ where fn set_setting(&mut SocketFile, Self::SettingT, &[u8]) -> syscall::Result; fn new_socket( + &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, &str, u32, &mut Self::SchemeDataT, - ) -> syscall::Result<(Socket<'static, 'static>, Self::DataT)>; + ) -> syscall::Result<(SocketHandle, Self::DataT)>; fn close_file(&self, &SchemeFile, &mut Self::SchemeDataT) -> syscall::Result<()>; fn write_buf(&mut self, &mut SocketFile, buf: &[u8]) -> syscall::Result; @@ -112,10 +114,10 @@ where fn fpath(&self, &SchemeFile, &mut [u8]) -> syscall::Result; fn dup( - &self, + &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, + SocketHandle, &mut SchemeFile, usize, - SocketHandle, &str, &mut Self::SchemeDataT, ) -> syscall::Result>; @@ -123,8 +125,7 @@ where pub struct SocketScheme where - SocketT: SchemeSocket, - Socket<'static, 'static>: AsSocket, + SocketT: SchemeSocket + AnySocket<'static, 'static>, { next_fd: usize, fds: BTreeMap>, @@ -137,8 +138,7 @@ where impl SocketScheme where - SocketT: SchemeSocket, - Socket<'static, 'static>: AsSocket, + SocketT: SchemeSocket + AnySocket<'static, 'static>, { pub fn new(socket_set: SocketSet, scheme_file: File) -> SocketScheme { SocketScheme { @@ -180,7 +180,7 @@ where }) = *handle { let mut socket_set = self.socket_set.borrow_mut(); - let socket: &mut SocketT = socket_set.get_mut(socket_handle).as_socket(); + let socket = socket_set.get::(socket_handle); if events & syscall::EVENT_READ == syscall::EVENT_READ && socket.can_recv() { post_fevent(&mut self.scheme_file, fd, syscall::EVENT_READ, 1)?; @@ -373,16 +373,19 @@ where impl syscall::SchemeMut for SocketScheme where - SocketT: SchemeSocket, - Socket<'static, 'static>: AsSocket, + SocketT: SchemeSocket + AnySocket<'static, 'static>, { fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> syscall::Result { let path = str::from_utf8(url).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?; trace!("open {}", path); - let (socket, data) = SocketT::new_socket(path, uid, &mut self.scheme_data)?; + let (socket_handle, data) = SocketT::new_socket( + &mut self.socket_set.borrow_mut(), + path, + uid, + &mut self.scheme_data, + )?; - let socket_handle = self.socket_set.borrow_mut().add(socket); let id = self.next_fd; self.fds.insert( @@ -411,7 +414,7 @@ where let scheme_file = self.fds.remove(&fd); let mut socket_set = self.socket_set.borrow_mut(); if let Some(scheme_file) = scheme_file { - let socket: &mut SocketT = socket_set.get_mut(socket_handle).as_socket(); + let socket = socket_set.get::(socket_handle); socket.close_file(&scheme_file, &mut self.scheme_data)?; } let remove_wq = @@ -447,9 +450,9 @@ where } SchemeFile::Socket(ref mut handle) => { let mut socket_set = self.socket_set.borrow_mut(); - let socket: &mut SocketT = socket_set.get_mut(handle.socket_handle).as_socket(); + let mut socket = socket_set.get::(handle.socket_handle); - return ::write_buf(socket, handle, buf); + return ::write_buf(&mut socket, handle, buf); } } }; @@ -467,8 +470,8 @@ where } SchemeFile::Socket(ref mut handle) => { let mut socket_set = self.socket_set.borrow_mut(); - let socket: &mut SocketT = socket_set.get_mut(handle.socket_handle).as_socket(); - return ::read_buf(socket, handle, buf); + let mut socket = socket_set.get::(handle.socket_handle); + return ::read_buf(&mut socket, handle, buf); } } }; @@ -485,15 +488,17 @@ where let socket_handle = handle.socket_handle(); - let (new_handle, update_with) = { - let mut socket_set = self.socket_set.borrow_mut(); - let socket: &mut SocketT = socket_set.get_mut(handle.socket_handle()).as_socket(); - socket.dup(handle, fd, socket_handle, path, &mut self.scheme_data)? - }; + let (new_handle, update_with) = SocketT::dup( + &mut self.socket_set.borrow_mut(), + socket_handle, + handle, + fd, + path, + &mut self.scheme_data, + )?; - if let Some((socket, data)) = update_with { + if let Some((socket_handle, data)) = update_with { if let SchemeFile::Socket(ref mut handle) = *handle { - let socket_handle = self.socket_set.borrow_mut().add(socket); trace!("Updating {} to a new socket handle {:?}", fd, socket_handle); Self::move_handle_to_new_socket_handle( &mut self.wait_queue_map, @@ -549,7 +554,7 @@ where .ok_or_else(|| syscall::Error::new(syscall::EBADF))?; let mut socket_set = self.socket_set.borrow_mut(); - let socket: &mut SocketT = socket_set.get_mut(handle.socket_handle()).as_socket(); + let socket = socket_set.get::(handle.socket_handle()); socket.fpath(handle, buf) } diff --git a/src/smolnetd/scheme/tcp.rs b/src/smolnetd/scheme/tcp.rs index 0889ac7de9..46e6de4173 100644 --- a/src/smolnetd/scheme/tcp.rs +++ b/src/smolnetd/scheme/tcp.rs @@ -1,7 +1,8 @@ use super::socket::*; -use smoltcp::socket::{AsSocket, Socket, SocketHandle, TcpSocket, TcpSocketBuffer}; +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; @@ -99,10 +100,11 @@ impl<'a> SchemeSocket for TcpSocket<'a> { } fn new_socket( + socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, path: &str, uid: u32, port_set: &mut Self::SchemeDataT, - ) -> syscall::Result<(Socket<'static, 'static>, Self::DataT)> { + ) -> syscall::Result<(SocketHandle, Self::DataT)> { trace!("TCP open {}", path); let mut parts = path.split('/'); let remote_endpoint = parse_endpoint(parts.next().unwrap_or("")); @@ -116,7 +118,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { let tx_packets = vec![0; 65_535]; let rx_buffer = TcpSocketBuffer::new(rx_packets); let tx_buffer = TcpSocketBuffer::new(tx_packets); - let mut socket = TcpSocket::new(rx_buffer, tx_buffer); + let socket = TcpSocket::new(rx_buffer, tx_buffer); if local_endpoint.port == 0 { local_endpoint.port = port_set @@ -126,23 +128,23 @@ impl<'a> SchemeSocket for TcpSocket<'a> { return Err(syscall::Error::new(syscall::EADDRINUSE)); } - { - let tcp_socket: &mut TcpSocket = socket.as_socket(); + let socket_handle = socket_set.add(socket); - if remote_endpoint.is_specified() { - trace!("Connecting tcp {} {}", local_endpoint, remote_endpoint); - tcp_socket - .connect(remote_endpoint, local_endpoint) - .expect("Can't connect tcp socket "); - } else { - trace!("Listening tcp {}", local_endpoint); - tcp_socket - .listen(local_endpoint) - .expect("Can't listen on local endpoint"); - } + let mut tcp_socket = socket_set.get::(socket_handle); + + if remote_endpoint.is_specified() { + trace!("Connecting tcp {} {}", local_endpoint, remote_endpoint); + tcp_socket + .connect(remote_endpoint, local_endpoint) + .expect("Can't connect tcp socket "); + } else { + trace!("Listening tcp {}", local_endpoint); + tcp_socket + .listen(local_endpoint) + .expect("Can't listen on local endpoint"); } - Ok((socket, ())) + Ok((socket_handle, ())) } fn close_file( @@ -191,13 +193,18 @@ impl<'a> SchemeSocket for TcpSocket<'a> { } fn dup( - &self, + socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, + socket_handle: SocketHandle, file: &mut SchemeFile, fd: usize, - socket_handle: SocketHandle, path: &str, port_set: &mut Self::SchemeDataT, ) -> syscall::Result> { + let (is_active, local_endpoint) = { + let socket = socket_set.get::(socket_handle); + (socket.is_active(), socket.local_endpoint()) + }; + let handle = match path { "ttl" => SchemeFile::Setting(SettingFile { socket_handle, @@ -215,7 +222,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { setting: Setting::WriteTimeout, }), "listen" => if let SchemeFile::Socket(ref tcp_handle) = *file { - if !self.is_active() { + if !is_active { return Err(syscall::Error::new(syscall::EWOULDBLOCK)); } trace!("TCP creating new listening socket"); @@ -225,15 +232,16 @@ impl<'a> SchemeSocket for TcpSocket<'a> { let tx_packets = vec![0; 65_535]; let rx_buffer = TcpSocketBuffer::new(rx_packets); let tx_buffer = TcpSocketBuffer::new(tx_packets); - let mut socket = TcpSocket::new(rx_buffer, tx_buffer); + let socket = TcpSocket::new(rx_buffer, tx_buffer); + let new_socket_handle = socket_set.add(socket); { - let tcp_socket: &mut TcpSocket = socket.as_socket(); + let mut tcp_socket = socket_set.get::(new_socket_handle); tcp_socket - .listen(self.local_endpoint()) + .listen(local_endpoint) .expect("Can't listen on local endpoint"); } - port_set.acquire_port(self.local_endpoint().port); - return Ok((new_handle, Some((socket, ())))); + port_set.acquire_port(local_endpoint.port); + return Ok((new_handle, Some((new_socket_handle, ())))); } else { return Err(syscall::Error::new(syscall::EBADF)); }, @@ -248,7 +256,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> { }; if let SchemeFile::Socket(_) = handle { - port_set.acquire_port(self.local_endpoint().port); + port_set.acquire_port(local_endpoint.port); } Ok((handle, None)) diff --git a/src/smolnetd/scheme/udp.rs b/src/smolnetd/scheme/udp.rs index 93203e4bca..9641984b7d 100644 --- a/src/smolnetd/scheme/udp.rs +++ b/src/smolnetd/scheme/udp.rs @@ -1,7 +1,8 @@ use super::socket::*; -use smoltcp::socket::{AsSocket, Socket, SocketHandle, UdpPacketBuffer, UdpSocket, UdpSocketBuffer}; +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 std::str; @@ -100,10 +101,11 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { } fn new_socket( + socket_set: &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, path: &str, uid: u32, port_set: &mut Self::SchemeDataT, - ) -> syscall::Result<(Socket<'static, 'static>, Self::DataT)> { + ) -> syscall::Result<(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("")); @@ -120,7 +122,7 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { } let rx_buffer = UdpSocketBuffer::new(rx_packets); let tx_buffer = UdpSocketBuffer::new(tx_packets); - let mut udp_socket = UdpSocket::new(rx_buffer, tx_buffer); + let udp_socket = UdpSocket::new(rx_buffer, tx_buffer); if local_endpoint.port == 0 { local_endpoint.port = port_set @@ -130,14 +132,14 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { return Err(syscall::Error::new(syscall::EADDRINUSE)); } - { - let udp_socket: &mut UdpSocket = udp_socket.as_socket(); - udp_socket - .bind(local_endpoint) - .expect("Can't bind udp socket to local endpoint"); - } + let socket_handle = socket_set.add(udp_socket); - Ok((udp_socket, remote_endpoint)) + let mut udp_socket = socket_set.get::(socket_handle); + udp_socket + .bind(local_endpoint) + .expect("Can't bind udp socket to local endpoint"); + + Ok((socket_handle, remote_endpoint)) } fn close_file( @@ -185,10 +187,10 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { } fn dup( - &self, + socket_set: &mut smoltcp::socket::SocketSet, + socket_handle: SocketHandle, file: &mut SchemeFile, fd: usize, - socket_handle: SocketHandle, path: &str, port_set: &mut Self::SchemeDataT, ) -> syscall::Result> { @@ -224,8 +226,13 @@ impl<'a, 'b> SchemeSocket for UdpSocket<'a, 'b> { } }; + let endpoint = { + let socket = socket_set.get::(socket_handle); + socket.endpoint() + }; + if let SchemeFile::Socket(_) = handle { - port_set.acquire_port(self.endpoint().port); + port_set.acquire_port(endpoint.port); } Ok((handle, None)) From ecd3848de9a7f191556419869dc4fc7838c3de79 Mon Sep 17 00:00:00 2001 From: Egor Karavaev Date: Sat, 7 Oct 2017 01:29:36 +0300 Subject: [PATCH 3/3] Code cleanup. --- src/smolnetd/main.rs | 2 +- src/smolnetd/scheme/ip.rs | 126 +++---------- src/smolnetd/scheme/mod.rs | 65 ++++--- src/smolnetd/scheme/socket.rs | 336 +++++++++++++++++++++------------- src/smolnetd/scheme/tcp.rs | 157 ++++------------ src/smolnetd/scheme/udp.rs | 155 ++++------------ 6 files changed, 346 insertions(+), 495 deletions(-) diff --git a/src/smolnetd/main.rs b/src/smolnetd/main.rs index 1f78c09590..60cf1df69d 100644 --- a/src/smolnetd/main.rs +++ b/src/smolnetd/main.rs @@ -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::*; diff --git a/src/smolnetd/scheme/ip.rs b/src/smolnetd/scheme/ip.rs index 4edb53b5f9..be014679a4 100644 --- a/src/smolnetd/scheme/ip.rs +++ b/src/smolnetd/scheme/ip.rs @@ -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>; -#[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, - setting: Self::SettingT, - buf: &mut [u8], - ) -> syscall::Result { - 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::() { - 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, + _setting: Self::SettingT, + _buf: &mut [u8], + ) -> SyscallResult { + Ok(0) } fn set_setting( - file: &mut SocketFile, - setting: Self::SettingT, - buf: &[u8], - ) -> syscall::Result { - match setting { - Setting::ReadTimeout | Setting::WriteTimeout => { - let (timeout, count) = { - if buf.len() < mem::size_of::() { - (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, + _setting: Self::SettingT, + _buf: &[u8], + ) -> SyscallResult { + 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, _: &mut Self::SchemeDataT) -> syscall::Result<()> { + fn close_file(&self, _: &SchemeFile, _: &mut Self::SchemeDataT) -> SyscallResult<()> { Ok(()) } @@ -132,14 +82,14 @@ impl<'a, 'b> SchemeSocket for RawSocket<'a, 'b> { &mut self, file: &mut SocketFile, buf: &[u8], - ) -> syscall::Result { + ) -> SyscallResult { 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, buf: &mut [u8], - ) -> syscall::Result { + ) -> SyscallResult { 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, - fd: usize, - path: &str, + _path: &str, _: &mut Self::SchemeDataT, - ) -> syscall::Result> { - 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> { + Err(SyscallError::new(syscall::EBADF)) } - fn fpath(&self, _file: &SchemeFile, buf: &mut [u8]) -> syscall::Result { + fn fpath(&self, _file: &SchemeFile, buf: &mut [u8]) -> SyscallResult { let path = format!("ip:{}", self.ip_protocol()); let path = path.as_bytes(); diff --git a/src/smolnetd/scheme/mod.rs b/src/smolnetd/scheme/mod.rs index 39f3977ac5..a65296521b 100644 --- a/src/smolnetd/scheme/mod.rs +++ b/src/smolnetd/scheme/mod.rs @@ -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>>; +type SocketSet = SmoltcpSocketSet<'static, 'static, 'static>; pub struct Smolnetd { network_file: Rc>, time_file: File, - iface: smoltcp::iface::EthernetInterface<'static, 'static, 'static, NetworkDevice>, - socket_set: SocketSet, + iface: EthernetInterface<'static, 'static, 'static, NetworkDevice>, + socket_set: Rc>, 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, + Box::new(arp_cache) as Box, 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> { self.ip_scheme.on_scheme_event()?; - self.poll()?; + let _ = self.poll()?; Ok(None) } pub fn on_udp_scheme_event(&mut self) -> Result> { self.udp_scheme.on_scheme_event()?; - self.poll()?; + let _ = self.poll()?; Ok(None) } pub fn on_tcp_scheme_event(&mut self) -> Result> { self.tcp_scheme.on_scheme_event()?; - self.poll()?; + let _ = self.poll()?; Ok(None) } pub fn on_time_event(&mut self) -> Result> { 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::() { + fn schedule_time_event(&mut self, timeout: i64) -> Result<()> { + let mut time = TimeSpec::default(); + if self.time_file.read(&mut time)? < size_of::() { 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::() + .unwrap_or(0); + IpEndpoint::new(host, port) +} diff --git a/src/smolnetd/scheme/socket.rs b/src/smolnetd/scheme/socket.rs index 7d5b3ec05e..b36af6e1d7 100644 --- a/src/smolnetd/scheme/socket.rs +++ b/src/smolnetd/scheme/socket.rs @@ -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 { pub flags: usize, + pub data: DataT, + events: usize, socket_handle: SocketHandle, - pub data: DataT, - pub read_timeout: Option, - pub write_timeout: Option, + read_timeout: Option, + write_timeout: Option, } impl SocketFile { @@ -46,10 +50,18 @@ impl SocketFile { } } -pub struct SettingFile { - pub fd: usize, - pub socket_handle: SocketHandle, - pub setting: SettingT, +#[derive(Copy, Clone)] +enum Setting { + Ttl, + ReadTimeout, + WriteTimeout, + #[allow(dead_code)] Other(SettingT), +} + +pub struct SettingFile { + fd: usize, + socket_handle: SocketHandle, + setting: Setting, } pub enum SchemeFile @@ -64,7 +76,7 @@ impl SchemeFile 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, - packet: syscall::Packet, + packet: SyscallPacket, } type WaitQueue = Vec; type WaitQueueMap = BTreeMap; -pub type DupResult = (SchemeFile, Option<(SocketHandle, T::DataT)>); +pub type DupResult = ( + SchemeFile, + Option<(SocketHandle, ::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::SettingT, &mut [u8]) -> syscall::Result; - fn set_setting(&mut SocketFile, Self::SettingT, &[u8]) -> syscall::Result; + fn get_setting(&SocketFile, Self::SettingT, &mut [u8]) -> SyscallResult; + fn set_setting(&mut SocketFile, Self::SettingT, &[u8]) -> SyscallResult; 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, &mut Self::SchemeDataT) -> syscall::Result<()>; + ) -> SyscallResult<(SocketHandle, Self::DataT)>; - fn write_buf(&mut self, &mut SocketFile, buf: &[u8]) -> syscall::Result; - fn read_buf(&mut self, &mut SocketFile, buf: &mut [u8]) -> syscall::Result; + fn close_file(&self, &SchemeFile, &mut Self::SchemeDataT) -> SyscallResult<()>; - fn fpath(&self, &SchemeFile, &mut [u8]) -> syscall::Result; + fn write_buf(&mut self, &mut SocketFile, buf: &[u8]) -> SyscallResult; + + fn read_buf(&mut self, &mut SocketFile, buf: &mut [u8]) -> SyscallResult; + + fn fpath(&self, &SchemeFile, &mut [u8]) -> SyscallResult; fn dup( - &mut smoltcp::socket::SocketSet<'static, 'static, 'static>, - SocketHandle, + &mut SocketSet, &mut SchemeFile, - usize, &str, &mut Self::SchemeDataT, - ) -> syscall::Result>; + ) -> SyscallResult>; } pub struct SocketScheme @@ -128,8 +143,8 @@ where SocketT: SchemeSocket + AnySocket<'static, 'static>, { next_fd: usize, - fds: BTreeMap>, - socket_set: SocketSet, + files: BTreeMap>, + socket_set: Rc>, scheme_file: File, wait_queue_map: WaitQueueMap, scheme_data: SocketT::SchemeDataT, @@ -140,10 +155,10 @@ impl SocketScheme where SocketT: SchemeSocket + AnySocket<'static, 'static>, { - pub fn new(socket_set: SocketSet, scheme_file: File) -> SocketScheme { + pub fn new(socket_set: Rc>, scheme_file: File) -> SocketScheme { 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> { 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::(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, buf: &mut [u8], - ) -> syscall::Result { - let handle = self.fds + ) -> SyscallResult { + 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::() { + 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, buf: &[u8], - ) -> syscall::Result { - let handle = self.fds + ) -> SyscallResult { + 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::() { + (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 syscall::SchemeMut for SocketScheme where SocketT: SchemeSocket + AnySocket<'static, 'static>, { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> syscall::Result { - 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 { + 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 { - trace!("close {}", fd); + fn close(&mut self, fd: usize) -> SyscallResult { 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::(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 { + fn write(&mut self, fd: usize, buf: &[u8]) -> SyscallResult { 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::(handle.socket_handle); - - return ::write_buf(&mut socket, handle, buf); + let mut socket = socket_set.get::(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 { + fn read(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult { 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::(handle.socket_handle); - return ::read_buf(&mut socket, handle, buf); + let mut socket = socket_set.get::(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 { - let path = str::from_utf8(buf).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?; + fn dup(&mut self, fd: usize, buf: &[u8]) -> SyscallResult { + 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 { - let handle = self.fds + fn fevent(&mut self, fd: usize, events: usize) -> SyscallResult { + 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 { + fn fsync(&mut self, fd: usize) -> SyscallResult { { - 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 { - let handle = self.fds + fn fpath(&mut self, fd: usize, buf: &mut [u8]) -> SyscallResult { + 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::(handle.socket_handle()); + let socket = socket_set.get::(file.socket_handle()); - socket.fpath(handle, buf) + socket.fpath(file, buf) } - fn fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> syscall::Result { - let handle = self.fds + fn fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> SyscallResult { + 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)) } } } diff --git a/src/smolnetd/scheme/tcp.rs b/src/smolnetd/scheme/tcp.rs index 46e6de4173..1ce10f3020 100644 --- a/src/smolnetd/scheme/tcp.rs +++ b/src/smolnetd/scheme/tcp.rs @@ -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>; -#[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, - setting: Self::SettingT, - buf: &mut [u8], - ) -> syscall::Result { - 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::() { - 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, + _setting: Self::SettingT, + _buf: &mut [u8], + ) -> SyscallResult { + Ok(0) } fn set_setting( - file: &mut SocketFile, - setting: Self::SettingT, - buf: &[u8], - ) -> syscall::Result { - trace!("TCP set setting {:?}", setting); - match setting { - Setting::ReadTimeout | Setting::WriteTimeout => { - let (timeout, count) = { - if buf.len() < mem::size_of::() { - (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, + _setting: Self::SettingT, + _buf: &[u8], + ) -> SyscallResult { 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, 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, buf: &[u8], - ) -> syscall::Result { + ) -> SyscallResult { 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, buf: &mut [u8], - ) -> syscall::Result { + ) -> SyscallResult { 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, - fd: usize, path: &str, port_set: &mut Self::SchemeDataT, - ) -> syscall::Result> { + ) -> SyscallResult> { + let socket_handle = file.socket_handle(); + let (is_active, local_endpoint) = { let socket = socket_set.get::(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, buf: &mut [u8]) -> syscall::Result { + fn fpath(&self, _: &SchemeFile, buf: &mut [u8]) -> SyscallResult { 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::() - .unwrap_or(0); - IpEndpoint::new(host, port) -} diff --git a/src/smolnetd/scheme/udp.rs b/src/smolnetd/scheme/udp.rs index 9641984b7d..87f65b9bdb 100644 --- a/src/smolnetd/scheme/udp.rs +++ b/src/smolnetd/scheme/udp.rs @@ -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>; -#[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, - setting: Self::SettingT, - buf: &mut [u8], - ) -> syscall::Result { - 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::() { - 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, + _setting: Self::SettingT, + _buf: &mut [u8], + ) -> SyscallResult { + Ok(0) } fn set_setting( - file: &mut SocketFile, - setting: Self::SettingT, - buf: &[u8], - ) -> syscall::Result { - match setting { - Setting::ReadTimeout | Setting::WriteTimeout => { - let (timeout, count) = { - if buf.len() < mem::size_of::() { - (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, + _setting: Self::SettingT, + _buf: &[u8], + ) -> SyscallResult { 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, 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, buf: &[u8], - ) -> syscall::Result { + ) -> SyscallResult { 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, buf: &mut [u8], - ) -> syscall::Result { + ) -> SyscallResult { 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, - fd: usize, path: &str, port_set: &mut Self::SchemeDataT, - ) -> syscall::Result> { - 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> { + 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, buf: &mut [u8]) -> syscall::Result { - if let &SchemeFile::Socket(ref socket_file) = file { + fn fpath(&self, file: &SchemeFile, buf: &mut [u8]) -> SyscallResult { + 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::() - .unwrap_or(0); - IpEndpoint::new(host, port) -}