smoltcp/iface/
socket_meta.rs

1use super::SocketHandle;
2use crate::{
3    socket::PollAt,
4    time::{Duration, Instant},
5    wire::IpAddress,
6};
7
8/// Neighbor dependency.
9///
10/// This enum tracks whether the socket should be polled based on the neighbor
11/// it is going to send packets to.
12#[derive(Debug, Default)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14enum NeighborState {
15    /// Socket can be polled immediately.
16    #[default]
17    Active,
18    /// Socket should not be polled until either `silent_until` passes or
19    /// `neighbor` appears in the neighbor cache.
20    Waiting {
21        neighbor: IpAddress,
22        silent_until: Instant,
23    },
24}
25
26/// Network socket metadata.
27///
28/// This includes things that only external (to the socket, that is) code
29/// is interested in, but which are more conveniently stored inside the socket
30/// itself.
31#[derive(Debug, Default)]
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33pub(crate) struct Meta {
34    /// Handle of this socket within its enclosing `SocketSet`.
35    /// Mainly useful for debug output.
36    pub(crate) handle: SocketHandle,
37    /// See [NeighborState](struct.NeighborState.html).
38    neighbor_state: NeighborState,
39}
40
41impl Meta {
42    /// Minimum delay between neighbor discovery requests for this particular
43    /// socket, in milliseconds.
44    ///
45    /// See also `iface::NeighborCache::SILENT_TIME`.
46    pub(crate) const DISCOVERY_SILENT_TIME: Duration = Duration::from_millis(1_000);
47
48    pub(crate) fn poll_at<F>(&self, socket_poll_at: PollAt, has_neighbor: F) -> PollAt
49    where
50        F: Fn(IpAddress) -> bool,
51    {
52        match self.neighbor_state {
53            NeighborState::Active => socket_poll_at,
54            NeighborState::Waiting { neighbor, .. } if has_neighbor(neighbor) => socket_poll_at,
55            NeighborState::Waiting { silent_until, .. } => PollAt::Time(silent_until),
56        }
57    }
58
59    pub(crate) fn egress_permitted<F>(&mut self, timestamp: Instant, has_neighbor: F) -> bool
60    where
61        F: Fn(IpAddress) -> bool,
62    {
63        match self.neighbor_state {
64            NeighborState::Active => true,
65            NeighborState::Waiting {
66                neighbor,
67                silent_until,
68            } => {
69                if has_neighbor(neighbor) {
70                    net_trace!(
71                        "{}: neighbor {} discovered, unsilencing",
72                        self.handle,
73                        neighbor
74                    );
75                    self.neighbor_state = NeighborState::Active;
76                    true
77                } else if timestamp >= silent_until {
78                    net_trace!(
79                        "{}: neighbor {} silence timer expired, rediscovering",
80                        self.handle,
81                        neighbor
82                    );
83                    true
84                } else {
85                    false
86                }
87            }
88        }
89    }
90
91    pub(crate) fn neighbor_missing(&mut self, timestamp: Instant, neighbor: IpAddress) {
92        net_trace!(
93            "{}: neighbor {} missing, silencing until t+{}",
94            self.handle,
95            neighbor,
96            Self::DISCOVERY_SILENT_TIME
97        );
98        self.neighbor_state = NeighborState::Waiting {
99            neighbor,
100            silent_until: timestamp + Self::DISCOVERY_SILENT_TIME,
101        };
102    }
103}