Make interfaces not own the sockets.

v0.7.x
whitequark 2017-01-11 05:25:54 +00:00
parent 83b70b12af
commit 362c954624
4 changed files with 35 additions and 49 deletions

View File

@ -15,7 +15,7 @@ use smoltcp::phy::{Tracer, FaultInjector, TapInterface};
use smoltcp::wire::{EthernetFrame, EthernetAddress, IpAddress};
use smoltcp::wire::PrettyPrinter;
use smoltcp::iface::{ArpCache, SliceArpCache, EthernetInterface};
use smoltcp::socket::AsSocket;
use smoltcp::socket::{AsSocket, SocketSet};
use smoltcp::socket::{UdpSocket, UdpSocketBuffer, UdpPacketBuffer};
use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
@ -83,18 +83,19 @@ fn main() {
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
let protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
let mut iface = EthernetInterface::new(
Box::new(device), hardware_addr, protocol_addrs,
Box::new(arp_cache) as Box<ArpCache>, []);
Box::new(device), Box::new(arp_cache) as Box<ArpCache>,
hardware_addr, protocol_addrs);
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 sockets = SocketSet::new(vec![]);
let udp_handle = sockets.add(udp_socket);
let tcp1_handle = sockets.add(tcp1_socket);
let tcp2_handle = sockets.add(tcp2_socket);
let mut tcp_6969_connected = false;
loop {
// udp:6969: respond "yo dawg"
{
let socket: &mut UdpSocket = iface.sockets_mut().get_mut(&udp_handle).as_socket();
let socket: &mut UdpSocket = sockets.get_mut(&udp_handle).as_socket();
if socket.endpoint().is_unspecified() {
socket.bind(6969)
}
@ -123,7 +124,7 @@ fn main() {
// tcp:6969: respond "yo dawg"
{
let socket: &mut TcpSocket = iface.sockets_mut().get_mut(&tcp1_handle).as_socket();
let socket: &mut TcpSocket = sockets.get_mut(&tcp1_handle).as_socket();
if !socket.is_open() {
socket.listen(6969).unwrap();
}
@ -140,7 +141,7 @@ fn main() {
// tcp:6970: echo with reverse
{
let socket: &mut TcpSocket = iface.sockets_mut().get_mut(&tcp2_handle).as_socket();
let socket: &mut TcpSocket = sockets.get_mut(&tcp2_handle).as_socket();
if !socket.is_open() {
socket.listen(6970).unwrap()
}
@ -178,7 +179,7 @@ fn main() {
let timestamp = Instant::now().duration_since(startup_time);
let timestamp_ms = (timestamp.as_secs() * 1000) +
(timestamp.subsec_nanos() / 1000000) as u64;
match iface.poll(timestamp_ms) {
match iface.poll(&mut sockets, timestamp_ms) {
Ok(()) => (),
Err(e) => debug!("poll error: {}", e)
}

View File

@ -8,42 +8,37 @@ use wire::{Ipv4Packet, Ipv4Repr};
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
use wire::{IpAddress, IpProtocol, IpRepr};
use wire::{TcpPacket, TcpRepr, TcpControl};
use socket::{Socket, SocketSet};
use super::{ArpCache};
use socket::SocketSet;
use super::ArpCache;
/// An Ethernet network interface.
///
/// The network interface logically owns a number of other data structures; to avoid
/// a dependency on heap allocation, it instead owns a `BorrowMut<[T]>`, which can be
/// a `&mut [T]`, or `Vec<T>` if a heap is available.
pub struct Interface<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a> {
pub struct Interface<'a, 'b, 'c, DeviceT: Device + 'a> {
device: Managed<'a, DeviceT>,
arp_cache: Managed<'b, ArpCache>,
hardware_addr: EthernetAddress,
protocol_addrs: ManagedSlice<'b, IpAddress>,
arp_cache: Managed<'c, ArpCache>,
sockets: SocketSet<'d, 'e, 'f>
protocol_addrs: ManagedSlice<'c, IpAddress>,
}
impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
Interface<'a, 'b, 'c, 'd, 'e, 'f, DeviceT> {
impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
/// Create a network interface using the provided network device.
///
/// # Panics
/// See the restrictions on [set_hardware_addr](#method.set_hardware_addr)
/// and [set_protocol_addrs](#method.set_protocol_addrs) functions.
pub fn new<DeviceMT, ProtocolAddrsMT, ArpCacheMT, SocketsMT>
(device: DeviceMT,
hardware_addr: EthernetAddress, protocol_addrs: ProtocolAddrsMT,
arp_cache: ArpCacheMT, sockets: SocketsMT) ->
Interface<'a, 'b, 'c, 'd, 'e, 'f, DeviceT>
pub fn new<DeviceMT, ArpCacheMT, ProtocolAddrsMT>
(device: DeviceMT, arp_cache: ArpCacheMT,
hardware_addr: EthernetAddress, protocol_addrs: ProtocolAddrsMT) ->
Interface<'a, 'b, 'c, DeviceT>
where DeviceMT: Into<Managed<'a, DeviceT>>,
ProtocolAddrsMT: Into<ManagedSlice<'b, IpAddress>>,
ArpCacheMT: Into<Managed<'c, ArpCache>>,
SocketsMT: Into<ManagedSlice<'d, Option<Socket<'e, 'f>>>> {
ArpCacheMT: Into<Managed<'b, ArpCache>>,
ProtocolAddrsMT: Into<ManagedSlice<'c, IpAddress>>, {
let device = device.into();
let protocol_addrs = protocol_addrs.into();
let arp_cache = arp_cache.into();
let sockets = SocketSet::new(sockets);
let protocol_addrs = protocol_addrs.into();
Self::check_hardware_addr(&hardware_addr);
Self::check_protocol_addrs(&protocol_addrs);
@ -52,7 +47,6 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
arp_cache: arp_cache,
hardware_addr: hardware_addr,
protocol_addrs: protocol_addrs,
sockets: sockets
}
}
@ -93,7 +87,7 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
///
/// # Panics
/// This function panics if any of the addresses is not unicast.
pub fn update_protocol_addrs<F: FnOnce(&mut ManagedSlice<'b, IpAddress>)>(&mut self, f: F) {
pub fn update_protocol_addrs<F: FnOnce(&mut ManagedSlice<'c, IpAddress>)>(&mut self, f: F) {
f(&mut self.protocol_addrs);
Self::check_protocol_addrs(&self.protocol_addrs)
}
@ -104,20 +98,11 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
self.protocol_addrs.iter().any(|&probe| probe == addr)
}
/// Get the set of sockets owned by the interface.
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
}
/// Receive and process a packet, if available, and then transmit a packet, if necessary.
/// Receive and process a packet, if available, and then transmit a packet, if necessary,
/// handling the given set of sockets.
///
/// The timestamp is a monotonically increasing number of milliseconds.
pub fn poll(&mut self, timestamp: u64) -> Result<(), Error> {
pub fn poll(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<(), Error> {
enum Response<'a> {
Nop,
Arp(ArpRepr),
@ -127,7 +112,7 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
// First, transmit any outgoing packets.
loop {
if try!(self.emit(timestamp)) { break }
if try!(self.emit(sockets, timestamp)) { break }
}
// Now, receive any incoming packets.
@ -217,7 +202,7 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
// Try dispatching a packet to a socket.
Ipv4Repr { src_addr, dst_addr, protocol } => {
let mut handled = false;
for socket in self.sockets.iter_mut() {
for socket in sockets.iter_mut() {
let ip_repr = IpRepr::Ipv4(ipv4_repr);
match socket.process(timestamp, &ip_repr, ipv4_packet.payload()) {
Ok(()) => {
@ -360,7 +345,7 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
}
}
fn emit(&mut self, timestamp: u64) -> Result<bool, Error> {
fn emit(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool, Error> {
// Borrow checker is being overly careful around closures, so we have
// to hack around that.
let src_hardware_addr = self.hardware_addr;
@ -369,7 +354,7 @@ impl<'a, 'b, 'c, 'd, 'e: 'd, 'f: 'e + 'd, DeviceT: Device + 'a>
let device = &mut self.device;
let mut nothing_to_transmit = true;
for socket in self.sockets.iter_mut() {
for socket in sockets.iter_mut() {
let result = socket.dispatch(timestamp, &mut |repr, payload| {
let repr = try!(repr.lower(src_protocol_addrs));

View File

@ -27,7 +27,7 @@
//! Ethernet interface is provided.
//!
//! The interface layer handles the control messages, physical addressing and neighbor discovery.
//! It owns the sockets and routes packets to and from them.
//! It routes packets to and from sockets.
//!
//! # The physical layer
//! The physical layer APIs are provided in the module [phy](phy/index.html); currently,

View File

@ -113,8 +113,8 @@ pub struct UdpSocket<'a, 'b: 'a> {
impl<'a, 'b> UdpSocket<'a, 'b> {
/// Create an UDP socket with the given buffers.
pub fn new(rx_buffer: SocketBuffer<'a, 'b>, tx_buffer: SocketBuffer<'a, 'b>)
-> Socket<'a, 'b> {
pub fn new(rx_buffer: SocketBuffer<'a, 'b>,
tx_buffer: SocketBuffer<'a, 'b>) -> Socket<'a, 'b> {
Socket::Udp(UdpSocket {
endpoint: IpEndpoint::default(),
rx_buffer: rx_buffer,