Initial support for UDP options.
This commit is contained in:
+93
-39
@@ -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))?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user