Implement socket sets.

This commit is contained in:
whitequark 2017-01-11 04:05:41 +00:00
parent 83bb8c6ae8
commit 234e5ef29e
5 changed files with 153 additions and 11 deletions

View File

@ -12,7 +12,7 @@ license = "0BSD"
[dependencies]
byteorder = { version = "1.0", default-features = false }
managed = { version = "0.2", default-features = false }
managed = { version = "0.2.1", default-features = false }
log = { version = "0.3", default-features = false, optional = true }
libc = { version = "0.2.18", optional = true }

View File

@ -84,16 +84,19 @@ fn main() {
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
let protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
let sockets = vec![udp_socket, tcp1_socket, tcp2_socket];
let mut iface = EthernetInterface::new(
Box::new(device), hardware_addr, protocol_addrs,
Box::new(arp_cache) as Box<ArpCache>, sockets);
Box::new(arp_cache) as Box<ArpCache>, []);
let udp_handle = iface.sockets_mut().add(udp_socket);
let tcp1_handle = iface.sockets_mut().add(tcp1_socket);
let tcp2_handle = iface.sockets_mut().add(tcp2_socket);
let mut tcp_6969_connected = false;
loop {
// udp:6969: respond "yo dawg"
{
let socket: &mut UdpSocket = iface.sockets()[0].as_socket();
let socket: &mut UdpSocket = iface.sockets_mut().get_mut(&udp_handle).as_socket();
let client = match socket.recv() {
Ok((endpoint, data)) => {
debug!("udp:6969 recv data: {:?} from {}",
@ -118,7 +121,7 @@ fn main() {
// tcp:6969: respond "yo dawg"
{
let socket: &mut TcpSocket = iface.sockets()[1].as_socket();
let socket: &mut TcpSocket = iface.sockets_mut().get_mut(&tcp1_handle).as_socket();
if !socket.is_open() {
socket.listen(6969).unwrap();
}
@ -135,7 +138,7 @@ fn main() {
// tcp:6970: echo with reverse
{
let socket: &mut TcpSocket = iface.sockets()[2].as_socket();
let socket: &mut TcpSocket = iface.sockets_mut().get_mut(&tcp2_handle).as_socket();
if !socket.is_open() {
socket.listen(6970).unwrap()
}

View File

@ -8,7 +8,7 @@ use wire::{Ipv4Packet, Ipv4Repr};
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
use wire::{IpAddress, IpProtocol, IpRepr};
use wire::{TcpPacket, TcpRepr, TcpControl};
use socket::Socket;
use socket::{Socket, SocketSet};
use super::{ArpCache};
/// An Ethernet network interface.
@ -21,7 +21,7 @@ pub struct Interface<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
hardware_addr: EthernetAddress,
protocol_addrs: ManagedSlice<'b, IpAddress>,
arp_cache: Managed<'c, ArpCache>,
sockets: ManagedSlice<'d, Socket<'e, 'f>>
sockets: SocketSet<'d, 'e, 'f>
}
impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
@ -39,11 +39,11 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
where DeviceMT: Into<Managed<'a, DeviceT>>,
ProtocolAddrsMT: Into<ManagedSlice<'b, IpAddress>>,
ArpCacheMT: Into<Managed<'c, ArpCache>>,
SocketsMT: Into<ManagedSlice<'d, Socket<'e, 'f>>> {
SocketsMT: Into<ManagedSlice<'d, Option<Socket<'e, 'f>>>> {
let device = device.into();
let protocol_addrs = protocol_addrs.into();
let arp_cache = arp_cache.into();
let sockets = sockets.into();
let sockets = SocketSet::new(sockets);
Self::check_hardware_addr(&hardware_addr);
Self::check_protocol_addrs(&protocol_addrs);
@ -105,7 +105,12 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
}
/// Get the set of sockets owned by the interface.
pub fn sockets(&mut self) -> &mut ManagedSlice<'d, Socket<'e, 'f>> {
pub fn sockets(&self) -> &SocketSet<'d, 'e, 'f> {
&self.sockets
}
/// Get the set of sockets owned by the interface, as mutable.
pub fn sockets_mut(&mut self) -> &mut SocketSet<'d, 'e, 'f> {
&mut self.sockets
}

View File

@ -15,6 +15,7 @@ use wire::IpRepr;
mod udp;
mod tcp;
mod set;
pub use self::udp::PacketBuffer as UdpPacketBuffer;
pub use self::udp::SocketBuffer as UdpSocketBuffer;
@ -24,6 +25,9 @@ pub use self::tcp::SocketBuffer as TcpSocketBuffer;
pub use self::tcp::State as TcpState;
pub use self::tcp::TcpSocket;
pub use self::set::{Set as SocketSet, Handle as SocketHandle};
pub use self::set::{Iter as SocketSetIter, IterMut as SocketSetIterMut};
/// A network socket.
///
/// This enumeration abstracts the various types of sockets based on the IP protocol.

130
src/socket/set.rs Normal file
View File

@ -0,0 +1,130 @@
use managed::ManagedSlice;
use core::slice;
use super::Socket;
/// A handle, identifying a socket in a set.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Handle {
index: usize
}
/// An extensible set of sockets, with stable numeric identifiers.
pub struct Set<'a, 'b: 'a, 'c: 'a + 'b> {
sockets: ManagedSlice<'a, Option<Socket<'b, 'c>>>
}
impl<'a, 'b: 'a, 'c: 'a + 'b> Set<'a, 'b, 'c> {
/// Create a socket set using the provided storage.
pub fn new<SocketsT>(sockets: SocketsT) -> Set<'a, 'b, 'c>
where SocketsT: Into<ManagedSlice<'a, Option<Socket<'b, 'c>>>> {
let sockets = sockets.into();
Set {
sockets: sockets
}
}
/// Add a socket to the set, and return its handle.
///
/// # Panics
/// This function panics if the storage is fixed-size (not a `Vec`) and is full.
pub fn add(&mut self, socket: Socket<'b, 'c>) -> Handle {
for (index, slot) in self.sockets.iter_mut().enumerate() {
if slot.is_none() {
*slot = Some(socket);
return Handle { index: index }
}
}
match self.sockets {
ManagedSlice::Borrowed(_) => {
panic!("adding a socket to a full SocketSet")
}
ManagedSlice::Owned(ref mut sockets) => {
sockets.push(Some(socket));
Handle { index: sockets.len() - 1 }
}
}
}
/// Get a socket from the set by its handle.
///
/// # Panics
/// This function may panic if the handle does not belong to this socket set.
pub fn get(&self, handle: &Handle) -> &Socket<'b, 'c> {
self.sockets[handle.index]
.as_ref()
.expect("handle does not contain a valid socket index")
}
/// Get a socket from the set by its handle, as mutable.
///
/// # Panics
/// This function may panic if the handle does not belong to this socket set.
pub fn get_mut(&mut self, handle: &Handle) -> &mut Socket<'b, 'c> {
self.sockets[handle.index]
.as_mut()
.expect("handle does not contain a valid socket index")
}
/// Remove a socket from the set, without changing its state.
///
/// # Panics
/// This function may panic if the handle does not belong to this socket set.
pub fn remove(&mut self, handle: Handle) {
assert!(self.sockets[handle.index].is_some());
self.sockets[handle.index] = None
}
/// Iterate every socket in this set.
pub fn iter<'d>(&'d self) -> Iter<'d, 'b, 'c> {
Iter { lower: self.sockets.iter() }
}
/// Iterate every socket in this set, as mutable.
pub fn iter_mut<'d>(&'d mut self) -> IterMut<'d, 'b, 'c> {
IterMut { lower: self.sockets.iter_mut() }
}
}
/// Immutable socket set iterator.
///
/// This struct is created by the [iter](struct.SocketSet.html#method.iter)
/// on [socket sets](struct.SocketSet.html).
pub struct Iter<'a, 'b: 'a, 'c: 'a + 'b> {
lower: slice::Iter<'a, Option<Socket<'b, 'c>>>
}
impl<'a, 'b: 'a, 'c: 'a + 'b> Iterator for Iter<'a, 'b, 'c> {
type Item = &'a Socket<'b, 'c>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(socket_opt) = self.lower.next() {
if let Some(socket) = socket_opt.as_ref() {
return Some(socket)
}
}
None
}
}
/// Mutable socket set iterator.
///
/// This struct is created by the [iter_mut](struct.SocketSet.html#method.iter_mut)
/// on [socket sets](struct.SocketSet.html).
pub struct IterMut<'a, 'b: 'a, 'c: 'a + 'b> {
lower: slice::IterMut<'a, Option<Socket<'b, 'c>>>
}
impl<'a, 'b: 'a, 'c: 'a + 'b> Iterator for IterMut<'a, 'b, 'c> {
type Item = &'a mut Socket<'b, 'c>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(socket_opt) = self.lower.next() {
if let Some(socket) = socket_opt.as_mut() {
return Some(socket)
}
}
None
}
}