Initial support for UDP options.

This commit is contained in:
Egor Karavaev
2017-09-20 00:23:22 +03:00
parent 05650efcb1
commit a15184ce1f
2 changed files with 130 additions and 85 deletions
+93 -39
View File
@@ -2,22 +2,43 @@ use netutils::Ipv4Addr;
use smoltcp::socket::{AsSocket, SocketHandle, UdpPacketBuffer, UdpSocket, UdpSocketBuffer};
use smoltcp::wire::{IpAddress, IpEndpoint, Ipv4Address};
use std::collections::BTreeMap;
use std::str;
use syscall;
use device::NetworkDevice;
use error::Result;
use super::{Smolnetd, SocketSet};
pub struct UdpHandle {
enum Setting {
Ttl,
ReadTimeout,
WriteTimeout,
}
struct UdpHandle {
flags: usize,
events: usize,
remote_endpoint: IpEndpoint,
pub socket_handle: SocketHandle,
socket_handle: SocketHandle,
}
enum FdHandle {
Setting(SocketHandle, Setting),
Socket(UdpHandle),
}
impl FdHandle {
fn socket_handle(&self) -> SocketHandle {
match *self {
FdHandle::Socket(UdpHandle { socket_handle, .. }) => socket_handle,
FdHandle::Setting(socket_handle, _) => socket_handle,
}
}
}
pub struct UdpScheme {
next_udp_fd: usize,
udp_sockets: BTreeMap<usize, UdpHandle>,
udp_fds: BTreeMap<usize, FdHandle>,
socket_set: SocketSet,
}
@@ -25,17 +46,19 @@ impl UdpScheme {
pub fn new(socket_set: SocketSet) -> UdpScheme {
UdpScheme {
next_udp_fd: 1,
udp_sockets: BTreeMap::new(),
udp_fds: BTreeMap::new(),
socket_set,
}
}
pub fn notify_ready_sockets<F: FnMut(usize) -> Result<()>>(&self, mut f: F) -> Result<()> {
for (&fd, ref handle) in &self.udp_sockets {
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_send() {
f(fd)?
for (&fd, handle) in &self.udp_fds {
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() {
f(fd)?
}
}
}
Ok(())
@@ -44,8 +67,6 @@ impl UdpScheme {
impl syscall::SchemeMut for UdpScheme {
fn open(&mut self, url: &[u8], flags: usize, _uid: u32, _gid: u32) -> syscall::Result<usize> {
use std::str;
let path = str::from_utf8(url).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?;
trace!("Udp open {} ", path);
let mut parts = path.split("/");
@@ -75,9 +96,9 @@ impl syscall::SchemeMut for UdpScheme {
let socket_handle = self.socket_set.borrow_mut().add(udp_socket);
let id = self.next_udp_fd;
self.udp_sockets.insert(
self.udp_fds.insert(
id,
UdpHandle {
FdHandle::Socket(UdpHandle {
flags,
events: 0,
socket_handle,
@@ -85,7 +106,7 @@ impl syscall::SchemeMut for UdpScheme {
IpAddress::Ipv4(Ipv4Address::from_bytes(&remote_ip.bytes)),
remote_port,
),
},
}),
);
self.next_udp_fd += 1;
trace!("Udp open fd {} ", id);
@@ -95,61 +116,94 @@ impl syscall::SchemeMut for UdpScheme {
fn close(&mut self, fd: usize) -> syscall::Result<usize> {
trace!("Upd close {}", fd);
let socket_handle = {
let handle = self.udp_sockets
let handle = self.udp_fds
.get(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
handle.socket_handle
handle.socket_handle()
};
self.udp_sockets.remove(&fd);
self.socket_set.borrow_mut().remove(socket_handle);
self.udp_fds.remove(&fd);
let mut socket_set = self.socket_set.borrow_mut();
socket_set.release(socket_handle);
//TODO: removing sockets in release should make prune unnecessary
socket_set.prune();
Ok(0)
}
fn write(&mut self, fd: usize, buf: &[u8]) -> syscall::Result<usize> {
trace!("Upd write {} len {}", fd, buf.len());
let handle = self.udp_sockets
let handle = self.udp_fds
.get(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
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");
match *handle {
FdHandle::Setting(_, _) => {
//TODO: udp settings
// pretend we've accepted
}
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();
socket
.send_slice(buf, handle.remote_endpoint)
.expect("Can't send slice");
}
}
Ok(buf.len())
}
fn read(&mut self, fd: usize, buf: &mut [u8]) -> syscall::Result<usize> {
let handle = self.udp_sockets.get(&fd).ok_or_else(|| {
let handle = self.udp_fds.get(&fd).ok_or_else(|| {
trace!("UDP read EBADF {}", fd);
syscall::Error::new(syscall::EBADF)
})?;
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))
match *handle {
FdHandle::Setting(_, _) => {
//TODO: udp settings
Ok(0)
}
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))
}
}
}
}
fn dup(&mut self, fd: usize, buf: &[u8]) -> syscall::Result<usize> {
let handle = self.udp_fds
.get_mut(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
let path = str::from_utf8(buf).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?;
trace!("udp dup {} {}", fd, path);
Ok(0)
}
fn fevent(&mut self, fd: usize, events: usize) -> syscall::Result<usize> {
trace!("udp fevent {}", fd);
let handle = self.udp_sockets
let handle = self.udp_fds
.get_mut(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
handle.events = events;
Ok(fd)
match *handle {
FdHandle::Setting(_, _) => Err(syscall::Error::new(syscall::EBADF)),
FdHandle::Socket(ref mut handle) => {
handle.events = events;
Ok(fd)
}
}
}
fn fsync(&mut self, fd: usize) -> syscall::Result<usize> {
trace!("udp fsync {}", fd);
{
let _handle = self.udp_sockets
let _handle = self.udp_fds
.get_mut(&fd)
.ok_or_else(|| syscall::Error::new(syscall::EBADF))?;
}