Skip to main content

netstack3_base/socket/
base.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! General-purpose socket utilities common to device layer and IP layer
6//! sockets.
7
8use core::fmt::Debug;
9use core::hash::Hash;
10use core::marker::PhantomData;
11use core::num::NonZeroU16;
12
13use derivative::Derivative;
14use net_types::ip::{GenericOverIp, Ip, IpAddress, IpVersion, IpVersionMarker, Ipv4, Ipv6};
15use net_types::{
16    AddrAndZone, MulticastAddress, ScopeableAddress, SpecifiedAddr, Witness, ZonedAddr,
17};
18use thiserror::Error;
19
20use crate::LocalAddressError;
21use crate::data_structures::socketmap::{
22    Entry, IterShadows, OccupiedEntry as SocketMapOccupiedEntry, SocketMap, Tagged,
23};
24use crate::device::{
25    DeviceIdentifier, EitherDeviceId, StrongDeviceIdentifier, WeakDeviceIdentifier,
26};
27use crate::error::{ExistsError, NotFoundError, ZonedAddressError};
28use crate::ip::BroadcastIpExt;
29use crate::socket::SocketCookie;
30use crate::socket::address::{
31    AddrVecIter, ConnAddr, ConnIpAddr, ListenerAddr, ListenerIpAddr, SocketIpAddr,
32};
33use packet_formats::ip::{IpProto, Ipv4Proto, Ipv6Proto};
34
35/// A dual stack IP extention trait that provides the `OtherVersion` associated
36/// type.
37pub trait DualStackIpExt: Ip {
38    /// The "other" IP version, e.g. [`Ipv4`] for [`Ipv6`] and vice-versa.
39    type OtherVersion: DualStackIpExt<OtherVersion = Self>;
40}
41
42impl DualStackIpExt for Ipv4 {
43    type OtherVersion = Ipv6;
44}
45
46impl DualStackIpExt for Ipv6 {
47    type OtherVersion = Ipv4;
48}
49
50/// A tuple of values for `T` for both `I` and `I::OtherVersion`.
51pub struct DualStackTuple<I: DualStackIpExt, T: GenericOverIp<I> + GenericOverIp<I::OtherVersion>> {
52    this_stack: <T as GenericOverIp<I>>::Type,
53    other_stack: <T as GenericOverIp<I::OtherVersion>>::Type,
54    _marker: IpVersionMarker<I>,
55}
56
57impl<I: DualStackIpExt, T: GenericOverIp<I> + GenericOverIp<I::OtherVersion>> DualStackTuple<I, T> {
58    /// Creates a new tuple with `this_stack` and `other_stack` values.
59    pub fn new(this_stack: T, other_stack: <T as GenericOverIp<I::OtherVersion>>::Type) -> Self
60    where
61        T: GenericOverIp<I, Type = T>,
62    {
63        Self { this_stack, other_stack, _marker: IpVersionMarker::new() }
64    }
65
66    /// Retrieves `(this_stack, other_stack)` from the tuple.
67    pub fn into_inner(
68        self,
69    ) -> (<T as GenericOverIp<I>>::Type, <T as GenericOverIp<I::OtherVersion>>::Type) {
70        let Self { this_stack, other_stack, _marker } = self;
71        (this_stack, other_stack)
72    }
73
74    /// Retrieves `this_stack` from the tuple.
75    pub fn into_this_stack(self) -> <T as GenericOverIp<I>>::Type {
76        self.this_stack
77    }
78
79    /// Borrows `this_stack` from the tuple.
80    pub fn this_stack(&self) -> &<T as GenericOverIp<I>>::Type {
81        &self.this_stack
82    }
83
84    /// Retrieves `other_stack` from the tuple.
85    pub fn into_other_stack(self) -> <T as GenericOverIp<I::OtherVersion>>::Type {
86        self.other_stack
87    }
88
89    /// Borrows `other_stack` from the tuple.
90    pub fn other_stack(&self) -> &<T as GenericOverIp<I::OtherVersion>>::Type {
91        &self.other_stack
92    }
93
94    /// Flips the types, making `this_stack` `other_stack` and vice-versa.
95    pub fn flip(self) -> DualStackTuple<I::OtherVersion, T> {
96        let Self { this_stack, other_stack, _marker } = self;
97        DualStackTuple {
98            this_stack: other_stack,
99            other_stack: this_stack,
100            _marker: IpVersionMarker::new(),
101        }
102    }
103
104    /// Casts to IP version `X`.
105    ///
106    /// Given `DualStackTuple` contains complete information for both IP
107    /// versions, it can be easily cast into an arbitrary `X` IP version.
108    ///
109    /// This can be used to tie together type parameters when dealing with dual
110    /// stack sockets. For example, a `DualStackTuple` defined for `SockI` can
111    /// be cast to any `WireI`.
112    pub fn cast<X>(self) -> DualStackTuple<X, T>
113    where
114        X: DualStackIpExt,
115        T: GenericOverIp<X>
116            + GenericOverIp<X::OtherVersion>
117            + GenericOverIp<Ipv4>
118            + GenericOverIp<Ipv6>,
119    {
120        I::map_ip_in(
121            self,
122            |v4| X::map_ip_out(v4, |t| t, |t| t.flip()),
123            |v6| X::map_ip_out(v6, |t| t.flip(), |t| t),
124        )
125    }
126}
127
128impl<
129    I: DualStackIpExt,
130    NewIp: DualStackIpExt,
131    T: GenericOverIp<NewIp>
132        + GenericOverIp<NewIp::OtherVersion>
133        + GenericOverIp<I>
134        + GenericOverIp<I::OtherVersion>,
135> GenericOverIp<NewIp> for DualStackTuple<I, T>
136{
137    type Type = DualStackTuple<NewIp, T>;
138}
139
140/// Extension trait for `Ip` providing socket-specific functionality.
141pub trait SocketIpExt: Ip {
142    /// `Self::LOOPBACK_ADDRESS`, but wrapped in the `SocketIpAddr` type.
143    const LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR: SocketIpAddr<Self::Addr> = unsafe {
144        // SAFETY: The loopback address is a valid SocketIpAddr, as verified
145        // in the `loopback_addr_is_valid_socket_addr` test.
146        SocketIpAddr::new_from_specified_unchecked(Self::LOOPBACK_ADDRESS)
147    };
148}
149
150impl<I: Ip> SocketIpExt for I {}
151
152#[cfg(test)]
153mod socket_ip_ext_test {
154    use super::*;
155    use ip_test_macro::ip_test;
156
157    #[ip_test(I)]
158    fn loopback_addr_is_valid_socket_addr<I: SocketIpExt>() {
159        // `LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR is defined with the "unchecked"
160        // constructor (which supports const construction). Verify here that the
161        // addr actually satisfies all the requirements (protecting against far
162        // away changes)
163        let _addr = SocketIpAddr::new(I::LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR.addr())
164            .expect("loopback address should be a valid SocketIpAddr");
165    }
166}
167
168/// An IP version-specific protocol.
169#[derive(Copy, Clone, Debug, PartialEq, Eq, GenericOverIp)]
170#[generic_over_ip()]
171pub enum EitherIpProto {
172    /// An IPv4 protocol.
173    V4(Ipv4Proto),
174    /// An IPv6 protocol.
175    V6(Ipv6Proto),
176}
177
178impl EitherIpProto {
179    /// Returns the IP version of the protocol.
180    pub fn ip_version(&self) -> IpVersion {
181        match self {
182            Self::V4(_) => IpVersion::V4,
183            Self::V6(_) => IpVersion::V6,
184        }
185    }
186
187    /// Returns the transport protocol if it is standard.
188    pub fn ip_proto(&self) -> Option<IpProto> {
189        match self {
190            Self::V4(p) => match p {
191                Ipv4Proto::Proto(proto) => Some(*proto),
192                _ => None,
193            },
194            Self::V6(p) => match p {
195                Ipv6Proto::Proto(proto) => Some(*proto),
196                _ => None,
197            },
198        }
199    }
200
201    /// Returns the raw protocol number as a u8.
202    pub fn u8_value(&self) -> u8 {
203        match self {
204            Self::V4(p) => (*p).into(),
205            Self::V6(p) => (*p).into(),
206        }
207    }
208}
209
210/// Information about a socket passed to a socket operations filter.
211#[derive(Clone, Debug)]
212#[cfg_attr(any(test, feature = "testutils"), derive(PartialEq, Eq))]
213pub struct SocketInfo {
214    /// The IP-version-specific transport protocol.
215    pub proto: EitherIpProto,
216    /// The socket cookie.
217    pub cookie: SocketCookie,
218}
219
220/// State belonging to either IP stack.
221///
222/// Like `[either::Either]`, but with more helpful variant names.
223///
224/// Note that this type is not optimally type-safe, because `T` and `O` are not
225/// bound by `IP` and `IP::OtherVersion`, respectively. In many cases it may be
226/// more appropriate to define a one-off enum parameterized over `I: Ip`.
227#[derive(Debug, PartialEq, Eq)]
228pub enum EitherStack<T, O> {
229    /// In the current stack version.
230    ThisStack(T),
231    /// In the other version of the stack.
232    OtherStack(O),
233}
234
235impl<T, O> Clone for EitherStack<T, O>
236where
237    T: Clone,
238    O: Clone,
239{
240    #[cfg_attr(feature = "instrumented", track_caller)]
241    fn clone(&self) -> Self {
242        match self {
243            Self::ThisStack(t) => Self::ThisStack(t.clone()),
244            Self::OtherStack(t) => Self::OtherStack(t.clone()),
245        }
246    }
247}
248
249/// Control flow type containing either a dual-stack or non-dual-stack context.
250///
251/// This type exists to provide nice names to the result of
252/// [`BoundStateContext::dual_stack_context`], and to allow generic code to
253/// match on when checking whether a socket protocol and IP version support
254/// dual-stack operation. If dual-stack operation is supported, a
255/// [`MaybeDualStack::DualStack`] value will be held, otherwise a `NonDualStack`
256/// value.
257///
258/// Note that the templated types to not have trait bounds; those are provided
259/// by the trait with the `dual_stack_context` function.
260///
261/// In monomorphized code, this type frequently has exactly one template
262/// parameter that is uninstantiable (it contains an instance of `!` or some
263/// other empty enum, or a reference to the same)! That lets the compiler
264/// optimize it out completely, creating no actual runtime overhead.
265#[derive(Debug)]
266#[allow(missing_docs)]
267pub enum MaybeDualStack<DS, NDS> {
268    DualStack(DS),
269    NotDualStack(NDS),
270}
271
272// Implement `GenericOverIp` for a `MaybeDualStack` whose `DS` and `NDS` also
273// implement `GenericOverIp`.
274impl<I: DualStackIpExt, DS: GenericOverIp<I>, NDS: GenericOverIp<I>> GenericOverIp<I>
275    for MaybeDualStack<DS, NDS>
276{
277    type Type = MaybeDualStack<<DS as GenericOverIp<I>>::Type, <NDS as GenericOverIp<I>>::Type>;
278}
279
280/// An error encountered while enabling or disabling dual-stack operation.
281#[derive(Copy, Clone, Debug, Eq, GenericOverIp, PartialEq, Error)]
282#[generic_over_ip()]
283pub enum SetDualStackEnabledError {
284    /// A socket can only have dual stack enabled or disabled while unbound.
285    #[error("a socket can only have dual stack enabled or disabled while unbound")]
286    SocketIsBound,
287    /// The socket's protocol is not dual stack capable.
288    #[error(transparent)]
289    NotCapable(#[from] NotDualStackCapableError),
290}
291
292/// An error encountered when attempting to perform dual stack operations on
293/// socket with a non dual stack capable protocol.
294#[derive(Copy, Clone, Debug, Eq, GenericOverIp, PartialEq, Error)]
295#[generic_over_ip()]
296#[error("socket's protocol is not dual-stack capable")]
297pub struct NotDualStackCapableError;
298
299/// Describes which direction(s) of the data path should be shut down.
300#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
301pub struct Shutdown {
302    /// True if the send path is shut down for the owning socket.
303    ///
304    /// If this is true, the socket should not be able to send packets.
305    pub send: bool,
306    /// True if the receive path is shut down for the owning socket.
307    ///
308    /// If this is true, the socket should not be able to receive packets.
309    pub receive: bool,
310}
311
312/// Which direction(s) to shut down for a socket.
313#[derive(Copy, Clone, Debug, Eq, GenericOverIp, PartialEq)]
314#[generic_over_ip()]
315pub enum ShutdownType {
316    /// Prevent sending packets on the socket.
317    Send,
318    /// Prevent receiving packets on the socket.
319    Receive,
320    /// Prevent sending and receiving packets on the socket.
321    SendAndReceive,
322}
323
324impl ShutdownType {
325    /// Returns a tuple of booleans for `(shutdown_send, shutdown_receive)`.
326    pub fn to_send_receive(&self) -> (bool, bool) {
327        match self {
328            Self::Send => (true, false),
329            Self::Receive => (false, true),
330            Self::SendAndReceive => (true, true),
331        }
332    }
333
334    /// Creates a [`ShutdownType`] from a pair of bools for send and receive.
335    pub fn from_send_receive(send: bool, receive: bool) -> Option<Self> {
336        match (send, receive) {
337            (true, false) => Some(Self::Send),
338            (false, true) => Some(Self::Receive),
339            (true, true) => Some(Self::SendAndReceive),
340            (false, false) => None,
341        }
342    }
343}
344
345/// Extensions to IP Address witnesses useful in the context of sockets.
346pub trait SocketIpAddrExt<A: IpAddress>: Witness<A> + ScopeableAddress {
347    /// Determines whether the provided address is underspecified by itself.
348    ///
349    /// Some addresses are ambiguous and so must have a zone identifier in order
350    /// to be used in a socket address. This function returns true for IPv6
351    /// link-local addresses and false for all others.
352    fn must_have_zone(&self) -> bool
353    where
354        Self: Copy,
355    {
356        self.try_into_null_zoned().is_some()
357    }
358
359    /// Converts into a [`AddrAndZone<A, ()>`] if the address requires a zone.
360    ///
361    /// Otherwise returns `None`.
362    fn try_into_null_zoned(self) -> Option<AddrAndZone<Self, ()>> {
363        if self.get().is_loopback() {
364            return None;
365        }
366        AddrAndZone::new(self, ())
367    }
368}
369
370impl<A: IpAddress, W: Witness<A> + ScopeableAddress> SocketIpAddrExt<A> for W {}
371
372/// An extention trait for [`ZonedAddr`].
373pub trait SocketZonedAddrExt<W, A, D> {
374    /// Returns the address and device that should be used for a socket.
375    ///
376    /// Given an address for a socket and an optional device that the socket is
377    /// already bound on, returns the address and device that should be used
378    /// for the socket. If `addr` and `device` require inconsistent devices,
379    /// or if `addr` requires a zone but there is none specified (by `addr` or
380    /// `device`), an error is returned.
381    fn resolve_addr_with_device(
382        self,
383        device: Option<D::Weak>,
384    ) -> Result<(W, Option<EitherDeviceId<D, D::Weak>>), ZonedAddressError>
385    where
386        D: StrongDeviceIdentifier;
387}
388
389impl<W, A, D> SocketZonedAddrExt<W, A, D> for ZonedAddr<W, D>
390where
391    W: ScopeableAddress + AsRef<SpecifiedAddr<A>>,
392    A: IpAddress,
393{
394    fn resolve_addr_with_device(
395        self,
396        device: Option<D::Weak>,
397    ) -> Result<(W, Option<EitherDeviceId<D, D::Weak>>), ZonedAddressError>
398    where
399        D: StrongDeviceIdentifier,
400    {
401        let (addr, zone) = self.into_addr_zone();
402        let device = match (zone, device) {
403            (Some(zone), Some(device)) => {
404                if device != zone {
405                    return Err(ZonedAddressError::DeviceZoneMismatch);
406                }
407                Some(EitherDeviceId::Strong(zone))
408            }
409            (Some(zone), None) => Some(EitherDeviceId::Strong(zone)),
410            (None, Some(device)) => Some(EitherDeviceId::Weak(device)),
411            (None, None) => {
412                if addr.as_ref().must_have_zone() {
413                    return Err(ZonedAddressError::RequiredZoneNotProvided);
414                } else {
415                    None
416                }
417            }
418        };
419        Ok((addr, device))
420    }
421}
422
423/// A helper type to verify if applying socket updates is allowed for a given
424/// current state.
425///
426/// The fields in `SocketDeviceUpdate` define the current state,
427/// [`SocketDeviceUpdate::try_update`] applies the verification logic.
428pub struct SocketDeviceUpdate<'a, A: IpAddress, D: WeakDeviceIdentifier> {
429    /// The current local IP address.
430    pub local_ip: Option<&'a SpecifiedAddr<A>>,
431    /// The current remote IP address.
432    pub remote_ip: Option<&'a SpecifiedAddr<A>>,
433    /// The currently bound device.
434    pub old_device: Option<&'a D>,
435}
436
437impl<'a, A: IpAddress, D: WeakDeviceIdentifier> SocketDeviceUpdate<'a, A, D> {
438    /// Checks if an update from `old_device` to `new_device` is allowed,
439    /// returning an error if not.
440    pub fn check_update<N>(
441        self,
442        new_device: Option<&N>,
443    ) -> Result<(), SocketDeviceUpdateNotAllowedError>
444    where
445        D: PartialEq<N>,
446    {
447        let Self { local_ip, remote_ip, old_device } = self;
448        let must_have_zone = local_ip.is_some_and(|a| a.must_have_zone())
449            || remote_ip.is_some_and(|a| a.must_have_zone());
450
451        if !must_have_zone {
452            return Ok(());
453        }
454
455        let old_device = old_device.unwrap_or_else(|| {
456            panic!("local_ip={:?} or remote_ip={:?} must have zone", local_ip, remote_ip)
457        });
458
459        if new_device.is_some_and(|new_device| old_device == new_device) {
460            Ok(())
461        } else {
462            Err(SocketDeviceUpdateNotAllowedError)
463        }
464    }
465}
466
467/// The device can't be updated on a socket.
468pub struct SocketDeviceUpdateNotAllowedError;
469
470/// Specification for the identifiers in an [`AddrVec`].
471///
472/// This is a convenience trait for bundling together the local and remote
473/// identifiers for a protocol.
474pub trait SocketMapAddrSpec {
475    /// The local identifier portion of a socket address.
476    type LocalIdentifier: Copy + Clone + Debug + Send + Sync + Hash + Eq + Into<NonZeroU16>;
477    /// The remote identifier portion of a socket address.
478    type RemoteIdentifier: Copy + Clone + Debug + Send + Sync + Hash + Eq;
479}
480
481/// Information about the address in a [`ListenerAddr`].
482pub struct ListenerAddrInfo {
483    /// Whether the address has a device bound.
484    pub has_device: bool,
485    /// Whether the listener is on a specified address (as opposed to a blanket
486    /// listener).
487    pub specified_addr: bool,
488}
489
490impl<A: IpAddress, D: DeviceIdentifier, LI> ListenerAddr<ListenerIpAddr<A, LI>, D> {
491    pub(crate) fn info(&self) -> ListenerAddrInfo {
492        let Self { device, ip: ListenerIpAddr { addr, identifier: _ } } = self;
493        ListenerAddrInfo { has_device: device.is_some(), specified_addr: addr.is_some() }
494    }
495}
496
497/// Specifies the types parameters for [`BoundSocketMap`] state as a single bundle.
498pub trait SocketMapStateSpec {
499    /// The tag value of a socket address vector entry.
500    ///
501    /// These values are derived from [`Self::ListenerAddrState`] and
502    /// [`Self::ConnAddrState`].
503    type AddrVecTag: Eq + Copy + Debug + 'static;
504
505    /// Returns a the tag for a listener in the socket map.
506    fn listener_tag(info: ListenerAddrInfo, state: &Self::ListenerAddrState) -> Self::AddrVecTag;
507
508    /// Returns a the tag for a connected socket in the socket map.
509    fn connected_tag(has_device: bool, state: &Self::ConnAddrState) -> Self::AddrVecTag;
510
511    /// An identifier for a listening socket.
512    type ListenerId: Clone + Debug;
513    /// An identifier for a connected socket.
514    type ConnId: Clone + Debug;
515
516    /// The state stored for a listening socket that is used to determine
517    /// whether sockets can share an address.
518    type ListenerSharingState: Clone + Debug;
519
520    /// The state stored for a connected socket that is used to determine
521    /// whether sockets can share an address.
522    type ConnSharingState: Clone + Debug;
523
524    /// The state stored for a listener socket address.
525    type ListenerAddrState: SocketMapAddrStateSpec<Id = Self::ListenerId, SharingState = Self::ListenerSharingState>
526        + Debug;
527
528    /// The state stored for a connected socket address.
529    type ConnAddrState: SocketMapAddrStateSpec<Id = Self::ConnId, SharingState = Self::ConnSharingState>
530        + Debug;
531}
532
533/// Error returned by implementations of [`SocketMapAddrStateSpec`] to indicate
534/// incompatible changes to a socket map.
535#[derive(Copy, Clone, Debug, Eq, PartialEq)]
536pub struct IncompatibleError;
537
538/// An inserter into a [`SocketMap`].
539pub trait Inserter<T> {
540    /// Inserts the provided item and consumes `self`.
541    ///
542    /// Inserts a single item and consumes the inserter (thus preventing
543    /// additional insertions).
544    fn insert(self, item: T);
545}
546
547impl<'a, T, E: Extend<T>> Inserter<T> for &'a mut E {
548    fn insert(self, item: T) {
549        self.extend([item])
550    }
551}
552
553impl<T> Inserter<T> for ! {
554    fn insert(self, _: T) {
555        match self {}
556    }
557}
558
559/// Describes an entry in a [`SocketMap`] for a listener or connection address.
560pub trait SocketMapAddrStateSpec {
561    /// The type of ID that can be present at the address.
562    type Id;
563
564    /// The sharing state for the address.
565    ///
566    /// This can be used to determine whether a socket can be inserted at the
567    /// address. Every socket has its own sharing state associated with it,
568    /// though the sharing state is not necessarily stored in the address
569    /// entry.
570    type SharingState;
571
572    /// The type of inserter returned by [`SocketMapAddrStateSpec::try_get_inserter`].
573    type Inserter<'a>: Inserter<Self::Id> + 'a
574    where
575        Self: 'a,
576        Self::Id: 'a;
577
578    /// Creates a new `Self` holding the provided socket with the given new
579    /// sharing state at the specified address.
580    fn new(new_sharing_state: &Self::SharingState, id: Self::Id) -> Self;
581
582    /// Looks up the ID in self, returning `true` if it is present.
583    fn contains_id(&self, id: &Self::Id) -> bool;
584
585    /// Enables insertion in `self` for a new socket with the provided sharing
586    /// state.
587    ///
588    /// If the new state is incompatible with the existing socket(s),
589    /// implementations of this function should return `Err(IncompatibleError)`.
590    /// If `Ok(x)` is returned, calling `x.insert(y)` will insert `y` into
591    /// `self`.
592    fn try_get_inserter<'a, 'b>(
593        &'b mut self,
594        new_sharing_state: &'a Self::SharingState,
595    ) -> Result<Self::Inserter<'b>, IncompatibleError>;
596
597    /// Returns `Ok` if an entry with the given sharing state could be added
598    /// to `self`.
599    ///
600    /// If this returns `Ok`, `try_get_dest` should succeed.
601    fn could_insert(&self, new_sharing_state: &Self::SharingState)
602    -> Result<(), IncompatibleError>;
603
604    /// Removes the given socket from the existing state.
605    ///
606    /// Implementations should assume that `id` is contained in `self`.
607    fn remove_by_id(&mut self, id: Self::Id) -> RemoveResult;
608
609    /// Returns the sharing state for the address.
610    fn sharing_state(&self) -> Self::SharingState;
611}
612
613/// Provides behavior on updating the sharing state of a [`SocketMap`] entry.
614pub trait SocketMapAddrStateUpdateSharingSpec: SocketMapAddrStateSpec {
615    /// Attempts to update the sharing state of the address state with id `id`
616    /// to `new_sharing_state`.
617    fn try_update_sharing(
618        &mut self,
619        id: Self::Id,
620        new_sharing_state: &Self::SharingState,
621    ) -> Result<(), IncompatibleError>;
622}
623
624/// Provides conflict detection for a [`SocketMapStateSpec`].
625pub trait SocketMapConflictPolicy<
626    Addr,
627    SharingState,
628    I: Ip,
629    D: DeviceIdentifier,
630    A: SocketMapAddrSpec,
631>: SocketMapStateSpec
632{
633    /// Checks whether a new socket with the provided state can be inserted at
634    /// the given address in the existing socket map, returning an error
635    /// otherwise.
636    ///
637    /// Implementations of this function should check for any potential
638    /// conflicts that would arise when inserting a socket with state
639    /// `new_sharing_state` into a new or existing entry at `addr` in
640    /// `socketmap`.
641    fn check_insert_conflicts(
642        new_sharing_state: &SharingState,
643        addr: &Addr,
644        socketmap: &SocketMap<AddrVec<I, D, A>, Bound<Self>>,
645    ) -> Result<(), InsertError>;
646}
647
648/// Defines the policy for updating the sharing state of entries in the
649/// [`SocketMap`].
650pub trait SocketMapUpdateSharingPolicy<Addr, SharingState, I: Ip, D: DeviceIdentifier, A>:
651    SocketMapConflictPolicy<Addr, SharingState, I, D, A>
652where
653    A: SocketMapAddrSpec,
654{
655    /// Returns whether the entry `addr` in `socketmap` allows the sharing state
656    /// to transition from `old_sharing` to `new_sharing`.
657    fn allows_sharing_update(
658        socketmap: &SocketMap<AddrVec<I, D, A>, Bound<Self>>,
659        addr: &Addr,
660        old_sharing: &SharingState,
661        new_sharing: &SharingState,
662    ) -> Result<(), UpdateSharingError>;
663}
664
665/// A bound socket state that is either a listener or a connection.
666#[derive(Derivative)]
667#[derivative(Debug(bound = "S::ListenerAddrState: Debug, S::ConnAddrState: Debug"))]
668#[allow(missing_docs)]
669pub enum Bound<S: SocketMapStateSpec + ?Sized> {
670    Listen(S::ListenerAddrState),
671    Conn(S::ConnAddrState),
672}
673
674/// An "address vector" type that can hold any address in a [`SocketMap`].
675///
676/// This is a "vector" in the mathematical sense, in that it denotes an address
677/// in a space. Here, the space is the possible addresses to which a socket
678/// receiving IP packets can be bound.
679///
680/// `AddrVec`s are used as keys for the `SocketMap` type. Since an incoming
681/// packet can match more than one address, for each incoming packet there is a
682/// set of possible `AddrVec` keys whose entries (sockets) in a `SocketMap`
683/// might receive the packet.
684///
685/// This set of keys can be ordered by precedence as described in the
686/// documentation for [`AddrVecIter`]. Calling [`IterShadows::iter_shadows`] on
687/// an instance will produce the sequence of addresses it has precedence over.
688#[derive(Derivative)]
689#[derivative(
690    Debug(bound = "D: Debug"),
691    Clone(bound = "D: Clone"),
692    Eq(bound = "D: Eq"),
693    PartialEq(bound = "D: PartialEq"),
694    Hash(bound = "D: Hash")
695)]
696#[allow(missing_docs)]
697pub enum AddrVec<I: Ip, D, A: SocketMapAddrSpec + ?Sized> {
698    Listen(ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>),
699    Conn(ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>),
700}
701
702impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec + ?Sized>
703    Tagged<AddrVec<I, D, A>> for Bound<S>
704{
705    type Tag = S::AddrVecTag;
706    fn tag(&self, address: &AddrVec<I, D, A>) -> Self::Tag {
707        match (self, address) {
708            (Bound::Listen(l), AddrVec::Listen(addr)) => S::listener_tag(addr.info(), l),
709            (Bound::Conn(c), AddrVec::Conn(ConnAddr { device, ip: _ })) => {
710                S::connected_tag(device.is_some(), c)
711            }
712            (Bound::Listen(_), AddrVec::Conn(_)) => {
713                unreachable!("found listen state for conn addr")
714            }
715            (Bound::Conn(_), AddrVec::Listen(_)) => {
716                unreachable!("found conn state for listen addr")
717            }
718        }
719    }
720}
721
722impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec> IterShadows for AddrVec<I, D, A> {
723    type IterShadows = AddrVecIter<I, D, A>;
724
725    fn iter_shadows(&self) -> Self::IterShadows {
726        let (socket_ip_addr, device) = match self.clone() {
727            AddrVec::Conn(ConnAddr { ip, device }) => (ip.into(), device),
728            AddrVec::Listen(ListenerAddr { ip, device }) => (ip.into(), device),
729        };
730        let mut iter = match device {
731            Some(device) => AddrVecIter::with_device(socket_ip_addr, device),
732            None => AddrVecIter::without_device(socket_ip_addr),
733        };
734        // Skip the first element, which is always `*self`.
735        assert_eq!(iter.next().as_ref(), Some(self));
736        iter
737    }
738}
739
740/// How a socket is bound on the system.
741#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
742#[allow(missing_docs)]
743pub enum SocketAddrType {
744    AnyListener,
745    SpecificListener,
746    Connected,
747}
748
749impl<'a, A: IpAddress, LI> From<&'a ListenerIpAddr<A, LI>> for SocketAddrType {
750    fn from(ListenerIpAddr { addr, identifier: _ }: &'a ListenerIpAddr<A, LI>) -> Self {
751        match addr {
752            Some(_) => SocketAddrType::SpecificListener,
753            None => SocketAddrType::AnyListener,
754        }
755    }
756}
757
758impl<'a, A: IpAddress, LI, RI> From<&'a ConnIpAddr<A, LI, RI>> for SocketAddrType {
759    fn from(_: &'a ConnIpAddr<A, LI, RI>) -> Self {
760        SocketAddrType::Connected
761    }
762}
763
764/// The result of attempting to remove a socket from a collection of sockets.
765pub enum RemoveResult {
766    /// The value was removed successfully.
767    Success,
768    /// The value is the last value in the collection so the entire collection
769    /// should be removed.
770    IsLast,
771}
772
773#[derive(Derivative)]
774#[derivative(Clone(bound = "S::ListenerId: Clone, S::ConnId: Clone"), Debug(bound = ""))]
775pub enum SocketId<S: SocketMapStateSpec> {
776    Listener(S::ListenerId),
777    Connection(S::ConnId),
778}
779
780/// A map from socket addresses to sockets.
781///
782/// The types of keys and IDs is determined by the [`SocketMapStateSpec`]
783/// parameter. Each listener and connected socket stores additional state.
784/// Listener and connected sockets are keyed independently, but share the same
785/// address vector space. Conflicts are detected on attempted insertion of new
786/// sockets.
787///
788/// Listener addresses map to listener-address-specific state, and likewise
789/// with connected addresses. Depending on protocol (determined by the
790/// `SocketMapStateSpec` protocol), these address states can hold one or more
791/// socket identifiers (e.g. UDP sockets with `SO_REUSEPORT` set can share an
792/// address).
793#[derive(Derivative)]
794#[derivative(Default(bound = ""))]
795pub struct BoundSocketMap<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec> {
796    addr_to_state: SocketMap<AddrVec<I, D, A>, Bound<S>>,
797}
798
799impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec>
800    BoundSocketMap<I, D, A, S>
801{
802    /// Returns the number of entries in the map.
803    pub fn len(&self) -> usize {
804        self.addr_to_state.len()
805    }
806}
807
808/// Uninstantiable tag type for denoting listening sockets.
809pub enum Listener {}
810/// Uninstantiable tag type for denoting connected sockets.
811pub enum Connection {}
812
813/// View struct over one type of sockets in a [`BoundSocketMap`].
814pub struct Sockets<AddrToStateMap, SocketType>(AddrToStateMap, PhantomData<SocketType>);
815
816impl<
817    'a,
818    I: Ip,
819    D: DeviceIdentifier,
820    SocketType: ConvertSocketMapState<I, D, A, S>,
821    A: SocketMapAddrSpec,
822    S: SocketMapConflictPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
823> Sockets<&'a SocketMap<AddrVec<I, D, A>, Bound<S>>, SocketType>
824{
825    /// Returns the state at an address, if there is any.
826    pub fn get_by_addr(self, addr: &SocketType::Addr) -> Option<&'a SocketType::AddrState> {
827        let Self(addr_to_state, _marker) = self;
828        addr_to_state.get(&SocketType::to_addr_vec(addr)).map(|state| {
829            SocketType::from_bound_ref(state)
830                .unwrap_or_else(|| unreachable!("found {:?} for address {:?}", state, addr))
831        })
832    }
833
834    /// Returns `Ok(())` if a socket could be inserted, otherwise an error.
835    ///
836    /// Goes through a dry run of inserting a socket at the given address and
837    /// with the given sharing state, returning `Ok(())` if the insertion would
838    /// succeed, otherwise the error that would be returned.
839    pub fn could_insert(
840        self,
841        addr: &SocketType::Addr,
842        sharing: &SocketType::SharingState,
843    ) -> Result<(), InsertError> {
844        let Self(addr_to_state, _) = self;
845        match self.get_by_addr(addr) {
846            Some(state) => {
847                state.could_insert(sharing).map_err(|IncompatibleError| InsertError::Exists)
848            }
849            None => S::check_insert_conflicts(&sharing, &addr, &addr_to_state),
850        }
851    }
852}
853
854/// A borrowed state entry in a [`SocketMap`].
855#[derive(Derivative)]
856#[derivative(Debug(bound = ""))]
857pub struct SocketStateEntry<
858    'a,
859    I: Ip,
860    D: DeviceIdentifier,
861    A: SocketMapAddrSpec,
862    S: SocketMapStateSpec,
863    SocketType,
864> {
865    id: SocketId<S>,
866    addr_entry: SocketMapOccupiedEntry<'a, AddrVec<I, D, A>, Bound<S>>,
867    _marker: PhantomData<SocketType>,
868}
869
870impl<
871    'a,
872    I: Ip,
873    D: DeviceIdentifier,
874    SocketType: ConvertSocketMapState<I, D, A, S>,
875    A: SocketMapAddrSpec,
876    S: SocketMapConflictPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
877> Sockets<&'a mut SocketMap<AddrVec<I, D, A>, Bound<S>>, SocketType>
878where
879    SocketType::SharingState: Clone,
880    SocketType::Id: Clone,
881{
882    /// Attempts to insert a new entry into the [`SocketMap`] backing this
883    /// `Sockets`.
884    pub fn try_insert(
885        self,
886        socket_addr: SocketType::Addr,
887        tag_state: SocketType::SharingState,
888        id: SocketType::Id,
889    ) -> Result<SocketStateEntry<'a, I, D, A, S, SocketType>, InsertError> {
890        self.try_insert_with(socket_addr, tag_state, |_addr, _sharing| (id, ()))
891            .map(|(entry, ())| entry)
892    }
893
894    /// Like [`Sockets::try_insert`] but calls `make_id` to create a socket ID
895    /// before inserting into the map.
896    ///
897    /// `make_id` returns type `R` that is returned to the caller on success.
898    pub fn try_insert_with<R>(
899        self,
900        socket_addr: SocketType::Addr,
901        tag_state: SocketType::SharingState,
902        make_id: impl FnOnce(SocketType::Addr, SocketType::SharingState) -> (SocketType::Id, R),
903    ) -> Result<(SocketStateEntry<'a, I, D, A, S, SocketType>, R), InsertError> {
904        let Self(addr_to_state, _) = self;
905        S::check_insert_conflicts(&tag_state, &socket_addr, &addr_to_state)?;
906
907        let addr = SocketType::to_addr_vec(&socket_addr);
908
909        match addr_to_state.entry(addr) {
910            Entry::Occupied(mut o) => {
911                let (id, ret) = o.map_mut(|bound| {
912                    let bound = match SocketType::from_bound_mut(bound) {
913                        Some(bound) => bound,
914                        None => unreachable!("found {:?} for address {:?}", bound, socket_addr),
915                    };
916                    match <SocketType::AddrState as SocketMapAddrStateSpec>::try_get_inserter(
917                        bound, &tag_state,
918                    ) {
919                        Ok(v) => {
920                            let (id, ret) = make_id(socket_addr, tag_state);
921                            v.insert(id.clone());
922                            Ok((SocketType::to_socket_id(id), ret))
923                        }
924                        Err(IncompatibleError) => Err(InsertError::Exists),
925                    }
926                })?;
927                Ok((SocketStateEntry { id, addr_entry: o, _marker: Default::default() }, ret))
928            }
929            Entry::Vacant(v) => {
930                let (id, ret) = make_id(socket_addr, tag_state.clone());
931                let addr_entry = v.insert(SocketType::to_bound(SocketType::AddrState::new(
932                    &tag_state,
933                    id.clone(),
934                )));
935                let id = SocketType::to_socket_id(id);
936                Ok((SocketStateEntry { id, addr_entry, _marker: Default::default() }, ret))
937            }
938        }
939    }
940
941    /// Returns a borrowed entry at `id` and `addr`.
942    pub fn entry(
943        self,
944        id: &SocketType::Id,
945        addr: &SocketType::Addr,
946    ) -> Option<SocketStateEntry<'a, I, D, A, S, SocketType>> {
947        let Self(addr_to_state, _) = self;
948        let addr_entry = match addr_to_state.entry(SocketType::to_addr_vec(addr)) {
949            Entry::Vacant(_) => return None,
950            Entry::Occupied(o) => o,
951        };
952        let state = SocketType::from_bound_ref(addr_entry.get())?;
953
954        state.contains_id(id).then_some(SocketStateEntry {
955            id: SocketType::to_socket_id(id.clone()),
956            addr_entry,
957            _marker: PhantomData::default(),
958        })
959    }
960
961    /// Removes the entry with `id` and `addr`.
962    pub fn remove(self, id: &SocketType::Id, addr: &SocketType::Addr) -> Result<(), NotFoundError> {
963        self.entry(id, addr)
964            .map(|entry| {
965                entry.remove();
966            })
967            .ok_or(NotFoundError)
968    }
969}
970
971/// The error returned when updating the sharing state for a [`SocketMap`] entry
972/// fails.
973#[derive(Debug)]
974pub struct UpdateSharingError;
975
976impl<
977    'a,
978    I: Ip,
979    D: DeviceIdentifier,
980    SocketType: ConvertSocketMapState<I, D, A, S>,
981    A: SocketMapAddrSpec,
982    S: SocketMapConflictPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
983> SocketStateEntry<'a, I, D, A, S, SocketType>
984where
985    SocketType::Id: Clone,
986{
987    /// Returns this entry's address.
988    pub fn get_addr(&self) -> &SocketType::Addr {
989        let Self { id: _, addr_entry, _marker } = self;
990        SocketType::from_addr_vec_ref(addr_entry.key())
991    }
992
993    /// Returns this entry's identifier.
994    pub fn id(&self) -> &SocketType::Id {
995        let Self { id, addr_entry: _, _marker } = self;
996        SocketType::from_socket_id_ref(id)
997    }
998
999    /// Attempts to update the address for this entry.
1000    pub fn try_update_addr(self, new_addr: SocketType::Addr) -> Result<Self, (ExistsError, Self)> {
1001        let Self { id, addr_entry, _marker } = self;
1002
1003        let new_addrvec = SocketType::to_addr_vec(&new_addr);
1004        let old_addr = addr_entry.key().clone();
1005        let (addr_state, addr_to_state) = addr_entry.remove_from_map();
1006        let addr_to_state = match addr_to_state.entry(new_addrvec) {
1007            Entry::Occupied(o) => o.into_map(),
1008            Entry::Vacant(v) => {
1009                let sharing_state = SocketType::from_bound_ref(&addr_state)
1010                    .unwrap_or_else(|| {
1011                        unreachable!("found {:?} for address {:?}", addr_state, old_addr)
1012                    })
1013                    .sharing_state();
1014                match S::check_insert_conflicts(&sharing_state, &new_addr, v.get_map()) {
1015                    Ok(_) => {
1016                        let new_addr_entry = v.insert(addr_state);
1017                        return Ok(SocketStateEntry { id, addr_entry: new_addr_entry, _marker });
1018                    }
1019                    Err(_) => v.into_map(),
1020                }
1021            }
1022        };
1023        let to_restore = addr_state;
1024        // Restore the old state before returning an error.
1025        let addr_entry = match addr_to_state.entry(old_addr) {
1026            Entry::Occupied(_) => unreachable!("just-removed-from entry is occupied"),
1027            Entry::Vacant(v) => v.insert(to_restore),
1028        };
1029        return Err((ExistsError, SocketStateEntry { id, addr_entry, _marker }));
1030    }
1031
1032    /// Removes this entry from the map.
1033    pub fn remove(self) {
1034        let Self { id, mut addr_entry, _marker } = self;
1035        let addr = addr_entry.key().clone();
1036        match addr_entry.map_mut(|value| {
1037            let value = match SocketType::from_bound_mut(value) {
1038                Some(value) => value,
1039                None => unreachable!("found {:?} for address {:?}", value, addr),
1040            };
1041            value.remove_by_id(SocketType::from_socket_id_ref(&id).clone())
1042        }) {
1043            RemoveResult::Success => (),
1044            RemoveResult::IsLast => {
1045                let _: Bound<S> = addr_entry.remove();
1046            }
1047        }
1048    }
1049
1050    /// Attempts to update the sharing state for this entry.
1051    pub fn try_update_sharing(
1052        &mut self,
1053        old_sharing_state: &SocketType::SharingState,
1054        new_sharing_state: SocketType::SharingState,
1055    ) -> Result<(), UpdateSharingError>
1056    where
1057        SocketType::AddrState: SocketMapAddrStateUpdateSharingSpec,
1058        S: SocketMapUpdateSharingPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
1059    {
1060        let Self { id, addr_entry, _marker } = self;
1061        let addr = SocketType::from_addr_vec_ref(addr_entry.key());
1062
1063        S::allows_sharing_update(
1064            addr_entry.get_map(),
1065            addr,
1066            old_sharing_state,
1067            &new_sharing_state,
1068        )?;
1069
1070        addr_entry
1071            .map_mut(|value| {
1072                let value = match SocketType::from_bound_mut(value) {
1073                    Some(value) => value,
1074                    // We shouldn't ever be storing listener state in a bound
1075                    // address, or bound state in a listener address. Doing so means
1076                    // we've got a serious bug.
1077                    None => unreachable!("found invalid state {:?}", value),
1078                };
1079
1080                value.try_update_sharing(
1081                    SocketType::from_socket_id_ref(id).clone(),
1082                    &new_sharing_state,
1083                )
1084            })
1085            .map_err(|IncompatibleError| UpdateSharingError)
1086    }
1087}
1088
1089impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S> BoundSocketMap<I, D, A, S>
1090where
1091    AddrVec<I, D, A>: IterShadows,
1092    S: SocketMapStateSpec,
1093{
1094    /// Returns an iterator over the listeners on the socket map.
1095    pub fn listeners(&self) -> Sockets<&SocketMap<AddrVec<I, D, A>, Bound<S>>, Listener>
1096    where
1097        S: SocketMapConflictPolicy<
1098                ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>,
1099                <S as SocketMapStateSpec>::ListenerSharingState,
1100                I,
1101                D,
1102                A,
1103            >,
1104        S::ListenerAddrState:
1105            SocketMapAddrStateSpec<Id = S::ListenerId, SharingState = S::ListenerSharingState>,
1106    {
1107        let Self { addr_to_state } = self;
1108        Sockets(addr_to_state, Default::default())
1109    }
1110
1111    /// Returns a mutable iterator over the listeners on the socket map.
1112    pub fn listeners_mut(&mut self) -> Sockets<&mut SocketMap<AddrVec<I, D, A>, Bound<S>>, Listener>
1113    where
1114        S: SocketMapConflictPolicy<
1115                ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>,
1116                <S as SocketMapStateSpec>::ListenerSharingState,
1117                I,
1118                D,
1119                A,
1120            >,
1121        S::ListenerAddrState:
1122            SocketMapAddrStateSpec<Id = S::ListenerId, SharingState = S::ListenerSharingState>,
1123    {
1124        let Self { addr_to_state } = self;
1125        Sockets(addr_to_state, Default::default())
1126    }
1127
1128    /// Returns an iterator over the connections on the socket map.
1129    pub fn conns(&self) -> Sockets<&SocketMap<AddrVec<I, D, A>, Bound<S>>, Connection>
1130    where
1131        S: SocketMapConflictPolicy<
1132                ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1133                <S as SocketMapStateSpec>::ConnSharingState,
1134                I,
1135                D,
1136                A,
1137            >,
1138        S::ConnAddrState:
1139            SocketMapAddrStateSpec<Id = S::ConnId, SharingState = S::ConnSharingState>,
1140    {
1141        let Self { addr_to_state } = self;
1142        Sockets(addr_to_state, Default::default())
1143    }
1144
1145    /// Returns a mutable iterator over the connections on the socket map.
1146    pub fn conns_mut(&mut self) -> Sockets<&mut SocketMap<AddrVec<I, D, A>, Bound<S>>, Connection>
1147    where
1148        S: SocketMapConflictPolicy<
1149                ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1150                <S as SocketMapStateSpec>::ConnSharingState,
1151                I,
1152                D,
1153                A,
1154            >,
1155        S::ConnAddrState:
1156            SocketMapAddrStateSpec<Id = S::ConnId, SharingState = S::ConnSharingState>,
1157    {
1158        let Self { addr_to_state } = self;
1159        Sockets(addr_to_state, Default::default())
1160    }
1161
1162    #[cfg(test)]
1163    pub(crate) fn iter_addrs(&self) -> impl Iterator<Item = &AddrVec<I, D, A>> {
1164        let Self { addr_to_state } = self;
1165        addr_to_state.iter().map(|(a, _v): (_, &Bound<S>)| a)
1166    }
1167
1168    /// Gets the number of shadower entries for `addr`.
1169    pub fn get_shadower_counts(&self, addr: &AddrVec<I, D, A>) -> usize {
1170        let Self { addr_to_state } = self;
1171        addr_to_state.descendant_counts(&addr).map(|(_sharing, size)| size.get()).sum()
1172    }
1173}
1174
1175/// The type returned by [`BoundSocketMap::iter_receivers`].
1176pub enum FoundSockets<A, It> {
1177    /// A single recipient was found for the address.
1178    Single(A),
1179    /// Indicates the looked-up address was multicast, and holds an iterator of
1180    /// the found receivers.
1181    Multicast(It),
1182}
1183
1184/// A borrowed entry in a [`BoundSocketMap`].
1185#[allow(missing_docs)]
1186#[derive(Debug)]
1187pub enum AddrEntry<'a, I: Ip, D, A: SocketMapAddrSpec, S: SocketMapStateSpec> {
1188    Listen(&'a S::ListenerAddrState, ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>),
1189    Conn(
1190        &'a S::ConnAddrState,
1191        ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1192    ),
1193}
1194
1195impl<I, D, A, S> BoundSocketMap<I, D, A, S>
1196where
1197    I: BroadcastIpExt<Addr: MulticastAddress>,
1198    D: DeviceIdentifier,
1199    A: SocketMapAddrSpec,
1200    S: SocketMapStateSpec
1201        + SocketMapConflictPolicy<
1202            ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>,
1203            <S as SocketMapStateSpec>::ListenerSharingState,
1204            I,
1205            D,
1206            A,
1207        > + SocketMapConflictPolicy<
1208            ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1209            <S as SocketMapStateSpec>::ConnSharingState,
1210            I,
1211            D,
1212            A,
1213        >,
1214{
1215    /// Looks up a connected socket.
1216    ///
1217    /// This is a lightweight version of `iter_receivers()` that doesn't try to
1218    /// lookup listening sockets. It is used for early demux, which applies only
1219    /// to connected sockets.
1220    pub fn lookup_connected(
1221        &self,
1222        (src_ip, src_port): (SocketIpAddr<I::Addr>, A::RemoteIdentifier),
1223        (dst_ip, dst_port): (SocketIpAddr<I::Addr>, A::LocalIdentifier),
1224        device: D,
1225    ) -> Option<&'_ S::ConnAddrState> {
1226        let mut addr = ConnAddr {
1227            ip: ConnIpAddr { local: (dst_ip, dst_port), remote: (src_ip, src_port) },
1228            device: Some(device),
1229        };
1230        let entry = self.conns().get_by_addr(&addr);
1231        if entry.is_some() {
1232            return entry;
1233        }
1234        addr.device = None;
1235        self.conns().get_by_addr(&addr)
1236    }
1237
1238    /// Finds the socket(s) that should receive an incoming packet.
1239    ///
1240    /// Uses the provided addresses and receiving device to look up sockets that
1241    /// should receive a matching incoming packet. Returns `None` if no sockets
1242    /// were found, or the results of the lookup.
1243    pub fn iter_receivers(
1244        &self,
1245        (src_ip, src_port): (Option<SocketIpAddr<I::Addr>>, Option<A::RemoteIdentifier>),
1246        (dst_ip, dst_port): (SocketIpAddr<I::Addr>, A::LocalIdentifier),
1247        device: D,
1248        broadcast: Option<I::BroadcastMarker>,
1249    ) -> Option<
1250        FoundSockets<
1251            AddrEntry<'_, I, D, A, S>,
1252            impl Iterator<Item = AddrEntry<'_, I, D, A, S>> + '_,
1253        >,
1254    > {
1255        let mut matching_entries = AddrVecIter::with_device(
1256            match (src_ip, src_port) {
1257                (Some(specified_src_ip), Some(src_port)) => {
1258                    ConnIpAddr { local: (dst_ip, dst_port), remote: (specified_src_ip, src_port) }
1259                        .into()
1260                }
1261                _ => ListenerIpAddr { addr: Some(dst_ip), identifier: dst_port }.into(),
1262            },
1263            device,
1264        )
1265        .filter_map(move |addr: AddrVec<I, D, A>| match addr {
1266            AddrVec::Listen(l) => {
1267                self.listeners().get_by_addr(&l).map(|state| AddrEntry::Listen(state, l))
1268            }
1269            AddrVec::Conn(c) => self.conns().get_by_addr(&c).map(|state| AddrEntry::Conn(state, c)),
1270        });
1271
1272        if broadcast.is_some() || dst_ip.addr().is_multicast() {
1273            Some(FoundSockets::Multicast(matching_entries))
1274        } else {
1275            let single_entry: Option<_> = matching_entries.next();
1276            single_entry.map(FoundSockets::Single)
1277        }
1278    }
1279}
1280
1281/// Errors observed by [`SocketMapConflictPolicy`].
1282#[derive(Debug, Eq, PartialEq)]
1283pub enum InsertError {
1284    /// A shadow address exists for the entry.
1285    ShadowAddrExists,
1286    /// Entry already exists.
1287    Exists,
1288    /// Entry would shadow existing entry.
1289    WouldShadowExisting,
1290    /// An indirect conflict was detected.
1291    IndirectConflict,
1292}
1293
1294impl From<InsertError> for LocalAddressError {
1295    fn from(value: InsertError) -> Self {
1296        match value {
1297            InsertError::ShadowAddrExists
1298            | InsertError::Exists
1299            | InsertError::IndirectConflict
1300            | InsertError::WouldShadowExisting => LocalAddressError::AddressInUse,
1301        }
1302    }
1303}
1304
1305/// Helper trait for converting between [`AddrVec`] and [`Bound`] and their
1306/// variants.
1307pub trait ConvertSocketMapState<I: Ip, D, A: SocketMapAddrSpec, S: SocketMapStateSpec> {
1308    type Id;
1309    type SharingState;
1310    type Addr: Debug;
1311    type AddrState: SocketMapAddrStateSpec<Id = Self::Id, SharingState = Self::SharingState>;
1312
1313    fn to_addr_vec(addr: &Self::Addr) -> AddrVec<I, D, A>;
1314    fn from_addr_vec_ref(addr: &AddrVec<I, D, A>) -> &Self::Addr;
1315    fn from_bound_ref(bound: &Bound<S>) -> Option<&Self::AddrState>;
1316    fn from_bound_mut(bound: &mut Bound<S>) -> Option<&mut Self::AddrState>;
1317    fn to_bound(state: Self::AddrState) -> Bound<S>;
1318    fn to_socket_id(id: Self::Id) -> SocketId<S>;
1319    fn from_socket_id_ref(id: &SocketId<S>) -> &Self::Id;
1320}
1321
1322impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec>
1323    ConvertSocketMapState<I, D, A, S> for Listener
1324{
1325    type Id = S::ListenerId;
1326    type SharingState = S::ListenerSharingState;
1327    type Addr = ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>;
1328    type AddrState = S::ListenerAddrState;
1329    fn to_addr_vec(addr: &Self::Addr) -> AddrVec<I, D, A> {
1330        AddrVec::Listen(addr.clone())
1331    }
1332
1333    fn from_addr_vec_ref(addr: &AddrVec<I, D, A>) -> &Self::Addr {
1334        match addr {
1335            AddrVec::Listen(l) => l,
1336            AddrVec::Conn(c) => unreachable!("conn addr for listener: {c:?}"),
1337        }
1338    }
1339
1340    fn from_bound_ref(bound: &Bound<S>) -> Option<&S::ListenerAddrState> {
1341        match bound {
1342            Bound::Listen(l) => Some(l),
1343            Bound::Conn(_c) => None,
1344        }
1345    }
1346
1347    fn from_bound_mut(bound: &mut Bound<S>) -> Option<&mut S::ListenerAddrState> {
1348        match bound {
1349            Bound::Listen(l) => Some(l),
1350            Bound::Conn(_c) => None,
1351        }
1352    }
1353
1354    fn to_bound(state: S::ListenerAddrState) -> Bound<S> {
1355        Bound::Listen(state)
1356    }
1357    fn from_socket_id_ref(id: &SocketId<S>) -> &Self::Id {
1358        match id {
1359            SocketId::Listener(id) => id,
1360            SocketId::Connection(_) => unreachable!("connection ID for listener"),
1361        }
1362    }
1363    fn to_socket_id(id: Self::Id) -> SocketId<S> {
1364        SocketId::Listener(id)
1365    }
1366}
1367
1368impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec>
1369    ConvertSocketMapState<I, D, A, S> for Connection
1370{
1371    type Id = S::ConnId;
1372    type SharingState = S::ConnSharingState;
1373    type Addr = ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>;
1374    type AddrState = S::ConnAddrState;
1375    fn to_addr_vec(addr: &Self::Addr) -> AddrVec<I, D, A> {
1376        AddrVec::Conn(addr.clone())
1377    }
1378
1379    fn from_addr_vec_ref(addr: &AddrVec<I, D, A>) -> &Self::Addr {
1380        match addr {
1381            AddrVec::Conn(c) => c,
1382            AddrVec::Listen(l) => unreachable!("listener addr for conn: {l:?}"),
1383        }
1384    }
1385
1386    fn from_bound_ref(bound: &Bound<S>) -> Option<&S::ConnAddrState> {
1387        match bound {
1388            Bound::Listen(_l) => None,
1389            Bound::Conn(c) => Some(c),
1390        }
1391    }
1392
1393    fn from_bound_mut(bound: &mut Bound<S>) -> Option<&mut S::ConnAddrState> {
1394        match bound {
1395            Bound::Listen(_l) => None,
1396            Bound::Conn(c) => Some(c),
1397        }
1398    }
1399
1400    fn to_bound(state: S::ConnAddrState) -> Bound<S> {
1401        Bound::Conn(state)
1402    }
1403
1404    fn from_socket_id_ref(id: &SocketId<S>) -> &Self::Id {
1405        match id {
1406            SocketId::Connection(id) => id,
1407            SocketId::Listener(_) => unreachable!("listener ID for connection"),
1408        }
1409    }
1410    fn to_socket_id(id: Self::Id) -> SocketId<S> {
1411        SocketId::Connection(id)
1412    }
1413}
1414
1415/// An identifier of a sharing domain used for SO_REUSEPORT.
1416#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
1417pub struct SharingDomain(u64);
1418
1419impl SharingDomain {
1420    /// Creates a new instance with the specified ID. Caller must ensure that the `id`
1421    /// uniquely identifies the sharing domain and that the client is authorized to use it,
1422    /// e.g. on Fuchsia the ID is the KOID of a handle provided by the client.
1423    pub const fn new(id: u64) -> Self {
1424        SharingDomain(id)
1425    }
1426}
1427
1428/// A value of the SO_REUSEPORT option. Also encodes the sharing domain, which allows
1429/// to ensure that only sockets in the same domain can share ports.
1430#[derive(Default, Debug, Eq, PartialEq, Clone, Copy, Hash)]
1431pub enum ReusePortOption {
1432    /// The option is disabled.
1433    #[default]
1434    Disabled,
1435
1436    /// The option is enabled: the port is shareable with other sockets in the
1437    /// same sharing domain.
1438    Enabled(SharingDomain),
1439}
1440
1441impl ReusePortOption {
1442    /// Returns `true` if the option is enabled.
1443    pub fn is_enabled(&self) -> bool {
1444        matches!(self, ReusePortOption::Enabled(_))
1445    }
1446
1447    /// Returns `true` if the socket is shareable with a socket with the
1448    /// specified value of the SO_REUSEPORT option.
1449    pub fn is_shareable_with(&self, other: &Self) -> bool {
1450        match (self, other) {
1451            (ReusePortOption::Enabled(domain1), ReusePortOption::Enabled(domain2)) => {
1452                domain1 == domain2
1453            }
1454            _ => false,
1455        }
1456    }
1457}
1458
1459/// A trait abstracting over the data required to calculate socket
1460/// diagnostics. Allows delaying the computation arbitrarily long.
1461pub trait SocketDiagnosticsSeed {
1462    /// The concrete output type.
1463    type Output;
1464
1465    /// Completes the diagnostics construction.
1466    fn resolve(self) -> Option<Self::Output>;
1467}
1468
1469#[cfg(test)]
1470mod tests {
1471    use alloc::vec;
1472    use alloc::vec::Vec;
1473
1474    use assert_matches::assert_matches;
1475    use net_declare::{net_ip_v4, net_ip_v6};
1476    use net_types::ip::{Ipv4Addr, Ipv6, Ipv6Addr};
1477    use netstack3_hashmap::HashSet;
1478    use test_case::test_case;
1479
1480    use crate::device::testutil::{FakeDeviceId, FakeWeakDeviceId, MultipleDevicesId};
1481    use crate::testutil::set_logger_for_test;
1482
1483    use super::*;
1484
1485    #[test_case(net_ip_v4!("8.8.8.8"))]
1486    #[test_case(net_ip_v4!("127.0.0.1"))]
1487    #[test_case(net_ip_v4!("127.0.8.9"))]
1488    #[test_case(net_ip_v4!("224.1.2.3"))]
1489    fn must_never_have_zone_ipv4(addr: Ipv4Addr) {
1490        // No IPv4 addresses are allowed to have a zone.
1491        let addr = SpecifiedAddr::new(addr).unwrap();
1492        assert_eq!(addr.must_have_zone(), false);
1493    }
1494
1495    #[test_case(net_ip_v6!("1::2:3"), false)]
1496    #[test_case(net_ip_v6!("::1"), false; "localhost")]
1497    #[test_case(net_ip_v6!("1::"), false)]
1498    #[test_case(net_ip_v6!("ff03:1:2:3::1"), false)]
1499    #[test_case(net_ip_v6!("ff02:1:2:3::1"), true)]
1500    #[test_case(Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.get(), true)]
1501    #[test_case(net_ip_v6!("fe80::1"), true)]
1502    fn must_have_zone_ipv6(addr: Ipv6Addr, must_have: bool) {
1503        // Only link-local unicast and multicast addresses are allowed to have
1504        // zones.
1505        let addr = SpecifiedAddr::new(addr).unwrap();
1506        assert_eq!(addr.must_have_zone(), must_have);
1507    }
1508
1509    #[test]
1510    fn try_into_null_zoned_ipv6() {
1511        assert_eq!(Ipv6::LOOPBACK_ADDRESS.try_into_null_zoned(), None);
1512        let zoned = Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.into_specified();
1513        const ZONE: u32 = 5;
1514        assert_eq!(
1515            zoned.try_into_null_zoned().map(|a| a.map_zone(|()| ZONE)),
1516            Some(AddrAndZone::new(zoned, ZONE).unwrap())
1517        );
1518    }
1519
1520    enum FakeSpec {}
1521
1522    #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
1523    struct Listener(usize);
1524
1525    #[derive(PartialEq, Eq, Debug, Copy, Clone)]
1526    struct SharingState {
1527        tag: char,
1528        shared: bool,
1529    }
1530
1531    impl SharingState {
1532        fn exclusive(tag: char) -> Self {
1533            Self { tag, shared: false }
1534        }
1535
1536        fn shared(tag: char) -> Self {
1537            Self { tag, shared: true }
1538        }
1539    }
1540
1541    impl SharingState {
1542        fn can_share_with(&self, other: &Self) -> bool {
1543            self.tag == other.tag && self.shared && other.shared
1544        }
1545    }
1546
1547    #[derive(PartialEq, Eq, Debug)]
1548    struct Multiple<T> {
1549        sharing_state: SharingState,
1550        entries: Vec<T>,
1551    }
1552
1553    impl<T> Multiple<T> {
1554        fn new_exclusive(tag: char, entries: Vec<T>) -> Self {
1555            Self { sharing_state: SharingState { tag, shared: false }, entries }
1556        }
1557    }
1558
1559    #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
1560    struct Conn(usize);
1561
1562    enum FakeAddrSpec {}
1563
1564    impl SocketMapAddrSpec for FakeAddrSpec {
1565        type LocalIdentifier = NonZeroU16;
1566        type RemoteIdentifier = ();
1567    }
1568
1569    impl SocketMapStateSpec for FakeSpec {
1570        type AddrVecTag = SharingState;
1571
1572        type ListenerId = Listener;
1573        type ConnId = Conn;
1574
1575        type ListenerSharingState = SharingState;
1576        type ConnSharingState = SharingState;
1577
1578        type ListenerAddrState = Multiple<Listener>;
1579        type ConnAddrState = Multiple<Conn>;
1580
1581        fn listener_tag(_: ListenerAddrInfo, state: &Self::ListenerAddrState) -> Self::AddrVecTag {
1582            state.sharing_state
1583        }
1584
1585        fn connected_tag(_has_device: bool, state: &Self::ConnAddrState) -> Self::AddrVecTag {
1586            state.sharing_state
1587        }
1588    }
1589
1590    type FakeBoundSocketMap =
1591        BoundSocketMap<Ipv4, FakeWeakDeviceId<FakeDeviceId>, FakeAddrSpec, FakeSpec>;
1592
1593    /// Generator for unique socket IDs that don't have any state.
1594    ///
1595    /// Calling [`FakeSocketIdGen::next`] returns a unique ID.
1596    #[derive(Default)]
1597    struct FakeSocketIdGen {
1598        next_id: usize,
1599    }
1600
1601    impl FakeSocketIdGen {
1602        fn next(&mut self) -> usize {
1603            let next_next_id = self.next_id + 1;
1604            core::mem::replace(&mut self.next_id, next_next_id)
1605        }
1606    }
1607
1608    impl<I: Eq> SocketMapAddrStateSpec for Multiple<I> {
1609        type Id = I;
1610        type SharingState = SharingState;
1611        type Inserter<'a>
1612            = &'a mut Vec<I>
1613        where
1614            I: 'a;
1615
1616        fn new(sharing_state: &SharingState, id: I) -> Self {
1617            Self { sharing_state: *sharing_state, entries: vec![id] }
1618        }
1619
1620        fn contains_id(&self, id: &Self::Id) -> bool {
1621            self.entries.contains(id)
1622        }
1623
1624        fn try_get_inserter<'a, 'b>(
1625            &'b mut self,
1626            new_sharing_state: &'a SharingState,
1627        ) -> Result<Self::Inserter<'b>, IncompatibleError> {
1628            (self.sharing_state == *new_sharing_state)
1629                .then_some(&mut self.entries)
1630                .ok_or(IncompatibleError)
1631        }
1632
1633        fn could_insert(&self, new_sharing_state: &SharingState) -> Result<(), IncompatibleError> {
1634            (self.sharing_state == *new_sharing_state).then_some(()).ok_or(IncompatibleError)
1635        }
1636
1637        fn remove_by_id(&mut self, id: I) -> RemoveResult {
1638            let index = self.entries.iter().position(|i| i == &id).expect("did not find id");
1639            let _: I = self.entries.swap_remove(index);
1640            if self.entries.is_empty() { RemoveResult::IsLast } else { RemoveResult::Success }
1641        }
1642
1643        fn sharing_state(&self) -> Self::SharingState {
1644            self.sharing_state
1645        }
1646    }
1647
1648    impl<D: DeviceIdentifier, A: Into<AddrVec<Ipv4, D, FakeAddrSpec>> + Clone>
1649        SocketMapConflictPolicy<A, SharingState, Ipv4, D, FakeAddrSpec> for FakeSpec
1650    {
1651        fn check_insert_conflicts(
1652            new_sharing_state: &SharingState,
1653            addr: &A,
1654            socketmap: &SocketMap<AddrVec<Ipv4, D, FakeAddrSpec>, Bound<FakeSpec>>,
1655        ) -> Result<(), InsertError> {
1656            let dest: AddrVec<_, _, _> = addr.clone().into();
1657            if dest.iter_shadows().any(|a| {
1658                let entry = socketmap.get(&a);
1659                match entry {
1660                    Some(Bound::Listen(Multiple { sharing_state, .. }))
1661                    | Some(Bound::Conn(Multiple { sharing_state, .. })) => {
1662                        !sharing_state.can_share_with(new_sharing_state)
1663                    }
1664                    None => false,
1665                }
1666            }) {
1667                return Err(InsertError::ShadowAddrExists);
1668            }
1669
1670            match socketmap.get(&dest) {
1671                Some(Bound::Listen(Multiple { sharing_state, .. }))
1672                | Some(Bound::Conn(Multiple { sharing_state, .. })) => {
1673                    // Require that all sockets inserted in a `Multiple` entry
1674                    // have the same sharing state.
1675                    if sharing_state != new_sharing_state {
1676                        return Err(InsertError::Exists);
1677                    }
1678                }
1679                None => (),
1680            }
1681
1682            if socketmap
1683                .descendant_counts(&dest)
1684                .any(|(sharing_state, _count)| !sharing_state.can_share_with(new_sharing_state))
1685            {
1686                Err(InsertError::WouldShadowExisting)
1687            } else {
1688                Ok(())
1689            }
1690        }
1691    }
1692
1693    impl<I: Eq> SocketMapAddrStateUpdateSharingSpec for Multiple<I> {
1694        fn try_update_sharing(
1695            &mut self,
1696            id: Self::Id,
1697            new_sharing_state: &Self::SharingState,
1698        ) -> Result<(), IncompatibleError> {
1699            if self.sharing_state == *new_sharing_state {
1700                return Ok(());
1701            }
1702
1703            // Preserve the invariant that all sockets inserted in a `Multiple`
1704            // entry have the same sharing state. That means we can't change
1705            // the sharing state of all the sockets at the address unless there
1706            // is exactly one!
1707            if self.entries.len() != 1 {
1708                return Err(IncompatibleError);
1709            }
1710            assert!(self.entries.contains(&id));
1711            self.sharing_state = *new_sharing_state;
1712            Ok(())
1713        }
1714    }
1715
1716    impl<D: DeviceIdentifier, A: Into<AddrVec<Ipv4, D, FakeAddrSpec>> + Clone>
1717        SocketMapUpdateSharingPolicy<A, SharingState, Ipv4, D, FakeAddrSpec> for FakeSpec
1718    {
1719        fn allows_sharing_update(
1720            _socketmap: &SocketMap<AddrVec<Ipv4, D, FakeAddrSpec>, Bound<Self>>,
1721            _addr: &A,
1722            _old_sharing: &SharingState,
1723            _new_sharing_state: &SharingState,
1724        ) -> Result<(), UpdateSharingError> {
1725            Ok(())
1726        }
1727    }
1728
1729    const LISTENER_ADDR: ListenerAddr<
1730        ListenerIpAddr<Ipv4Addr, NonZeroU16>,
1731        FakeWeakDeviceId<FakeDeviceId>,
1732    > = ListenerAddr {
1733        ip: ListenerIpAddr {
1734            addr: Some(unsafe { SocketIpAddr::new_unchecked(net_ip_v4!("1.2.3.4")) }),
1735            identifier: NonZeroU16::new(1).unwrap(),
1736        },
1737        device: None,
1738    };
1739
1740    const CONN_ADDR: ConnAddr<
1741        ConnIpAddr<Ipv4Addr, NonZeroU16, ()>,
1742        FakeWeakDeviceId<FakeDeviceId>,
1743    > = ConnAddr {
1744        ip: ConnIpAddr {
1745            local: (
1746                unsafe { SocketIpAddr::new_unchecked(net_ip_v4!("5.6.7.8")) },
1747                NonZeroU16::new(1).unwrap(),
1748            ),
1749            remote: unsafe { (SocketIpAddr::new_unchecked(net_ip_v4!("8.7.6.5")), ()) },
1750        },
1751        device: None,
1752    };
1753
1754    #[test]
1755    fn bound_insert_get_remove_listener() {
1756        set_logger_for_test();
1757        let mut bound = FakeBoundSocketMap::default();
1758        let mut fake_id_gen = FakeSocketIdGen::default();
1759
1760        let addr = LISTENER_ADDR;
1761
1762        let id = {
1763            let entry = bound
1764                .listeners_mut()
1765                .try_insert(addr, SharingState::exclusive('v'), Listener(fake_id_gen.next()))
1766                .unwrap();
1767            assert_eq!(entry.get_addr(), &addr);
1768            entry.id().clone()
1769        };
1770
1771        assert_eq!(
1772            bound.listeners().get_by_addr(&addr),
1773            Some(&Multiple::new_exclusive('v', vec![id]))
1774        );
1775
1776        assert_eq!(bound.listeners_mut().remove(&id, &addr), Ok(()));
1777        assert_eq!(bound.listeners().get_by_addr(&addr), None);
1778    }
1779
1780    #[test]
1781    fn bound_insert_get_remove_conn() {
1782        set_logger_for_test();
1783        let mut bound = FakeBoundSocketMap::default();
1784        let mut fake_id_gen = FakeSocketIdGen::default();
1785
1786        let addr = CONN_ADDR;
1787
1788        let id = {
1789            let entry = bound
1790                .conns_mut()
1791                .try_insert(addr, SharingState::exclusive('v'), Conn(fake_id_gen.next()))
1792                .unwrap();
1793            assert_eq!(entry.get_addr(), &addr);
1794            entry.id().clone()
1795        };
1796
1797        assert_eq!(bound.conns().get_by_addr(&addr), Some(&Multiple::new_exclusive('v', vec![id])));
1798
1799        assert_eq!(bound.conns_mut().remove(&id, &addr), Ok(()));
1800        assert_eq!(bound.conns().get_by_addr(&addr), None);
1801    }
1802
1803    #[test]
1804    fn bound_iter_addrs() {
1805        set_logger_for_test();
1806        let mut bound = FakeBoundSocketMap::default();
1807        let mut fake_id_gen = FakeSocketIdGen::default();
1808
1809        let listener_addrs = [
1810            (Some(net_ip_v4!("1.1.1.1")), 1),
1811            (Some(net_ip_v4!("2.2.2.2")), 2),
1812            (Some(net_ip_v4!("1.1.1.1")), 3),
1813            (None, 4),
1814        ]
1815        .map(|(ip, identifier)| ListenerAddr {
1816            device: None,
1817            ip: ListenerIpAddr {
1818                addr: ip.map(|x| SocketIpAddr::new(x).unwrap()),
1819                identifier: NonZeroU16::new(identifier).unwrap(),
1820            },
1821        });
1822        let conn_addrs = [
1823            (net_ip_v4!("3.3.3.3"), 3, net_ip_v4!("4.4.4.4")),
1824            (net_ip_v4!("4.4.4.4"), 3, net_ip_v4!("3.3.3.3")),
1825        ]
1826        .map(|(local_ip, local_identifier, remote_ip)| ConnAddr {
1827            ip: ConnIpAddr {
1828                local: (
1829                    SocketIpAddr::new(local_ip).unwrap(),
1830                    NonZeroU16::new(local_identifier).unwrap(),
1831                ),
1832                remote: (SocketIpAddr::new(remote_ip).unwrap(), ()),
1833            },
1834            device: None,
1835        });
1836
1837        for addr in listener_addrs.iter().cloned() {
1838            let _entry = bound
1839                .listeners_mut()
1840                .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1841                .unwrap();
1842        }
1843        for addr in conn_addrs.iter().cloned() {
1844            let _entry = bound
1845                .conns_mut()
1846                .try_insert(addr, SharingState::exclusive('a'), Conn(fake_id_gen.next()))
1847                .unwrap();
1848        }
1849        let expected_addrs = listener_addrs
1850            .into_iter()
1851            .map(Into::into)
1852            .chain(conn_addrs.into_iter().map(Into::into))
1853            .collect::<HashSet<_>>();
1854
1855        assert_eq!(expected_addrs, bound.iter_addrs().cloned().collect());
1856    }
1857
1858    #[test]
1859    fn try_insert_with_callback_not_called_on_error() {
1860        // TODO(https://fxbug.dev/42076891): remove this test along with
1861        // try_insert_with.
1862        set_logger_for_test();
1863        let mut bound = FakeBoundSocketMap::default();
1864        let addr = LISTENER_ADDR;
1865
1866        // Insert a listener so that future calls can conflict.
1867        let _: &Listener = bound
1868            .listeners_mut()
1869            .try_insert(addr, SharingState::exclusive('a'), Listener(0))
1870            .unwrap()
1871            .id();
1872
1873        // All of the below try_insert_with calls should fail, but more
1874        // importantly, they should not call the `make_id` callback (because it
1875        // is only called once success is certain).
1876        fn is_never_called<A, B, T>(_: A, _: B) -> (T, ()) {
1877            panic!("should never be called");
1878        }
1879
1880        assert_matches!(
1881            bound.listeners_mut().try_insert_with(
1882                addr,
1883                SharingState::exclusive('b'),
1884                is_never_called
1885            ),
1886            Err(InsertError::Exists)
1887        );
1888        assert_matches!(
1889            bound.listeners_mut().try_insert_with(
1890                ListenerAddr { device: Some(FakeWeakDeviceId(FakeDeviceId)), ..addr },
1891                SharingState::exclusive('b'),
1892                is_never_called
1893            ),
1894            Err(InsertError::ShadowAddrExists)
1895        );
1896        assert_matches!(
1897            bound.conns_mut().try_insert_with(
1898                ConnAddr {
1899                    device: None,
1900                    ip: ConnIpAddr {
1901                        local: (addr.ip.addr.unwrap(), addr.ip.identifier),
1902                        remote: (SocketIpAddr::new(net_ip_v4!("1.1.1.1")).unwrap(), ()),
1903                    },
1904                },
1905                SharingState::exclusive('b'),
1906                is_never_called,
1907            ),
1908            Err(InsertError::ShadowAddrExists)
1909        );
1910    }
1911
1912    #[test]
1913    fn insert_listener_conflict_with_listener() {
1914        set_logger_for_test();
1915        let mut bound = FakeBoundSocketMap::default();
1916        let mut fake_id_gen = FakeSocketIdGen::default();
1917        let addr = LISTENER_ADDR;
1918
1919        let _: &Listener = bound
1920            .listeners_mut()
1921            .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1922            .unwrap()
1923            .id();
1924        assert_matches!(
1925            bound.listeners_mut().try_insert(
1926                addr,
1927                SharingState::exclusive('b'),
1928                Listener(fake_id_gen.next())
1929            ),
1930            Err(InsertError::Exists)
1931        );
1932    }
1933
1934    #[test]
1935    fn insert_listener_conflict_with_shadower() {
1936        set_logger_for_test();
1937        let mut bound = FakeBoundSocketMap::default();
1938        let mut fake_id_gen = FakeSocketIdGen::default();
1939        let addr = LISTENER_ADDR;
1940        let shadows_addr = {
1941            assert_eq!(addr.device, None);
1942            ListenerAddr { device: Some(FakeWeakDeviceId(FakeDeviceId)), ..addr }
1943        };
1944
1945        let _: &Listener = bound
1946            .listeners_mut()
1947            .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1948            .unwrap()
1949            .id();
1950        assert_matches!(
1951            bound.listeners_mut().try_insert(
1952                shadows_addr,
1953                SharingState::exclusive('b'),
1954                Listener(fake_id_gen.next())
1955            ),
1956            Err(InsertError::ShadowAddrExists)
1957        );
1958    }
1959
1960    #[test]
1961    fn insert_conn_conflict_with_listener() {
1962        set_logger_for_test();
1963        let mut bound = FakeBoundSocketMap::default();
1964        let mut fake_id_gen = FakeSocketIdGen::default();
1965        let addr = LISTENER_ADDR;
1966        let shadows_addr = ConnAddr {
1967            device: None,
1968            ip: ConnIpAddr {
1969                local: (addr.ip.addr.unwrap(), addr.ip.identifier),
1970                remote: (SocketIpAddr::new(net_ip_v4!("1.1.1.1")).unwrap(), ()),
1971            },
1972        };
1973
1974        let _: &Listener = bound
1975            .listeners_mut()
1976            .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1977            .unwrap()
1978            .id();
1979        assert_matches!(
1980            bound.conns_mut().try_insert(
1981                shadows_addr,
1982                SharingState::exclusive('b'),
1983                Conn(fake_id_gen.next())
1984            ),
1985            Err(InsertError::ShadowAddrExists)
1986        );
1987    }
1988
1989    #[test]
1990    fn insert_and_remove_listener() {
1991        set_logger_for_test();
1992        let mut bound = FakeBoundSocketMap::default();
1993        let mut fake_id_gen = FakeSocketIdGen::default();
1994        let addr = LISTENER_ADDR;
1995
1996        let a = bound
1997            .listeners_mut()
1998            .try_insert(addr, SharingState::exclusive('x'), Listener(fake_id_gen.next()))
1999            .unwrap()
2000            .id()
2001            .clone();
2002        let b = bound
2003            .listeners_mut()
2004            .try_insert(addr, SharingState::exclusive('x'), Listener(fake_id_gen.next()))
2005            .unwrap()
2006            .id()
2007            .clone();
2008        assert_ne!(a, b);
2009
2010        assert_eq!(bound.listeners_mut().remove(&a, &addr), Ok(()));
2011        assert_eq!(
2012            bound.listeners().get_by_addr(&addr),
2013            Some(&Multiple::new_exclusive('x', vec![b]))
2014        );
2015    }
2016
2017    #[test]
2018    fn insert_and_remove_conn() {
2019        set_logger_for_test();
2020        let mut bound = FakeBoundSocketMap::default();
2021        let mut fake_id_gen = FakeSocketIdGen::default();
2022        let addr = CONN_ADDR;
2023
2024        let a = bound
2025            .conns_mut()
2026            .try_insert(addr, SharingState::exclusive('x'), Conn(fake_id_gen.next()))
2027            .unwrap()
2028            .id()
2029            .clone();
2030        let b = bound
2031            .conns_mut()
2032            .try_insert(addr, SharingState::exclusive('x'), Conn(fake_id_gen.next()))
2033            .unwrap()
2034            .id()
2035            .clone();
2036        assert_ne!(a, b);
2037
2038        assert_eq!(bound.conns_mut().remove(&a, &addr), Ok(()));
2039        assert_eq!(bound.conns().get_by_addr(&addr), Some(&Multiple::new_exclusive('x', vec![b])));
2040    }
2041
2042    #[test]
2043    fn update_listener_to_shadowed_addr_fails() {
2044        let mut bound = FakeBoundSocketMap::default();
2045        let mut fake_id_gen = FakeSocketIdGen::default();
2046
2047        let first_addr = LISTENER_ADDR;
2048        let second_addr = ListenerAddr {
2049            ip: ListenerIpAddr {
2050                addr: Some(SocketIpAddr::new(net_ip_v4!("1.1.1.1")).unwrap()),
2051                ..LISTENER_ADDR.ip
2052            },
2053            ..LISTENER_ADDR
2054        };
2055        let both_shadow = ListenerAddr {
2056            ip: ListenerIpAddr { addr: None, identifier: first_addr.ip.identifier },
2057            device: None,
2058        };
2059
2060        let first = bound
2061            .listeners_mut()
2062            .try_insert(first_addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
2063            .unwrap()
2064            .id()
2065            .clone();
2066        let second = bound
2067            .listeners_mut()
2068            .try_insert(second_addr, SharingState::exclusive('b'), Listener(fake_id_gen.next()))
2069            .unwrap()
2070            .id()
2071            .clone();
2072
2073        // Moving from (1, "aaa") to (1, None) should fail since it is shadowed
2074        // by (1, "yyy"), and vise versa.
2075        let (ExistsError, entry) = bound
2076            .listeners_mut()
2077            .entry(&second, &second_addr)
2078            .unwrap()
2079            .try_update_addr(both_shadow)
2080            .expect_err("update should fail");
2081
2082        // The entry should correspond to `second`.
2083        assert_eq!(entry.id(), &second);
2084        drop(entry);
2085
2086        let (ExistsError, entry) = bound
2087            .listeners_mut()
2088            .entry(&first, &first_addr)
2089            .unwrap()
2090            .try_update_addr(both_shadow)
2091            .expect_err("update should fail");
2092        assert_eq!(entry.get_addr(), &first_addr);
2093    }
2094
2095    #[test]
2096    fn update_listener_to_conflicting_addr_fails() {
2097        let mut bound = BoundSocketMap::<
2098            Ipv4,
2099            FakeWeakDeviceId<MultipleDevicesId>,
2100            FakeAddrSpec,
2101            FakeSpec,
2102        >::default();
2103        let mut fake_id_gen = FakeSocketIdGen::default();
2104        let device_a_wildcard_addr = ListenerAddr {
2105            ip: ListenerIpAddr { addr: None, identifier: NonZeroU16::new(80).unwrap() },
2106            device: Some(FakeWeakDeviceId(MultipleDevicesId::A)),
2107        };
2108        let device_b_specific_addr = ListenerAddr {
2109            ip: ListenerIpAddr {
2110                addr: Some(SocketIpAddr::new(net_ip_v4!("192.168.1.1")).unwrap()),
2111                identifier: NonZeroU16::new(80).unwrap(),
2112            },
2113            device: Some(FakeWeakDeviceId(MultipleDevicesId::B)),
2114        };
2115        let device_a_specific_addr = ListenerAddr {
2116            ip: ListenerIpAddr {
2117                addr: Some(SocketIpAddr::new(net_ip_v4!("192.168.1.1")).unwrap()),
2118                identifier: NonZeroU16::new(80).unwrap(),
2119            },
2120            device: Some(FakeWeakDeviceId(MultipleDevicesId::A)),
2121        };
2122
2123        let _ = bound
2124            .listeners_mut()
2125            .try_insert(
2126                device_a_wildcard_addr,
2127                SharingState::exclusive('a'),
2128                Listener(fake_id_gen.next()),
2129            )
2130            .expect("binding wildcard listener should succeed");
2131
2132        // Binding to a specific listener on device A should fail.
2133        assert_matches!(
2134            bound.listeners_mut().try_insert(
2135                device_a_specific_addr,
2136                SharingState::exclusive('b'),
2137                Listener(fake_id_gen.next()),
2138            ),
2139            Err(_)
2140        );
2141
2142        // Binding to a specific listener on device B and then moving it to
2143        // device A should also fail.
2144        let specific_entry = bound
2145            .listeners_mut()
2146            .try_insert(
2147                device_b_specific_addr,
2148                SharingState::exclusive('b'),
2149                Listener(fake_id_gen.next()),
2150            )
2151            .expect("binding dev A specific listener should succeed");
2152
2153        assert_matches!(specific_entry.try_update_addr(device_a_specific_addr), Err(_));
2154    }
2155
2156    #[test]
2157    fn nonexistent_conn_entry() {
2158        let mut map = FakeBoundSocketMap::default();
2159        let mut fake_id_gen = FakeSocketIdGen::default();
2160        let addr = CONN_ADDR;
2161        let conn_id = map
2162            .conns_mut()
2163            .try_insert(addr.clone(), SharingState::exclusive('a'), Conn(fake_id_gen.next()))
2164            .expect("failed to insert")
2165            .id()
2166            .clone();
2167        assert_matches!(map.conns_mut().remove(&conn_id, &addr), Ok(()));
2168
2169        assert!(map.conns_mut().entry(&conn_id, &addr).is_none());
2170    }
2171
2172    #[test]
2173    fn update_conn_sharing() {
2174        let mut map = FakeBoundSocketMap::default();
2175        let mut fake_id_gen = FakeSocketIdGen::default();
2176        let addr = CONN_ADDR;
2177        let mut entry = map
2178            .conns_mut()
2179            .try_insert(addr.clone(), SharingState::exclusive('a'), Conn(fake_id_gen.next()))
2180            .expect("failed to insert");
2181
2182        entry
2183            .try_update_sharing(&SharingState::exclusive('a'), SharingState::exclusive('d'))
2184            .expect("worked");
2185        // Updating sharing is only allowed if there are no other occupants at
2186        // the address.
2187        let mut second_conn = map
2188            .conns_mut()
2189            .try_insert(addr.clone(), SharingState::exclusive('d'), Conn(fake_id_gen.next()))
2190            .expect("can insert");
2191        assert_matches!(
2192            second_conn
2193                .try_update_sharing(&SharingState::exclusive('d'), SharingState::exclusive('e')),
2194            Err(UpdateSharingError)
2195        );
2196    }
2197
2198    #[test]
2199    fn lookup_connected() {
2200        let mut map = FakeBoundSocketMap::default();
2201        let mut fake_id_gen = FakeSocketIdGen::default();
2202
2203        let sharing_state = SharingState::shared('a');
2204
2205        let device_id = FakeWeakDeviceId(FakeDeviceId);
2206        let entry1 = map
2207            .conns_mut()
2208            .try_insert(CONN_ADDR, sharing_state, Conn(fake_id_gen.next()))
2209            .expect("failed to insert")
2210            .id()
2211            .clone();
2212        let conn = map
2213            .lookup_connected(CONN_ADDR.ip.remote, CONN_ADDR.ip.local, device_id)
2214            .expect("lookup should succeed");
2215        assert!(conn.contains_id(&entry1));
2216
2217        // Add a second entry with a device ID. This one should be preferred
2218        // over the first one.
2219        let addr_with_device = ConnAddr { device: Some(device_id), ..CONN_ADDR };
2220        let entry2 = map
2221            .conns_mut()
2222            .try_insert(addr_with_device, sharing_state, Conn(fake_id_gen.next()))
2223            .expect("failed to insert")
2224            .id()
2225            .clone();
2226        let conn = map
2227            .lookup_connected(CONN_ADDR.ip.remote, CONN_ADDR.ip.local, device_id)
2228            .expect("lookup should succeed");
2229        assert!(conn.contains_id(&entry2));
2230    }
2231}