diff --git a/Cargo.toml b/Cargo.toml index 02e6c0d..67f6e07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 } diff --git a/examples/server.rs b/examples/server.rs index 356dbcd..488bdb5 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -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, sockets); + Box::new(arp_cache) as Box, []); + + 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() } diff --git a/src/iface/ethernet.rs b/src/iface/ethernet.rs index 7350f82..27909cf 100644 --- a/src/iface/ethernet.rs +++ b/src/iface/ethernet.rs @@ -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>, ProtocolAddrsMT: Into>, ArpCacheMT: Into>, - SocketsMT: Into>> { + SocketsMT: Into>>> { 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 } diff --git a/src/socket/mod.rs b/src/socket/mod.rs index 52485ba..88503aa 100644 --- a/src/socket/mod.rs +++ b/src/socket/mod.rs @@ -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. diff --git a/src/socket/set.rs b/src/socket/set.rs new file mode 100644 index 0000000..696e38c --- /dev/null +++ b/src/socket/set.rs @@ -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>> +} + +impl<'a, 'b: 'a, 'c: 'a + 'b> Set<'a, 'b, 'c> { + /// Create a socket set using the provided storage. + pub fn new(sockets: SocketsT) -> Set<'a, 'b, 'c> + where SocketsT: Into>>> { + 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>> +} + +impl<'a, 'b: 'a, 'c: 'a + 'b> Iterator for Iter<'a, 'b, 'c> { + type Item = &'a Socket<'b, 'c>; + + fn next(&mut self) -> Option { + 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>> +} + +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 { + while let Some(socket_opt) = self.lower.next() { + if let Some(socket) = socket_opt.as_mut() { + return Some(socket) + } + } + None + } +}