Implement socket sets.
This commit is contained in:
parent
83bb8c6ae8
commit
234e5ef29e
|
@ -12,7 +12,7 @@ license = "0BSD"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = { version = "1.0", default-features = false }
|
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 }
|
log = { version = "0.3", default-features = false, optional = true }
|
||||||
libc = { version = "0.2.18", optional = true }
|
libc = { version = "0.2.18", optional = true }
|
||||||
|
|
||||||
|
|
|
@ -84,16 +84,19 @@ fn main() {
|
||||||
|
|
||||||
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
|
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
|
||||||
let protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
|
let protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
|
||||||
let sockets = vec![udp_socket, tcp1_socket, tcp2_socket];
|
|
||||||
let mut iface = EthernetInterface::new(
|
let mut iface = EthernetInterface::new(
|
||||||
Box::new(device), hardware_addr, protocol_addrs,
|
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;
|
let mut tcp_6969_connected = false;
|
||||||
loop {
|
loop {
|
||||||
// udp:6969: respond "yo dawg"
|
// 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() {
|
let client = match socket.recv() {
|
||||||
Ok((endpoint, data)) => {
|
Ok((endpoint, data)) => {
|
||||||
debug!("udp:6969 recv data: {:?} from {}",
|
debug!("udp:6969 recv data: {:?} from {}",
|
||||||
|
@ -118,7 +121,7 @@ fn main() {
|
||||||
|
|
||||||
// tcp:6969: respond "yo dawg"
|
// 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() {
|
if !socket.is_open() {
|
||||||
socket.listen(6969).unwrap();
|
socket.listen(6969).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -135,7 +138,7 @@ fn main() {
|
||||||
|
|
||||||
// tcp:6970: echo with reverse
|
// 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() {
|
if !socket.is_open() {
|
||||||
socket.listen(6970).unwrap()
|
socket.listen(6970).unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use wire::{Ipv4Packet, Ipv4Repr};
|
||||||
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
|
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
|
||||||
use wire::{IpAddress, IpProtocol, IpRepr};
|
use wire::{IpAddress, IpProtocol, IpRepr};
|
||||||
use wire::{TcpPacket, TcpRepr, TcpControl};
|
use wire::{TcpPacket, TcpRepr, TcpControl};
|
||||||
use socket::Socket;
|
use socket::{Socket, SocketSet};
|
||||||
use super::{ArpCache};
|
use super::{ArpCache};
|
||||||
|
|
||||||
/// An Ethernet network interface.
|
/// 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,
|
hardware_addr: EthernetAddress,
|
||||||
protocol_addrs: ManagedSlice<'b, IpAddress>,
|
protocol_addrs: ManagedSlice<'b, IpAddress>,
|
||||||
arp_cache: Managed<'c, ArpCache>,
|
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>
|
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>>,
|
where DeviceMT: Into<Managed<'a, DeviceT>>,
|
||||||
ProtocolAddrsMT: Into<ManagedSlice<'b, IpAddress>>,
|
ProtocolAddrsMT: Into<ManagedSlice<'b, IpAddress>>,
|
||||||
ArpCacheMT: Into<Managed<'c, ArpCache>>,
|
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 device = device.into();
|
||||||
let protocol_addrs = protocol_addrs.into();
|
let protocol_addrs = protocol_addrs.into();
|
||||||
let arp_cache = arp_cache.into();
|
let arp_cache = arp_cache.into();
|
||||||
let sockets = sockets.into();
|
let sockets = SocketSet::new(sockets);
|
||||||
|
|
||||||
Self::check_hardware_addr(&hardware_addr);
|
Self::check_hardware_addr(&hardware_addr);
|
||||||
Self::check_protocol_addrs(&protocol_addrs);
|
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.
|
/// 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
|
&mut self.sockets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ use wire::IpRepr;
|
||||||
|
|
||||||
mod udp;
|
mod udp;
|
||||||
mod tcp;
|
mod tcp;
|
||||||
|
mod set;
|
||||||
|
|
||||||
pub use self::udp::PacketBuffer as UdpPacketBuffer;
|
pub use self::udp::PacketBuffer as UdpPacketBuffer;
|
||||||
pub use self::udp::SocketBuffer as UdpSocketBuffer;
|
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::State as TcpState;
|
||||||
pub use self::tcp::TcpSocket;
|
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.
|
/// A network socket.
|
||||||
///
|
///
|
||||||
/// This enumeration abstracts the various types of sockets based on the IP protocol.
|
/// This enumeration abstracts the various types of sockets based on the IP protocol.
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue