netstack3_tcp/
socket.rs

1// Copyright 2022 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//! Defines how TCP state machines are used for TCP sockets.
6//!
7//! TCP state machine implemented in the parent module aims to only implement
8//! RFC 793 which lacks posix semantics.
9//!
10//! To actually support posix-style sockets:
11//! We would need two kinds of active sockets, listeners/connections (or
12//! server sockets/client sockets; both are not very accurate terms, the key
13//! difference is that the former has only local addresses but the later has
14//! remote addresses in addition). [`Connection`]s are backed by a state
15//! machine, however the state can be in any state. [`Listener`]s don't have
16//! state machines, but they create [`Connection`]s that are backed by
17//! [`State::Listen`] an incoming SYN and keep track of whether the connection
18//! is established.
19
20pub(crate) mod accept_queue;
21pub(crate) mod demux;
22pub(crate) mod diagnostics;
23pub(crate) mod generators;
24
25use core::convert::Infallible as Never;
26use core::fmt::{self, Debug};
27use core::marker::PhantomData;
28use core::num::{NonZeroU16, NonZeroUsize};
29use core::ops::{Deref, DerefMut, RangeInclusive};
30
31use assert_matches::assert_matches;
32use derivative::Derivative;
33use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
34use log::{debug, error, trace};
35use net_types::ip::{
36    GenericOverIp, Ip, IpAddr, IpAddress, IpVersion, IpVersionMarker, Ipv4, Ipv4Addr, Ipv6,
37    Ipv6Addr,
38};
39use net_types::{
40    AddrAndPortFormatter, AddrAndZone, MulticastAddress as _, SpecifiedAddr, ZonedAddr,
41};
42use netstack3_base::socket::{
43    self, AddrIsMappedError, AddrVec, Bound, ConnAddr, ConnIpAddr, DualStackListenerIpAddr,
44    DualStackLocalIp, DualStackRemoteIp, DualStackTuple, EitherStack, IncompatibleError,
45    InsertError, Inserter, ListenerAddr, ListenerAddrInfo, ListenerIpAddr, MaybeDualStack,
46    NotDualStackCapableError, RemoveResult, SetDualStackEnabledError, ShutdownType, SocketCookie,
47    SocketDeviceUpdate, SocketDeviceUpdateNotAllowedError, SocketIpAddr, SocketIpExt,
48    SocketMapAddrSpec, SocketMapAddrStateSpec, SocketMapAddrStateUpdateSharingSpec,
49    SocketMapConflictPolicy, SocketMapStateSpec, SocketMapUpdateSharingPolicy,
50    SocketZonedAddrExt as _, UpdateSharingError,
51};
52use netstack3_base::socketmap::{IterShadows as _, SocketMap};
53use netstack3_base::sync::RwLock;
54use netstack3_base::{
55    AnyDevice, BidirectionalConverter as _, ContextPair, Control, CoreTimerContext,
56    CoreTxMetadataContext, CtxPair, DeferredResourceRemovalContext, DeviceIdContext,
57    EitherDeviceId, ExistsError, HandleableTimer, IcmpErrorCode, Inspector, InspectorDeviceExt,
58    InspectorExt, InstantBindingsTypes, IpDeviceAddr, IpExt, IpSocketPropertiesMatcher,
59    LocalAddressError, Mark, MarkDomain, MatcherBindingsTypes, Mss,
60    OwnedOrRefsBidirectionalConverter, PortAllocImpl, ReferenceNotifiersExt as _,
61    RemoveResourceResult, ResourceCounterContext as _, RngContext, Segment, SeqNum,
62    SettingsContext, StrongDeviceIdentifier, TimerBindingsTypes, TimerContext,
63    TxMetadataBindingsTypes, WeakDeviceIdentifier, ZonedAddressError,
64};
65use netstack3_filter::{FilterIpExt, SocketOpsFilterBindingContext, Tuple};
66use netstack3_hashmap::{HashMap, hash_map};
67use netstack3_ip::socket::{
68    DeviceIpSocketHandler, IpSock, IpSockCreateAndSendError, IpSockCreationError, IpSocketArgs,
69    IpSocketHandler,
70};
71use netstack3_ip::{self as ip, BaseTransportIpContext, TransportIpContext};
72use netstack3_trace::{TraceResourceId, trace_duration};
73use packet_formats::ip::IpProto;
74use smallvec::{SmallVec, smallvec};
75use thiserror::Error;
76
77use crate::internal::base::{
78    BufferSizes, BuffersRefMut, ConnectionError, SocketOptions, TcpIpSockOptions,
79    TcpSocketTxMetadata,
80};
81use crate::internal::buffer::{Buffer, IntoBuffers, ReceiveBuffer, SendBuffer};
82use crate::internal::counters::{
83    self, CombinedTcpCounters, TcpCounterContext, TcpCountersRefs, TcpCountersWithSocket,
84};
85use crate::internal::settings::TcpSettings;
86use crate::internal::socket::accept_queue::{AcceptQueue, ListenerNotifier};
87use crate::internal::socket::demux::tcp_serialize_segment;
88use crate::internal::socket::diagnostics::{TcpSocketDiagnostics, TcpSocketStateForMatching};
89
90use crate::internal::socket::generators::{IsnGenerator, TimestampOffsetGenerator};
91use crate::internal::state::{
92    CloseError, CloseReason, Closed, Initial, NewlyClosed, ShouldRetransmit, State,
93    StateMachineDebugId, Takeable, TakeableRef,
94};
95
96/// A marker trait for dual-stack socket features.
97///
98/// This trait acts as a marker for [`DualStackBaseIpExt`] for both `Self` and
99/// `Self::OtherVersion`.
100pub trait DualStackIpExt:
101    DualStackBaseIpExt + netstack3_base::socket::DualStackIpExt<OtherVersion: DualStackBaseIpExt>
102{
103}
104
105impl<I> DualStackIpExt for I where
106    I: DualStackBaseIpExt
107        + netstack3_base::socket::DualStackIpExt<OtherVersion: DualStackBaseIpExt>
108{
109}
110
111/// A dual stack IP extension trait for TCP.
112pub trait DualStackBaseIpExt:
113    netstack3_base::socket::DualStackIpExt + SocketIpExt + netstack3_base::IpExt + FilterIpExt
114{
115    /// For `Ipv4`, this is [`EitherStack<TcpSocketId<Ipv4, _, _>, TcpSocketId<Ipv6, _, _>>`],
116    /// and for `Ipv6` it is just `TcpSocketId<Ipv6>`.
117    type DemuxSocketId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>: SpecSocketId;
118
119    /// The type for a connection, for [`Ipv4`], this will be just the single
120    /// stack version of the connection state and the connection address. For
121    /// [`Ipv6`], this will be a `EitherStack`.
122    type ConnectionAndAddr<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>: Send + Sync + Debug;
123
124    /// The type for the address that the listener is listening on. This should
125    /// be just [`ListenerIpAddr`] for [`Ipv4`], but a [`DualStackListenerIpAddr`]
126    /// for [`Ipv6`].
127    type ListenerIpAddr: Send + Sync + Debug + Clone;
128
129    /// The type for the original destination address of a connection. For
130    /// [`Ipv4`], this is always an [`Ipv4Addr`], and for [`Ipv6`], it is an
131    /// [`EitherStack<Ipv6Addr, Ipv4Addr>`].
132    type OriginalDstAddr;
133
134    /// IP options unique to a particular IP version.
135    type DualStackIpOptions: Send + Sync + Debug + Default + Clone + Copy;
136
137    /// Determines which stack the demux socket ID belongs to and converts
138    /// (by reference) to a dual stack TCP socket ID.
139    fn as_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
140        id: &Self::DemuxSocketId<D, BT>,
141    ) -> EitherStack<&TcpSocketId<Self, D, BT>, &TcpSocketId<Self::OtherVersion, D, BT>>
142    where
143        Self::OtherVersion: DualStackBaseIpExt;
144
145    /// Determines which stack the demux socket ID belongs to and converts
146    /// (by value) to a dual stack TCP socket ID.
147    fn into_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
148        id: Self::DemuxSocketId<D, BT>,
149    ) -> EitherStack<TcpSocketId<Self, D, BT>, TcpSocketId<Self::OtherVersion, D, BT>>
150    where
151        Self::OtherVersion: DualStackBaseIpExt;
152
153    /// Turns a [`TcpSocketId`] of the current stack into the demuxer ID.
154    fn into_demux_socket_id<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
155        id: TcpSocketId<Self, D, BT>,
156    ) -> Self::DemuxSocketId<D, BT>
157    where
158        Self::OtherVersion: DualStackBaseIpExt;
159
160    fn get_conn_info<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
161        conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
162    ) -> ConnectionInfo<Self::Addr, D>;
163    fn get_accept_queue_mut<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
164        conn_and_addr: &mut Self::ConnectionAndAddr<D, BT>,
165    ) -> &mut Option<
166        AcceptQueue<
167            TcpSocketId<Self, D, BT>,
168            BT::ReturnedBuffers,
169            BT::ListenerNotifierOrProvidedBuffers,
170        >,
171    >
172    where
173        Self::OtherVersion: DualStackBaseIpExt;
174    fn get_defunct<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
175        conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
176    ) -> bool;
177    fn get_state<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
178        conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
179    ) -> &State<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer, BT::ListenerNotifierOrProvidedBuffers>;
180    fn get_bound_info<D: WeakDeviceIdentifier>(
181        listener_addr: &ListenerAddr<Self::ListenerIpAddr, D>,
182    ) -> BoundInfo<Self::Addr, D>;
183
184    fn destroy_socket_with_demux_id<
185        CC: TcpContext<Self, BC> + TcpContext<Self::OtherVersion, BC>,
186        BC: TcpBindingsContext<CC::DeviceId>,
187    >(
188        core_ctx: &mut CC,
189        bindings_ctx: &mut BC,
190        demux_id: Self::DemuxSocketId<CC::WeakDeviceId, BC>,
191    ) where
192        Self::OtherVersion: DualStackBaseIpExt;
193
194    /// Take the original destination of the socket's connection and return an
195    /// address that is always in this socket's stack. For [`Ipv4`], this is a
196    /// no-op, but for [`Ipv6`] it may require mapping a dual-stack IPv4 address
197    /// into the IPv6 address space.
198    fn get_original_dst(addr: Self::OriginalDstAddr) -> Self::Addr;
199}
200
201impl DualStackBaseIpExt for Ipv4 {
202    type DemuxSocketId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> =
203        EitherStack<TcpSocketId<Ipv4, D, BT>, TcpSocketId<Ipv6, D, BT>>;
204    type ConnectionAndAddr<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> =
205        (Connection<Ipv4, Ipv4, D, BT>, ConnAddr<ConnIpAddr<Ipv4Addr, NonZeroU16, NonZeroU16>, D>);
206    type ListenerIpAddr = ListenerIpAddr<Ipv4Addr, NonZeroU16>;
207    type OriginalDstAddr = Ipv4Addr;
208    type DualStackIpOptions = ();
209
210    fn as_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
211        id: &Self::DemuxSocketId<D, BT>,
212    ) -> EitherStack<&TcpSocketId<Self, D, BT>, &TcpSocketId<Self::OtherVersion, D, BT>> {
213        match id {
214            EitherStack::ThisStack(id) => EitherStack::ThisStack(id),
215            EitherStack::OtherStack(id) => EitherStack::OtherStack(id),
216        }
217    }
218    fn into_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
219        id: Self::DemuxSocketId<D, BT>,
220    ) -> EitherStack<TcpSocketId<Self, D, BT>, TcpSocketId<Self::OtherVersion, D, BT>> {
221        id
222    }
223    fn into_demux_socket_id<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
224        id: TcpSocketId<Self, D, BT>,
225    ) -> Self::DemuxSocketId<D, BT> {
226        EitherStack::ThisStack(id)
227    }
228    fn get_conn_info<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
229        (_conn, addr): &Self::ConnectionAndAddr<D, BT>,
230    ) -> ConnectionInfo<Self::Addr, D> {
231        addr.clone().into()
232    }
233    fn get_accept_queue_mut<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
234        (conn, _addr): &mut Self::ConnectionAndAddr<D, BT>,
235    ) -> &mut Option<
236        AcceptQueue<
237            TcpSocketId<Self, D, BT>,
238            BT::ReturnedBuffers,
239            BT::ListenerNotifierOrProvidedBuffers,
240        >,
241    > {
242        &mut conn.accept_queue
243    }
244    fn get_defunct<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
245        (conn, _addr): &Self::ConnectionAndAddr<D, BT>,
246    ) -> bool {
247        conn.defunct
248    }
249    fn get_state<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
250        (conn, _addr): &Self::ConnectionAndAddr<D, BT>,
251    ) -> &State<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer, BT::ListenerNotifierOrProvidedBuffers>
252    {
253        &conn.state
254    }
255    fn get_bound_info<D: WeakDeviceIdentifier>(
256        listener_addr: &ListenerAddr<Self::ListenerIpAddr, D>,
257    ) -> BoundInfo<Self::Addr, D> {
258        listener_addr.clone().into()
259    }
260
261    fn destroy_socket_with_demux_id<
262        CC: TcpContext<Self, BC> + TcpContext<Self::OtherVersion, BC>,
263        BC: TcpBindingsContext<CC::DeviceId>,
264    >(
265        core_ctx: &mut CC,
266        bindings_ctx: &mut BC,
267        demux_id: Self::DemuxSocketId<CC::WeakDeviceId, BC>,
268    ) {
269        match demux_id {
270            EitherStack::ThisStack(id) => destroy_socket(core_ctx, bindings_ctx, id),
271            EitherStack::OtherStack(id) => destroy_socket(core_ctx, bindings_ctx, id),
272        }
273    }
274
275    fn get_original_dst(addr: Self::OriginalDstAddr) -> Self::Addr {
276        addr
277    }
278}
279
280/// Socket options that are accessible on IPv6 sockets.
281#[derive(Derivative, Debug, Clone, Copy, PartialEq, Eq)]
282#[derivative(Default)]
283pub struct Ipv6Options {
284    /// True if this socket has dual stack enabled.
285    #[derivative(Default(value = "true"))]
286    pub dual_stack_enabled: bool,
287}
288
289impl DualStackBaseIpExt for Ipv6 {
290    type DemuxSocketId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> = TcpSocketId<Ipv6, D, BT>;
291    type ConnectionAndAddr<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> = EitherStack<
292        (Connection<Ipv6, Ipv6, D, BT>, ConnAddr<ConnIpAddr<Ipv6Addr, NonZeroU16, NonZeroU16>, D>),
293        (Connection<Ipv6, Ipv4, D, BT>, ConnAddr<ConnIpAddr<Ipv4Addr, NonZeroU16, NonZeroU16>, D>),
294    >;
295    type DualStackIpOptions = Ipv6Options;
296    type ListenerIpAddr = DualStackListenerIpAddr<Ipv6Addr, NonZeroU16>;
297    type OriginalDstAddr = EitherStack<Ipv6Addr, Ipv4Addr>;
298
299    fn as_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
300        id: &Self::DemuxSocketId<D, BT>,
301    ) -> EitherStack<&TcpSocketId<Self, D, BT>, &TcpSocketId<Self::OtherVersion, D, BT>> {
302        EitherStack::ThisStack(id)
303    }
304    fn into_dual_stack_ip_socket<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
305        id: Self::DemuxSocketId<D, BT>,
306    ) -> EitherStack<TcpSocketId<Self, D, BT>, TcpSocketId<Self::OtherVersion, D, BT>> {
307        EitherStack::ThisStack(id)
308    }
309
310    fn into_demux_socket_id<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
311        id: TcpSocketId<Self, D, BT>,
312    ) -> Self::DemuxSocketId<D, BT> {
313        id
314    }
315    fn get_conn_info<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
316        conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
317    ) -> ConnectionInfo<Self::Addr, D> {
318        match conn_and_addr {
319            EitherStack::ThisStack((_conn, addr)) => addr.clone().into(),
320            EitherStack::OtherStack((
321                _conn,
322                ConnAddr {
323                    ip:
324                        ConnIpAddr { local: (local_ip, local_port), remote: (remote_ip, remote_port) },
325                    device,
326                },
327            )) => ConnectionInfo {
328                local_addr: SocketAddr {
329                    ip: maybe_zoned(local_ip.addr().to_ipv6_mapped(), device),
330                    port: *local_port,
331                },
332                remote_addr: SocketAddr {
333                    ip: maybe_zoned(remote_ip.addr().to_ipv6_mapped(), device),
334                    port: *remote_port,
335                },
336                device: device.clone(),
337            },
338        }
339    }
340    fn get_accept_queue_mut<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
341        conn_and_addr: &mut Self::ConnectionAndAddr<D, BT>,
342    ) -> &mut Option<
343        AcceptQueue<
344            TcpSocketId<Self, D, BT>,
345            BT::ReturnedBuffers,
346            BT::ListenerNotifierOrProvidedBuffers,
347        >,
348    > {
349        match conn_and_addr {
350            EitherStack::ThisStack((conn, _addr)) => &mut conn.accept_queue,
351            EitherStack::OtherStack((conn, _addr)) => &mut conn.accept_queue,
352        }
353    }
354    fn get_defunct<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
355        conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
356    ) -> bool {
357        match conn_and_addr {
358            EitherStack::ThisStack((conn, _addr)) => conn.defunct,
359            EitherStack::OtherStack((conn, _addr)) => conn.defunct,
360        }
361    }
362    fn get_state<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
363        conn_and_addr: &Self::ConnectionAndAddr<D, BT>,
364    ) -> &State<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer, BT::ListenerNotifierOrProvidedBuffers>
365    {
366        match conn_and_addr {
367            EitherStack::ThisStack((conn, _addr)) => &conn.state,
368            EitherStack::OtherStack((conn, _addr)) => &conn.state,
369        }
370    }
371    fn get_bound_info<D: WeakDeviceIdentifier>(
372        ListenerAddr { ip, device }: &ListenerAddr<Self::ListenerIpAddr, D>,
373    ) -> BoundInfo<Self::Addr, D> {
374        match ip {
375            DualStackListenerIpAddr::ThisStack(ip) => {
376                ListenerAddr { ip: ip.clone(), device: device.clone() }.into()
377            }
378            DualStackListenerIpAddr::OtherStack(ListenerIpAddr {
379                addr,
380                identifier: local_port,
381            }) => BoundInfo {
382                addr: Some(maybe_zoned(
383                    addr.map(|a| a.addr()).unwrap_or(Ipv4::UNSPECIFIED_ADDRESS).to_ipv6_mapped(),
384                    &device,
385                )),
386                port: *local_port,
387                device: device.clone(),
388            },
389            DualStackListenerIpAddr::BothStacks(local_port) => {
390                BoundInfo { addr: None, port: *local_port, device: device.clone() }
391            }
392        }
393    }
394
395    fn destroy_socket_with_demux_id<
396        CC: TcpContext<Self, BC> + TcpContext<Self::OtherVersion, BC>,
397        BC: TcpBindingsContext<CC::DeviceId>,
398    >(
399        core_ctx: &mut CC,
400        bindings_ctx: &mut BC,
401        demux_id: Self::DemuxSocketId<CC::WeakDeviceId, BC>,
402    ) {
403        destroy_socket(core_ctx, bindings_ctx, demux_id)
404    }
405
406    fn get_original_dst(addr: Self::OriginalDstAddr) -> Self::Addr {
407        match addr {
408            EitherStack::ThisStack(addr) => addr,
409            EitherStack::OtherStack(addr) => *addr.to_ipv6_mapped(),
410        }
411    }
412}
413
414/// Timer ID for TCP connections.
415#[derive(Derivative, GenericOverIp)]
416#[generic_over_ip()]
417#[derivative(
418    Clone(bound = ""),
419    Eq(bound = ""),
420    PartialEq(bound = ""),
421    Hash(bound = ""),
422    Debug(bound = "")
423)]
424#[allow(missing_docs)]
425pub enum TcpTimerId<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
426    V4(WeakTcpSocketId<Ipv4, D, BT>),
427    V6(WeakTcpSocketId<Ipv6, D, BT>),
428}
429
430impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
431    From<WeakTcpSocketId<I, D, BT>> for TcpTimerId<D, BT>
432{
433    fn from(f: WeakTcpSocketId<I, D, BT>) -> Self {
434        I::map_ip(f, TcpTimerId::V4, TcpTimerId::V6)
435    }
436}
437
438/// Bindings types for TCP.
439///
440/// The relationship between buffers  is as follows:
441///
442/// The Bindings will receive the `ReturnedBuffers` so that it can: 1. give the
443/// application a handle to read/write data; 2. Observe whatever signal required
444/// from the application so that it can inform Core. The peer end of returned
445/// handle will be held by the state machine inside the netstack. Specialized
446/// receive/send buffers will be derived from `ProvidedBuffers` from Bindings.
447///
448/// +-------------------------------+
449/// |       +--------------+        |
450/// |       |   returned   |        |
451/// |       |    buffers   |        |
452/// |       +------+-------+        |
453/// |              |     application|
454/// +--------------+----------------+
455///                |
456/// +--------------+----------------+
457/// |              |        netstack|
458/// |   +---+------+-------+---+    |
459/// |   |   |  provided    |   |    |
460/// |   | +-+-  buffers   -+-+ |    |
461/// |   +-+-+--------------+-+-+    |
462/// |     v                  v      |
463/// |receive buffer     send buffer |
464/// +-------------------------------+
465
466pub trait TcpBindingsTypes:
467    InstantBindingsTypes + TimerBindingsTypes + TxMetadataBindingsTypes + MatcherBindingsTypes + 'static
468{
469    /// Receive buffer used by TCP.
470    type ReceiveBuffer: ReceiveBuffer + Send + Sync;
471    /// Send buffer used by TCP.
472    type SendBuffer: SendBuffer + Send + Sync;
473    /// The object that will be returned by the state machine when a passive
474    /// open connection becomes established. The bindings can use this object
475    /// to read/write bytes from/into the created buffers.
476    type ReturnedBuffers: Debug + Send + Sync;
477    /// The extra information provided by the Bindings that implements platform
478    /// dependent behaviors. It serves as a [`ListenerNotifier`] if the socket
479    /// was used as a listener and it will be used to provide buffers if used
480    /// to establish connections.
481    type ListenerNotifierOrProvidedBuffers: Debug
482        + IntoBuffers<Self::ReceiveBuffer, Self::SendBuffer>
483        + ListenerNotifier
484        + Send
485        + Sync;
486
487    /// Creates new buffers and returns the object that Bindings need to
488    /// read/write from/into the created buffers.
489    fn new_passive_open_buffers(
490        buffer_sizes: BufferSizes,
491    ) -> (Self::ReceiveBuffer, Self::SendBuffer, Self::ReturnedBuffers);
492}
493
494/// The bindings context for TCP.
495///
496/// TCP timers are scoped by weak device IDs.
497pub trait TcpBindingsContext<D: StrongDeviceIdentifier>:
498    Sized
499    + DeferredResourceRemovalContext
500    + TimerContext
501    + RngContext
502    + TcpBindingsTypes
503    + SocketOpsFilterBindingContext<D>
504    + SettingsContext<TcpSettings>
505{
506}
507
508impl<D, BC> TcpBindingsContext<D> for BC
509where
510    D: StrongDeviceIdentifier,
511    BC: Sized
512        + DeferredResourceRemovalContext
513        + TimerContext
514        + RngContext
515        + TcpBindingsTypes
516        + SocketOpsFilterBindingContext<D>
517        + SettingsContext<TcpSettings>,
518{
519}
520
521/// The core execution context abstracting demux state access for TCP.
522pub trait TcpDemuxContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
523    TcpCoreTimerContext<I, D, BT>
524{
525    /// The inner IP transport context.
526    type IpTransportCtx<'a>: TransportIpContext<I, BT, DeviceId = D::Strong, WeakDeviceId = D>
527        + DeviceIpSocketHandler<I, BT>
528        + TcpCoreTimerContext<I, D, BT>;
529
530    /// Calls `f` with non-mutable access to the demux state.
531    fn with_demux<O, F: FnOnce(&DemuxState<I, D, BT>) -> O>(&mut self, cb: F) -> O;
532
533    /// Calls `f` with mutable access to the demux state.
534    fn with_demux_mut<O, F: FnOnce(&mut DemuxState<I, D, BT>) -> O>(&mut self, cb: F) -> O;
535}
536
537/// Provides access to the current stack of the context.
538///
539/// This is useful when dealing with logic that applies to the current stack
540/// but we want to be version agnostic: we have different associated types for
541/// single-stack and dual-stack contexts, we can use this function to turn them
542/// into the same type that only provides access to the current version of the
543/// stack and trims down access to `I::OtherVersion`.
544pub trait AsThisStack<T> {
545    /// Get the this stack version of the context.
546    fn as_this_stack(&mut self) -> &mut T;
547}
548
549impl<T> AsThisStack<T> for T {
550    fn as_this_stack(&mut self) -> &mut T {
551        self
552    }
553}
554
555/// A marker traits for all traits used to access TCP socket.
556pub trait TcpSocketContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
557    TcpCounterContext<I, D, BT> + CoreTxMetadataContext<TcpSocketTxMetadata<I, D, BT>, BT>
558{
559}
560
561impl<CC, I, D, BC> TcpSocketContext<I, D, BC> for CC
562where
563    I: DualStackIpExt,
564    D: WeakDeviceIdentifier,
565    BC: TcpBindingsTypes,
566    CC: TcpCounterContext<I, D, BC> + CoreTxMetadataContext<TcpSocketTxMetadata<I, D, BC>, BC>,
567{
568}
569
570/// A shortcut for the `CoreTimerContext` required by TCP.
571pub trait TcpCoreTimerContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BC: TcpBindingsTypes>:
572    CoreTimerContext<WeakTcpSocketId<I, D, BC>, BC>
573{
574}
575
576impl<CC, I, D, BC> TcpCoreTimerContext<I, D, BC> for CC
577where
578    I: DualStackIpExt,
579    D: WeakDeviceIdentifier,
580    BC: TcpBindingsTypes,
581    CC: CoreTimerContext<WeakTcpSocketId<I, D, BC>, BC>,
582{
583}
584
585/// A marker trait for all dual stack conversions in [`TcpContext`].
586pub trait DualStackConverter<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
587    OwnedOrRefsBidirectionalConverter<
588        I::ConnectionAndAddr<D, BT>,
589        EitherStack<
590            (
591                Connection<I, I, D, BT>,
592                ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
593            ),
594            (
595                Connection<I, I::OtherVersion, D, BT>,
596                ConnAddr<ConnIpAddr<<I::OtherVersion as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
597            ),
598        >,
599    > + OwnedOrRefsBidirectionalConverter<
600        I::ListenerIpAddr,
601        DualStackListenerIpAddr<I::Addr, NonZeroU16>,
602    > + OwnedOrRefsBidirectionalConverter<
603        ListenerAddr<I::ListenerIpAddr, D>,
604        ListenerAddr<DualStackListenerIpAddr<I::Addr, NonZeroU16>, D>,
605    > + OwnedOrRefsBidirectionalConverter<
606        I::OriginalDstAddr,
607        EitherStack<I::Addr, <I::OtherVersion as Ip>::Addr>,
608    >
609{
610}
611
612impl<I, D, BT, O> DualStackConverter<I, D, BT> for O
613where
614    I: DualStackIpExt,
615    D: WeakDeviceIdentifier,
616    BT: TcpBindingsTypes,
617    O: OwnedOrRefsBidirectionalConverter<
618            I::ConnectionAndAddr<D, BT>,
619            EitherStack<
620                (
621                    Connection<I, I, D, BT>,
622                    ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
623                ),
624                (
625                    Connection<I, I::OtherVersion, D, BT>,
626                    ConnAddr<ConnIpAddr<<I::OtherVersion as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
627                ),
628            >,
629        > + OwnedOrRefsBidirectionalConverter<
630            I::ListenerIpAddr,
631            DualStackListenerIpAddr<I::Addr, NonZeroU16>,
632        > + OwnedOrRefsBidirectionalConverter<
633            ListenerAddr<I::ListenerIpAddr, D>,
634            ListenerAddr<DualStackListenerIpAddr<I::Addr, NonZeroU16>, D>,
635        > + OwnedOrRefsBidirectionalConverter<
636            I::OriginalDstAddr,
637            EitherStack<I::Addr, <I::OtherVersion as Ip>::Addr>,
638        >,
639{
640}
641
642/// A marker trait for all single stack conversions in [`TcpContext`].
643pub trait SingleStackConverter<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>:
644    OwnedOrRefsBidirectionalConverter<
645        I::ConnectionAndAddr<D, BT>,
646        (Connection<I, I, D, BT>, ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>),
647    > + OwnedOrRefsBidirectionalConverter<I::ListenerIpAddr, ListenerIpAddr<I::Addr, NonZeroU16>>
648    + OwnedOrRefsBidirectionalConverter<
649        ListenerAddr<I::ListenerIpAddr, D>,
650        ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
651    > + OwnedOrRefsBidirectionalConverter<I::OriginalDstAddr, I::Addr>
652{
653}
654
655impl<I, D, BT, O> SingleStackConverter<I, D, BT> for O
656where
657    I: DualStackIpExt,
658    D: WeakDeviceIdentifier,
659    BT: TcpBindingsTypes,
660    O: OwnedOrRefsBidirectionalConverter<
661            I::ConnectionAndAddr<D, BT>,
662            (
663                Connection<I, I, D, BT>,
664                ConnAddr<ConnIpAddr<<I as Ip>::Addr, NonZeroU16, NonZeroU16>, D>,
665            ),
666        > + OwnedOrRefsBidirectionalConverter<I::ListenerIpAddr, ListenerIpAddr<I::Addr, NonZeroU16>>
667        + OwnedOrRefsBidirectionalConverter<
668            ListenerAddr<I::ListenerIpAddr, D>,
669            ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
670        > + OwnedOrRefsBidirectionalConverter<I::OriginalDstAddr, I::Addr>,
671{
672}
673
674/// Core context for TCP.
675pub trait TcpContext<I: DualStackIpExt, BC: TcpBindingsTypes>:
676    TcpDemuxContext<I, Self::WeakDeviceId, BC>
677    + IpSocketHandler<I, BC>
678    + TcpSocketContext<I, Self::WeakDeviceId, BC>
679{
680    /// The core context for the current version of the IP protocol. This is
681    /// used to be version agnostic when the operation is on the current stack.
682    type ThisStackIpTransportAndDemuxCtx<'a>: TransportIpContext<I, BC, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
683        + DeviceIpSocketHandler<I, BC>
684        + TcpDemuxContext<I, Self::WeakDeviceId, BC>
685        + TcpSocketContext<I, Self::WeakDeviceId, BC>;
686
687    /// The core context that will give access to this version of the IP layer.
688    type SingleStackIpTransportAndDemuxCtx<'a>: TransportIpContext<I, BC, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
689        + DeviceIpSocketHandler<I, BC>
690        + TcpDemuxContext<I, Self::WeakDeviceId, BC>
691        + AsThisStack<Self::ThisStackIpTransportAndDemuxCtx<'a>>
692        + TcpSocketContext<I, Self::WeakDeviceId, BC>;
693
694    /// A collection of type assertions that must be true in the single stack
695    /// version, associated types and concrete types must unify and we can
696    /// inspect types by converting them into the concrete types.
697    type SingleStackConverter: SingleStackConverter<I, Self::WeakDeviceId, BC>;
698
699    /// The core context that will give access to both versions of the IP layer.
700    type DualStackIpTransportAndDemuxCtx<'a>: TransportIpContext<I, BC, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
701        + DeviceIpSocketHandler<I, BC>
702        + TcpDemuxContext<I, Self::WeakDeviceId, BC>
703        + TransportIpContext<
704            I::OtherVersion,
705            BC,
706            DeviceId = Self::DeviceId,
707            WeakDeviceId = Self::WeakDeviceId,
708        > + DeviceIpSocketHandler<I::OtherVersion, BC>
709        + TcpDemuxContext<I::OtherVersion, Self::WeakDeviceId, BC>
710        + TcpDualStackContext<I, Self::WeakDeviceId, BC>
711        + AsThisStack<Self::ThisStackIpTransportAndDemuxCtx<'a>>
712        + TcpSocketContext<I, Self::WeakDeviceId, BC>
713        + TcpCounterContext<I::OtherVersion, Self::WeakDeviceId, BC>;
714
715    /// A collection of type assertions that must be true in the dual stack
716    /// version, associated types and concrete types must unify and we can
717    /// inspect types by converting them into the concrete types.
718    type DualStackConverter: DualStackConverter<I, Self::WeakDeviceId, BC>;
719
720    /// Calls the function with mutable access to the set with all TCP sockets.
721    fn with_all_sockets_mut<O, F: FnOnce(&mut TcpSocketSet<I, Self::WeakDeviceId, BC>) -> O>(
722        &mut self,
723        cb: F,
724    ) -> O;
725
726    /// Calls the callback once for each currently installed socket.
727    fn for_each_socket<
728        F: FnMut(&TcpSocketId<I, Self::WeakDeviceId, BC>, &TcpSocketState<I, Self::WeakDeviceId, BC>),
729    >(
730        &mut self,
731        cb: F,
732    );
733
734    /// Calls the function with access to the socket state,
735    /// ISN & Timestamp Offset generators, and Transport + Demux context.
736    fn with_socket_mut_generators_transport_demux<
737        O,
738        F: for<'a> FnOnce(
739            MaybeDualStack<
740                (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
741                (&'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>, Self::SingleStackConverter),
742            >,
743            &mut TcpSocketState<I, Self::WeakDeviceId, BC>,
744            &IsnGenerator<BC::Instant>,
745            &TimestampOffsetGenerator<BC::Instant>,
746        ) -> O,
747    >(
748        &mut self,
749        id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
750        cb: F,
751    ) -> O;
752
753    /// Calls the function with immutable access to the socket state.
754    fn with_socket<O, F: FnOnce(&TcpSocketState<I, Self::WeakDeviceId, BC>) -> O>(
755        &mut self,
756        id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
757        cb: F,
758    ) -> O {
759        self.with_socket_and_converter(id, |socket_state, _converter| cb(socket_state))
760    }
761
762    /// Calls the function with the immutable reference to the socket state and
763    /// a converter to inspect.
764    fn with_socket_and_converter<
765        O,
766        F: FnOnce(
767            &TcpSocketState<I, Self::WeakDeviceId, BC>,
768            MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
769        ) -> O,
770    >(
771        &mut self,
772        id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
773        cb: F,
774    ) -> O;
775
776    /// Calls the function with access to the socket state and Transport + Demux
777    /// context.
778    fn with_socket_mut_transport_demux<
779        O,
780        F: for<'a> FnOnce(
781            MaybeDualStack<
782                (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
783                (&'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>, Self::SingleStackConverter),
784            >,
785            &mut TcpSocketState<I, Self::WeakDeviceId, BC>,
786        ) -> O,
787    >(
788        &mut self,
789        id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
790        cb: F,
791    ) -> O {
792        self.with_socket_mut_generators_transport_demux(
793            id,
794            |ctx, socket_state, _isn, _timestamp_offset| cb(ctx, socket_state),
795        )
796    }
797
798    /// Calls the function with mutable access to the socket state.
799    fn with_socket_mut<O, F: FnOnce(&mut TcpSocketState<I, Self::WeakDeviceId, BC>) -> O>(
800        &mut self,
801        id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
802        cb: F,
803    ) -> O {
804        self.with_socket_mut_generators_transport_demux(
805            id,
806            |_ctx, socket_state, _isn, _timestamp_offset| cb(socket_state),
807        )
808    }
809
810    /// Calls the function with the mutable reference to the socket state and a
811    /// converter to inspect.
812    fn with_socket_mut_and_converter<
813        O,
814        F: FnOnce(
815            &mut TcpSocketState<I, Self::WeakDeviceId, BC>,
816            MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
817        ) -> O,
818    >(
819        &mut self,
820        id: &TcpSocketId<I, Self::WeakDeviceId, BC>,
821        cb: F,
822    ) -> O {
823        self.with_socket_mut_generators_transport_demux(
824            id,
825            |ctx, socket_state, _isn, _timestamp_offset| {
826                let converter = match ctx {
827                    MaybeDualStack::NotDualStack((_core_ctx, converter)) => {
828                        MaybeDualStack::NotDualStack(converter)
829                    }
830                    MaybeDualStack::DualStack((_core_ctx, converter)) => {
831                        MaybeDualStack::DualStack(converter)
832                    }
833                };
834                cb(socket_state, converter)
835            },
836        )
837    }
838}
839
840/// A ZST that helps convert IPv6 socket IDs into IPv4 demux IDs.
841#[derive(Clone, Copy)]
842pub struct Ipv6SocketIdToIpv4DemuxIdConverter;
843
844/// This trait allows us to work around the life-time issue when we need to
845/// convert an IPv6 socket ID into an IPv4 demux ID without holding on the
846/// a dual-stack CoreContext.
847pub trait DualStackDemuxIdConverter<I: DualStackIpExt>: 'static + Clone + Copy {
848    /// Turns a [`TcpSocketId`] into the demuxer ID of the other stack.
849    fn convert<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
850        &self,
851        id: TcpSocketId<I, D, BT>,
852    ) -> <I::OtherVersion as DualStackBaseIpExt>::DemuxSocketId<D, BT>;
853}
854
855impl DualStackDemuxIdConverter<Ipv6> for Ipv6SocketIdToIpv4DemuxIdConverter {
856    fn convert<D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
857        &self,
858        id: TcpSocketId<Ipv6, D, BT>,
859    ) -> <Ipv4 as DualStackBaseIpExt>::DemuxSocketId<D, BT> {
860        EitherStack::OtherStack(id)
861    }
862}
863
864/// A provider of dualstack socket functionality required by TCP sockets.
865pub trait TcpDualStackContext<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
866    /// The inner IP transport context,
867    type DualStackIpTransportCtx<'a>: TransportIpContext<I, BT, DeviceId = D::Strong, WeakDeviceId = D>
868        + DeviceIpSocketHandler<I, BT>
869        + TcpCoreTimerContext<I, D, BT>
870        + TransportIpContext<I::OtherVersion, BT, DeviceId = D::Strong, WeakDeviceId = D>
871        + DeviceIpSocketHandler<I::OtherVersion, BT>
872        + TcpCoreTimerContext<I::OtherVersion, D, BT>;
873
874    /// Gets a converter to get the demux socket ID for the other stack.
875    fn other_demux_id_converter(&self) -> impl DualStackDemuxIdConverter<I>;
876
877    /// Turns a [`TcpSocketId`] into the demuxer ID of the other stack.
878    fn into_other_demux_socket_id(
879        &self,
880        id: TcpSocketId<I, D, BT>,
881    ) -> <I::OtherVersion as DualStackBaseIpExt>::DemuxSocketId<D, BT> {
882        self.other_demux_id_converter().convert(id)
883    }
884
885    /// Returns a dual stack tuple with both demux identifiers for `id`.
886    fn dual_stack_demux_id(
887        &self,
888        id: TcpSocketId<I, D, BT>,
889    ) -> DualStackTuple<I, DemuxSocketId<I, D, BT>> {
890        let this_id = DemuxSocketId::<I, _, _>(I::into_demux_socket_id(id.clone()));
891        let other_id = DemuxSocketId::<I::OtherVersion, _, _>(self.into_other_demux_socket_id(id));
892        DualStackTuple::new(this_id, other_id)
893    }
894
895    /// Gets the enabled state of dual stack operations on the given socket.
896    fn dual_stack_enabled(&self, ip_options: &I::DualStackIpOptions) -> bool;
897    /// Sets the enabled state of dual stack operations on the given socket.
898    fn set_dual_stack_enabled(&self, ip_options: &mut I::DualStackIpOptions, value: bool);
899
900    /// Calls `cb` with mutable access to both demux states.
901    fn with_both_demux_mut<
902        O,
903        F: FnOnce(&mut DemuxState<I, D, BT>, &mut DemuxState<I::OtherVersion, D, BT>) -> O,
904    >(
905        &mut self,
906        cb: F,
907    ) -> O;
908}
909
910/// Socket address includes the ip address and the port number.
911#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, GenericOverIp)]
912#[generic_over_ip(A, IpAddress)]
913pub struct SocketAddr<A: IpAddress, D> {
914    /// The IP component of the address.
915    pub ip: ZonedAddr<SpecifiedAddr<A>, D>,
916    /// The port component of the address.
917    pub port: NonZeroU16,
918}
919
920impl<A: IpAddress, D> From<SocketAddr<A, D>>
921    for IpAddr<SocketAddr<Ipv4Addr, D>, SocketAddr<Ipv6Addr, D>>
922{
923    fn from(addr: SocketAddr<A, D>) -> IpAddr<SocketAddr<Ipv4Addr, D>, SocketAddr<Ipv6Addr, D>> {
924        <A::Version as Ip>::map_ip_in(addr, |i| IpAddr::V4(i), |i| IpAddr::V6(i))
925    }
926}
927
928impl<A: IpAddress, D> SocketAddr<A, D> {
929    /// Maps the [`SocketAddr`]'s zone type.
930    pub fn map_zone<Y>(self, f: impl FnOnce(D) -> Y) -> SocketAddr<A, Y> {
931        let Self { ip, port } = self;
932        SocketAddr { ip: ip.map_zone(f), port }
933    }
934}
935
936impl<A: IpAddress, D: fmt::Display> fmt::Display for SocketAddr<A, D> {
937    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
938        let Self { ip, port } = self;
939        let formatter = AddrAndPortFormatter::<_, _, A::Version>::new(
940            ip.as_ref().map_addr(core::convert::AsRef::<A>::as_ref),
941            port,
942        );
943        formatter.fmt(f)
944    }
945}
946
947/// Uninstantiable type used to implement [`SocketMapAddrSpec`] for TCP
948pub(crate) enum TcpPortSpec {}
949
950impl SocketMapAddrSpec for TcpPortSpec {
951    type RemoteIdentifier = NonZeroU16;
952    type LocalIdentifier = NonZeroU16;
953}
954
955/// An implementation of [`IpTransportContext`] for TCP.
956pub enum TcpIpTransportContext {}
957
958/// This trait is only used as a marker for the identifier that
959/// [`TcpSocketSpec`] keeps in the socket map. This is effectively only
960/// implemented for [`TcpSocketId`] but defining a trait effectively reduces the
961/// number of type parameters percolating down to the socket map types since
962/// they only really care about the identifier's behavior.
963pub trait SpecSocketId: Clone + Eq + PartialEq + Debug + 'static {}
964impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> SpecSocketId
965    for TcpSocketId<I, D, BT>
966{
967}
968
969impl<A: SpecSocketId, B: SpecSocketId> SpecSocketId for EitherStack<A, B> {}
970
971/// Uninstantiatable type for implementing [`SocketMapStateSpec`].
972struct TcpSocketSpec<I, D, BT>(PhantomData<(I, D, BT)>, Never);
973
974impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> SocketMapStateSpec
975    for TcpSocketSpec<I, D, BT>
976{
977    type ListenerId = I::DemuxSocketId<D, BT>;
978    type ConnId = I::DemuxSocketId<D, BT>;
979
980    type ListenerSharingState = ListenerSharingState;
981    type ConnSharingState = SharingState;
982    type AddrVecTag = AddrVecTag;
983
984    type ListenerAddrState = ListenerAddrState<Self::ListenerId>;
985    type ConnAddrState = ConnAddrState<Self::ConnId>;
986
987    fn listener_tag(
988        ListenerAddrInfo { has_device, specified_addr: _ }: ListenerAddrInfo,
989        state: &Self::ListenerAddrState,
990    ) -> Self::AddrVecTag {
991        let (sharing, state) = match state {
992            ListenerAddrState::ExclusiveBound(_) => {
993                (SharingState::Exclusive, SocketTagState::Bound)
994            }
995            ListenerAddrState::ExclusiveListener(_) => {
996                (SharingState::Exclusive, SocketTagState::Listener)
997            }
998            ListenerAddrState::Shared { listener, bound: _ } => (
999                SharingState::ReuseAddress,
1000                match listener {
1001                    Some(_) => SocketTagState::Listener,
1002                    None => SocketTagState::Bound,
1003                },
1004            ),
1005        };
1006        AddrVecTag { sharing, state, has_device }
1007    }
1008
1009    fn connected_tag(has_device: bool, state: &Self::ConnAddrState) -> Self::AddrVecTag {
1010        let ConnAddrState { sharing, id: _ } = state;
1011        AddrVecTag { sharing: *sharing, has_device, state: SocketTagState::Conn }
1012    }
1013}
1014
1015#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1016struct AddrVecTag {
1017    sharing: SharingState,
1018    state: SocketTagState,
1019    has_device: bool,
1020}
1021
1022#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1023enum SocketTagState {
1024    Conn,
1025    Listener,
1026    Bound,
1027}
1028
1029#[derive(Debug)]
1030enum ListenerAddrState<S> {
1031    ExclusiveBound(S),
1032    ExclusiveListener(S),
1033    Shared { listener: Option<S>, bound: SmallVec<[S; 1]> },
1034}
1035
1036#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1037pub struct ListenerSharingState {
1038    pub(crate) sharing: SharingState,
1039    pub(crate) listening: bool,
1040}
1041
1042enum ListenerAddrInserter<'a, S> {
1043    Listener(&'a mut Option<S>),
1044    Bound(&'a mut SmallVec<[S; 1]>),
1045}
1046
1047impl<'a, S> Inserter<S> for ListenerAddrInserter<'a, S> {
1048    fn insert(self, id: S) {
1049        match self {
1050            Self::Listener(o) => *o = Some(id),
1051            Self::Bound(b) => b.push(id),
1052        }
1053    }
1054}
1055
1056#[derive(Derivative)]
1057#[derivative(Debug(bound = "D: Debug"))]
1058pub enum BoundSocketState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1059    Listener((MaybeListener<I, D, BT>, ListenerSharingState, ListenerAddr<I::ListenerIpAddr, D>)),
1060    Connected { conn: I::ConnectionAndAddr<D, BT>, sharing: SharingState, timer: BT::Timer },
1061}
1062
1063impl<S: SpecSocketId> SocketMapAddrStateSpec for ListenerAddrState<S> {
1064    type SharingState = ListenerSharingState;
1065    type Id = S;
1066    type Inserter<'a> = ListenerAddrInserter<'a, S>;
1067
1068    fn new(new_sharing_state: &Self::SharingState, id: Self::Id) -> Self {
1069        let ListenerSharingState { sharing, listening } = new_sharing_state;
1070        match sharing {
1071            SharingState::Exclusive => match listening {
1072                true => Self::ExclusiveListener(id),
1073                false => Self::ExclusiveBound(id),
1074            },
1075            SharingState::ReuseAddress => {
1076                let (listener, bound) =
1077                    if *listening { (Some(id), Default::default()) } else { (None, smallvec![id]) };
1078                Self::Shared { listener, bound }
1079            }
1080        }
1081    }
1082
1083    fn contains_id(&self, id: &Self::Id) -> bool {
1084        match self {
1085            Self::ExclusiveBound(x) | Self::ExclusiveListener(x) => id == x,
1086            Self::Shared { listener, bound } => {
1087                listener.as_ref().is_some_and(|x| id == x) || bound.contains(id)
1088            }
1089        }
1090    }
1091
1092    fn could_insert(
1093        &self,
1094        new_sharing_state: &Self::SharingState,
1095    ) -> Result<(), IncompatibleError> {
1096        match self {
1097            Self::ExclusiveBound(_) | Self::ExclusiveListener(_) => Err(IncompatibleError),
1098            Self::Shared { listener, bound: _ } => {
1099                let ListenerSharingState { listening: _, sharing } = new_sharing_state;
1100                match sharing {
1101                    SharingState::Exclusive => Err(IncompatibleError),
1102                    SharingState::ReuseAddress => match listener {
1103                        Some(_) => Err(IncompatibleError),
1104                        None => Ok(()),
1105                    },
1106                }
1107            }
1108        }
1109    }
1110
1111    fn remove_by_id(&mut self, id: Self::Id) -> RemoveResult {
1112        match self {
1113            Self::ExclusiveBound(b) => {
1114                assert_eq!(*b, id);
1115                RemoveResult::IsLast
1116            }
1117            Self::ExclusiveListener(l) => {
1118                assert_eq!(*l, id);
1119                RemoveResult::IsLast
1120            }
1121            Self::Shared { listener, bound } => {
1122                match listener {
1123                    Some(l) if *l == id => {
1124                        *listener = None;
1125                    }
1126                    Some(_) | None => {
1127                        let index = bound.iter().position(|b| *b == id).expect("invalid socket ID");
1128                        let _: S = bound.swap_remove(index);
1129                    }
1130                };
1131                match (listener, bound.is_empty()) {
1132                    (Some(_), _) => RemoveResult::Success,
1133                    (None, false) => RemoveResult::Success,
1134                    (None, true) => RemoveResult::IsLast,
1135                }
1136            }
1137        }
1138    }
1139
1140    fn try_get_inserter<'a, 'b>(
1141        &'b mut self,
1142        new_sharing_state: &'a Self::SharingState,
1143    ) -> Result<Self::Inserter<'b>, IncompatibleError> {
1144        match self {
1145            Self::ExclusiveBound(_) | Self::ExclusiveListener(_) => Err(IncompatibleError),
1146            Self::Shared { listener, bound } => {
1147                let ListenerSharingState { listening, sharing } = new_sharing_state;
1148                match sharing {
1149                    SharingState::Exclusive => Err(IncompatibleError),
1150                    SharingState::ReuseAddress => {
1151                        match listener {
1152                            Some(_) => {
1153                                // Always fail to insert if there is already a
1154                                // listening socket.
1155                                Err(IncompatibleError)
1156                            }
1157                            None => Ok(match listening {
1158                                true => ListenerAddrInserter::Listener(listener),
1159                                false => ListenerAddrInserter::Bound(bound),
1160                            }),
1161                        }
1162                    }
1163                }
1164            }
1165        }
1166    }
1167}
1168
1169impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1170    SocketMapUpdateSharingPolicy<
1171        ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1172        ListenerSharingState,
1173        I,
1174        D,
1175        TcpPortSpec,
1176    > for TcpSocketSpec<I, D, BT>
1177{
1178    fn allows_sharing_update(
1179        socketmap: &SocketMap<AddrVec<I, D, TcpPortSpec>, Bound<Self>>,
1180        addr: &ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1181        ListenerSharingState{listening: old_listening, sharing: old_sharing}: &ListenerSharingState,
1182        ListenerSharingState{listening: new_listening, sharing: new_sharing}: &ListenerSharingState,
1183    ) -> Result<(), UpdateSharingError> {
1184        let ListenerAddr { device, ip } = addr;
1185        match (old_listening, new_listening) {
1186            (true, false) => (), // Changing a listener to bound is always okay.
1187            (true, true) | (false, false) => (), // No change
1188            (false, true) => {
1189                // Upgrading a bound socket to a listener requires no other listeners on similar
1190                // addresses. This boils down to checking for listeners on either
1191                //   1. addresses that this address shadows, or
1192                //   2. addresses that shadow this address.
1193
1194                // First, check for condition (1).
1195                let addr = AddrVec::Listen(addr.clone());
1196                for a in addr.iter_shadows() {
1197                    if let Some(s) = socketmap.get(&a) {
1198                        match s {
1199                            Bound::Conn(c) => {
1200                                unreachable!("found conn state {c:?} at listener addr {a:?}")
1201                            }
1202                            Bound::Listen(l) => match l {
1203                                ListenerAddrState::ExclusiveListener(_)
1204                                | ListenerAddrState::ExclusiveBound(_) => {
1205                                    return Err(UpdateSharingError);
1206                                }
1207                                ListenerAddrState::Shared { listener, bound: _ } => {
1208                                    match listener {
1209                                        Some(_) => {
1210                                            return Err(UpdateSharingError);
1211                                        }
1212                                        None => (),
1213                                    }
1214                                }
1215                            },
1216                        }
1217                    }
1218                }
1219
1220                // Next, check for condition (2).
1221                if socketmap.descendant_counts(&ListenerAddr { device: None, ip: *ip }.into()).any(
1222                    |(AddrVecTag { state, has_device: _, sharing: _ }, _): &(_, NonZeroUsize)| {
1223                        match state {
1224                            SocketTagState::Conn | SocketTagState::Bound => false,
1225                            SocketTagState::Listener => true,
1226                        }
1227                    },
1228                ) {
1229                    return Err(UpdateSharingError);
1230                }
1231            }
1232        }
1233
1234        match (old_sharing, new_sharing) {
1235            (SharingState::Exclusive, SharingState::Exclusive)
1236            | (SharingState::ReuseAddress, SharingState::ReuseAddress)
1237            | (SharingState::Exclusive, SharingState::ReuseAddress) => (),
1238            (SharingState::ReuseAddress, SharingState::Exclusive) => {
1239                // Linux allows this, but it introduces inconsistent socket
1240                // state: if some sockets were allowed to bind because they all
1241                // had SO_REUSEADDR set, then allowing clearing SO_REUSEADDR on
1242                // one of them makes the state inconsistent. We only allow this
1243                // if it doesn't introduce inconsistencies.
1244                let root_addr = ListenerAddr {
1245                    device: None,
1246                    ip: ListenerIpAddr { addr: None, identifier: ip.identifier },
1247                };
1248
1249                let conflicts = match device {
1250                    // If the socket doesn't have a device, it conflicts with
1251                    // any listeners that shadow it or that it shadows.
1252                    None => {
1253                        socketmap.descendant_counts(&addr.clone().into()).any(
1254                            |(AddrVecTag { has_device: _, sharing: _, state }, _)| match state {
1255                                SocketTagState::Conn => false,
1256                                SocketTagState::Bound | SocketTagState::Listener => true,
1257                            },
1258                        ) || (addr != &root_addr && socketmap.get(&root_addr.into()).is_some())
1259                    }
1260                    Some(_) => {
1261                        // If the socket has a device, it will indirectly
1262                        // conflict with a listener that doesn't have a device
1263                        // that is either on the same address or the unspecified
1264                        // address (on the same port).
1265                        socketmap.descendant_counts(&root_addr.into()).any(
1266                            |(AddrVecTag { has_device, sharing: _, state }, _)| match state {
1267                                SocketTagState::Conn => false,
1268                                SocketTagState::Bound | SocketTagState::Listener => !has_device,
1269                            },
1270                        )
1271                        // Detect a conflict with a shadower (which must also
1272                        // have a device) on the same address or on a specific
1273                        // address if this socket is on the unspecified address.
1274                        || socketmap.descendant_counts(&addr.clone().into()).any(
1275                            |(AddrVecTag { has_device: _, sharing: _, state }, _)| match state {
1276                                SocketTagState::Conn => false,
1277                                SocketTagState::Bound | SocketTagState::Listener => true,
1278                            },
1279                        )
1280                    }
1281                };
1282
1283                if conflicts {
1284                    return Err(UpdateSharingError);
1285                }
1286            }
1287        }
1288
1289        Ok(())
1290    }
1291}
1292
1293impl<S: SpecSocketId> SocketMapAddrStateUpdateSharingSpec for ListenerAddrState<S> {
1294    fn try_update_sharing(
1295        &mut self,
1296        id: Self::Id,
1297        ListenerSharingState{listening: new_listening, sharing: new_sharing}: &Self::SharingState,
1298    ) -> Result<(), IncompatibleError> {
1299        match self {
1300            Self::ExclusiveBound(i) | Self::ExclusiveListener(i) => {
1301                assert_eq!(i, &id);
1302                *self = match new_sharing {
1303                    SharingState::Exclusive => match new_listening {
1304                        true => Self::ExclusiveListener(id),
1305                        false => Self::ExclusiveBound(id),
1306                    },
1307                    SharingState::ReuseAddress => {
1308                        let (listener, bound) = match new_listening {
1309                            true => (Some(id), Default::default()),
1310                            false => (None, smallvec![id]),
1311                        };
1312                        Self::Shared { listener, bound }
1313                    }
1314                };
1315                Ok(())
1316            }
1317            Self::Shared { listener, bound } => {
1318                if listener.as_ref() == Some(&id) {
1319                    match new_sharing {
1320                        SharingState::Exclusive => {
1321                            if bound.is_empty() {
1322                                *self = match new_listening {
1323                                    true => Self::ExclusiveListener(id),
1324                                    false => Self::ExclusiveBound(id),
1325                                };
1326                                Ok(())
1327                            } else {
1328                                Err(IncompatibleError)
1329                            }
1330                        }
1331                        SharingState::ReuseAddress => match new_listening {
1332                            true => Ok(()), // no-op
1333                            false => {
1334                                bound.push(id);
1335                                *listener = None;
1336                                Ok(())
1337                            }
1338                        },
1339                    }
1340                } else {
1341                    let index = bound
1342                        .iter()
1343                        .position(|b| b == &id)
1344                        .expect("ID is neither listener nor bound");
1345                    if *new_listening && listener.is_some() {
1346                        return Err(IncompatibleError);
1347                    }
1348                    match new_sharing {
1349                        SharingState::Exclusive => {
1350                            if bound.len() > 1 {
1351                                return Err(IncompatibleError);
1352                            } else {
1353                                *self = match new_listening {
1354                                    true => Self::ExclusiveListener(id),
1355                                    false => Self::ExclusiveBound(id),
1356                                };
1357                                Ok(())
1358                            }
1359                        }
1360                        SharingState::ReuseAddress => {
1361                            match new_listening {
1362                                false => Ok(()), // no-op
1363                                true => {
1364                                    let _: S = bound.swap_remove(index);
1365                                    *listener = Some(id);
1366                                    Ok(())
1367                                }
1368                            }
1369                        }
1370                    }
1371                }
1372            }
1373        }
1374    }
1375}
1376
1377#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1378pub enum SharingState {
1379    Exclusive,
1380    ReuseAddress,
1381}
1382
1383impl Default for SharingState {
1384    fn default() -> Self {
1385        Self::Exclusive
1386    }
1387}
1388
1389impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1390    SocketMapConflictPolicy<
1391        ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1392        ListenerSharingState,
1393        I,
1394        D,
1395        TcpPortSpec,
1396    > for TcpSocketSpec<I, D, BT>
1397{
1398    fn check_insert_conflicts(
1399        sharing: &ListenerSharingState,
1400        addr: &ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>,
1401        socketmap: &SocketMap<AddrVec<I, D, TcpPortSpec>, Bound<Self>>,
1402    ) -> Result<(), InsertError> {
1403        let addr = AddrVec::Listen(addr.clone());
1404        let ListenerSharingState { listening: _, sharing } = sharing;
1405        // Check if any shadow address is present, specifically, if
1406        // there is an any-listener with the same port.
1407        for a in addr.iter_shadows() {
1408            if let Some(s) = socketmap.get(&a) {
1409                match s {
1410                    Bound::Conn(c) => unreachable!("found conn state {c:?} at listener addr {a:?}"),
1411                    Bound::Listen(l) => match l {
1412                        ListenerAddrState::ExclusiveListener(_)
1413                        | ListenerAddrState::ExclusiveBound(_) => {
1414                            return Err(InsertError::ShadowAddrExists);
1415                        }
1416                        ListenerAddrState::Shared { listener, bound: _ } => match sharing {
1417                            SharingState::Exclusive => return Err(InsertError::ShadowAddrExists),
1418                            SharingState::ReuseAddress => match listener {
1419                                Some(_) => return Err(InsertError::ShadowAddrExists),
1420                                None => (),
1421                            },
1422                        },
1423                    },
1424                }
1425            }
1426        }
1427
1428        // Check if shadower exists. Note: Listeners do conflict with existing
1429        // connections, unless the listeners and connections have sharing
1430        // enabled.
1431        for (tag, _count) in socketmap.descendant_counts(&addr) {
1432            let AddrVecTag { sharing: tag_sharing, has_device: _, state: _ } = tag;
1433            match (tag_sharing, sharing) {
1434                (SharingState::Exclusive, SharingState::Exclusive | SharingState::ReuseAddress) => {
1435                    return Err(InsertError::ShadowerExists);
1436                }
1437                (SharingState::ReuseAddress, SharingState::Exclusive) => {
1438                    return Err(InsertError::ShadowerExists);
1439                }
1440                (SharingState::ReuseAddress, SharingState::ReuseAddress) => (),
1441            }
1442        }
1443        Ok(())
1444    }
1445}
1446
1447impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1448    SocketMapConflictPolicy<
1449        ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, D>,
1450        SharingState,
1451        I,
1452        D,
1453        TcpPortSpec,
1454    > for TcpSocketSpec<I, D, BT>
1455{
1456    fn check_insert_conflicts(
1457        _sharing: &SharingState,
1458        addr: &ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, D>,
1459        socketmap: &SocketMap<AddrVec<I, D, TcpPortSpec>, Bound<Self>>,
1460    ) -> Result<(), InsertError> {
1461        // We need to make sure there are no present sockets that have the same
1462        // 4-tuple with the to-be-added socket.
1463        let addr = AddrVec::Conn(ConnAddr { device: None, ..*addr });
1464        if let Some(_) = socketmap.get(&addr) {
1465            return Err(InsertError::Exists);
1466        }
1467        // No shadower exists, i.e., no sockets with the same 4-tuple but with
1468        // a device bound.
1469        if socketmap.descendant_counts(&addr).len() > 0 {
1470            return Err(InsertError::ShadowerExists);
1471        }
1472        // Otherwise, connections don't conflict with existing listeners.
1473        Ok(())
1474    }
1475}
1476
1477#[derive(Debug)]
1478struct ConnAddrState<S> {
1479    sharing: SharingState,
1480    id: S,
1481}
1482
1483impl<S: SpecSocketId> ConnAddrState<S> {
1484    #[cfg_attr(feature = "instrumented", track_caller)]
1485    pub(crate) fn id(&self) -> S {
1486        self.id.clone()
1487    }
1488}
1489
1490impl<S: SpecSocketId> SocketMapAddrStateSpec for ConnAddrState<S> {
1491    type Id = S;
1492    type Inserter<'a> = Never;
1493    type SharingState = SharingState;
1494
1495    fn new(new_sharing_state: &Self::SharingState, id: Self::Id) -> Self {
1496        Self { sharing: *new_sharing_state, id }
1497    }
1498
1499    fn contains_id(&self, id: &Self::Id) -> bool {
1500        &self.id == id
1501    }
1502
1503    fn could_insert(
1504        &self,
1505        _new_sharing_state: &Self::SharingState,
1506    ) -> Result<(), IncompatibleError> {
1507        Err(IncompatibleError)
1508    }
1509
1510    fn remove_by_id(&mut self, id: Self::Id) -> RemoveResult {
1511        let Self { sharing: _, id: existing_id } = self;
1512        assert_eq!(*existing_id, id);
1513        return RemoveResult::IsLast;
1514    }
1515
1516    fn try_get_inserter<'a, 'b>(
1517        &'b mut self,
1518        _new_sharing_state: &'a Self::SharingState,
1519    ) -> Result<Self::Inserter<'b>, IncompatibleError> {
1520        Err(IncompatibleError)
1521    }
1522}
1523
1524#[derive(Debug, Clone)]
1525#[cfg_attr(test, derive(PartialEq))]
1526pub struct Unbound<D, Extra> {
1527    bound_device: Option<D>,
1528    buffer_sizes: BufferSizes,
1529    sharing: SharingState,
1530    socket_extra: Takeable<Extra>,
1531}
1532
1533type PrimaryRc<I, D, BT> = netstack3_base::sync::PrimaryRc<ReferenceState<I, D, BT>>;
1534type StrongRc<I, D, BT> = netstack3_base::sync::StrongRc<ReferenceState<I, D, BT>>;
1535type WeakRc<I, D, BT> = netstack3_base::sync::WeakRc<ReferenceState<I, D, BT>>;
1536
1537#[derive(Derivative)]
1538#[derivative(Debug(bound = "D: Debug"))]
1539pub enum TcpSocketSetEntry<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1540    /// The socket set is holding a primary reference.
1541    Primary(PrimaryRc<I, D, BT>),
1542    /// The socket set is holding a "dead on arrival" (DOA) entry for a strong
1543    /// reference.
1544    ///
1545    /// This mechanism guards against a subtle race between a connected socket
1546    /// created from a listener being added to the socket set and the same
1547    /// socket attempting to close itself before the listener has had a chance
1548    /// to add it to the set.
1549    ///
1550    /// See [`destroy_socket`] for the details handling this.
1551    DeadOnArrival,
1552}
1553
1554/// A thin wrapper around a hash map that keeps a set of all the known TCP
1555/// sockets in the system.
1556#[derive(Debug, Derivative)]
1557#[derivative(Default(bound = ""))]
1558pub struct TcpSocketSet<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1559    HashMap<TcpSocketId<I, D, BT>, TcpSocketSetEntry<I, D, BT>>,
1560);
1561
1562impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Deref
1563    for TcpSocketSet<I, D, BT>
1564{
1565    type Target = HashMap<TcpSocketId<I, D, BT>, TcpSocketSetEntry<I, D, BT>>;
1566    fn deref(&self) -> &Self::Target {
1567        &self.0
1568    }
1569}
1570
1571impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> DerefMut
1572    for TcpSocketSet<I, D, BT>
1573{
1574    fn deref_mut(&mut self) -> &mut Self::Target {
1575        &mut self.0
1576    }
1577}
1578
1579/// A custom drop impl for the entire set to make tests easier to handle.
1580///
1581/// Because [`TcpSocketId`] is not really RAII in respect to closing the socket,
1582/// tests might finish without closing them and it's easier to deal with that in
1583/// a single place.
1584impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Drop
1585    for TcpSocketSet<I, D, BT>
1586{
1587    fn drop(&mut self) {
1588        // Listening sockets may hold references to other sockets so we walk
1589        // through all of the sockets looking for unclosed listeners and close
1590        // their accept queue so that dropping everything doesn't spring the
1591        // primary reference checks.
1592        //
1593        // Note that we don't pay attention to lock ordering here. Assuming that
1594        // when the set is dropped everything is going down and no locks are
1595        // held.
1596        let Self(map) = self;
1597        for TcpSocketId(rc) in map.keys() {
1598            let guard = rc.locked_state.read();
1599            let accept_queue = match &(*guard).socket_state {
1600                TcpSocketStateInner::Bound(BoundSocketState::Listener((
1601                    MaybeListener::Listener(Listener { accept_queue, .. }),
1602                    ..,
1603                ))) => accept_queue,
1604                _ => continue,
1605            };
1606            if !accept_queue.is_closed() {
1607                let (_pending_sockets_iterator, _): (_, BT::ListenerNotifierOrProvidedBuffers) =
1608                    accept_queue.close();
1609            }
1610        }
1611    }
1612}
1613
1614type BoundSocketMap<I, D, BT> = socket::BoundSocketMap<I, D, TcpPortSpec, TcpSocketSpec<I, D, BT>>;
1615
1616/// TCP demux state.
1617#[derive(GenericOverIp)]
1618#[generic_over_ip(I, Ip)]
1619pub struct DemuxState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1620    socketmap: BoundSocketMap<I, D, BT>,
1621}
1622
1623/// Holds all the TCP socket states.
1624pub struct Sockets<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1625    demux: RwLock<DemuxState<I, D, BT>>,
1626    // Destroy all_sockets last so the strong references in the demux are
1627    // dropped before the primary references in the set.
1628    all_sockets: RwLock<TcpSocketSet<I, D, BT>>,
1629}
1630
1631impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1632    OrderedLockAccess<DemuxState<I, D, BT>> for Sockets<I, D, BT>
1633{
1634    type Lock = RwLock<DemuxState<I, D, BT>>;
1635    fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
1636        OrderedLockRef::new(&self.demux)
1637    }
1638}
1639
1640impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1641    OrderedLockAccess<TcpSocketSet<I, D, BT>> for Sockets<I, D, BT>
1642{
1643    type Lock = RwLock<TcpSocketSet<I, D, BT>>;
1644    fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
1645        OrderedLockRef::new(&self.all_sockets)
1646    }
1647}
1648
1649/// The state held by a [`TcpSocketId`].
1650#[derive(Derivative)]
1651#[derivative(Debug(bound = "D: Debug"))]
1652pub struct ReferenceState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1653    locked_state: RwLock<TcpSocketState<I, D, BT>>,
1654    counters: TcpCountersWithSocket<I>,
1655}
1656
1657/// The locked state held by a TCP socket.
1658#[derive(Derivative)]
1659#[derivative(Debug(bound = "D: Debug"))]
1660pub struct TcpSocketState<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1661    socket_state: TcpSocketStateInner<I, D, BT>,
1662    // Options specific to the IP version.
1663    ip_options: I::DualStackIpOptions,
1664    // All other options.
1665    socket_options: SocketOptions,
1666}
1667
1668#[derive(Derivative)]
1669#[derivative(Debug(bound = "D: Debug"))]
1670pub enum TcpSocketStateInner<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1671    Unbound(Unbound<D, BT::ListenerNotifierOrProvidedBuffers>),
1672    Bound(BoundSocketState<I, D, BT>),
1673}
1674
1675struct TcpPortAlloc<'a, I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1676    &'a BoundSocketMap<I, D, BT>,
1677);
1678
1679impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> PortAllocImpl
1680    for TcpPortAlloc<'_, I, D, BT>
1681{
1682    const EPHEMERAL_RANGE: RangeInclusive<u16> = 49152..=65535;
1683    type Id = Option<SocketIpAddr<I::Addr>>;
1684    /// The TCP port allocator takes an extra optional argument with a port to
1685    /// avoid.
1686    ///
1687    /// This is used to sidestep possible self-connections when allocating a
1688    /// local port on a connect call with an unset local port.
1689    type PortAvailableArg = Option<NonZeroU16>;
1690
1691    fn is_port_available(&self, addr: &Self::Id, port: u16, arg: &Option<NonZeroU16>) -> bool {
1692        let Self(socketmap) = self;
1693        // We can safely unwrap here, because the ports received in
1694        // `is_port_available` are guaranteed to be in `EPHEMERAL_RANGE`.
1695        let port = NonZeroU16::new(port).unwrap();
1696
1697        // Reject ports matching the argument.
1698        if arg.is_some_and(|a| a == port) {
1699            return false;
1700        }
1701
1702        let root_addr = AddrVec::from(ListenerAddr {
1703            ip: ListenerIpAddr { addr: *addr, identifier: port },
1704            device: None,
1705        });
1706
1707        // A port is free if there are no sockets currently using it, and if
1708        // there are no sockets that are shadowing it.
1709
1710        root_addr.iter_shadows().chain(core::iter::once(root_addr.clone())).all(|a| match &a {
1711            AddrVec::Listen(l) => socketmap.listeners().get_by_addr(&l).is_none(),
1712            AddrVec::Conn(_c) => {
1713                unreachable!("no connection shall be included in an iteration from a listener")
1714            }
1715        }) && socketmap.get_shadower_counts(&root_addr) == 0
1716    }
1717}
1718
1719struct TcpDualStackPortAlloc<'a, I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1720    &'a BoundSocketMap<I, D, BT>,
1721    &'a BoundSocketMap<I::OtherVersion, D, BT>,
1722);
1723
1724/// When binding to IPv6 ANY address (::), we need to allocate a port that is
1725/// available in both stacks.
1726impl<'a, I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> PortAllocImpl
1727    for TcpDualStackPortAlloc<'a, I, D, BT>
1728{
1729    const EPHEMERAL_RANGE: RangeInclusive<u16> =
1730        <TcpPortAlloc<'a, I, D, BT> as PortAllocImpl>::EPHEMERAL_RANGE;
1731    type Id = ();
1732    type PortAvailableArg = ();
1733
1734    fn is_port_available(&self, (): &Self::Id, port: u16, (): &Self::PortAvailableArg) -> bool {
1735        let Self(this, other) = self;
1736        TcpPortAlloc(this).is_port_available(&None, port, &None)
1737            && TcpPortAlloc(other).is_port_available(&None, port, &None)
1738    }
1739}
1740
1741impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Sockets<I, D, BT> {
1742    pub(crate) fn new() -> Self {
1743        Self {
1744            demux: RwLock::new(DemuxState { socketmap: Default::default() }),
1745            all_sockets: Default::default(),
1746        }
1747    }
1748}
1749
1750/// The Connection state.
1751///
1752/// Note: the `state` is not guaranteed to be [`State::Established`]. The
1753/// connection can be in any state as long as both the local and remote socket
1754/// addresses are specified.
1755#[derive(Derivative)]
1756#[derivative(Debug(bound = "D: Debug"))]
1757pub struct Connection<
1758    SockI: DualStackIpExt,
1759    WireI: DualStackIpExt,
1760    D: WeakDeviceIdentifier,
1761    BT: TcpBindingsTypes,
1762> {
1763    accept_queue: Option<
1764        AcceptQueue<
1765            TcpSocketId<SockI, D, BT>,
1766            BT::ReturnedBuffers,
1767            BT::ListenerNotifierOrProvidedBuffers,
1768        >,
1769    >,
1770    state: State<
1771        BT::Instant,
1772        BT::ReceiveBuffer,
1773        BT::SendBuffer,
1774        BT::ListenerNotifierOrProvidedBuffers,
1775    >,
1776    ip_sock: IpSock<WireI, D>,
1777    /// The user has indicated that this connection will never be used again, we
1778    /// keep the connection in the socketmap to perform the shutdown but it will
1779    /// be auto removed once the state reaches Closed.
1780    defunct: bool,
1781    /// In contrast to a hard error, which will cause a connection to be closed,
1782    /// a soft error will not abort the connection, but it can be read by either
1783    /// calling `get_socket_error`, or after the connection times out.
1784    soft_error: Option<ConnectionError>,
1785    /// Whether the handshake has finished or aborted.
1786    handshake_status: HandshakeStatus,
1787}
1788
1789impl<SockI: DualStackIpExt, WireI: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1790    Connection<SockI, WireI, D, BT>
1791{
1792    /// Updates this connection's state to reflect the error.
1793    ///
1794    /// The connection's soft error, if previously unoccupied, holds the error.
1795    fn on_icmp_error<CC: TcpCounterContext<SockI, D, BT>>(
1796        &mut self,
1797        core_ctx: &mut CC,
1798        id: &TcpSocketId<SockI, D, BT>,
1799        seq: SeqNum,
1800        error: IcmpErrorCode,
1801    ) -> (NewlyClosed, ShouldRetransmit) {
1802        let Connection { soft_error, state, .. } = self;
1803        let (new_soft_error, newly_closed, should_send) =
1804            state.on_icmp_error(&TcpCountersRefs::from_ctx(core_ctx, id), error, seq);
1805        *soft_error = soft_error.or(new_soft_error);
1806        (newly_closed, should_send)
1807    }
1808}
1809
1810/// The Listener state.
1811///
1812/// State for sockets that participate in the passive open. Contrary to
1813/// [`Connection`], only the local address is specified.
1814#[derive(Derivative)]
1815#[derivative(Debug(bound = "D: Debug"))]
1816#[cfg_attr(
1817    test,
1818    derivative(
1819        PartialEq(
1820            bound = "BT::ReturnedBuffers: PartialEq, BT::ListenerNotifierOrProvidedBuffers: PartialEq"
1821        ),
1822        Eq(bound = "BT::ReturnedBuffers: Eq, BT::ListenerNotifierOrProvidedBuffers: Eq"),
1823    )
1824)]
1825pub struct Listener<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1826    backlog: NonZeroUsize,
1827    accept_queue: AcceptQueue<
1828        TcpSocketId<I, D, BT>,
1829        BT::ReturnedBuffers,
1830        BT::ListenerNotifierOrProvidedBuffers,
1831    >,
1832    buffer_sizes: BufferSizes,
1833    // If ip sockets can be half-specified so that only the local address
1834    // is needed, we can construct an ip socket here to be reused.
1835}
1836
1837impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Listener<I, D, BT> {
1838    fn new(
1839        backlog: NonZeroUsize,
1840        buffer_sizes: BufferSizes,
1841        notifier: BT::ListenerNotifierOrProvidedBuffers,
1842    ) -> Self {
1843        Self { backlog, accept_queue: AcceptQueue::new(notifier), buffer_sizes }
1844    }
1845}
1846
1847#[derive(Clone, Debug)]
1848#[cfg_attr(test, derive(Eq, PartialEq))]
1849pub struct BoundState<Extra> {
1850    buffer_sizes: BufferSizes,
1851    socket_extra: Takeable<Extra>,
1852}
1853
1854/// Represents either a bound socket or a listener socket.
1855#[derive(Derivative)]
1856#[derivative(Debug(bound = "D: Debug"))]
1857#[cfg_attr(
1858    test,
1859    derivative(
1860        Eq(bound = "BT::ReturnedBuffers: Eq, BT::ListenerNotifierOrProvidedBuffers: Eq"),
1861        PartialEq(
1862            bound = "BT::ReturnedBuffers: PartialEq, BT::ListenerNotifierOrProvidedBuffers: PartialEq"
1863        )
1864    )
1865)]
1866pub enum MaybeListener<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
1867    Bound(BoundState<BT::ListenerNotifierOrProvidedBuffers>),
1868    Listener(Listener<I, D, BT>),
1869}
1870
1871/// A TCP Socket ID.
1872#[derive(Derivative, GenericOverIp)]
1873#[generic_over_ip(I, Ip)]
1874#[derivative(Eq(bound = ""), PartialEq(bound = ""), Hash(bound = ""))]
1875pub struct TcpSocketId<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1876    StrongRc<I, D, BT>,
1877);
1878
1879impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Clone
1880    for TcpSocketId<I, D, BT>
1881{
1882    #[cfg_attr(feature = "instrumented", track_caller)]
1883    fn clone(&self) -> Self {
1884        let Self(rc) = self;
1885        Self(StrongRc::clone(rc))
1886    }
1887}
1888
1889impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
1890    pub(crate) fn new(
1891        socket_state: TcpSocketStateInner<I, D, BT>,
1892        socket_options: SocketOptions,
1893    ) -> (Self, PrimaryRc<I, D, BT>) {
1894        let primary = PrimaryRc::new(ReferenceState {
1895            locked_state: RwLock::new(TcpSocketState {
1896                socket_state,
1897                ip_options: Default::default(),
1898                socket_options,
1899            }),
1900            counters: Default::default(),
1901        });
1902        let socket = Self(PrimaryRc::clone_strong(&primary));
1903        (socket, primary)
1904    }
1905
1906    pub(crate) fn new_cyclic<
1907        F: FnOnce(WeakTcpSocketId<I, D, BT>) -> TcpSocketStateInner<I, D, BT>,
1908    >(
1909        init: F,
1910        socket_options: SocketOptions,
1911    ) -> (Self, PrimaryRc<I, D, BT>) {
1912        let primary = PrimaryRc::new_cyclic(move |weak| {
1913            let socket_state = init(WeakTcpSocketId(weak));
1914            ReferenceState {
1915                locked_state: RwLock::new(TcpSocketState {
1916                    socket_state,
1917                    ip_options: Default::default(),
1918                    socket_options,
1919                }),
1920                counters: Default::default(),
1921            }
1922        });
1923        let socket = Self(PrimaryRc::clone_strong(&primary));
1924        (socket, primary)
1925    }
1926
1927    /// Obtains the counters tracked for this TCP socket.
1928    pub fn counters(&self) -> &TcpCountersWithSocket<I> {
1929        let Self(rc) = self;
1930        &rc.counters
1931    }
1932
1933    pub(crate) fn trace_id(&self) -> TraceResourceId<'_> {
1934        let Self(inner) = self;
1935        TraceResourceId::new(inner.resource_token())
1936    }
1937
1938    /// Returns `SocketCookie` for the socket.
1939    pub fn socket_cookie(&self) -> SocketCookie {
1940        let Self(inner) = self;
1941        SocketCookie::new(inner.resource_token())
1942    }
1943
1944    pub(crate) fn either(&self) -> EitherTcpSocketId<'_, D, BT> {
1945        I::map_ip_in(self, EitherTcpSocketId::V4, EitherTcpSocketId::V6)
1946    }
1947}
1948
1949impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Debug
1950    for TcpSocketId<I, D, BT>
1951{
1952    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1953        let Self(rc) = self;
1954        f.debug_tuple("TcpSocketId").field(&StrongRc::debug_id(rc)).finish()
1955    }
1956}
1957
1958impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
1959    pub(crate) fn downgrade(&self) -> WeakTcpSocketId<I, D, BT> {
1960        let Self(this) = self;
1961        WeakTcpSocketId(StrongRc::downgrade(this))
1962    }
1963}
1964
1965/// A Weak TCP Socket ID.
1966#[derive(Derivative, GenericOverIp)]
1967#[generic_over_ip(I, Ip)]
1968#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Hash(bound = ""))]
1969pub struct WeakTcpSocketId<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
1970    WeakRc<I, D, BT>,
1971);
1972
1973impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> Debug
1974    for WeakTcpSocketId<I, D, BT>
1975{
1976    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1977        let Self(rc) = self;
1978        f.debug_tuple("WeakTcpSocketId").field(&rc.debug_id()).finish()
1979    }
1980}
1981
1982impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
1983    PartialEq<TcpSocketId<I, D, BT>> for WeakTcpSocketId<I, D, BT>
1984{
1985    fn eq(&self, other: &TcpSocketId<I, D, BT>) -> bool {
1986        let Self(this) = self;
1987        let TcpSocketId(other) = other;
1988        StrongRc::weak_ptr_eq(other, this)
1989    }
1990}
1991
1992impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> WeakTcpSocketId<I, D, BT> {
1993    /// Tries to upgrade to a strong reference.
1994    #[cfg_attr(feature = "instrumented", track_caller)]
1995    pub fn upgrade(&self) -> Option<TcpSocketId<I, D, BT>> {
1996        let Self(this) = self;
1997        this.upgrade().map(TcpSocketId)
1998    }
1999}
2000
2001impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>
2002    OrderedLockAccess<TcpSocketState<I, D, BT>> for TcpSocketId<I, D, BT>
2003{
2004    type Lock = RwLock<TcpSocketState<I, D, BT>>;
2005    fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
2006        let Self(rc) = self;
2007        OrderedLockRef::new(&rc.locked_state)
2008    }
2009}
2010
2011/// A borrow of either an IPv4 or IPv6 TCP socket.
2012///
2013/// This type is used to implement [`StateMachineDebugId`] in a way that doesn't
2014/// taint the state machine with IP-specific types, avoiding code generation
2015/// duplication.
2016#[derive(Derivative)]
2017#[derivative(Debug(bound = ""))]
2018pub(crate) enum EitherTcpSocketId<'a, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> {
2019    #[derivative(Debug = "transparent")]
2020    V4(&'a TcpSocketId<Ipv4, D, BT>),
2021    #[derivative(Debug = "transparent")]
2022    V6(&'a TcpSocketId<Ipv6, D, BT>),
2023}
2024
2025impl<D: WeakDeviceIdentifier, BT: TcpBindingsTypes> StateMachineDebugId
2026    for EitherTcpSocketId<'_, D, BT>
2027{
2028    fn trace_id(&self) -> TraceResourceId<'_> {
2029        match self {
2030            Self::V4(v4) => v4.trace_id(),
2031            Self::V6(v6) => v6.trace_id(),
2032        }
2033    }
2034}
2035
2036/// The status of a handshake.
2037#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2038pub enum HandshakeStatus {
2039    /// The handshake is still pending.
2040    Pending,
2041    /// The handshake is aborted.
2042    Aborted,
2043    /// The handshake is completed.
2044    Completed {
2045        /// Whether it has been reported to the user yet.
2046        reported: bool,
2047    },
2048}
2049
2050impl HandshakeStatus {
2051    fn update_if_pending(&mut self, new_status: Self) -> bool {
2052        if *self == HandshakeStatus::Pending {
2053            *self = new_status;
2054            true
2055        } else {
2056            false
2057        }
2058    }
2059}
2060
2061/// Resolves the demux local address and bound device for the `bind` operation.
2062fn bind_get_local_addr_and_device<I, BT, CC>(
2063    core_ctx: &mut CC,
2064    addr: Option<ZonedAddr<SocketIpAddr<I::Addr>, CC::DeviceId>>,
2065    bound_device: &Option<CC::WeakDeviceId>,
2066) -> Result<(Option<SocketIpAddr<I::Addr>>, Option<CC::WeakDeviceId>), LocalAddressError>
2067where
2068    I: DualStackIpExt,
2069    BT: TcpBindingsTypes,
2070    CC: TransportIpContext<I, BT>,
2071{
2072    let (local_ip, device) = match addr {
2073        Some(addr) => {
2074            // Extract the specified address and the device. The
2075            // device is either the one from the address or the one
2076            // to which the socket was previously bound.
2077            let (addr, required_device) = addr
2078                .resolve_addr_with_device(bound_device.clone())
2079                .map_err(LocalAddressError::Zone)?;
2080
2081            // TCP sockets cannot bind to multicast addresses.
2082            // TODO(https://fxbug.dev/424874749): Put this check in a witness type.
2083            if addr.addr().is_multicast()
2084                || I::map_ip_in(addr.addr(), |ip| ip.is_limited_broadcast(), |_| false)
2085            {
2086                return Err(LocalAddressError::CannotBindToAddress);
2087            }
2088
2089            core_ctx.with_devices_with_assigned_addr(addr.clone().into(), |mut assigned_to| {
2090                if !assigned_to.any(|d| {
2091                    required_device
2092                        .as_ref()
2093                        .map_or(true, |device| device == &EitherDeviceId::Strong(d))
2094                }) {
2095                    Err(LocalAddressError::AddressMismatch)
2096                } else {
2097                    Ok(())
2098                }
2099            })?;
2100            (Some(addr), required_device)
2101        }
2102        None => (None, bound_device.clone().map(EitherDeviceId::Weak)),
2103    };
2104    let weak_device = device.map(|d| d.as_weak().into_owned());
2105    Ok((local_ip, weak_device))
2106}
2107
2108fn bind_install_in_demux<I, D, BC>(
2109    bindings_ctx: &mut BC,
2110    demux_socket_id: I::DemuxSocketId<D, BC>,
2111    local_ip: Option<SocketIpAddr<I::Addr>>,
2112    weak_device: Option<D>,
2113    port: Option<NonZeroU16>,
2114    sharing: SharingState,
2115    DemuxState { socketmap }: &mut DemuxState<I, D, BC>,
2116) -> Result<
2117    (ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, D>, ListenerSharingState),
2118    LocalAddressError,
2119>
2120where
2121    I: DualStackIpExt,
2122    BC: TcpBindingsTypes + RngContext,
2123    D: WeakDeviceIdentifier,
2124{
2125    let port = match port {
2126        None => {
2127            match netstack3_base::simple_randomized_port_alloc(
2128                &mut bindings_ctx.rng(),
2129                &local_ip,
2130                &TcpPortAlloc(socketmap),
2131                &None,
2132            ) {
2133                Some(port) => NonZeroU16::new(port).expect("ephemeral ports must be non-zero"),
2134                None => {
2135                    return Err(LocalAddressError::FailedToAllocateLocalPort);
2136                }
2137            }
2138        }
2139        Some(port) => port,
2140    };
2141
2142    let addr = ListenerAddr {
2143        ip: ListenerIpAddr { addr: local_ip, identifier: port },
2144        device: weak_device,
2145    };
2146    let sharing = ListenerSharingState { sharing, listening: false };
2147
2148    let _inserted = socketmap
2149        .listeners_mut()
2150        .try_insert(addr.clone(), sharing.clone(), demux_socket_id)
2151        .map_err(|_: (InsertError, ListenerSharingState)| LocalAddressError::AddressInUse)?;
2152
2153    Ok((addr, sharing))
2154}
2155
2156fn try_update_listener_sharing<I, CC, BT>(
2157    core_ctx: MaybeDualStack<
2158        (&mut CC::DualStackIpTransportAndDemuxCtx<'_>, CC::DualStackConverter),
2159        (&mut CC::SingleStackIpTransportAndDemuxCtx<'_>, CC::SingleStackConverter),
2160    >,
2161    id: &TcpSocketId<I, CC::WeakDeviceId, BT>,
2162    addr: ListenerAddr<I::ListenerIpAddr, CC::WeakDeviceId>,
2163    sharing: &ListenerSharingState,
2164    new_sharing: ListenerSharingState,
2165) -> Result<ListenerSharingState, UpdateSharingError>
2166where
2167    I: DualStackIpExt,
2168    CC: TcpContext<I, BT>,
2169    BT: TcpBindingsTypes,
2170{
2171    match core_ctx {
2172        MaybeDualStack::NotDualStack((core_ctx, converter)) => {
2173            core_ctx.with_demux_mut(|DemuxState { socketmap }| {
2174                let mut entry = socketmap
2175                    .listeners_mut()
2176                    .entry(&I::into_demux_socket_id(id.clone()), &converter.convert(addr))
2177                    .expect("invalid listener id");
2178                entry.try_update_sharing(sharing, new_sharing)
2179            })
2180        }
2181        MaybeDualStack::DualStack((core_ctx, converter)) => match converter.convert(addr) {
2182            ListenerAddr { ip: DualStackListenerIpAddr::ThisStack(ip), device } => {
2183                TcpDemuxContext::<I, _, _>::with_demux_mut(core_ctx, |DemuxState { socketmap }| {
2184                    let mut entry = socketmap
2185                        .listeners_mut()
2186                        .entry(&I::into_demux_socket_id(id.clone()), &ListenerAddr { ip, device })
2187                        .expect("invalid listener id");
2188                    entry.try_update_sharing(sharing, new_sharing)
2189                })
2190            }
2191            ListenerAddr { ip: DualStackListenerIpAddr::OtherStack(ip), device } => {
2192                let demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2193                TcpDemuxContext::<I::OtherVersion, _, _>::with_demux_mut(
2194                    core_ctx,
2195                    |DemuxState { socketmap }| {
2196                        let mut entry = socketmap
2197                            .listeners_mut()
2198                            .entry(&demux_id, &ListenerAddr { ip, device })
2199                            .expect("invalid listener id");
2200                        entry.try_update_sharing(sharing, new_sharing)
2201                    },
2202                )
2203            }
2204            ListenerAddr { ip: DualStackListenerIpAddr::BothStacks(port), device } => {
2205                let other_demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2206                let demux_id = I::into_demux_socket_id(id.clone());
2207                core_ctx.with_both_demux_mut(
2208                    |DemuxState { socketmap: this_socketmap, .. },
2209                     DemuxState { socketmap: other_socketmap, .. }| {
2210                        let this_stack_listener_addr = ListenerAddr {
2211                            ip: ListenerIpAddr { addr: None, identifier: port },
2212                            device: device.clone(),
2213                        };
2214                        let mut this_stack_entry = this_socketmap
2215                            .listeners_mut()
2216                            .entry(&demux_id, &this_stack_listener_addr)
2217                            .expect("invalid listener id");
2218                        this_stack_entry.try_update_sharing(sharing, new_sharing)?;
2219                        let mut other_stack_entry = other_socketmap
2220                            .listeners_mut()
2221                            .entry(
2222                                &other_demux_id,
2223                                &ListenerAddr {
2224                                    ip: ListenerIpAddr { addr: None, identifier: port },
2225                                    device,
2226                                },
2227                            )
2228                            .expect("invalid listener id");
2229                        match other_stack_entry.try_update_sharing(sharing, new_sharing) {
2230                            Ok(()) => Ok(()),
2231                            Err(err) => {
2232                                this_stack_entry
2233                                    .try_update_sharing(&new_sharing, *sharing)
2234                                    .expect("failed to revert the sharing setting");
2235                                Err(err)
2236                            }
2237                        }
2238                    },
2239                )
2240            }
2241        },
2242    }?;
2243    Ok(new_sharing)
2244}
2245
2246/// The TCP socket API.
2247pub struct TcpApi<I: Ip, C>(C, IpVersionMarker<I>);
2248
2249impl<I: Ip, C> TcpApi<I, C> {
2250    /// Creates a new `TcpApi` from `ctx`.
2251    pub fn new(ctx: C) -> Self {
2252        Self(ctx, IpVersionMarker::new())
2253    }
2254}
2255
2256/// A local alias for [`TcpSocketId`] for use in [`TcpApi`].
2257///
2258/// TODO(https://github.com/rust-lang/rust/issues/8995): Make this an inherent
2259/// associated type.
2260type TcpApiSocketId<I, C> = TcpSocketId<
2261    I,
2262    <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
2263    <C as ContextPair>::BindingsContext,
2264>;
2265
2266impl<I, C> TcpApi<I, C>
2267where
2268    I: DualStackIpExt,
2269    C: ContextPair,
2270    C::CoreContext: TcpContext<I, C::BindingsContext>,
2271    C::BindingsContext: TcpBindingsContext<
2272        <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
2273    >,
2274{
2275    pub(crate) fn core_ctx(&mut self) -> &mut C::CoreContext {
2276        let Self(pair, IpVersionMarker { .. }) = self;
2277        pair.core_ctx()
2278    }
2279
2280    pub(crate) fn contexts(&mut self) -> (&mut C::CoreContext, &mut C::BindingsContext) {
2281        let Self(pair, IpVersionMarker { .. }) = self;
2282        pair.contexts()
2283    }
2284
2285    /// Creates a new socket in unbound state.
2286    pub fn create(
2287        &mut self,
2288        socket_extra: <C::BindingsContext as TcpBindingsTypes>::ListenerNotifierOrProvidedBuffers,
2289    ) -> TcpApiSocketId<I, C> {
2290        let (core_ctx, bindings_ctx) = self.contexts();
2291        let settings = bindings_ctx.settings();
2292        let buffer_sizes = BufferSizes {
2293            send: settings.send_buffer.default().get(),
2294            receive: settings.receive_buffer.default().get(),
2295        };
2296        core_ctx.with_all_sockets_mut(|all_sockets| {
2297            let (sock, primary) = TcpSocketId::new(
2298                TcpSocketStateInner::Unbound(Unbound {
2299                    bound_device: Default::default(),
2300                    buffer_sizes,
2301                    sharing: Default::default(),
2302                    socket_extra: Takeable::new(socket_extra),
2303                }),
2304                SocketOptions::default(),
2305            );
2306            assert_matches::assert_matches!(
2307                all_sockets.insert(sock.clone(), TcpSocketSetEntry::Primary(primary)),
2308                None
2309            );
2310            sock
2311        })
2312    }
2313
2314    /// Binds an unbound socket to a local socket address.
2315    ///
2316    /// Requests that the given socket be bound to the local address, if one is
2317    /// provided; otherwise to all addresses. If `port` is specified (is
2318    /// `Some`), the socket will be bound to that port. Otherwise a port will be
2319    /// selected to not conflict with existing bound or connected sockets.
2320    pub fn bind(
2321        &mut self,
2322        id: &TcpApiSocketId<I, C>,
2323        addr: Option<
2324            ZonedAddr<
2325                SpecifiedAddr<I::Addr>,
2326                <C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
2327            >,
2328        >,
2329        port: Option<NonZeroU16>,
2330    ) -> Result<(), BindError> {
2331        #[derive(GenericOverIp)]
2332        #[generic_over_ip(I, Ip)]
2333        enum BindAddr<I: DualStackIpExt, D> {
2334            BindInBothStacks,
2335            BindInOneStack(
2336                EitherStack<
2337                    Option<ZonedAddr<SocketIpAddr<I::Addr>, D>>,
2338                    Option<ZonedAddr<SocketIpAddr<<I::OtherVersion as Ip>::Addr>, D>>,
2339                >,
2340            ),
2341        }
2342        debug!("bind {id:?} to {addr:?}:{port:?}");
2343        let bind_addr = match addr {
2344            None => I::map_ip(
2345                (),
2346                |()| BindAddr::BindInOneStack(EitherStack::ThisStack(None)),
2347                |()| BindAddr::BindInBothStacks,
2348            ),
2349            Some(addr) => match DualStackLocalIp::<I, _>::new(addr) {
2350                DualStackLocalIp::ThisStack(addr) => {
2351                    BindAddr::BindInOneStack(EitherStack::ThisStack(Some(addr)))
2352                }
2353                DualStackLocalIp::OtherStack(addr) => {
2354                    BindAddr::BindInOneStack(EitherStack::OtherStack(addr))
2355                }
2356            },
2357        };
2358
2359        let (core_ctx, bindings_ctx) = self.contexts();
2360        let result = core_ctx.with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
2361            let TcpSocketState { socket_state, ip_options, socket_options: _ } = socket_state;
2362            let Unbound { bound_device, buffer_sizes, sharing, socket_extra } =
2363                match socket_state {
2364                    TcpSocketStateInner::Unbound(u) => u,
2365                    TcpSocketStateInner::Bound(_) => return Err(BindError::AlreadyBound),
2366                };
2367
2368            let (listener_addr, sharing) = match core_ctx {
2369                MaybeDualStack::NotDualStack((core_ctx, converter)) => match bind_addr {
2370                    BindAddr::BindInOneStack(EitherStack::ThisStack(local_addr)) => {
2371                        let (local_addr, device) = bind_get_local_addr_and_device(core_ctx, local_addr, bound_device)?;
2372                        let (addr, sharing) =
2373                            core_ctx.with_demux_mut(|demux| {
2374                                bind_install_in_demux(
2375                                    bindings_ctx,
2376                                    I::into_demux_socket_id(id.clone()),
2377                                    local_addr,
2378                                    device,
2379                                    port,
2380                                    *sharing,
2381                                    demux,
2382                                )
2383                            })?;
2384                        (converter.convert_back(addr), sharing)
2385                    }
2386                    BindAddr::BindInOneStack(EitherStack::OtherStack(_)) | BindAddr::BindInBothStacks => {
2387                        return Err(LocalAddressError::CannotBindToAddress.into());
2388                    }
2389                },
2390                MaybeDualStack::DualStack((core_ctx, converter)) => {
2391                    let bind_addr = match (
2392                            core_ctx.dual_stack_enabled(&ip_options),
2393                            bind_addr
2394                        ) {
2395                        // Allow binding in both stacks when dual stack is
2396                        // enabled.
2397                        (true, BindAddr::BindInBothStacks)
2398                            => BindAddr::<I, _>::BindInBothStacks,
2399                        // Only bind in this stack if dual stack is not enabled.
2400                        (false, BindAddr::BindInBothStacks)
2401                            => BindAddr::BindInOneStack(EitherStack::ThisStack(None)),
2402                        // Binding to this stack is always allowed.
2403                        (true | false, BindAddr::BindInOneStack(EitherStack::ThisStack(ip)))
2404                            => BindAddr::BindInOneStack(EitherStack::ThisStack(ip)),
2405                        // Can bind to the other stack only when dual stack is
2406                        // enabled, otherwise an error is returned.
2407                        (true, BindAddr::BindInOneStack(EitherStack::OtherStack(ip)))
2408                            => BindAddr::BindInOneStack(EitherStack::OtherStack(ip)),
2409                        (false, BindAddr::BindInOneStack(EitherStack::OtherStack(_)))
2410                            => return Err(LocalAddressError::CannotBindToAddress.into()),
2411                    };
2412                    match bind_addr {
2413                        BindAddr::BindInOneStack(EitherStack::ThisStack(addr)) => {
2414                            let (addr, device) = bind_get_local_addr_and_device::<I, _, _>(core_ctx, addr, bound_device)?;
2415                            let (ListenerAddr { ip, device }, sharing) =
2416                                core_ctx.with_demux_mut(|demux: &mut DemuxState<I, _, _>| {
2417                                    bind_install_in_demux(
2418                                        bindings_ctx,
2419                                        I::into_demux_socket_id(id.clone()),
2420                                        addr,
2421                                        device,
2422                                        port,
2423                                        *sharing,
2424                                        demux,
2425                                    )
2426                                })?;
2427                            (
2428                                converter.convert_back(ListenerAddr {
2429                                    ip: DualStackListenerIpAddr::ThisStack(ip),
2430                                    device,
2431                                }),
2432                                sharing,
2433                            )
2434                        }
2435                        BindAddr::BindInOneStack(EitherStack::OtherStack(addr)) => {
2436                            let other_demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2437                            let (addr, device) = bind_get_local_addr_and_device::<I::OtherVersion, _, _>(core_ctx, addr, bound_device)?;
2438                            let (ListenerAddr { ip, device }, sharing) =
2439                                core_ctx.with_demux_mut(|demux: &mut DemuxState<I::OtherVersion, _, _>| {
2440                                    bind_install_in_demux(
2441                                        bindings_ctx,
2442                                        other_demux_id,
2443                                        addr,
2444                                        device,
2445                                        port,
2446                                        *sharing,
2447                                        demux,
2448                                    )
2449                                })?;
2450                            (
2451                                converter.convert_back(ListenerAddr {
2452                                    ip: DualStackListenerIpAddr::OtherStack(ip),
2453                                    device,
2454                                }),
2455                                sharing,
2456                            )
2457                        }
2458                        BindAddr::BindInBothStacks => {
2459                            let other_demux_id = core_ctx.into_other_demux_socket_id(id.clone());
2460                            let (port, device, sharing) =
2461                                core_ctx.with_both_demux_mut(|demux, other_demux| {
2462                                    // We need to allocate the port for both
2463                                    // stacks before `bind_inner` tries to make
2464                                    // a decision, because it might give two
2465                                    // unrelated ports which is undesired.
2466                                    let port_alloc = TcpDualStackPortAlloc(
2467                                        &demux.socketmap,
2468                                        &other_demux.socketmap
2469                                    );
2470                                    let port = match port {
2471                                        Some(port) => port,
2472                                        None => match netstack3_base::simple_randomized_port_alloc(
2473                                            &mut bindings_ctx.rng(),
2474                                            &(),
2475                                            &port_alloc,
2476                                            &(),
2477                                        ){
2478                                            Some(port) => NonZeroU16::new(port)
2479                                                .expect("ephemeral ports must be non-zero"),
2480                                            None => {
2481                                                return Err(LocalAddressError::FailedToAllocateLocalPort);
2482                                            }
2483                                        }
2484                                    };
2485                                    let (this_stack_addr, this_stack_sharing) = bind_install_in_demux(
2486                                        bindings_ctx,
2487                                        I::into_demux_socket_id(id.clone()),
2488                                        None,
2489                                        bound_device.clone(),
2490                                        Some(port),
2491                                        *sharing,
2492                                        demux,
2493                                    )?;
2494                                    match bind_install_in_demux(
2495                                        bindings_ctx,
2496                                        other_demux_id,
2497                                        None,
2498                                        bound_device.clone(),
2499                                        Some(port),
2500                                        *sharing,
2501                                        other_demux,
2502                                    ) {
2503                                        Ok((ListenerAddr { ip, device }, other_stack_sharing)) => {
2504                                            assert_eq!(this_stack_addr.ip.identifier, ip.identifier);
2505                                            assert_eq!(this_stack_sharing, other_stack_sharing);
2506                                            Ok((port, device, this_stack_sharing))
2507                                        }
2508                                        Err(err) => {
2509                                            demux.socketmap.listeners_mut().remove(&I::into_demux_socket_id(id.clone()), &this_stack_addr).expect("failed to unbind");
2510                                            Err(err)
2511                                        }
2512                                    }
2513                                })?;
2514                            (
2515                                ListenerAddr {
2516                                    ip: converter.convert_back(DualStackListenerIpAddr::BothStacks(port)),
2517                                    device,
2518                                },
2519                                sharing,
2520                            )
2521                        }
2522                    }
2523                },
2524            };
2525
2526            let bound_state = BoundState {
2527                buffer_sizes: buffer_sizes.clone(),
2528                socket_extra: Takeable::from_ref(socket_extra.to_ref()),
2529            };
2530
2531            *socket_state = TcpSocketStateInner::Bound(BoundSocketState::Listener((
2532                MaybeListener::Bound(bound_state),
2533                sharing,
2534                listener_addr,
2535            )));
2536            Ok(())
2537        });
2538        match &result {
2539            Err(BindError::LocalAddressError(LocalAddressError::FailedToAllocateLocalPort)) => {
2540                core_ctx.increment_both(id, |c| &c.failed_port_reservations);
2541            }
2542            Err(_) | Ok(_) => {}
2543        }
2544        result
2545    }
2546
2547    /// Listens on an already bound socket.
2548    pub fn listen(
2549        &mut self,
2550        id: &TcpApiSocketId<I, C>,
2551        backlog: NonZeroUsize,
2552    ) -> Result<(), ListenError> {
2553        debug!("listen on {id:?} with backlog {backlog}");
2554        self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
2555            let TcpSocketState { socket_state, ip_options: _, socket_options: _ } = socket_state;
2556            let (listener, listener_sharing, addr) = match socket_state {
2557                TcpSocketStateInner::Bound(BoundSocketState::Listener((l, sharing, addr))) => {
2558                    match l {
2559                        MaybeListener::Listener(_) => return Err(ListenError::NotSupported),
2560                        MaybeListener::Bound(_) => (l, sharing, addr),
2561                    }
2562                }
2563                TcpSocketStateInner::Bound(BoundSocketState::Connected { .. })
2564                | TcpSocketStateInner::Unbound(_) => return Err(ListenError::NotSupported),
2565            };
2566            let new_sharing = {
2567                let ListenerSharingState { sharing, listening } = listener_sharing;
2568                debug_assert!(!*listening, "invalid bound ID that has a listener socket");
2569                ListenerSharingState { sharing: *sharing, listening: true }
2570            };
2571            *listener_sharing = try_update_listener_sharing::<_, C::CoreContext, _>(
2572                core_ctx,
2573                id,
2574                addr.clone(),
2575                listener_sharing,
2576                new_sharing,
2577            )
2578            .map_err(|UpdateSharingError| ListenError::ListenerExists)?;
2579
2580            match listener {
2581                MaybeListener::Bound(BoundState { buffer_sizes, socket_extra }) => {
2582                    *listener = MaybeListener::Listener(Listener::new(
2583                        backlog,
2584                        buffer_sizes.clone(),
2585                        socket_extra.to_ref().take(),
2586                    ));
2587                }
2588                MaybeListener::Listener(_) => {
2589                    unreachable!("invalid bound id that points to a listener entry")
2590                }
2591            }
2592            Ok(())
2593        })
2594    }
2595
2596    /// Accepts an established socket from the queue of a listener socket.
2597    ///
2598    /// Note: The accepted socket will have the marks of the incoming SYN
2599    /// instead of the listener itself.
2600    pub fn accept(
2601        &mut self,
2602        id: &TcpApiSocketId<I, C>,
2603    ) -> Result<
2604        (
2605            TcpApiSocketId<I, C>,
2606            SocketAddr<I::Addr, <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId>,
2607            <C::BindingsContext as TcpBindingsTypes>::ReturnedBuffers,
2608        ),
2609        AcceptError,
2610    > {
2611        let (conn_id, client_buffers) = self.core_ctx().with_socket_mut(id, |socket_state| {
2612            let TcpSocketState { socket_state, ip_options: _, socket_options: _ } = socket_state;
2613            debug!("accept on {id:?}");
2614            let Listener { backlog: _, buffer_sizes: _, accept_queue } = match socket_state {
2615                TcpSocketStateInner::Bound(BoundSocketState::Listener((
2616                    MaybeListener::Listener(l),
2617                    _sharing,
2618                    _addr,
2619                ))) => l,
2620                TcpSocketStateInner::Unbound(_)
2621                | TcpSocketStateInner::Bound(BoundSocketState::Connected { .. })
2622                | TcpSocketStateInner::Bound(BoundSocketState::Listener((
2623                    MaybeListener::Bound(_),
2624                    _,
2625                    _,
2626                ))) => return Err(AcceptError::NotSupported),
2627            };
2628            let (conn_id, client_buffers) =
2629                accept_queue.pop_ready().ok_or(AcceptError::WouldBlock)?;
2630
2631            Ok::<_, AcceptError>((conn_id, client_buffers))
2632        })?;
2633
2634        let remote_addr =
2635            self.core_ctx().with_socket_mut_and_converter(&conn_id, |socket_state, _converter| {
2636                let TcpSocketState { socket_state, ip_options: _, socket_options: _ } =
2637                    socket_state;
2638                let conn_and_addr = assert_matches!(
2639                    socket_state,
2640                    TcpSocketStateInner::Bound(BoundSocketState::Connected{ conn, .. }) => conn,
2641                    "invalid socket ID"
2642                );
2643                *I::get_accept_queue_mut(conn_and_addr) = None;
2644                let ConnectionInfo { local_addr: _, remote_addr, device: _ } =
2645                    I::get_conn_info(conn_and_addr);
2646                remote_addr
2647            });
2648
2649        debug!("accepted connection {conn_id:?} from {remote_addr:?} on {id:?}");
2650        Ok((conn_id, remote_addr, client_buffers))
2651    }
2652
2653    /// Connects a socket to a remote address.
2654    ///
2655    /// When the method returns, the connection is not guaranteed to be
2656    /// established. It is up to the caller (Bindings) to determine when the
2657    /// connection has been established. Bindings are free to use anything
2658    /// available on the platform to check, for instance, signals.
2659    pub fn connect(
2660        &mut self,
2661        id: &TcpApiSocketId<I, C>,
2662        remote_ip: Option<
2663            ZonedAddr<
2664                SpecifiedAddr<I::Addr>,
2665                <C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
2666            >,
2667        >,
2668        remote_port: NonZeroU16,
2669    ) -> Result<(), ConnectError> {
2670        let (core_ctx, bindings_ctx) = self.contexts();
2671        let result = core_ctx.with_socket_mut_generators_transport_demux(
2672            id,
2673            |core_ctx, socket_state, isn, timestamp_offset| {
2674                let TcpSocketState { socket_state, ip_options, socket_options } = socket_state;
2675                debug!("connect on {id:?} to {remote_ip:?}:{remote_port}");
2676                let remote_ip = DualStackRemoteIp::<I, _>::new(remote_ip);
2677                let (local_addr, sharing, buffer_sizes, socket_extra) = match socket_state {
2678                    TcpSocketStateInner::Bound(BoundSocketState::Connected {
2679                        conn,
2680                        sharing: _,
2681                        timer: _,
2682                    }) => {
2683                        let handshake_status = match core_ctx {
2684                            MaybeDualStack::NotDualStack((_core_ctx, converter)) => {
2685                                let (conn, _addr) = converter.convert(conn);
2686                                &mut conn.handshake_status
2687                            }
2688                            MaybeDualStack::DualStack((_core_ctx, converter)) => {
2689                                match converter.convert(conn) {
2690                                    EitherStack::ThisStack((conn, _addr)) => {
2691                                        &mut conn.handshake_status
2692                                    }
2693                                    EitherStack::OtherStack((conn, _addr)) => {
2694                                        &mut conn.handshake_status
2695                                    }
2696                                }
2697                            }
2698                        };
2699                        match handshake_status {
2700                            HandshakeStatus::Pending => return Err(ConnectError::Pending),
2701                            HandshakeStatus::Aborted => return Err(ConnectError::Aborted),
2702                            HandshakeStatus::Completed { reported } => {
2703                                if *reported {
2704                                    return Err(ConnectError::Completed);
2705                                } else {
2706                                    *reported = true;
2707                                    return Ok(());
2708                                }
2709                            }
2710                        }
2711                    }
2712                    TcpSocketStateInner::Unbound(Unbound {
2713                        bound_device: _,
2714                        socket_extra,
2715                        buffer_sizes,
2716                        sharing,
2717                    }) => (
2718                        DualStackTuple::<I, _>::new(None, None),
2719                        *sharing,
2720                        *buffer_sizes,
2721                        socket_extra.to_ref(),
2722                    ),
2723                    TcpSocketStateInner::Bound(BoundSocketState::Listener((
2724                        listener,
2725                        ListenerSharingState { sharing, listening: _ },
2726                        addr,
2727                    ))) => {
2728                        let local_addr = match &core_ctx {
2729                            MaybeDualStack::DualStack((_core_ctx, converter)) => {
2730                                match converter.convert(addr.clone()) {
2731                                    ListenerAddr {
2732                                        ip: DualStackListenerIpAddr::ThisStack(ip),
2733                                        device,
2734                                    } => {
2735                                        DualStackTuple::new(Some(ListenerAddr { ip, device }), None)
2736                                    }
2737                                    ListenerAddr {
2738                                        ip: DualStackListenerIpAddr::OtherStack(ip),
2739                                        device,
2740                                    } => {
2741                                        DualStackTuple::new(None, Some(ListenerAddr { ip, device }))
2742                                    }
2743                                    ListenerAddr {
2744                                        ip: DualStackListenerIpAddr::BothStacks(port),
2745                                        device,
2746                                    } => DualStackTuple::new(
2747                                        Some(ListenerAddr {
2748                                            ip: ListenerIpAddr { addr: None, identifier: port },
2749                                            device: device.clone(),
2750                                        }),
2751                                        Some(ListenerAddr {
2752                                            ip: ListenerIpAddr { addr: None, identifier: port },
2753                                            device,
2754                                        }),
2755                                    ),
2756                                }
2757                            }
2758                            MaybeDualStack::NotDualStack((_core_ctx, converter)) => {
2759                                DualStackTuple::new(Some(converter.convert(addr.clone())), None)
2760                            }
2761                        };
2762                        match listener {
2763                            MaybeListener::Bound(BoundState { buffer_sizes, socket_extra }) => {
2764                                (local_addr, *sharing, *buffer_sizes, socket_extra.to_ref())
2765                            }
2766                            MaybeListener::Listener(_) => return Err(ConnectError::Listener),
2767                        }
2768                    }
2769                };
2770                // Local addr is a tuple of (this_stack, other_stack) bound
2771                // local address.
2772                let local_addr = local_addr.into_inner();
2773                match (core_ctx, local_addr, remote_ip) {
2774                    // If not dual stack, we allow the connect operation if socket
2775                    // was not bound or bound to a this-stack local address before,
2776                    // and the remote address also belongs to this stack.
2777                    (
2778                        MaybeDualStack::NotDualStack((core_ctx, converter)),
2779                        (local_addr_this_stack, None),
2780                        DualStackRemoteIp::ThisStack(remote_ip),
2781                    ) => {
2782                        *socket_state = connect_inner(
2783                            core_ctx,
2784                            bindings_ctx,
2785                            id,
2786                            isn,
2787                            timestamp_offset,
2788                            local_addr_this_stack.clone(),
2789                            remote_ip,
2790                            remote_port,
2791                            socket_extra,
2792                            buffer_sizes,
2793                            socket_options,
2794                            sharing,
2795                            SingleStackDemuxStateAccessor(
2796                                &I::into_demux_socket_id(id.clone()),
2797                                local_addr_this_stack,
2798                            ),
2799                            |conn, addr| converter.convert_back((conn, addr)),
2800                            <C::CoreContext as CoreTimerContext<_, _>>::convert_timer,
2801                        )?;
2802                        Ok(())
2803                    }
2804                    // If dual stack, we can perform a this-stack only
2805                    // connection as long as we're not *only* bound in the other
2806                    // stack.
2807                    (
2808                        MaybeDualStack::DualStack((core_ctx, converter)),
2809                        (local_addr_this_stack, local_addr_other_stack @ None)
2810                        | (local_addr_this_stack @ Some(_), local_addr_other_stack @ Some(_)),
2811                        DualStackRemoteIp::ThisStack(remote_ip),
2812                    ) => {
2813                        *socket_state = connect_inner(
2814                            core_ctx,
2815                            bindings_ctx,
2816                            id,
2817                            isn,
2818                            timestamp_offset,
2819                            local_addr_this_stack.clone(),
2820                            remote_ip,
2821                            remote_port,
2822                            socket_extra,
2823                            buffer_sizes,
2824                            socket_options,
2825                            sharing,
2826                            DualStackDemuxStateAccessor(
2827                                id,
2828                                DualStackTuple::new(local_addr_this_stack, local_addr_other_stack),
2829                            ),
2830                            |conn, addr| {
2831                                converter.convert_back(EitherStack::ThisStack((conn, addr)))
2832                            },
2833                            <C::CoreContext as CoreTimerContext<_, _>>::convert_timer,
2834                        )?;
2835                        Ok(())
2836                    }
2837                    // If dual stack, we can perform an other-stack only
2838                    // connection as long as we're not *only* bound in this
2839                    // stack.
2840                    (
2841                        MaybeDualStack::DualStack((core_ctx, converter)),
2842                        (local_addr_this_stack @ None, local_addr_other_stack)
2843                        | (local_addr_this_stack @ Some(_), local_addr_other_stack @ Some(_)),
2844                        DualStackRemoteIp::OtherStack(remote_ip),
2845                    ) => {
2846                        if !core_ctx.dual_stack_enabled(ip_options) {
2847                            return Err(ConnectError::NoRoute);
2848                        }
2849                        *socket_state = connect_inner(
2850                            core_ctx,
2851                            bindings_ctx,
2852                            id,
2853                            isn,
2854                            timestamp_offset,
2855                            local_addr_other_stack.clone(),
2856                            remote_ip,
2857                            remote_port,
2858                            socket_extra,
2859                            buffer_sizes,
2860                            socket_options,
2861                            sharing,
2862                            DualStackDemuxStateAccessor(
2863                                id,
2864                                DualStackTuple::new(local_addr_this_stack, local_addr_other_stack),
2865                            ),
2866                            |conn, addr| {
2867                                converter.convert_back(EitherStack::OtherStack((conn, addr)))
2868                            },
2869                            <C::CoreContext as CoreTimerContext<_, _>>::convert_timer,
2870                        )?;
2871                        Ok(())
2872                    }
2873                    // Not possible for a non-dual-stack socket to bind in the other
2874                    // stack.
2875                    (
2876                        MaybeDualStack::NotDualStack(_),
2877                        (_, Some(_other_stack_local_addr)),
2878                        DualStackRemoteIp::ThisStack(_) | DualStackRemoteIp::OtherStack(_),
2879                    ) => unreachable!("The socket cannot be bound in the other stack"),
2880                    // Can't connect from one stack to the other.
2881                    (
2882                        MaybeDualStack::DualStack(_),
2883                        (_, Some(_other_stack_local_addr)),
2884                        DualStackRemoteIp::ThisStack(_),
2885                    ) => Err(ConnectError::NoRoute),
2886                    // Can't connect from one stack to the other.
2887                    (
2888                        MaybeDualStack::DualStack(_) | MaybeDualStack::NotDualStack(_),
2889                        (Some(_this_stack_local_addr), _),
2890                        DualStackRemoteIp::OtherStack(_),
2891                    ) => Err(ConnectError::NoRoute),
2892                    // Can't connect to the other stack for non-dual-stack sockets.
2893                    (
2894                        MaybeDualStack::NotDualStack(_),
2895                        (None, None),
2896                        DualStackRemoteIp::OtherStack(_),
2897                    ) => Err(ConnectError::NoRoute),
2898                }
2899            },
2900        );
2901        match &result {
2902            Ok(()) => {}
2903            Err(err) => {
2904                core_ctx.increment_both(id, |counters| &counters.failed_connection_attempts);
2905                match err {
2906                    ConnectError::NoRoute => {
2907                        core_ctx
2908                            .increment_both(id, |counters| &counters.active_open_no_route_errors);
2909                    }
2910                    ConnectError::NoPort => {
2911                        core_ctx.increment_both(id, |counters| &counters.failed_port_reservations);
2912                    }
2913                    _ => {}
2914                }
2915            }
2916        }
2917        result
2918    }
2919
2920    /// Closes a socket.
2921    pub fn close(&mut self, id: TcpApiSocketId<I, C>) {
2922        debug!("close on {id:?}");
2923        let (core_ctx, bindings_ctx) = self.contexts();
2924        let (destroy, pending) =
2925            core_ctx.with_socket_mut_transport_demux(&id, |core_ctx, socket_state| {
2926                let TcpSocketState { socket_state, ip_options: _, socket_options } = socket_state;
2927                match socket_state {
2928                    TcpSocketStateInner::Unbound(_) => (true, None),
2929                    TcpSocketStateInner::Bound(BoundSocketState::Listener((
2930                        maybe_listener,
2931                        _sharing,
2932                        addr,
2933                    ))) => {
2934                        match core_ctx {
2935                            MaybeDualStack::NotDualStack((core_ctx, converter)) => {
2936                                TcpDemuxContext::<I, _, _>::with_demux_mut(
2937                                    core_ctx,
2938                                    |DemuxState { socketmap }| {
2939                                        socketmap
2940                                            .listeners_mut()
2941                                            .remove(
2942                                                &I::into_demux_socket_id(id.clone()),
2943                                                &converter.convert(addr),
2944                                            )
2945                                            .expect("failed to remove from socketmap");
2946                                    },
2947                                );
2948                            }
2949                            MaybeDualStack::DualStack((core_ctx, converter)) => {
2950                                match converter.convert(addr.clone()) {
2951                                    ListenerAddr {
2952                                        ip: DualStackListenerIpAddr::ThisStack(ip),
2953                                        device,
2954                                    } => TcpDemuxContext::<I, _, _>::with_demux_mut(
2955                                        core_ctx,
2956                                        |DemuxState { socketmap }| {
2957                                            socketmap
2958                                                .listeners_mut()
2959                                                .remove(
2960                                                    &I::into_demux_socket_id(id.clone()),
2961                                                    &ListenerAddr { ip, device },
2962                                                )
2963                                                .expect("failed to remove from socketmap");
2964                                        },
2965                                    ),
2966                                    ListenerAddr {
2967                                        ip: DualStackListenerIpAddr::OtherStack(ip),
2968                                        device,
2969                                    } => {
2970                                        let other_demux_id =
2971                                            core_ctx.into_other_demux_socket_id(id.clone());
2972                                        TcpDemuxContext::<I::OtherVersion, _, _>::with_demux_mut(
2973                                            core_ctx,
2974                                            |DemuxState { socketmap }| {
2975                                                socketmap
2976                                                    .listeners_mut()
2977                                                    .remove(
2978                                                        &other_demux_id,
2979                                                        &ListenerAddr { ip, device },
2980                                                    )
2981                                                    .expect("failed to remove from socketmap");
2982                                            },
2983                                        );
2984                                    }
2985                                    ListenerAddr {
2986                                        ip: DualStackListenerIpAddr::BothStacks(port),
2987                                        device,
2988                                    } => {
2989                                        let other_demux_id =
2990                                            core_ctx.into_other_demux_socket_id(id.clone());
2991                                        core_ctx.with_both_demux_mut(|demux, other_demux| {
2992                                            demux
2993                                                .socketmap
2994                                                .listeners_mut()
2995                                                .remove(
2996                                                    &I::into_demux_socket_id(id.clone()),
2997                                                    &ListenerAddr {
2998                                                        ip: ListenerIpAddr {
2999                                                            addr: None,
3000                                                            identifier: port,
3001                                                        },
3002                                                        device: device.clone(),
3003                                                    },
3004                                                )
3005                                                .expect("failed to remove from socketmap");
3006                                            other_demux
3007                                                .socketmap
3008                                                .listeners_mut()
3009                                                .remove(
3010                                                    &other_demux_id,
3011                                                    &ListenerAddr {
3012                                                        ip: ListenerIpAddr {
3013                                                            addr: None,
3014                                                            identifier: port,
3015                                                        },
3016                                                        device,
3017                                                    },
3018                                                )
3019                                                .expect("failed to remove from socketmap");
3020                                        });
3021                                    }
3022                                }
3023                            }
3024                        };
3025                        // Move the listener down to a `Bound` state so it won't
3026                        // accept any more connections and close the accept
3027                        // queue.
3028                        let pending =
3029                            replace_with::replace_with_and(maybe_listener, |maybe_listener| {
3030                                match maybe_listener {
3031                                    MaybeListener::Bound(b) => (MaybeListener::Bound(b), None),
3032                                    MaybeListener::Listener(listener) => {
3033                                        let Listener { backlog: _, accept_queue, buffer_sizes } =
3034                                            listener;
3035                                        let (pending, socket_extra) = accept_queue.close();
3036                                        let bound_state = BoundState {
3037                                            buffer_sizes,
3038                                            socket_extra: Takeable::new(socket_extra),
3039                                        };
3040                                        (MaybeListener::Bound(bound_state), Some(pending))
3041                                    }
3042                                }
3043                            });
3044                        (true, pending)
3045                    }
3046                    TcpSocketStateInner::Bound(BoundSocketState::Connected {
3047                        conn,
3048                        sharing: _,
3049                        timer,
3050                    }) => {
3051                        fn do_close<SockI, WireI, CC, BC>(
3052                            core_ctx: &mut CC,
3053                            bindings_ctx: &mut BC,
3054                            id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
3055                            demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
3056                            socket_options: &SocketOptions,
3057                            conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
3058                            addr: &ConnAddr<
3059                                ConnIpAddr<<WireI as Ip>::Addr, NonZeroU16, NonZeroU16>,
3060                                CC::WeakDeviceId,
3061                            >,
3062                            timer: &mut BC::Timer,
3063                        ) -> bool
3064                        where
3065                            SockI: DualStackIpExt,
3066                            WireI: DualStackIpExt,
3067                            BC: TcpBindingsContext<CC::DeviceId>,
3068                            CC: TransportIpContext<WireI, BC>
3069                                + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>
3070                                + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
3071                        {
3072                            // Ignore the result - errors are handled below after calling `close`.
3073                            let _: Result<(), CloseError> = conn.state.shutdown_recv();
3074
3075                            conn.defunct = true;
3076                            let newly_closed = match conn.state.close(
3077                                &TcpCountersRefs::from_ctx(core_ctx, id),
3078                                CloseReason::Close { now: bindings_ctx.now() },
3079                                socket_options,
3080                            ) {
3081                                Err(CloseError::NoConnection) => NewlyClosed::No,
3082                                Err(CloseError::Closing) | Ok(NewlyClosed::No) => do_send_inner(
3083                                    &id,
3084                                    socket_options,
3085                                    conn,
3086                                    DoSendLimit::MultipleSegments,
3087                                    &addr,
3088                                    timer,
3089                                    core_ctx,
3090                                    bindings_ctx,
3091                                ),
3092                                Ok(NewlyClosed::Yes) => NewlyClosed::Yes,
3093                            };
3094                            // The connection transitions to closed because of
3095                            // this call, we need to unregister it from the
3096                            // socketmap.
3097                            handle_newly_closed(
3098                                core_ctx,
3099                                bindings_ctx,
3100                                newly_closed,
3101                                demux_id,
3102                                addr,
3103                                timer,
3104                            );
3105                            let now_closed = matches!(conn.state, State::Closed(_));
3106                            if now_closed {
3107                                debug_assert!(
3108                                    core_ctx.with_demux_mut(|DemuxState { socketmap }| {
3109                                        socketmap.conns_mut().entry(demux_id, addr).is_none()
3110                                    }),
3111                                    "lingering state in socketmap: demux_id: {:?}, addr: {:?}",
3112                                    demux_id,
3113                                    addr,
3114                                );
3115                                debug_assert_eq!(
3116                                    bindings_ctx.scheduled_instant(timer),
3117                                    None,
3118                                    "lingering timer for {:?}",
3119                                    id,
3120                                )
3121                            };
3122                            now_closed
3123                        }
3124                        let closed = match core_ctx {
3125                            MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3126                                let (conn, addr) = converter.convert(conn);
3127                                do_close(
3128                                    core_ctx,
3129                                    bindings_ctx,
3130                                    &id,
3131                                    &I::into_demux_socket_id(id.clone()),
3132                                    socket_options,
3133                                    conn,
3134                                    addr,
3135                                    timer,
3136                                )
3137                            }
3138                            MaybeDualStack::DualStack((core_ctx, converter)) => {
3139                                match converter.convert(conn) {
3140                                    EitherStack::ThisStack((conn, addr)) => do_close(
3141                                        core_ctx,
3142                                        bindings_ctx,
3143                                        &id,
3144                                        &I::into_demux_socket_id(id.clone()),
3145                                        socket_options,
3146                                        conn,
3147                                        addr,
3148                                        timer,
3149                                    ),
3150                                    EitherStack::OtherStack((conn, addr)) => do_close(
3151                                        core_ctx,
3152                                        bindings_ctx,
3153                                        &id,
3154                                        &core_ctx.into_other_demux_socket_id(id.clone()),
3155                                        socket_options,
3156                                        conn,
3157                                        addr,
3158                                        timer,
3159                                    ),
3160                                }
3161                            }
3162                        };
3163                        (closed, None)
3164                    }
3165                }
3166            });
3167
3168        close_pending_sockets(core_ctx, bindings_ctx, pending.into_iter().flatten());
3169
3170        if destroy {
3171            destroy_socket(core_ctx, bindings_ctx, id);
3172        }
3173    }
3174
3175    /// Shuts down a socket.
3176    ///
3177    /// For a connection, calling this function signals the other side of the
3178    /// connection that we will not be sending anything over the connection; The
3179    /// connection will be removed from the socketmap if the state moves to the
3180    /// `Closed` state.
3181    ///
3182    /// For a Listener, calling this function brings it back to bound state and
3183    /// shutdowns all the connection that is currently ready to be accepted.
3184    ///
3185    /// Returns Err(NoConnection) if the shutdown option does not apply.
3186    /// Otherwise, Whether a connection has been shutdown is returned, i.e., if
3187    /// the socket was a listener, the operation will succeed but false will be
3188    /// returned.
3189    pub fn shutdown(
3190        &mut self,
3191        id: &TcpApiSocketId<I, C>,
3192        shutdown_type: ShutdownType,
3193    ) -> Result<bool, NoConnection> {
3194        debug!("shutdown [{shutdown_type:?}] for {id:?}");
3195        let (core_ctx, bindings_ctx) = self.contexts();
3196        let (result, pending) =
3197            core_ctx.with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
3198                let TcpSocketState { socket_state, ip_options: _, socket_options  } = socket_state;
3199                match socket_state {
3200                    TcpSocketStateInner::Unbound(_) => Err(NoConnection),
3201                    TcpSocketStateInner::Bound(BoundSocketState::Connected {
3202                        conn,
3203                        sharing: _,
3204                        timer,
3205                    }) => {
3206                        fn do_shutdown<SockI, WireI, CC, BC>(
3207                            core_ctx: &mut CC,
3208                            bindings_ctx: &mut BC,
3209                            id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
3210                            demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
3211                            socket_options: &SocketOptions,
3212                            conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
3213                            addr: &ConnAddr<
3214                                ConnIpAddr<<WireI as Ip>::Addr, NonZeroU16, NonZeroU16>,
3215                                CC::WeakDeviceId,
3216                            >,
3217                            timer: &mut BC::Timer,
3218                            shutdown_type: ShutdownType,
3219                        ) -> Result<(), NoConnection>
3220                        where
3221                            SockI: DualStackIpExt,
3222                            WireI: DualStackIpExt,
3223                            BC: TcpBindingsContext<CC::DeviceId>,
3224                            CC: TransportIpContext<WireI, BC>
3225                                + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>
3226                                + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
3227                        {
3228                            let (shutdown_send, shutdown_receive) = shutdown_type.to_send_receive();
3229                            if shutdown_receive {
3230                                match conn.state.shutdown_recv() {
3231                                    Ok(()) => (),
3232                                    Err(CloseError::NoConnection) => return Err(NoConnection),
3233                                    Err(CloseError::Closing) => (),
3234                                }
3235                            }
3236
3237                            if !shutdown_send {
3238                                return Ok(());
3239                            }
3240
3241                            match conn.state.close(
3242                                &TcpCountersRefs::from_ctx(core_ctx, id),
3243                                CloseReason::Shutdown,
3244                                socket_options,
3245                            ) {
3246                                Ok(newly_closed) => {
3247                                    let newly_closed = match newly_closed {
3248                                        NewlyClosed::Yes => NewlyClosed::Yes,
3249                                        NewlyClosed::No => do_send_inner(
3250                                            id,
3251                                            socket_options,
3252                                            conn,
3253                                            DoSendLimit::MultipleSegments,
3254                                            addr,
3255                                            timer,
3256                                            core_ctx,
3257                                            bindings_ctx,
3258                                        ),
3259                                    };
3260                                    handle_newly_closed(
3261                                        core_ctx,
3262                                        bindings_ctx,
3263                                        newly_closed,
3264                                        demux_id,
3265                                        addr,
3266                                        timer,
3267                                    );
3268                                    Ok(())
3269                                }
3270                                Err(CloseError::NoConnection) => Err(NoConnection),
3271                                Err(CloseError::Closing) => Ok(()),
3272                            }
3273                        }
3274                        match core_ctx {
3275                            MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3276                                let (conn, addr) = converter.convert(conn);
3277                                do_shutdown(
3278                                    core_ctx,
3279                                    bindings_ctx,
3280                                    id,
3281                                    &I::into_demux_socket_id(id.clone()),
3282                                    socket_options,
3283                                    conn,
3284                                    addr,
3285                                    timer,
3286                                    shutdown_type,
3287                                )?
3288                            }
3289                            MaybeDualStack::DualStack((core_ctx, converter)) => {
3290                                match converter.convert(conn) {
3291                                    EitherStack::ThisStack((conn, addr)) => do_shutdown(
3292                                        core_ctx,
3293                                        bindings_ctx,
3294                                        id,
3295                                        &I::into_demux_socket_id(id.clone()),
3296                                        socket_options,
3297                                        conn,
3298                                        addr,
3299                                        timer,
3300                                        shutdown_type,
3301                                    )?,
3302                                    EitherStack::OtherStack((conn, addr)) => do_shutdown(
3303                                        core_ctx,
3304                                        bindings_ctx,
3305                                        id,
3306                                        &core_ctx.into_other_demux_socket_id(id.clone()),
3307                                        socket_options,
3308                                        conn,
3309                                        addr,
3310                                        timer,
3311                                        shutdown_type,
3312                                    )?,
3313                                }
3314                            }
3315                        };
3316                        Ok((true, None))
3317                    }
3318                    TcpSocketStateInner::Bound(BoundSocketState::Listener((
3319                        maybe_listener,
3320                        sharing,
3321                        addr,
3322                    ))) => {
3323                        let (_shutdown_send, shutdown_receive) = shutdown_type.to_send_receive();
3324
3325                        if !shutdown_receive {
3326                            return Ok((false, None));
3327                        }
3328                        match maybe_listener {
3329                            MaybeListener::Bound(_) => return Err(NoConnection),
3330                            MaybeListener::Listener(_) => {}
3331                        }
3332
3333                        let new_sharing = {
3334                            let ListenerSharingState { sharing, listening } = sharing;
3335                            assert!(*listening, "listener {id:?} is not listening");
3336                            ListenerSharingState { listening: false, sharing: sharing.clone() }
3337                        };
3338                        *sharing = try_update_listener_sharing::<_, C::CoreContext, _>(
3339                            core_ctx,
3340                            id,
3341                            addr.clone(),
3342                            sharing,
3343                            new_sharing,
3344                        )
3345                        .unwrap_or_else(|e| {
3346                            unreachable!(
3347                                "downgrading a TCP listener to bound should not fail, got {e:?}"
3348                            )
3349                        });
3350
3351                        let queued_items =
3352                            replace_with::replace_with_and(maybe_listener, |maybe_listener| {
3353                                let Listener {
3354                                    backlog: _,
3355                                    accept_queue,
3356                                    buffer_sizes,
3357                                } = assert_matches!(maybe_listener,
3358                            MaybeListener::Listener(l) => l, "must be a listener");
3359                                let (pending, socket_extra) = accept_queue.close();
3360                                let bound_state = BoundState {
3361                                    buffer_sizes,
3362                                    socket_extra: Takeable::new(socket_extra),
3363                                };
3364                                (MaybeListener::Bound(bound_state), pending)
3365                            });
3366
3367                        Ok((false, Some(queued_items)))
3368                    }
3369                }
3370            })?;
3371
3372        close_pending_sockets(core_ctx, bindings_ctx, pending.into_iter().flatten());
3373
3374        Ok(result)
3375    }
3376
3377    /// Polls the state machine after data is dequeued from the receive buffer.
3378    ///
3379    /// Possibly sends a window update to the peer if enough data has been read
3380    /// from the buffer and we suspect that the peer is in SWS avoidance.
3381    ///
3382    /// This does nothing for a disconnected socket.
3383    pub fn on_receive_buffer_read(&mut self, id: &TcpApiSocketId<I, C>) {
3384        let (core_ctx, bindings_ctx) = self.contexts();
3385        core_ctx.with_socket_mut_transport_demux(
3386            id,
3387            |core_ctx, TcpSocketState { socket_state, ip_options: _, socket_options }| {
3388                let conn = match socket_state {
3389                    TcpSocketStateInner::Unbound(_) => return,
3390                    TcpSocketStateInner::Bound(bound) => match bound {
3391                        BoundSocketState::Listener(_) => return,
3392                        BoundSocketState::Connected { conn, sharing: _, timer: _ } => conn,
3393                    },
3394                };
3395
3396                match core_ctx {
3397                    MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3398                        let (conn, addr) = converter.convert(conn);
3399                        if let Some(ack) = conn.state.poll_receive_data_dequeued() {
3400                            send_tcp_segment(
3401                                core_ctx,
3402                                bindings_ctx,
3403                                Some(id),
3404                                Some(&conn.ip_sock),
3405                                addr.ip,
3406                                ack.into_empty(),
3407                                &socket_options.ip_options,
3408                            )
3409                        }
3410                    }
3411                    MaybeDualStack::DualStack((core_ctx, converter)) => {
3412                        match converter.convert(conn) {
3413                            EitherStack::ThisStack((conn, addr)) => {
3414                                if let Some(ack) = conn.state.poll_receive_data_dequeued() {
3415                                    send_tcp_segment(
3416                                        core_ctx,
3417                                        bindings_ctx,
3418                                        Some(id),
3419                                        Some(&conn.ip_sock),
3420                                        addr.ip,
3421                                        ack.into_empty(),
3422                                        &socket_options.ip_options,
3423                                    )
3424                                }
3425                            }
3426                            EitherStack::OtherStack((conn, addr)) => {
3427                                if let Some(ack) = conn.state.poll_receive_data_dequeued() {
3428                                    send_tcp_segment(
3429                                        core_ctx,
3430                                        bindings_ctx,
3431                                        Some(id),
3432                                        Some(&conn.ip_sock),
3433                                        addr.ip,
3434                                        ack.into_empty(),
3435                                        &socket_options.ip_options,
3436                                    )
3437                                }
3438                            }
3439                        }
3440                    }
3441                }
3442            },
3443        )
3444    }
3445
3446    fn set_device_conn<SockI, WireI, CC>(
3447        core_ctx: &mut CC,
3448        bindings_ctx: &mut C::BindingsContext,
3449        addr: &mut ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
3450        demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, C::BindingsContext>,
3451        ip_options: &TcpIpSockOptions,
3452        conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, C::BindingsContext>,
3453        new_device: Option<CC::DeviceId>,
3454    ) -> Result<(), SetDeviceError>
3455    where
3456        SockI: DualStackIpExt,
3457        WireI: DualStackIpExt,
3458        CC: TransportIpContext<WireI, C::BindingsContext>
3459            + TcpDemuxContext<WireI, CC::WeakDeviceId, C::BindingsContext>,
3460    {
3461        let ConnAddr {
3462            device: old_device,
3463            ip: ConnIpAddr { local: (local_ip, _), remote: (remote_ip, _) },
3464        } = addr;
3465
3466        let update = SocketDeviceUpdate {
3467            local_ip: Some(local_ip.as_ref()),
3468            remote_ip: Some(remote_ip.as_ref()),
3469            old_device: old_device.as_ref(),
3470        };
3471        match update.check_update(new_device.as_ref()) {
3472            Ok(()) => (),
3473            Err(SocketDeviceUpdateNotAllowedError) => return Err(SetDeviceError::ZoneChange),
3474        }
3475        let new_socket = core_ctx
3476            .new_ip_socket(
3477                bindings_ctx,
3478                IpSocketArgs {
3479                    device: new_device.as_ref().map(EitherDeviceId::Strong),
3480                    local_ip: IpDeviceAddr::new_from_socket_ip_addr(*local_ip),
3481                    remote_ip: *remote_ip,
3482                    proto: IpProto::Tcp.into(),
3483                    options: ip_options,
3484                },
3485            )
3486            .map_err(|_: IpSockCreationError| SetDeviceError::Unroutable)?;
3487        let new_address = ConnAddr { device: new_socket.device().cloned(), ..addr.clone() };
3488        core_ctx.with_demux_mut(|DemuxState { socketmap }| {
3489            let entry = match socketmap.conns_mut().entry(demux_id, addr) {
3490                Some(entry) => entry,
3491                None => {
3492                    debug!("no demux entry for {addr:?} with {demux_id:?}");
3493                    // State must be closed or timewait if we have a bound
3494                    // and connected socket that is no longer present in the
3495                    // demux.
3496                    assert_matches!(&conn.state, State::Closed(_) | State::TimeWait(_));
3497                    // If the socket has already been removed from the
3498                    // demux, then we can update our address information
3499                    // locally.
3500                    *addr = new_address;
3501                    return Ok(());
3502                }
3503            };
3504
3505            match entry.try_update_addr(new_address) {
3506                Ok(entry) => {
3507                    *addr = entry.get_addr().clone();
3508                    conn.ip_sock = new_socket;
3509                    Ok(())
3510                }
3511                Err((ExistsError, _entry)) => Err(SetDeviceError::Conflict),
3512            }
3513        })
3514    }
3515
3516    /// Updates the `old_device` to the new device if it is allowed. Note that
3517    /// this `old_device` will be updated in-place, so it should come from the
3518    /// outside socketmap address.
3519    fn set_device_listener<WireI, D>(
3520        demux_id: &WireI::DemuxSocketId<D, C::BindingsContext>,
3521        ip_addr: ListenerIpAddr<WireI::Addr, NonZeroU16>,
3522        old_device: &mut Option<D>,
3523        new_device: Option<&D>,
3524        DemuxState { socketmap }: &mut DemuxState<WireI, D, C::BindingsContext>,
3525    ) -> Result<(), SetDeviceError>
3526    where
3527        WireI: DualStackIpExt,
3528        D: WeakDeviceIdentifier,
3529    {
3530        let entry = socketmap
3531            .listeners_mut()
3532            .entry(demux_id, &ListenerAddr { ip: ip_addr, device: old_device.clone() })
3533            .expect("invalid ID");
3534
3535        let update = SocketDeviceUpdate {
3536            local_ip: ip_addr.addr.as_ref().map(|a| a.as_ref()),
3537            remote_ip: None,
3538            old_device: old_device.as_ref(),
3539        };
3540        match update.check_update(new_device) {
3541            Ok(()) => (),
3542            Err(SocketDeviceUpdateNotAllowedError) => return Err(SetDeviceError::ZoneChange),
3543        }
3544        match entry.try_update_addr(ListenerAddr { device: new_device.cloned(), ip: ip_addr }) {
3545            Ok(entry) => {
3546                *old_device = entry.get_addr().device.clone();
3547                Ok(())
3548            }
3549            Err((ExistsError, _entry)) => Err(SetDeviceError::Conflict),
3550        }
3551    }
3552
3553    /// Sets the device on a socket.
3554    ///
3555    /// Passing `None` clears the bound device.
3556    pub fn set_device(
3557        &mut self,
3558        id: &TcpApiSocketId<I, C>,
3559        new_device: Option<<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>,
3560    ) -> Result<(), SetDeviceError> {
3561        let (core_ctx, bindings_ctx) = self.contexts();
3562        let weak_device = new_device.as_ref().map(|d| d.downgrade());
3563        core_ctx.with_socket_mut_transport_demux(id, move |core_ctx, socket_state| {
3564            debug!("set device on {id:?} to {new_device:?}");
3565            let TcpSocketState { socket_state, ip_options: _, socket_options } = socket_state;
3566            match socket_state {
3567                TcpSocketStateInner::Unbound(unbound) => {
3568                    unbound.bound_device = weak_device;
3569                    Ok(())
3570                }
3571                TcpSocketStateInner::Bound(BoundSocketState::Connected {
3572                    conn: conn_and_addr,
3573                    sharing: _,
3574                    timer: _,
3575                }) => {
3576                    let this_or_other_stack = match core_ctx {
3577                        MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3578                            let (conn, addr) = converter.convert(conn_and_addr);
3579                            EitherStack::ThisStack((
3580                                core_ctx.as_this_stack(),
3581                                conn,
3582                                addr,
3583                                I::into_demux_socket_id(id.clone()),
3584                            ))
3585                        }
3586                        MaybeDualStack::DualStack((core_ctx, converter)) => {
3587                            match converter.convert(conn_and_addr) {
3588                                EitherStack::ThisStack((conn, addr)) => EitherStack::ThisStack((
3589                                    core_ctx.as_this_stack(),
3590                                    conn,
3591                                    addr,
3592                                    I::into_demux_socket_id(id.clone()),
3593                                )),
3594                                EitherStack::OtherStack((conn, addr)) => {
3595                                    let demux_id = core_ctx.into_other_demux_socket_id(id.clone());
3596                                    EitherStack::OtherStack((core_ctx, conn, addr, demux_id))
3597                                }
3598                            }
3599                        }
3600                    };
3601                    match this_or_other_stack {
3602                        EitherStack::ThisStack((core_ctx, conn, addr, demux_id)) => {
3603                            Self::set_device_conn::<_, I, _>(
3604                                core_ctx,
3605                                bindings_ctx,
3606                                addr,
3607                                &demux_id,
3608                                &socket_options.ip_options,
3609                                conn,
3610                                new_device,
3611                            )
3612                        }
3613                        EitherStack::OtherStack((core_ctx, conn, addr, demux_id)) => {
3614                            Self::set_device_conn::<_, I::OtherVersion, _>(
3615                                core_ctx,
3616                                bindings_ctx,
3617                                addr,
3618                                &demux_id,
3619                                &socket_options.ip_options,
3620                                conn,
3621                                new_device,
3622                            )
3623                        }
3624                    }
3625                }
3626                TcpSocketStateInner::Bound(BoundSocketState::Listener((
3627                    _listener,
3628                    _sharing,
3629                    addr,
3630                ))) => match core_ctx {
3631                    MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3632                        let ListenerAddr { ip, device } = converter.convert(addr);
3633                        core_ctx.with_demux_mut(|demux| {
3634                            Self::set_device_listener(
3635                                &I::into_demux_socket_id(id.clone()),
3636                                ip.clone(),
3637                                device,
3638                                weak_device.as_ref(),
3639                                demux,
3640                            )
3641                        })
3642                    }
3643                    MaybeDualStack::DualStack((core_ctx, converter)) => {
3644                        match converter.convert(addr) {
3645                            ListenerAddr { ip: DualStackListenerIpAddr::ThisStack(ip), device } => {
3646                                TcpDemuxContext::<I, _, _>::with_demux_mut(core_ctx, |demux| {
3647                                    Self::set_device_listener(
3648                                        &I::into_demux_socket_id(id.clone()),
3649                                        ip.clone(),
3650                                        device,
3651                                        weak_device.as_ref(),
3652                                        demux,
3653                                    )
3654                                })
3655                            }
3656                            ListenerAddr {
3657                                ip: DualStackListenerIpAddr::OtherStack(ip),
3658                                device,
3659                            } => {
3660                                let other_demux_id =
3661                                    core_ctx.into_other_demux_socket_id(id.clone());
3662                                TcpDemuxContext::<I::OtherVersion, _, _>::with_demux_mut(
3663                                    core_ctx,
3664                                    |demux| {
3665                                        Self::set_device_listener(
3666                                            &other_demux_id,
3667                                            ip.clone(),
3668                                            device,
3669                                            weak_device.as_ref(),
3670                                            demux,
3671                                        )
3672                                    },
3673                                )
3674                            }
3675                            ListenerAddr {
3676                                ip: DualStackListenerIpAddr::BothStacks(port),
3677                                device,
3678                            } => {
3679                                let other_demux_id =
3680                                    core_ctx.into_other_demux_socket_id(id.clone());
3681                                core_ctx.with_both_demux_mut(|demux, other_demux| {
3682                                    Self::set_device_listener(
3683                                        &I::into_demux_socket_id(id.clone()),
3684                                        ListenerIpAddr { addr: None, identifier: *port },
3685                                        device,
3686                                        weak_device.as_ref(),
3687                                        demux,
3688                                    )?;
3689                                    match Self::set_device_listener(
3690                                        &other_demux_id,
3691                                        ListenerIpAddr { addr: None, identifier: *port },
3692                                        device,
3693                                        weak_device.as_ref(),
3694                                        other_demux,
3695                                    ) {
3696                                        Ok(()) => Ok(()),
3697                                        Err(e) => {
3698                                            Self::set_device_listener(
3699                                                &I::into_demux_socket_id(id.clone()),
3700                                                ListenerIpAddr { addr: None, identifier: *port },
3701                                                device,
3702                                                device.clone().as_ref(),
3703                                                demux,
3704                                            )
3705                                            .expect("failed to revert back the device setting");
3706                                            Err(e)
3707                                        }
3708                                    }
3709                                })
3710                            }
3711                        }
3712                    }
3713                },
3714            }
3715        })
3716    }
3717
3718    /// Get information for a TCP socket.
3719    pub fn get_info(
3720        &mut self,
3721        id: &TcpApiSocketId<I, C>,
3722    ) -> SocketInfo<I::Addr, <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId> {
3723        self.core_ctx().with_socket_and_converter(
3724            id,
3725            |TcpSocketState { socket_state, ip_options: _, socket_options: _ }, _converter| {
3726                match socket_state {
3727                    TcpSocketStateInner::Unbound(unbound) => SocketInfo::Unbound(unbound.into()),
3728                    TcpSocketStateInner::Bound(BoundSocketState::Connected {
3729                        conn: conn_and_addr,
3730                        sharing: _,
3731                        timer: _,
3732                    }) => SocketInfo::Connection(I::get_conn_info(conn_and_addr)),
3733                    TcpSocketStateInner::Bound(BoundSocketState::Listener((
3734                        _listener,
3735                        _sharing,
3736                        addr,
3737                    ))) => SocketInfo::Bound(I::get_bound_info(addr)),
3738                }
3739            },
3740        )
3741    }
3742
3743    /// Call this function whenever a socket can push out more data. That means
3744    /// either:
3745    ///
3746    /// - A retransmission timer fires.
3747    /// - An ack received from peer so that our send window is enlarged.
3748    /// - The user puts data into the buffer and we are notified.
3749    pub fn do_send(&mut self, conn_id: &TcpApiSocketId<I, C>) {
3750        let (core_ctx, bindings_ctx) = self.contexts();
3751        core_ctx.with_socket_mut_transport_demux(conn_id, |core_ctx, socket_state| {
3752            let TcpSocketState { socket_state, ip_options: _, socket_options } = socket_state;
3753            let (conn, timer) = assert_matches!(
3754                socket_state,
3755                TcpSocketStateInner::Bound(BoundSocketState::Connected {
3756                    conn, sharing: _, timer
3757                }) => (conn, timer)
3758            );
3759            match core_ctx {
3760                MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3761                    let (conn, addr) = converter.convert(conn);
3762                    do_send_inner_and_then_handle_newly_closed(
3763                        conn_id,
3764                        &I::into_demux_socket_id(conn_id.clone()),
3765                        socket_options,
3766                        conn,
3767                        DoSendLimit::MultipleSegments,
3768                        addr,
3769                        timer,
3770                        core_ctx,
3771                        bindings_ctx,
3772                    );
3773                }
3774                MaybeDualStack::DualStack((core_ctx, converter)) => match converter.convert(conn) {
3775                    EitherStack::ThisStack((conn, addr)) => {
3776                        do_send_inner_and_then_handle_newly_closed(
3777                            conn_id,
3778                            &I::into_demux_socket_id(conn_id.clone()),
3779                            socket_options,
3780                            conn,
3781                            DoSendLimit::MultipleSegments,
3782                            addr,
3783                            timer,
3784                            core_ctx,
3785                            bindings_ctx,
3786                        )
3787                    }
3788                    EitherStack::OtherStack((conn, addr)) => {
3789                        let other_demux_id = core_ctx.into_other_demux_socket_id(conn_id.clone());
3790                        do_send_inner_and_then_handle_newly_closed(
3791                            conn_id,
3792                            &other_demux_id,
3793                            socket_options,
3794                            conn,
3795                            DoSendLimit::MultipleSegments,
3796                            addr,
3797                            timer,
3798                            core_ctx,
3799                            bindings_ctx,
3800                        );
3801                    }
3802                },
3803            };
3804        })
3805    }
3806
3807    fn handle_timer(
3808        &mut self,
3809        weak_id: WeakTcpSocketId<
3810            I,
3811            <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
3812            C::BindingsContext,
3813        >,
3814    ) {
3815        let id = match weak_id.upgrade() {
3816            Some(c) => c,
3817            None => return,
3818        };
3819        let (core_ctx, bindings_ctx) = self.contexts();
3820        debug!("handle_timer on {id:?}");
3821        // Alias refs so we can move weak_id to the closure.
3822        let id_alias = &id;
3823        let bindings_ctx_alias = &mut *bindings_ctx;
3824        let closed_and_defunct =
3825            core_ctx.with_socket_mut_transport_demux(&id, move |core_ctx, socket_state| {
3826                let TcpSocketState { socket_state, ip_options: _, socket_options  } = socket_state;
3827                let id = id_alias;
3828                trace_duration!(c"tcp::handle_timer", "id" => id.trace_id());
3829                let bindings_ctx = bindings_ctx_alias;
3830                let (conn, timer) = assert_matches!(
3831                    socket_state,
3832                    TcpSocketStateInner::Bound(BoundSocketState::Connected{ conn, sharing: _, timer}) => (conn, timer)
3833                );
3834                fn do_handle_timer<SockI, WireI, CC, BC>(
3835                    core_ctx: &mut CC,
3836                    bindings_ctx: &mut BC,
3837                    id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
3838                    demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
3839                    socket_options: &SocketOptions,
3840                    conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
3841                    addr: &ConnAddr<
3842                        ConnIpAddr<<WireI as Ip>::Addr, NonZeroU16, NonZeroU16>,
3843                        CC::WeakDeviceId,
3844                    >,
3845                    timer: &mut BC::Timer,
3846                ) -> bool
3847                where
3848                    SockI: DualStackIpExt,
3849                    WireI: DualStackIpExt,
3850                    BC: TcpBindingsContext<CC::DeviceId>,
3851                    CC: TransportIpContext<WireI, BC>
3852                        + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>
3853                        + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
3854                {
3855                    let time_wait = matches!(conn.state, State::TimeWait(_));
3856                    let newly_closed = do_send_inner(
3857                        id,
3858                        socket_options,
3859                        conn,
3860                        DoSendLimit::MultipleSegments,
3861                        addr,
3862                        timer,
3863                        core_ctx,
3864                        bindings_ctx,
3865                    );
3866                    match (newly_closed, time_wait) {
3867                        // Moved to closed state, remove from demux and cancel
3868                        // timers.
3869                        (NewlyClosed::Yes, time_wait) => {
3870                            let result = core_ctx.with_demux_mut(|DemuxState { socketmap }| {
3871                                socketmap
3872                                    .conns_mut()
3873                                    .remove(demux_id, addr)
3874                            });
3875                            // Carve out an exception for time wait demux
3876                            // removal, since it could've been removed from the
3877                            // demux already as part of reuse.
3878                            //
3879                            // We can log rather silently because the demux will
3880                            // not allow us to remove the wrong connection, the
3881                            // panic is here to catch paths that are doing
3882                            // cleanup in the wrong way.
3883                            result.unwrap_or_else(|e| {
3884                                if time_wait {
3885                                    debug!(
3886                                        "raced with timewait removal for {id:?} {addr:?}: {e:?}"
3887                                    );
3888                                } else {
3889                                    panic!("failed to remove from socketmap: {e:?}");
3890                                }
3891                            });
3892                            let _: Option<_> = bindings_ctx.cancel_timer(timer);
3893                        }
3894                        (NewlyClosed::No, _) => {},
3895                    }
3896                    conn.defunct && matches!(conn.state, State::Closed(_))
3897                }
3898                match core_ctx {
3899                    MaybeDualStack::NotDualStack((core_ctx, converter)) => {
3900                        let (conn, addr) = converter.convert(conn);
3901                        do_handle_timer(
3902                            core_ctx,
3903                            bindings_ctx,
3904                            id,
3905                            &I::into_demux_socket_id(id.clone()),
3906                            socket_options,
3907                            conn,
3908                            addr,
3909                            timer,
3910                        )
3911                    }
3912                    MaybeDualStack::DualStack((core_ctx, converter)) => {
3913                        match converter.convert(conn) {
3914                            EitherStack::ThisStack((conn, addr)) => do_handle_timer(
3915                                core_ctx,
3916                                bindings_ctx,
3917                                id,
3918                                &I::into_demux_socket_id(id.clone()),
3919                                socket_options,
3920                                conn,
3921                                addr,
3922                                timer,
3923                            ),
3924                            EitherStack::OtherStack((conn, addr)) => do_handle_timer(
3925                                core_ctx,
3926                                bindings_ctx,
3927                                id,
3928                                &core_ctx.into_other_demux_socket_id(id.clone()),
3929                                socket_options,
3930                                conn,
3931                                addr,
3932                                timer,
3933                            ),
3934                        }
3935                    }
3936                }
3937            });
3938        if closed_and_defunct {
3939            // Remove the entry from the primary map and drop primary.
3940            destroy_socket(core_ctx, bindings_ctx, id);
3941        }
3942    }
3943
3944    /// Access options mutably for a TCP socket.
3945    pub fn with_socket_options_mut<R, F: FnOnce(&mut SocketOptions) -> R>(
3946        &mut self,
3947        id: &TcpApiSocketId<I, C>,
3948        f: F,
3949    ) -> R {
3950        let (core_ctx, _) = self.contexts();
3951        core_ctx.with_socket_mut(
3952            id,
3953            |TcpSocketState { socket_state: _, ip_options: _, socket_options }| f(socket_options),
3954        )
3955    }
3956
3957    /// Access socket options immutably for a TCP socket
3958    pub fn with_socket_options<R, F: FnOnce(&SocketOptions) -> R>(
3959        &mut self,
3960        id: &TcpApiSocketId<I, C>,
3961        f: F,
3962    ) -> R {
3963        self.core_ctx()
3964            .with_socket(id, |TcpSocketState { socket_state: _, ip_options: _, socket_options }| {
3965                f(socket_options)
3966            })
3967    }
3968
3969    /// Set the size of the send buffer for this socket and future derived
3970    /// sockets.
3971    pub fn set_send_buffer_size(&mut self, id: &TcpApiSocketId<I, C>, size: usize) {
3972        let (core_ctx, bindings_ctx) = self.contexts();
3973        set_buffer_size::<SendBufferSize, I, _, _>(core_ctx, bindings_ctx, id, size)
3974    }
3975
3976    /// Get the size of the send buffer for this socket and future derived
3977    /// sockets.
3978    pub fn send_buffer_size(&mut self, id: &TcpApiSocketId<I, C>) -> Option<usize> {
3979        get_buffer_size::<SendBufferSize, I, _, _>(self.core_ctx(), id)
3980    }
3981
3982    /// Set the size of the send buffer for this socket and future derived
3983    /// sockets.
3984    pub fn set_receive_buffer_size(&mut self, id: &TcpApiSocketId<I, C>, size: usize) {
3985        let (core_ctx, bindings_ctx) = self.contexts();
3986        set_buffer_size::<ReceiveBufferSize, I, _, _>(core_ctx, bindings_ctx, id, size)
3987    }
3988
3989    /// Get the size of the receive buffer for this socket and future derived
3990    /// sockets.
3991    pub fn receive_buffer_size(&mut self, id: &TcpApiSocketId<I, C>) -> Option<usize> {
3992        get_buffer_size::<ReceiveBufferSize, I, _, _>(self.core_ctx(), id)
3993    }
3994
3995    /// Sets the POSIX SO_REUSEADDR socket option on a socket.
3996    pub fn set_reuseaddr(
3997        &mut self,
3998        id: &TcpApiSocketId<I, C>,
3999        reuse: bool,
4000    ) -> Result<(), SetReuseAddrError> {
4001        let new_sharing = match reuse {
4002            true => SharingState::ReuseAddress,
4003            false => SharingState::Exclusive,
4004        };
4005        self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
4006            let TcpSocketState { socket_state, ip_options: _, socket_options: _ } = socket_state;
4007            match socket_state {
4008                TcpSocketStateInner::Unbound(unbound) => {
4009                    unbound.sharing = new_sharing;
4010                    Ok(())
4011                }
4012                TcpSocketStateInner::Bound(BoundSocketState::Listener((
4013                    _listener,
4014                    old_sharing,
4015                    addr,
4016                ))) => {
4017                    if new_sharing == old_sharing.sharing {
4018                        return Ok(());
4019                    }
4020                    let new_sharing = {
4021                        let ListenerSharingState { sharing: _, listening } = old_sharing;
4022                        ListenerSharingState { sharing: new_sharing, listening: *listening }
4023                    };
4024                    *old_sharing = try_update_listener_sharing::<_, C::CoreContext, _>(
4025                        core_ctx,
4026                        id,
4027                        addr.clone(),
4028                        old_sharing,
4029                        new_sharing,
4030                    )
4031                    .map_err(|UpdateSharingError| SetReuseAddrError::AddrInUse)?;
4032                    Ok(())
4033                }
4034                TcpSocketStateInner::Bound(BoundSocketState::Connected { .. }) => {
4035                    // TODO(https://fxbug.dev/42180094): Support setting the option
4036                    // for connection sockets.
4037                    Err(SetReuseAddrError::NotSupported)
4038                }
4039            }
4040        })
4041    }
4042
4043    /// Gets the POSIX SO_REUSEADDR socket option on a socket.
4044    pub fn reuseaddr(&mut self, id: &TcpApiSocketId<I, C>) -> bool {
4045        self.core_ctx().with_socket(
4046            id,
4047            |TcpSocketState { socket_state, ip_options: _, socket_options: _ }| match socket_state {
4048                TcpSocketStateInner::Unbound(Unbound { sharing, .. })
4049                | TcpSocketStateInner::Bound(
4050                    BoundSocketState::Connected { sharing, .. }
4051                    | BoundSocketState::Listener((_, ListenerSharingState { sharing, .. }, _)),
4052                ) => match sharing {
4053                    SharingState::Exclusive => false,
4054                    SharingState::ReuseAddress => true,
4055                },
4056            },
4057        )
4058    }
4059
4060    /// Gets the `dual_stack_enabled` option value.
4061    pub fn dual_stack_enabled(
4062        &mut self,
4063        id: &TcpSocketId<
4064            I,
4065            <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
4066            C::BindingsContext,
4067        >,
4068    ) -> Result<bool, NotDualStackCapableError> {
4069        self.core_ctx().with_socket_mut_transport_demux(
4070            id,
4071            |core_ctx, TcpSocketState { socket_state: _, ip_options, socket_options: _ }| {
4072                match core_ctx {
4073                    MaybeDualStack::NotDualStack(_) => Err(NotDualStackCapableError),
4074                    MaybeDualStack::DualStack((core_ctx, _converter)) => {
4075                        Ok(core_ctx.dual_stack_enabled(ip_options))
4076                    }
4077                }
4078            },
4079        )
4080    }
4081
4082    /// Sets the socket mark for the socket domain.
4083    pub fn set_mark(&mut self, id: &TcpApiSocketId<I, C>, domain: MarkDomain, mark: Mark) {
4084        self.with_socket_options_mut(id, |options| *options.ip_options.marks.get_mut(domain) = mark)
4085    }
4086
4087    /// Gets the socket mark for the socket domain.
4088    pub fn get_mark(&mut self, id: &TcpApiSocketId<I, C>, domain: MarkDomain) -> Mark {
4089        self.with_socket_options(id, |options| *options.ip_options.marks.get(domain))
4090    }
4091
4092    /// Sets the `dual_stack_enabled` option value.
4093    pub fn set_dual_stack_enabled(
4094        &mut self,
4095        id: &TcpSocketId<
4096            I,
4097            <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
4098            C::BindingsContext,
4099        >,
4100        value: bool,
4101    ) -> Result<(), SetDualStackEnabledError> {
4102        self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, socket_state| {
4103            let TcpSocketState { socket_state, ip_options, socket_options: _ } = socket_state;
4104            match core_ctx {
4105                MaybeDualStack::NotDualStack(_) => Err(NotDualStackCapableError.into()),
4106                MaybeDualStack::DualStack((core_ctx, _converter)) => match socket_state {
4107                    TcpSocketStateInner::Unbound(_) => {
4108                        Ok(core_ctx.set_dual_stack_enabled(ip_options, value))
4109                    }
4110                    TcpSocketStateInner::Bound(_) => Err(SetDualStackEnabledError::SocketIsBound),
4111                },
4112            }
4113        })
4114    }
4115
4116    fn on_icmp_error_conn(
4117        core_ctx: &mut C::CoreContext,
4118        bindings_ctx: &mut C::BindingsContext,
4119        id: TcpSocketId<
4120            I,
4121            <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
4122            C::BindingsContext,
4123        >,
4124        seq: SeqNum,
4125        error: IcmpErrorCode,
4126    ) {
4127        let destroy = core_ctx.with_socket_mut_transport_demux(&id, |core_ctx, socket_state| {
4128            let TcpSocketState { socket_state, ip_options: _, socket_options } = socket_state;
4129            let (conn_and_addr, timer) = assert_matches!(
4130                socket_state,
4131                TcpSocketStateInner::Bound(
4132                    BoundSocketState::Connected { conn, sharing: _, timer } ) => (conn, timer),
4133                "invalid socket ID");
4134            let (
4135                newly_closed,
4136                accept_queue,
4137                state,
4138                soft_error,
4139                handshake_status,
4140                this_or_other_stack,
4141            ) = match core_ctx {
4142                MaybeDualStack::NotDualStack((core_ctx, converter)) => {
4143                    let (conn, addr) = converter.convert(conn_and_addr);
4144                    let (newly_closed, should_send) = conn.on_icmp_error(core_ctx, &id, seq, error);
4145                    let core_ctx = core_ctx.as_this_stack();
4146                    let demux_id = I::into_demux_socket_id(id.clone());
4147
4148                    match should_send {
4149                        ShouldRetransmit::No => {}
4150                        ShouldRetransmit::Yes => do_send_inner_and_then_handle_newly_closed(
4151                            &id,
4152                            &demux_id,
4153                            socket_options,
4154                            conn,
4155                            DoSendLimit::OneSegment,
4156                            addr,
4157                            timer,
4158                            core_ctx,
4159                            bindings_ctx,
4160                        ),
4161                    }
4162
4163                    (
4164                        newly_closed,
4165                        &mut conn.accept_queue,
4166                        &mut conn.state,
4167                        &mut conn.soft_error,
4168                        &mut conn.handshake_status,
4169                        EitherStack::ThisStack((core_ctx, demux_id, addr)),
4170                    )
4171                }
4172                MaybeDualStack::DualStack((core_ctx, converter)) => {
4173                    match converter.convert(conn_and_addr) {
4174                        EitherStack::ThisStack((conn, addr)) => {
4175                            let (newly_closed, should_send) =
4176                                conn.on_icmp_error(core_ctx, &id, seq, error);
4177                            let core_ctx = core_ctx.as_this_stack();
4178                            let demux_id = I::into_demux_socket_id(id.clone());
4179
4180                            match should_send {
4181                                ShouldRetransmit::No => {}
4182                                ShouldRetransmit::Yes => {
4183                                    do_send_inner_and_then_handle_newly_closed(
4184                                        &id,
4185                                        &demux_id,
4186                                        socket_options,
4187                                        conn,
4188                                        DoSendLimit::OneSegment,
4189                                        addr,
4190                                        timer,
4191                                        core_ctx,
4192                                        bindings_ctx,
4193                                    )
4194                                }
4195                            }
4196
4197                            (
4198                                newly_closed,
4199                                &mut conn.accept_queue,
4200                                &mut conn.state,
4201                                &mut conn.soft_error,
4202                                &mut conn.handshake_status,
4203                                EitherStack::ThisStack((core_ctx, demux_id, addr)),
4204                            )
4205                        }
4206                        EitherStack::OtherStack((conn, addr)) => {
4207                            let (newly_closed, should_send) =
4208                                conn.on_icmp_error(core_ctx, &id, seq, error);
4209                            let demux_id = core_ctx.into_other_demux_socket_id(id.clone());
4210
4211                            match should_send {
4212                                ShouldRetransmit::No => {}
4213                                ShouldRetransmit::Yes => {
4214                                    do_send_inner_and_then_handle_newly_closed(
4215                                        &id,
4216                                        &demux_id,
4217                                        socket_options,
4218                                        conn,
4219                                        DoSendLimit::OneSegment,
4220                                        addr,
4221                                        timer,
4222                                        core_ctx,
4223                                        bindings_ctx,
4224                                    )
4225                                }
4226                            }
4227
4228                            (
4229                                newly_closed,
4230                                &mut conn.accept_queue,
4231                                &mut conn.state,
4232                                &mut conn.soft_error,
4233                                &mut conn.handshake_status,
4234                                EitherStack::OtherStack((core_ctx, demux_id, addr)),
4235                            )
4236                        }
4237                    }
4238                }
4239            };
4240
4241            if let State::Closed(Closed { reason }) = state {
4242                debug!("handshake_status: {handshake_status:?}");
4243                let _: bool = handshake_status.update_if_pending(HandshakeStatus::Aborted);
4244                // Unregister the socket from the socketmap if newly closed.
4245                match this_or_other_stack {
4246                    EitherStack::ThisStack((core_ctx, demux_id, addr)) => {
4247                        handle_newly_closed::<I, _, _, _>(
4248                            core_ctx,
4249                            bindings_ctx,
4250                            newly_closed,
4251                            &demux_id,
4252                            addr,
4253                            timer,
4254                        );
4255                    }
4256                    EitherStack::OtherStack((core_ctx, demux_id, addr)) => {
4257                        handle_newly_closed::<I::OtherVersion, _, _, _>(
4258                            core_ctx,
4259                            bindings_ctx,
4260                            newly_closed,
4261                            &demux_id,
4262                            addr,
4263                            timer,
4264                        );
4265                    }
4266                };
4267                match accept_queue {
4268                    Some(accept_queue) => {
4269                        accept_queue.remove(&id);
4270                        // destroy the socket if not held by the user.
4271                        return true;
4272                    }
4273                    None => {
4274                        if let Some(err) = reason {
4275                            if *err == ConnectionError::TimedOut {
4276                                *err = soft_error.unwrap_or(ConnectionError::TimedOut);
4277                            }
4278                        }
4279                    }
4280                }
4281            }
4282            false
4283        });
4284        if destroy {
4285            destroy_socket(core_ctx, bindings_ctx, id);
4286        }
4287    }
4288
4289    fn on_icmp_error(
4290        &mut self,
4291        orig_src_ip: SpecifiedAddr<I::Addr>,
4292        orig_dst_ip: SpecifiedAddr<I::Addr>,
4293        orig_src_port: NonZeroU16,
4294        orig_dst_port: NonZeroU16,
4295        seq: SeqNum,
4296        error: IcmpErrorCode,
4297    ) where
4298        C::CoreContext: TcpContext<I::OtherVersion, C::BindingsContext>,
4299        C::BindingsContext: TcpBindingsContext<
4300            <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId,
4301        >,
4302    {
4303        let (core_ctx, bindings_ctx) = self.contexts();
4304
4305        let orig_src_ip = match SocketIpAddr::try_from(orig_src_ip) {
4306            Ok(ip) => ip,
4307            Err(AddrIsMappedError {}) => {
4308                trace!("ignoring ICMP error from IPv4-mapped-IPv6 source: {}", orig_src_ip);
4309                return;
4310            }
4311        };
4312        let orig_dst_ip = match SocketIpAddr::try_from(orig_dst_ip) {
4313            Ok(ip) => ip,
4314            Err(AddrIsMappedError {}) => {
4315                trace!("ignoring ICMP error to IPv4-mapped-IPv6 destination: {}", orig_dst_ip);
4316                return;
4317            }
4318        };
4319
4320        let id = TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
4321            socketmap
4322                .conns()
4323                .get_by_addr(&ConnAddr {
4324                    ip: ConnIpAddr {
4325                        local: (orig_src_ip, orig_src_port),
4326                        remote: (orig_dst_ip, orig_dst_port),
4327                    },
4328                    device: None,
4329                })
4330                .map(|ConnAddrState { sharing: _, id }| id.clone())
4331        });
4332
4333        let id = match id {
4334            Some(id) => id,
4335            None => return,
4336        };
4337
4338        match I::into_dual_stack_ip_socket(id) {
4339            EitherStack::ThisStack(id) => {
4340                Self::on_icmp_error_conn(core_ctx, bindings_ctx, id, seq, error)
4341            }
4342            EitherStack::OtherStack(id) => TcpApi::<I::OtherVersion, C>::on_icmp_error_conn(
4343                core_ctx,
4344                bindings_ctx,
4345                id,
4346                seq,
4347                error,
4348            ),
4349        };
4350    }
4351
4352    /// Gets the last error on the connection.
4353    pub fn get_socket_error(&mut self, id: &TcpApiSocketId<I, C>) -> Option<ConnectionError> {
4354        self.core_ctx().with_socket_mut_and_converter(id, |socket_state, converter| {
4355            let TcpSocketState { socket_state, ip_options: _, socket_options: _ } = socket_state;
4356            match socket_state {
4357                TcpSocketStateInner::Unbound(_)
4358                | TcpSocketStateInner::Bound(BoundSocketState::Listener(_)) => None,
4359                TcpSocketStateInner::Bound(BoundSocketState::Connected {
4360                    conn,
4361                    sharing: _,
4362                    timer: _,
4363                }) => {
4364                    let (state, soft_error) = match converter {
4365                        MaybeDualStack::NotDualStack(converter) => {
4366                            let (conn, _addr) = converter.convert(conn);
4367                            (&conn.state, &mut conn.soft_error)
4368                        }
4369                        MaybeDualStack::DualStack(converter) => match converter.convert(conn) {
4370                            EitherStack::ThisStack((conn, _addr)) => {
4371                                (&conn.state, &mut conn.soft_error)
4372                            }
4373                            EitherStack::OtherStack((conn, _addr)) => {
4374                                (&conn.state, &mut conn.soft_error)
4375                            }
4376                        },
4377                    };
4378                    let hard_error = if let State::Closed(Closed { reason: hard_error }) = state {
4379                        hard_error.clone()
4380                    } else {
4381                        None
4382                    };
4383                    hard_error.or_else(|| soft_error.take())
4384                }
4385            }
4386        })
4387    }
4388
4389    /// Gets the original destination address for the socket, if it is connected
4390    /// and has a destination in the specified stack.
4391    ///
4392    /// Note that this always returns the original destination in the IP stack
4393    /// in which the socket is; for example, for a dual-stack IPv6 socket that
4394    /// is connected to an IPv4 address, this will return the IPv4-mapped IPv6
4395    /// version of that address.
4396    pub fn get_original_destination(
4397        &mut self,
4398        id: &TcpApiSocketId<I, C>,
4399    ) -> Result<(SpecifiedAddr<I::Addr>, NonZeroU16), OriginalDestinationError> {
4400        self.core_ctx().with_socket_mut_transport_demux(id, |core_ctx, state| {
4401            let TcpSocketState { socket_state, .. } = state;
4402            let conn = match socket_state {
4403                TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => conn,
4404                TcpSocketStateInner::Bound(BoundSocketState::Listener(_))
4405                | TcpSocketStateInner::Unbound(_) => {
4406                    return Err(OriginalDestinationError::NotConnected);
4407                }
4408            };
4409
4410            fn tuple<I: IpExt>(
4411                ConnIpAddr { local, remote }: ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>,
4412            ) -> Tuple<I> {
4413                let (local_addr, local_port) = local;
4414                let (remote_addr, remote_port) = remote;
4415                Tuple {
4416                    protocol: IpProto::Tcp.into(),
4417                    src_addr: local_addr.addr(),
4418                    dst_addr: remote_addr.addr(),
4419                    src_port_or_id: local_port.get(),
4420                    dst_port_or_id: remote_port.get(),
4421                }
4422            }
4423
4424            let (addr, port) = match core_ctx {
4425                MaybeDualStack::NotDualStack((core_ctx, converter)) => {
4426                    let (_conn, addr) = converter.convert(conn);
4427                    let tuple: Tuple<I> = tuple(addr.ip);
4428                    core_ctx
4429                        .get_original_destination(&tuple)
4430                        .ok_or(OriginalDestinationError::NotFound)
4431                }
4432                MaybeDualStack::DualStack((core_ctx, converter)) => match converter.convert(conn) {
4433                    EitherStack::ThisStack((_conn, addr)) => {
4434                        let tuple: Tuple<I> = tuple(addr.ip);
4435                        let (addr, port) = core_ctx
4436                            .get_original_destination(&tuple)
4437                            .ok_or(OriginalDestinationError::NotFound)?;
4438                        let addr = I::get_original_dst(
4439                            converter.convert_back(EitherStack::ThisStack(addr)),
4440                        );
4441                        Ok((addr, port))
4442                    }
4443                    EitherStack::OtherStack((_conn, addr)) => {
4444                        let tuple: Tuple<I::OtherVersion> = tuple(addr.ip);
4445                        let (addr, port) = core_ctx
4446                            .get_original_destination(&tuple)
4447                            .ok_or(OriginalDestinationError::NotFound)?;
4448                        let addr = I::get_original_dst(
4449                            converter.convert_back(EitherStack::OtherStack(addr)),
4450                        );
4451                        Ok((addr, port))
4452                    }
4453                },
4454            }?;
4455
4456            // TCP connections always have a specified destination address and
4457            // port, but this invariant is not upheld in the type system here
4458            // because we are retrieving the destination from the connection
4459            // tracking table.
4460            let addr = SpecifiedAddr::new(addr).ok_or_else(|| {
4461                error!("original destination for socket {id:?} had unspecified addr (port {port})");
4462                OriginalDestinationError::UnspecifiedDestinationAddr
4463            })?;
4464            let port = NonZeroU16::new(port).ok_or_else(|| {
4465                error!("original destination for socket {id:?} had unspecified port (addr {addr})");
4466                OriginalDestinationError::UnspecifiedDestinationPort
4467            })?;
4468            Ok((addr, port))
4469        })
4470    }
4471
4472    /// Get diagnostic information for sockets matching the provided matcher.
4473    pub fn bound_sockets_diagnostics<M, E>(&mut self, matcher: &M, results: &mut E)
4474    where
4475        M: IpSocketPropertiesMatcher<<C::BindingsContext as MatcherBindingsTypes>::DeviceClass>
4476            + ?Sized,
4477        E: Extend<TcpSocketDiagnostics<I>>,
4478        <C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId:
4479            netstack3_base::InterfaceProperties<
4480                    <C::BindingsContext as MatcherBindingsTypes>::DeviceClass,
4481                >,
4482    {
4483        self.core_ctx().for_each_socket(|id, state| {
4484            if !matcher.matches_ip_socket(&TcpSocketStateForMatching { state, id }) {
4485                return;
4486            }
4487
4488            // get_diagnostics returns None if the socket is unbound, which
4489            // we're not returning in order to match Linux's behavior.
4490            results.extend(state.get_diagnostics().map(|(tuple, state_machine, marks)| {
4491                TcpSocketDiagnostics { tuple, state_machine, cookie: id.socket_cookie(), marks }
4492            }));
4493        });
4494    }
4495
4496    /// Provides access to shared and per-socket TCP stats via a visitor.
4497    pub fn inspect<N>(&mut self, inspector: &mut N)
4498    where
4499        N: Inspector
4500            + InspectorDeviceExt<<C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId>,
4501    {
4502        self.core_ctx().for_each_socket(|socket_id, socket_state| {
4503            inspector.record_debug_child(socket_id, |node| {
4504                node.record_str("TransportProtocol", "TCP");
4505                node.record_str(
4506                    "NetworkProtocol",
4507                    match I::VERSION {
4508                        IpVersion::V4 => "IPv4",
4509                        IpVersion::V6 => "IPv6",
4510                    },
4511                );
4512                let TcpSocketState { socket_state, ip_options: _, socket_options } = socket_state;
4513                node.delegate_inspectable(&socket_options.ip_options.marks);
4514                match socket_state {
4515                    TcpSocketStateInner::Unbound(_) => {
4516                        node.record_local_socket_addr::<N, I::Addr, _, NonZeroU16>(None);
4517                        node.record_remote_socket_addr::<N, I::Addr, _, NonZeroU16>(None);
4518                    }
4519                    TcpSocketStateInner::Bound(BoundSocketState::Listener((
4520                        state,
4521                        _sharing,
4522                        addr,
4523                    ))) => {
4524                        let BoundInfo { addr, port, device } = I::get_bound_info(addr);
4525                        let local = addr.map_or_else(
4526                            || ZonedAddr::Unzoned(I::UNSPECIFIED_ADDRESS),
4527                            |addr| maybe_zoned(addr.addr(), &device).into(),
4528                        );
4529                        node.record_local_socket_addr::<N, _, _, _>(Some((local, port)));
4530                        node.record_remote_socket_addr::<N, I::Addr, _, NonZeroU16>(None);
4531                        match state {
4532                            MaybeListener::Bound(_bound_state) => {}
4533                            MaybeListener::Listener(Listener { accept_queue, backlog, .. }) => node
4534                                .record_child("AcceptQueue", |node| {
4535                                    node.record_usize("BacklogSize", *backlog);
4536                                    accept_queue.inspect(node);
4537                                }),
4538                        };
4539                    }
4540                    TcpSocketStateInner::Bound(BoundSocketState::Connected {
4541                        conn: conn_and_addr,
4542                        ..
4543                    }) => {
4544                        if I::get_defunct(conn_and_addr) {
4545                            return;
4546                        }
4547                        let state = I::get_state(conn_and_addr);
4548                        let ConnectionInfo {
4549                            local_addr: SocketAddr { ip: local_ip, port: local_port },
4550                            remote_addr: SocketAddr { ip: remote_ip, port: remote_port },
4551                            device: _,
4552                        } = I::get_conn_info(conn_and_addr);
4553                        node.record_local_socket_addr::<N, I::Addr, _, _>(Some((
4554                            local_ip.into(),
4555                            local_port,
4556                        )));
4557                        node.record_remote_socket_addr::<N, I::Addr, _, _>(Some((
4558                            remote_ip.into(),
4559                            remote_port,
4560                        )));
4561                        node.record_display("State", state);
4562                    }
4563                }
4564                node.record_child("Counters", |node| {
4565                    node.delegate_inspectable(&CombinedTcpCounters {
4566                        with_socket: socket_id.counters(),
4567                        without_socket: None,
4568                    })
4569                })
4570            });
4571        })
4572    }
4573
4574    /// Calls the callback with mutable access to the send buffer, if one is
4575    /// instantiated.
4576    ///
4577    /// If no buffer is instantiated returns `None`.
4578    pub fn with_send_buffer<
4579        R,
4580        F: FnOnce(&mut <C::BindingsContext as TcpBindingsTypes>::SendBuffer) -> R,
4581    >(
4582        &mut self,
4583        id: &TcpApiSocketId<I, C>,
4584        f: F,
4585    ) -> Option<R> {
4586        self.core_ctx().with_socket_mut_and_converter(id, |state, converter| {
4587            get_buffers_mut::<_, C::CoreContext, _>(state, converter).into_send_buffer().map(f)
4588        })
4589    }
4590
4591    /// Calls the callback with mutable access to the receive buffer, if one is
4592    /// instantiated.
4593    ///
4594    /// If no buffer is instantiated returns `None`.
4595    pub fn with_receive_buffer<
4596        R,
4597        F: FnOnce(&mut <C::BindingsContext as TcpBindingsTypes>::ReceiveBuffer) -> R,
4598    >(
4599        &mut self,
4600        id: &TcpApiSocketId<I, C>,
4601        f: F,
4602    ) -> Option<R> {
4603        self.core_ctx().with_socket_mut_and_converter(id, |state, converter| {
4604            get_buffers_mut::<_, C::CoreContext, _>(state, converter).into_receive_buffer().map(f)
4605        })
4606    }
4607}
4608
4609/// Destroys the socket with `id`.
4610fn destroy_socket<I, CC, BC>(
4611    core_ctx: &mut CC,
4612    bindings_ctx: &mut BC,
4613    id: TcpSocketId<I, CC::WeakDeviceId, BC>,
4614) where
4615    I: DualStackIpExt,
4616    CC: TcpContext<I, BC>,
4617    BC: TcpBindingsContext<CC::DeviceId>,
4618{
4619    let weak = id.downgrade();
4620
4621    core_ctx.with_all_sockets_mut(move |all_sockets| {
4622        let TcpSocketId(rc) = &id;
4623        let debug_refs = StrongRc::debug_references(rc);
4624        let entry = all_sockets.entry(id);
4625        let primary = match entry {
4626            hash_map::Entry::Occupied(o) => match o.get() {
4627                TcpSocketSetEntry::DeadOnArrival => {
4628                    let id = o.key();
4629                    debug!("{id:?} destruction skipped, socket is DOA. References={debug_refs:?}",);
4630                    None
4631                }
4632                TcpSocketSetEntry::Primary(_) => {
4633                    assert_matches!(o.remove_entry(), (_, TcpSocketSetEntry::Primary(p)) => Some(p))
4634                }
4635            },
4636            hash_map::Entry::Vacant(v) => {
4637                let id = v.key();
4638                let TcpSocketId(rc) = id;
4639                if !StrongRc::marked_for_destruction(rc) {
4640                    // Socket is not yet marked for destruction, we've raced
4641                    // this removal with the addition to the socket set. Mark
4642                    // the entry as DOA.
4643                    debug!(
4644                        "{id:?} raced with insertion, marking socket as DOA. \
4645                        References={debug_refs:?}",
4646                    );
4647                    let _: &mut _ = v.insert(TcpSocketSetEntry::DeadOnArrival);
4648                } else {
4649                    debug!("{id:?} destruction is already deferred. References={debug_refs:?}");
4650                }
4651                None
4652            }
4653        };
4654
4655        // There are a number of races that can happen with attempted socket
4656        // destruction, but these should not be possible in tests because
4657        // they're singlethreaded.
4658        #[cfg(test)]
4659        let primary = primary.unwrap_or_else(|| {
4660            panic!("deferred destruction not allowed in tests. References={debug_refs:?}")
4661        });
4662        #[cfg(not(test))]
4663        let Some(primary) = primary else {
4664            return;
4665        };
4666
4667        let remove_result =
4668            BC::unwrap_or_notify_with_new_reference_notifier(primary, |state| state);
4669        match remove_result {
4670            RemoveResourceResult::Removed(state) => debug!("destroyed {weak:?} {state:?}"),
4671            RemoveResourceResult::Deferred(receiver) => {
4672                debug!("deferred removal {weak:?}");
4673                bindings_ctx.defer_removal(receiver)
4674            }
4675        }
4676    })
4677}
4678
4679/// Closes all sockets in `pending`.
4680///
4681/// Used to cleanup all pending sockets in the accept queue when a listener
4682/// socket is shutdown or closed.
4683fn close_pending_sockets<I, CC, BC>(
4684    core_ctx: &mut CC,
4685    bindings_ctx: &mut BC,
4686    pending: impl Iterator<Item = TcpSocketId<I, CC::WeakDeviceId, BC>>,
4687) where
4688    I: DualStackIpExt,
4689    BC: TcpBindingsContext<CC::DeviceId>,
4690    CC: TcpContext<I, BC>,
4691{
4692    for conn_id in pending {
4693        core_ctx.with_socket_mut_transport_demux(&conn_id, |core_ctx, socket_state| {
4694            let TcpSocketState { socket_state, ip_options: _, socket_options } = socket_state;
4695            let (conn_and_addr, timer) = assert_matches!(
4696                socket_state,
4697                TcpSocketStateInner::Bound(BoundSocketState::Connected{
4698                    conn, sharing: _, timer
4699                }) => (conn, timer),
4700                "invalid socket ID"
4701            );
4702            let _: Option<BC::Instant> = bindings_ctx.cancel_timer(timer);
4703            let this_or_other_stack = match core_ctx {
4704                MaybeDualStack::NotDualStack((core_ctx, converter)) => {
4705                    let (conn, addr) = converter.convert(conn_and_addr);
4706                    EitherStack::ThisStack((
4707                        core_ctx.as_this_stack(),
4708                        I::into_demux_socket_id(conn_id.clone()),
4709                        conn,
4710                        addr.clone(),
4711                    ))
4712                }
4713                MaybeDualStack::DualStack((core_ctx, converter)) => match converter
4714                    .convert(conn_and_addr)
4715                {
4716                    EitherStack::ThisStack((conn, addr)) => EitherStack::ThisStack((
4717                        core_ctx.as_this_stack(),
4718                        I::into_demux_socket_id(conn_id.clone()),
4719                        conn,
4720                        addr.clone(),
4721                    )),
4722                    EitherStack::OtherStack((conn, addr)) => {
4723                        let other_demux_id = core_ctx.into_other_demux_socket_id(conn_id.clone());
4724                        EitherStack::OtherStack((core_ctx, other_demux_id, conn, addr.clone()))
4725                    }
4726                },
4727            };
4728
4729            match this_or_other_stack {
4730                EitherStack::ThisStack((core_ctx, demux_id, conn, conn_addr)) => {
4731                    close_pending_socket(
4732                        core_ctx,
4733                        bindings_ctx,
4734                        &conn_id,
4735                        &demux_id,
4736                        socket_options,
4737                        timer,
4738                        conn,
4739                        &conn_addr,
4740                    )
4741                }
4742                EitherStack::OtherStack((core_ctx, demux_id, conn, conn_addr)) => {
4743                    close_pending_socket(
4744                        core_ctx,
4745                        bindings_ctx,
4746                        &conn_id,
4747                        &demux_id,
4748                        socket_options,
4749                        timer,
4750                        conn,
4751                        &conn_addr,
4752                    )
4753                }
4754            }
4755        });
4756        destroy_socket(core_ctx, bindings_ctx, conn_id);
4757    }
4758}
4759
4760fn close_pending_socket<WireI, SockI, DC, BC>(
4761    core_ctx: &mut DC,
4762    bindings_ctx: &mut BC,
4763    sock_id: &TcpSocketId<SockI, DC::WeakDeviceId, BC>,
4764    demux_id: &WireI::DemuxSocketId<DC::WeakDeviceId, BC>,
4765    socket_options: &SocketOptions,
4766    timer: &mut BC::Timer,
4767    conn: &mut Connection<SockI, WireI, DC::WeakDeviceId, BC>,
4768    conn_addr: &ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, DC::WeakDeviceId>,
4769) where
4770    WireI: DualStackIpExt,
4771    SockI: DualStackIpExt,
4772    DC: TransportIpContext<WireI, BC>
4773        + DeviceIpSocketHandler<WireI, BC>
4774        + TcpDemuxContext<WireI, DC::WeakDeviceId, BC>
4775        + TcpSocketContext<SockI, DC::WeakDeviceId, BC>,
4776    BC: TcpBindingsContext<DC::DeviceId>,
4777{
4778    debug!("aborting pending socket {sock_id:?}");
4779    let (maybe_reset, newly_closed) =
4780        conn.state.abort(&TcpCountersRefs::from_ctx(core_ctx, sock_id));
4781    handle_newly_closed(core_ctx, bindings_ctx, newly_closed, demux_id, conn_addr, timer);
4782    if let Some(reset) = maybe_reset {
4783        let ConnAddr { ip, device: _ } = conn_addr;
4784        send_tcp_segment(
4785            core_ctx,
4786            bindings_ctx,
4787            Some(sock_id),
4788            Some(&conn.ip_sock),
4789            *ip,
4790            reset.into_empty(),
4791            &socket_options.ip_options,
4792        );
4793    }
4794}
4795
4796// How many segments to send as part of the "do_send" routine.
4797pub(crate) enum DoSendLimit {
4798    OneSegment,
4799    MultipleSegments,
4800}
4801
4802// Calls `do_send_inner` and handle the result.
4803fn do_send_inner_and_then_handle_newly_closed<SockI, WireI, CC, BC>(
4804    conn_id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
4805    demux_id: &WireI::DemuxSocketId<CC::WeakDeviceId, BC>,
4806    socket_options: &SocketOptions,
4807    conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
4808    limit: DoSendLimit,
4809    addr: &ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
4810    timer: &mut BC::Timer,
4811    core_ctx: &mut CC,
4812    bindings_ctx: &mut BC,
4813) where
4814    SockI: DualStackIpExt,
4815    WireI: DualStackIpExt,
4816    BC: TcpBindingsContext<CC::DeviceId>,
4817    CC: TransportIpContext<WireI, BC>
4818        + TcpSocketContext<SockI, CC::WeakDeviceId, BC>
4819        + TcpDemuxContext<WireI, CC::WeakDeviceId, BC>,
4820{
4821    let newly_closed =
4822        do_send_inner(conn_id, socket_options, conn, limit, addr, timer, core_ctx, bindings_ctx);
4823    handle_newly_closed(core_ctx, bindings_ctx, newly_closed, demux_id, addr, timer);
4824}
4825
4826#[inline]
4827fn handle_newly_closed<I, D, CC, BC>(
4828    core_ctx: &mut CC,
4829    bindings_ctx: &mut BC,
4830    newly_closed: NewlyClosed,
4831    demux_id: &I::DemuxSocketId<D, BC>,
4832    addr: &ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, D>,
4833    timer: &mut BC::Timer,
4834) where
4835    I: DualStackIpExt,
4836    D: WeakDeviceIdentifier,
4837    CC: TcpDemuxContext<I, D, BC>,
4838    BC: TcpBindingsContext<D::Strong>,
4839{
4840    if newly_closed == NewlyClosed::Yes {
4841        core_ctx.with_demux_mut(|DemuxState { socketmap }| {
4842            socketmap.conns_mut().remove(demux_id, addr).expect("failed to remove from demux");
4843            let _: Option<_> = bindings_ctx.cancel_timer(timer);
4844        });
4845    }
4846}
4847
4848fn do_send_inner<SockI, WireI, CC, BC>(
4849    conn_id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
4850    socket_options: &SocketOptions,
4851    conn: &mut Connection<SockI, WireI, CC::WeakDeviceId, BC>,
4852    limit: DoSendLimit,
4853    addr: &ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
4854    timer: &mut BC::Timer,
4855    core_ctx: &mut CC,
4856    bindings_ctx: &mut BC,
4857) -> NewlyClosed
4858where
4859    SockI: DualStackIpExt,
4860    WireI: DualStackIpExt,
4861    BC: TcpBindingsContext<CC::DeviceId>,
4862    CC: TransportIpContext<WireI, BC> + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
4863{
4864    let newly_closed = loop {
4865        match conn.state.poll_send(
4866            &conn_id.either(),
4867            &TcpCountersRefs::from_ctx(core_ctx, conn_id),
4868            bindings_ctx.now(),
4869            socket_options,
4870        ) {
4871            Ok(seg) => {
4872                send_tcp_segment(
4873                    core_ctx,
4874                    bindings_ctx,
4875                    Some(conn_id),
4876                    Some(&conn.ip_sock),
4877                    addr.ip.clone(),
4878                    seg,
4879                    &socket_options.ip_options,
4880                );
4881                match limit {
4882                    DoSendLimit::OneSegment => break NewlyClosed::No,
4883                    DoSendLimit::MultipleSegments => {}
4884                }
4885            }
4886            Err(newly_closed) => break newly_closed,
4887        }
4888    };
4889
4890    if let Some(instant) = conn.state.poll_send_at() {
4891        let _: Option<_> = bindings_ctx.schedule_timer_instant(instant, timer);
4892    }
4893
4894    newly_closed
4895}
4896
4897enum SendBufferSize {}
4898enum ReceiveBufferSize {}
4899
4900trait AccessBufferSize<R, S> {
4901    fn set_buffer_size(buffers: BuffersRefMut<'_, R, S>, new_size: usize);
4902    fn get_buffer_size(buffers: BuffersRefMut<'_, R, S>) -> Option<usize>;
4903    fn allowed_range(settings: &TcpSettings) -> (usize, usize);
4904}
4905
4906impl<R: Buffer, S: Buffer> AccessBufferSize<R, S> for SendBufferSize {
4907    fn set_buffer_size(buffers: BuffersRefMut<'_, R, S>, new_size: usize) {
4908        match buffers {
4909            BuffersRefMut::NoBuffers | BuffersRefMut::RecvOnly { .. } => {}
4910            BuffersRefMut::Both { send, recv: _ } | BuffersRefMut::SendOnly(send) => {
4911                send.request_capacity(new_size)
4912            }
4913            BuffersRefMut::Sizes(BufferSizes { send, receive: _ }) => *send = new_size,
4914        }
4915    }
4916
4917    fn allowed_range(settings: &TcpSettings) -> (usize, usize) {
4918        (settings.send_buffer.min().get(), settings.send_buffer.max().get())
4919    }
4920
4921    fn get_buffer_size(buffers: BuffersRefMut<'_, R, S>) -> Option<usize> {
4922        match buffers {
4923            BuffersRefMut::NoBuffers | BuffersRefMut::RecvOnly { .. } => None,
4924            BuffersRefMut::Both { send, recv: _ } | BuffersRefMut::SendOnly(send) => {
4925                Some(send.target_capacity())
4926            }
4927            BuffersRefMut::Sizes(BufferSizes { send, receive: _ }) => Some(*send),
4928        }
4929    }
4930}
4931
4932impl<R: Buffer, S: Buffer> AccessBufferSize<R, S> for ReceiveBufferSize {
4933    fn set_buffer_size(buffers: BuffersRefMut<'_, R, S>, new_size: usize) {
4934        match buffers {
4935            BuffersRefMut::NoBuffers | BuffersRefMut::SendOnly(_) => {}
4936            BuffersRefMut::Both { recv, send: _ } | BuffersRefMut::RecvOnly(recv) => {
4937                recv.request_capacity(new_size)
4938            }
4939            BuffersRefMut::Sizes(BufferSizes { receive, send: _ }) => *receive = new_size,
4940        }
4941    }
4942
4943    fn allowed_range(settings: &TcpSettings) -> (usize, usize) {
4944        (settings.receive_buffer.min().get(), settings.receive_buffer.max().get())
4945    }
4946
4947    fn get_buffer_size(buffers: BuffersRefMut<'_, R, S>) -> Option<usize> {
4948        match buffers {
4949            BuffersRefMut::NoBuffers | BuffersRefMut::SendOnly(_) => None,
4950            BuffersRefMut::Both { recv, send: _ } | BuffersRefMut::RecvOnly(recv) => {
4951                Some(recv.target_capacity())
4952            }
4953            BuffersRefMut::Sizes(BufferSizes { receive, send: _ }) => Some(*receive),
4954        }
4955    }
4956}
4957
4958fn get_buffers_mut<I, CC, BC>(
4959    state: &mut TcpSocketState<I, CC::WeakDeviceId, BC>,
4960    converter: MaybeDualStack<CC::DualStackConverter, CC::SingleStackConverter>,
4961) -> BuffersRefMut<'_, BC::ReceiveBuffer, BC::SendBuffer>
4962where
4963    I: DualStackIpExt,
4964    CC: TcpContext<I, BC>,
4965    BC: TcpBindingsContext<CC::DeviceId>,
4966{
4967    match &mut state.socket_state {
4968        TcpSocketStateInner::Unbound(Unbound { buffer_sizes, .. }) => {
4969            BuffersRefMut::Sizes(buffer_sizes)
4970        }
4971        TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
4972            let state = match converter {
4973                MaybeDualStack::NotDualStack(converter) => {
4974                    let (conn, _addr) = converter.convert(conn);
4975                    &mut conn.state
4976                }
4977                MaybeDualStack::DualStack(converter) => match converter.convert(conn) {
4978                    EitherStack::ThisStack((conn, _addr)) => &mut conn.state,
4979                    EitherStack::OtherStack((conn, _addr)) => &mut conn.state,
4980                },
4981            };
4982            state.buffers_mut()
4983        }
4984        TcpSocketStateInner::Bound(BoundSocketState::Listener((maybe_listener, _, _))) => {
4985            match maybe_listener {
4986                MaybeListener::Bound(BoundState { buffer_sizes, .. })
4987                | MaybeListener::Listener(Listener { buffer_sizes, .. }) => {
4988                    BuffersRefMut::Sizes(buffer_sizes)
4989                }
4990            }
4991        }
4992    }
4993}
4994
4995fn set_buffer_size<
4996    Which: AccessBufferSize<BC::ReceiveBuffer, BC::SendBuffer>,
4997    I: DualStackIpExt,
4998    BC: TcpBindingsContext<CC::DeviceId>,
4999    CC: TcpContext<I, BC>,
5000>(
5001    core_ctx: &mut CC,
5002    bindings_ctx: &mut BC,
5003    id: &TcpSocketId<I, CC::WeakDeviceId, BC>,
5004    size: usize,
5005) {
5006    let (min, max) = Which::allowed_range(&*bindings_ctx.settings());
5007    let size = size.clamp(min, max);
5008    core_ctx.with_socket_mut_and_converter(id, |state, converter| {
5009        Which::set_buffer_size(get_buffers_mut::<I, CC, BC>(state, converter), size)
5010    })
5011}
5012
5013fn get_buffer_size<
5014    Which: AccessBufferSize<BC::ReceiveBuffer, BC::SendBuffer>,
5015    I: DualStackIpExt,
5016    BC: TcpBindingsContext<CC::DeviceId>,
5017    CC: TcpContext<I, BC>,
5018>(
5019    core_ctx: &mut CC,
5020    id: &TcpSocketId<I, CC::WeakDeviceId, BC>,
5021) -> Option<usize> {
5022    core_ctx.with_socket_mut_and_converter(id, |state, converter| {
5023        Which::get_buffer_size(get_buffers_mut::<I, CC, BC>(state, converter))
5024    })
5025}
5026
5027/// Error returned when failing to set the bound device for a socket.
5028#[derive(Debug, GenericOverIp, Error)]
5029#[generic_over_ip()]
5030pub enum SetDeviceError {
5031    /// The socket would conflict with another socket.
5032    #[error("cannot set bound device due to conflict with another socket")]
5033    Conflict,
5034    /// The socket would become unroutable.
5035    #[error("cannot set bound device as socket would become unroutable")]
5036    Unroutable,
5037    /// The socket has an address with a different zone.
5038    #[error("cannot set bound device as socket's address has a different zone")]
5039    ZoneChange,
5040}
5041
5042/// Possible errors for accept operation.
5043#[derive(Debug, GenericOverIp, Error)]
5044#[generic_over_ip()]
5045pub enum AcceptError {
5046    /// There is no established socket currently.
5047    #[error("would block: no currently-established socket")]
5048    WouldBlock,
5049    /// Cannot accept on this socket.
5050    #[error("this socket does not support accept")]
5051    NotSupported,
5052}
5053
5054/// Errors for the listen operation.
5055#[derive(Debug, GenericOverIp, PartialEq, Error)]
5056#[generic_over_ip()]
5057pub enum ListenError {
5058    /// There would be a conflict with another listening socket.
5059    #[error("conflict with another listening socket")]
5060    ListenerExists,
5061    /// Cannot listen on such socket.
5062    #[error("listening not supported")]
5063    NotSupported,
5064}
5065
5066/// Possible error for calling `shutdown` on a not-yet connected socket.
5067#[derive(Debug, GenericOverIp, Eq, PartialEq, Error)]
5068#[generic_over_ip()]
5069#[error("no connection")]
5070pub struct NoConnection;
5071
5072/// Error returned when attempting to set the ReuseAddress option.
5073#[derive(Debug, GenericOverIp, Error)]
5074#[generic_over_ip()]
5075pub enum SetReuseAddrError {
5076    /// Cannot share the address because it is already used.
5077    #[error("cannot share in-use address")]
5078    AddrInUse,
5079    /// Cannot set ReuseAddr on a connected socket.
5080    #[error("cannot set ReuseAddr on a connected socket")]
5081    NotSupported,
5082}
5083
5084/// Possible errors when connecting a socket.
5085#[derive(Debug, Error, GenericOverIp)]
5086#[generic_over_ip()]
5087#[cfg_attr(test, derive(PartialEq, Eq))]
5088pub enum ConnectError {
5089    /// Cannot allocate a local port for the connection.
5090    #[error("unable to allocate a port")]
5091    NoPort,
5092    /// Cannot find a route to the remote host.
5093    #[error("no route to remote host")]
5094    NoRoute,
5095    /// There was a problem with the provided address relating to its zone.
5096    #[error(transparent)]
5097    Zone(#[from] ZonedAddressError),
5098    /// There is an existing connection with the same 4-tuple.
5099    #[error("there is already a connection at the address requested")]
5100    ConnectionExists,
5101    /// Doesn't support `connect` for a listener.
5102    #[error("called connect on a listener")]
5103    Listener,
5104    /// The handshake is still going on.
5105    #[error("the handshake has already started")]
5106    Pending,
5107    /// Cannot call connect on a connection that is already established.
5108    #[error("the handshake is completed")]
5109    Completed,
5110    /// The handshake is refused by the remote host.
5111    #[error("the handshake is aborted")]
5112    Aborted,
5113}
5114
5115/// Possible errors when connecting a socket.
5116#[derive(Debug, Error, GenericOverIp, PartialEq)]
5117#[generic_over_ip()]
5118pub enum BindError {
5119    /// The socket was already bound.
5120    #[error("the socket was already bound")]
5121    AlreadyBound,
5122    /// The socket cannot bind to the local address.
5123    #[error(transparent)]
5124    LocalAddressError(#[from] LocalAddressError),
5125}
5126
5127/// Possible errors when retrieving the original destination of a socket.
5128#[derive(GenericOverIp, Debug, Error)]
5129#[generic_over_ip()]
5130pub enum OriginalDestinationError {
5131    /// Cannot retrieve original destination for an unconnected socket.
5132    #[error("cannot retrieve original destination for unconnected socket")]
5133    NotConnected,
5134    /// The socket's original destination could not be found in the connection
5135    /// tracking table.
5136    #[error("socket's original destination could not be found in connection tracking table")]
5137    NotFound,
5138    /// The socket's original destination had an unspecified address, which is
5139    /// invalid for TCP.
5140    #[error("socket's original destination address should be specified for TCP")]
5141    UnspecifiedDestinationAddr,
5142    /// The socket's original destination had an unspecified port, which is
5143    /// invalid for TCP.
5144    #[error("socket's original destination port should be specified for TCP")]
5145    UnspecifiedDestinationPort,
5146}
5147
5148/// A `GenericOverIp` wrapper for `I::DemuxSocketId`.
5149#[derive(GenericOverIp)]
5150#[generic_over_ip(I, Ip)]
5151pub struct DemuxSocketId<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes>(
5152    I::DemuxSocketId<D, BT>,
5153);
5154
5155/// A helper trait to implement dual stack demux state access for connect.
5156///
5157/// `I` gives access to demux version `I`, which should be the wire IP version.
5158trait DemuxStateAccessor<I: DualStackIpExt, CC: DeviceIdContext<AnyDevice>, BT: TcpBindingsTypes> {
5159    /// Calls the callback with access to the demux state for IP version `I`.
5160    ///
5161    /// If `cb` returns `Ok`, implementations must remove previous bound-state
5162    /// demux entries.
5163    fn update_demux_state_for_connect<
5164        O,
5165        E,
5166        F: FnOnce(
5167            &I::DemuxSocketId<CC::WeakDeviceId, BT>,
5168            &mut DemuxState<I, CC::WeakDeviceId, BT>,
5169        ) -> Result<O, E>,
5170    >(
5171        self,
5172        core_ctx: &mut CC,
5173        cb: F,
5174    ) -> Result<O, E>;
5175}
5176
5177struct SingleStackDemuxStateAccessor<
5178    'a,
5179    I: DualStackIpExt,
5180    CC: DeviceIdContext<AnyDevice>,
5181    BT: TcpBindingsTypes,
5182>(
5183    &'a I::DemuxSocketId<CC::WeakDeviceId, BT>,
5184    Option<ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, CC::WeakDeviceId>>,
5185);
5186
5187impl<'a, I, CC, BT> DemuxStateAccessor<I, CC, BT> for SingleStackDemuxStateAccessor<'a, I, CC, BT>
5188where
5189    I: DualStackIpExt,
5190    BT: TcpBindingsTypes,
5191    CC: DeviceIdContext<AnyDevice> + TcpDemuxContext<I, CC::WeakDeviceId, BT>,
5192{
5193    fn update_demux_state_for_connect<
5194        O,
5195        E,
5196        F: FnOnce(
5197            &I::DemuxSocketId<CC::WeakDeviceId, BT>,
5198            &mut DemuxState<I, CC::WeakDeviceId, BT>,
5199        ) -> Result<O, E>,
5200    >(
5201        self,
5202        core_ctx: &mut CC,
5203        cb: F,
5204    ) -> Result<O, E> {
5205        core_ctx.with_demux_mut(|demux| {
5206            let Self(demux_id, listener_addr) = self;
5207            let output = cb(demux_id, demux)?;
5208
5209            // If update is successful we must remove the listener address
5210            // from the demux.
5211
5212            if let Some(listener_addr) = listener_addr {
5213                demux
5214                    .socketmap
5215                    .listeners_mut()
5216                    .remove(demux_id, &listener_addr)
5217                    .expect("failed to remove a bound socket");
5218            }
5219            Ok(output)
5220        })
5221    }
5222}
5223
5224struct DualStackDemuxStateAccessor<
5225    'a,
5226    I: DualStackIpExt,
5227    CC: DeviceIdContext<AnyDevice>,
5228    BT: TcpBindingsTypes,
5229>(
5230    &'a TcpSocketId<I, CC::WeakDeviceId, BT>,
5231    DualStackTuple<I, Option<ListenerAddr<ListenerIpAddr<I::Addr, NonZeroU16>, CC::WeakDeviceId>>>,
5232);
5233
5234impl<'a, SockI, WireI, CC, BT> DemuxStateAccessor<WireI, CC, BT>
5235    for DualStackDemuxStateAccessor<'a, SockI, CC, BT>
5236where
5237    SockI: DualStackIpExt,
5238    WireI: DualStackIpExt,
5239    BT: TcpBindingsTypes,
5240    CC: DeviceIdContext<AnyDevice>
5241        + TcpDualStackContext<SockI, CC::WeakDeviceId, BT>
5242        + TcpDemuxContext<WireI, CC::WeakDeviceId, BT>
5243        + TcpDemuxContext<WireI::OtherVersion, CC::WeakDeviceId, BT>,
5244{
5245    fn update_demux_state_for_connect<
5246        O,
5247        E,
5248        F: FnOnce(
5249            &WireI::DemuxSocketId<CC::WeakDeviceId, BT>,
5250            &mut DemuxState<WireI, CC::WeakDeviceId, BT>,
5251        ) -> Result<O, E>,
5252    >(
5253        self,
5254        core_ctx: &mut CC,
5255        cb: F,
5256    ) -> Result<O, E> {
5257        let Self(id, local_addr) = self;
5258        let (DemuxSocketId(wire_id), DemuxSocketId(other_id)) =
5259            core_ctx.dual_stack_demux_id(id.clone()).cast::<WireI>().into_inner();
5260        let (wire_local_addr, other_local_addr) = local_addr.cast::<WireI>().into_inner();
5261        let output = core_ctx.with_demux_mut(|wire_demux: &mut DemuxState<WireI, _, _>| {
5262            let output = cb(&wire_id, wire_demux)?;
5263
5264            // On success we must remove our local address.
5265            if let Some(wire_local_addr) = wire_local_addr {
5266                wire_demux
5267                    .socketmap
5268                    .listeners_mut()
5269                    .remove(&wire_id, &wire_local_addr)
5270                    .expect("failed to remove a bound socket");
5271            }
5272            Ok(output)
5273        })?;
5274
5275        // If the operation succeeded and we're bound on the other stack then we
5276        // must clean that up as well.
5277        if let Some(other_local_addr) = other_local_addr {
5278            core_ctx.with_demux_mut(|other_demux: &mut DemuxState<WireI::OtherVersion, _, _>| {
5279                other_demux
5280                    .socketmap
5281                    .listeners_mut()
5282                    .remove(&other_id, &other_local_addr)
5283                    .expect("failed to remove a bound socket");
5284            });
5285        }
5286
5287        Ok(output)
5288    }
5289}
5290
5291fn connect_inner<CC, BC, SockI, WireI, Demux>(
5292    core_ctx: &mut CC,
5293    bindings_ctx: &mut BC,
5294    sock_id: &TcpSocketId<SockI, CC::WeakDeviceId, BC>,
5295    isn: &IsnGenerator<BC::Instant>,
5296    timestamp_offset: &TimestampOffsetGenerator<BC::Instant>,
5297    listener_addr: Option<ListenerAddr<ListenerIpAddr<WireI::Addr, NonZeroU16>, CC::WeakDeviceId>>,
5298    remote_ip: ZonedAddr<SocketIpAddr<WireI::Addr>, CC::DeviceId>,
5299    remote_port: NonZeroU16,
5300    active_open: TakeableRef<'_, BC::ListenerNotifierOrProvidedBuffers>,
5301    buffer_sizes: BufferSizes,
5302    socket_options: &SocketOptions,
5303    sharing: SharingState,
5304    demux: Demux,
5305    convert_back_op: impl FnOnce(
5306        Connection<SockI, WireI, CC::WeakDeviceId, BC>,
5307        ConnAddr<ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
5308    ) -> SockI::ConnectionAndAddr<CC::WeakDeviceId, BC>,
5309    convert_timer: impl FnOnce(WeakTcpSocketId<SockI, CC::WeakDeviceId, BC>) -> BC::DispatchId,
5310) -> Result<TcpSocketStateInner<SockI, CC::WeakDeviceId, BC>, ConnectError>
5311where
5312    SockI: DualStackIpExt,
5313    WireI: DualStackIpExt,
5314    BC: TcpBindingsContext<CC::DeviceId>,
5315    CC: TransportIpContext<WireI, BC>
5316        + DeviceIpSocketHandler<WireI, BC>
5317        + TcpSocketContext<SockI, CC::WeakDeviceId, BC>,
5318    Demux: DemuxStateAccessor<WireI, CC, BC>,
5319{
5320    let (local_ip, bound_device, local_port) = match listener_addr {
5321        Some(ListenerAddr { ip: ListenerIpAddr { addr, identifier }, device }) => {
5322            (addr.and_then(IpDeviceAddr::new_from_socket_ip_addr), device, Some(identifier))
5323        }
5324        None => (None, None, None),
5325    };
5326    let (remote_ip, device) = remote_ip.resolve_addr_with_device(bound_device)?;
5327
5328    // TCP sockets cannot connect to multicast addresses so error out early.
5329    // Per RFC 9293 (https://datatracker.ietf.org/doc/html/rfc9293#name-open):
5330    //   A TCP implementation MUST reject as an error a local OPEN call for an invalid remote
5331    //   IP address (e.g., a broadcast or multicast address) (MUST-46).
5332    if remote_ip.addr().is_multicast()
5333        || WireI::map_ip_in(remote_ip.addr(), |ip| ip.is_limited_broadcast(), |_| false)
5334    {
5335        return Err(ConnectError::NoRoute);
5336    }
5337
5338    let ip_sock = core_ctx
5339        .new_ip_socket(
5340            bindings_ctx,
5341            IpSocketArgs {
5342                device: device.as_ref().map(|d| d.as_ref()),
5343                local_ip,
5344                remote_ip,
5345                proto: IpProto::Tcp.into(),
5346                options: &socket_options.ip_options,
5347            },
5348        )
5349        .map_err(|err| match err {
5350            IpSockCreationError::Route(_) => ConnectError::NoRoute,
5351        })?;
5352
5353    let device_mms = core_ctx.get_mms(bindings_ctx, &ip_sock, &socket_options.ip_options).map_err(
5354        |_err: ip::socket::MmsError| {
5355            // We either cannot find the route, or the device for
5356            // the route cannot handle the smallest TCP/IP packet.
5357            ConnectError::NoRoute
5358        },
5359    )?;
5360
5361    let conn_addr =
5362        demux.update_demux_state_for_connect(core_ctx, |demux_id, DemuxState { socketmap }| {
5363            let local_port = local_port.map_or_else(
5364                // NB: Pass the remote port into the allocator to avoid
5365                // unexpected self-connections when allocating a local port.
5366                // This could be optimized by checking if the IP socket has
5367                // resolved to local delivery, but excluding a single port
5368                // should be enough here and avoids adding more dependencies.
5369                || match netstack3_base::simple_randomized_port_alloc(
5370                    &mut bindings_ctx.rng(),
5371                    &Some(SocketIpAddr::from(*ip_sock.local_ip())),
5372                    &TcpPortAlloc(socketmap),
5373                    &Some(remote_port),
5374                ) {
5375                    Some(port) => {
5376                        Ok(NonZeroU16::new(port).expect("ephemeral ports must be non-zero"))
5377                    }
5378                    None => Err(ConnectError::NoPort),
5379                },
5380                Ok,
5381            )?;
5382
5383            let conn_addr = ConnAddr {
5384                ip: ConnIpAddr {
5385                    local: (SocketIpAddr::from(*ip_sock.local_ip()), local_port),
5386                    remote: (*ip_sock.remote_ip(), remote_port),
5387                },
5388                device: ip_sock.device().cloned(),
5389            };
5390
5391            let _entry = socketmap
5392                .conns_mut()
5393                .try_insert(conn_addr.clone(), sharing, demux_id.clone())
5394                .map_err(|(err, _sharing)| match err {
5395                    // The connection will conflict with an existing one.
5396                    InsertError::Exists | InsertError::ShadowerExists => {
5397                        ConnectError::ConnectionExists
5398                    }
5399                    // Connections don't conflict with listeners, and we should
5400                    // not observe the following errors.
5401                    InsertError::ShadowAddrExists | InsertError::IndirectConflict => {
5402                        panic!("failed to insert connection: {:?}", err)
5403                    }
5404                })?;
5405            Ok::<_, ConnectError>(conn_addr)
5406        })?;
5407
5408    let isn = isn.generate::<SocketIpAddr<WireI::Addr>, NonZeroU16>(
5409        bindings_ctx.now(),
5410        conn_addr.ip.local,
5411        conn_addr.ip.remote,
5412    );
5413    // TODO(https://fxbug.dev/360401604): Use this when initializing state for
5414    // the timestamp option.
5415    let _timestamp_offset = timestamp_offset.generate::<SocketIpAddr<WireI::Addr>, NonZeroU16>(
5416        bindings_ctx.now(),
5417        conn_addr.ip.local,
5418        conn_addr.ip.remote,
5419    );
5420
5421    let now = bindings_ctx.now();
5422    let mss = Mss::from_mms(device_mms).ok_or(ConnectError::NoRoute)?;
5423
5424    // No more errors can occur after here, because we're taking active_open
5425    // buffers out. Use a closure to guard against bad evolution.
5426    let active_open = active_open.take();
5427    Ok((move || {
5428        let (syn_sent, syn) = Closed::<Initial>::connect(
5429            isn,
5430            now,
5431            active_open,
5432            buffer_sizes,
5433            mss,
5434            Mss::default::<WireI>(),
5435            socket_options,
5436        );
5437        let state = State::<_, BC::ReceiveBuffer, BC::SendBuffer, _>::SynSent(syn_sent);
5438        let poll_send_at = state.poll_send_at().expect("no retrans timer");
5439
5440        // Send first SYN packet.
5441        send_tcp_segment(
5442            core_ctx,
5443            bindings_ctx,
5444            Some(&sock_id),
5445            Some(&ip_sock),
5446            conn_addr.ip,
5447            syn.into_empty(),
5448            &socket_options.ip_options,
5449        );
5450
5451        let mut timer = bindings_ctx.new_timer(convert_timer(sock_id.downgrade()));
5452        assert_eq!(bindings_ctx.schedule_timer_instant(poll_send_at, &mut timer), None);
5453
5454        let conn = convert_back_op(
5455            Connection {
5456                accept_queue: None,
5457                state,
5458                ip_sock,
5459                defunct: false,
5460                soft_error: None,
5461                handshake_status: HandshakeStatus::Pending,
5462            },
5463            conn_addr,
5464        );
5465        core_ctx.increment_both(sock_id, |counters| &counters.active_connection_openings);
5466        TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, sharing, timer })
5467    })())
5468}
5469
5470/// Information about a socket.
5471#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5472#[generic_over_ip(A, IpAddress)]
5473pub enum SocketInfo<A: IpAddress, D> {
5474    /// Unbound socket info.
5475    Unbound(UnboundInfo<D>),
5476    /// Bound or listener socket info.
5477    Bound(BoundInfo<A, D>),
5478    /// Connection socket info.
5479    Connection(ConnectionInfo<A, D>),
5480}
5481
5482/// Information about an unbound socket.
5483#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5484#[generic_over_ip()]
5485pub struct UnboundInfo<D> {
5486    /// The device the socket will be bound to.
5487    pub device: Option<D>,
5488}
5489
5490/// Information about a bound socket's address.
5491#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5492#[generic_over_ip(A, IpAddress)]
5493pub struct BoundInfo<A: IpAddress, D> {
5494    /// The IP address the socket is bound to, or `None` for all local IPs.
5495    pub addr: Option<ZonedAddr<SpecifiedAddr<A>, D>>,
5496    /// The port number the socket is bound to.
5497    pub port: NonZeroU16,
5498    /// The device the socket is bound to.
5499    pub device: Option<D>,
5500}
5501
5502/// Information about a connected socket's address.
5503#[derive(Clone, Debug, Eq, PartialEq, GenericOverIp)]
5504#[generic_over_ip(A, IpAddress)]
5505pub struct ConnectionInfo<A: IpAddress, D> {
5506    /// The local address the socket is bound to.
5507    pub local_addr: SocketAddr<A, D>,
5508    /// The remote address the socket is connected to.
5509    pub remote_addr: SocketAddr<A, D>,
5510    /// The device the socket is bound to.
5511    pub device: Option<D>,
5512}
5513
5514impl<D: Clone, Extra> From<&'_ Unbound<D, Extra>> for UnboundInfo<D> {
5515    fn from(unbound: &Unbound<D, Extra>) -> Self {
5516        let Unbound { bound_device: device, buffer_sizes: _, sharing: _, socket_extra: _ } =
5517            unbound;
5518        Self { device: device.clone() }
5519    }
5520}
5521
5522fn maybe_zoned<A: IpAddress, D: Clone>(
5523    ip: SpecifiedAddr<A>,
5524    device: &Option<D>,
5525) -> ZonedAddr<SpecifiedAddr<A>, D> {
5526    device
5527        .as_ref()
5528        .and_then(|device| {
5529            AddrAndZone::new(ip, device).map(|az| ZonedAddr::Zoned(az.map_zone(Clone::clone)))
5530        })
5531        .unwrap_or(ZonedAddr::Unzoned(ip))
5532}
5533
5534impl<A: IpAddress, D: Clone> From<ListenerAddr<ListenerIpAddr<A, NonZeroU16>, D>>
5535    for BoundInfo<A, D>
5536{
5537    fn from(addr: ListenerAddr<ListenerIpAddr<A, NonZeroU16>, D>) -> Self {
5538        let ListenerAddr { ip: ListenerIpAddr { addr, identifier }, device } = addr;
5539        let addr = addr.map(|ip| maybe_zoned(ip.into(), &device));
5540        BoundInfo { addr, port: identifier, device }
5541    }
5542}
5543
5544impl<A: IpAddress, D: Clone> From<ConnAddr<ConnIpAddr<A, NonZeroU16, NonZeroU16>, D>>
5545    for ConnectionInfo<A, D>
5546{
5547    fn from(addr: ConnAddr<ConnIpAddr<A, NonZeroU16, NonZeroU16>, D>) -> Self {
5548        let ConnAddr { ip: ConnIpAddr { local, remote }, device } = addr;
5549        let convert = |(ip, port): (SocketIpAddr<A>, NonZeroU16)| SocketAddr {
5550            ip: maybe_zoned(ip.into(), &device),
5551            port,
5552        };
5553        Self { local_addr: convert(local), remote_addr: convert(remote), device }
5554    }
5555}
5556
5557impl<CC, BC> HandleableTimer<CC, BC> for TcpTimerId<CC::WeakDeviceId, BC>
5558where
5559    BC: TcpBindingsContext<CC::DeviceId>,
5560    CC: TcpContext<Ipv4, BC> + TcpContext<Ipv6, BC>,
5561{
5562    fn handle(self, core_ctx: &mut CC, bindings_ctx: &mut BC, _: BC::UniqueTimerId) {
5563        let ctx_pair = CtxPair { core_ctx, bindings_ctx };
5564        match self {
5565            TcpTimerId::V4(conn_id) => TcpApi::new(ctx_pair).handle_timer(conn_id),
5566            TcpTimerId::V6(conn_id) => TcpApi::new(ctx_pair).handle_timer(conn_id),
5567        }
5568    }
5569}
5570
5571/// Send the given TCP Segment.
5572///
5573/// A centralized send path for TCP segments that increments counters and logs
5574/// errors.
5575///
5576/// When `ip_sock` is some, it is used to send the segment, otherwise, one is
5577/// constructed on demand to send a oneshot segment.
5578fn send_tcp_segment<'a, WireI, SockI, CC, BC, D>(
5579    core_ctx: &mut CC,
5580    bindings_ctx: &mut BC,
5581    socket_id: Option<&TcpSocketId<SockI, D, BC>>,
5582    ip_sock: Option<&IpSock<WireI, D>>,
5583    conn_addr: ConnIpAddr<WireI::Addr, NonZeroU16, NonZeroU16>,
5584    segment: Segment<<BC::SendBuffer as SendBuffer>::Payload<'a>>,
5585    ip_sock_options: &TcpIpSockOptions,
5586) where
5587    WireI: IpExt + FilterIpExt,
5588    SockI: IpExt + DualStackIpExt,
5589    CC: TcpSocketContext<SockI, D, BC>
5590        + IpSocketHandler<WireI, BC, DeviceId = D::Strong, WeakDeviceId = D>,
5591    BC: TcpBindingsTypes,
5592    D: WeakDeviceIdentifier,
5593{
5594    // NB: TCP does not use tx metadata to enforce send buffer. The TCP
5595    // application buffers only open send buffer space once the data is
5596    // acknowledged by the peer. That lives entirely in the TCP module and we
5597    // don't need to track segments sitting in device queues.
5598    let tx_metadata: BC::TxMetadata = match socket_id {
5599        Some(socket_id) => {
5600            core_ctx.convert_tx_meta(TcpSocketTxMetadata::new(socket_id.downgrade()))
5601        }
5602        None => Default::default(),
5603    };
5604
5605    let (header, data) = segment.into_parts();
5606    let control = header.control;
5607    let result = match ip_sock {
5608        Some(ip_sock) => {
5609            let body = tcp_serialize_segment(&header, data, conn_addr);
5610            core_ctx
5611                .send_ip_packet(bindings_ctx, ip_sock, body, ip_sock_options, tx_metadata)
5612                .map_err(|err| IpSockCreateAndSendError::Send(err))
5613        }
5614        None => {
5615            let ConnIpAddr { local: (local_ip, _), remote: (remote_ip, _) } = conn_addr;
5616            core_ctx.send_oneshot_ip_packet(
5617                bindings_ctx,
5618                IpSocketArgs {
5619                    device: None,
5620                    local_ip: IpDeviceAddr::new_from_socket_ip_addr(local_ip),
5621                    remote_ip,
5622                    proto: IpProto::Tcp.into(),
5623                    options: ip_sock_options,
5624                },
5625                tx_metadata,
5626                |_addr| tcp_serialize_segment(&header, data, conn_addr),
5627            )
5628        }
5629    };
5630    match result {
5631        Ok(()) => {
5632            counters::increment_counter_with_optional_socket_id(core_ctx, socket_id, |counters| {
5633                &counters.segments_sent
5634            });
5635            if let Some(control) = control {
5636                counters::increment_counter_with_optional_socket_id(
5637                    core_ctx,
5638                    socket_id,
5639                    |counters| match control {
5640                        Control::RST => &counters.resets_sent,
5641                        Control::SYN => &counters.syns_sent,
5642                        Control::FIN => &counters.fins_sent,
5643                    },
5644                )
5645            }
5646        }
5647        Err(err) => {
5648            counters::increment_counter_with_optional_socket_id(core_ctx, socket_id, |counters| {
5649                &counters.segment_send_errors
5650            });
5651            match socket_id {
5652                Some(socket_id) => debug!("{:?}: failed to send segment: {:?}", socket_id, err),
5653                None => debug!("TCP: failed to send segment: {:?}", err),
5654            }
5655        }
5656    }
5657}
5658
5659#[cfg(test)]
5660mod tests {
5661    use alloc::rc::Rc;
5662    use alloc::string::String;
5663    use alloc::sync::Arc;
5664    use alloc::vec::Vec;
5665    use alloc::{format, vec};
5666    use core::cell::RefCell;
5667    use core::num::NonZeroU16;
5668    use core::time::Duration;
5669
5670    use ip_test_macro::ip_test;
5671    use net_declare::net_ip_v6;
5672    use net_types::ip::{Ip, IpAddr, IpVersion, Ipv4, Ipv4SourceAddr, Ipv6, Ipv6SourceAddr, Mtu};
5673    use net_types::{LinkLocalAddr, Witness};
5674    use netstack3_base::sync::{DynDebugReferences, Mutex};
5675    use netstack3_base::testutil::{
5676        AlwaysDefaultsSettingsContext, FakeAtomicInstant, FakeCoreCtx, FakeCryptoRng, FakeDeviceId,
5677        FakeInstant, FakeNetwork, FakeNetworkSpec, FakeStrongDeviceId, FakeTimerCtx, FakeTimerId,
5678        FakeTxMetadata, FakeWeakDeviceId, InstantAndData, MultipleDevicesId, PendingFrameData,
5679        StepResult, TestIpExt, WithFakeFrameContext, WithFakeTimerContext, new_rng,
5680        run_with_many_seeds, set_logger_for_test,
5681    };
5682    use netstack3_base::{
5683        ContextProvider, CounterCollection, CounterContext, IcmpIpExt, Icmpv4ErrorCode,
5684        Icmpv6ErrorCode, Instant as _, InstantContext, LinkDevice, Mark, MarkDomain,
5685        MatcherBindingsTypes, Mms, ReferenceNotifiers, ResourceCounterContext,
5686        StrongDeviceIdentifier, Uninstantiable, UninstantiableWrapper,
5687    };
5688    use netstack3_filter::testutil::NoOpSocketOpsFilter;
5689    use netstack3_filter::{SocketOpsFilter, TransportPacketSerializer, Tuple};
5690    use netstack3_ip::device::IpDeviceStateIpExt;
5691    use netstack3_ip::nud::LinkResolutionContext;
5692    use netstack3_ip::nud::testutil::FakeLinkResolutionNotifier;
5693    use netstack3_ip::socket::testutil::{FakeDeviceConfig, FakeDualStackIpSocketCtx};
5694    use netstack3_ip::socket::{IpSockSendError, MmsError, RouteResolutionOptions, SendOptions};
5695    use netstack3_ip::testutil::DualStackSendIpPacketMeta;
5696    use netstack3_ip::{
5697        BaseTransportIpContext, HopLimits, IpTransportContext, LocalDeliveryPacketInfo,
5698    };
5699    use packet::{Buf, BufferMut, ParseBuffer as _};
5700    use packet_formats::icmp::{
5701        IcmpDestUnreachable, Icmpv4DestUnreachableCode, Icmpv4ParameterProblemCode,
5702        Icmpv4TimeExceededCode, Icmpv6DestUnreachableCode, Icmpv6ParameterProblemCode,
5703        Icmpv6TimeExceededCode,
5704    };
5705    use packet_formats::tcp::{TcpParseArgs, TcpSegment};
5706    use rand::Rng as _;
5707    use test_case::test_case;
5708    use test_util::assert_gt;
5709
5710    use super::*;
5711    use crate::internal::base::{ConnectionError, DEFAULT_FIN_WAIT2_TIMEOUT};
5712    use crate::internal::buffer::BufferLimits;
5713    use crate::internal::buffer::testutil::{
5714        ClientBuffers, ProvidedBuffers, RingBuffer, TestSendBuffer, WriteBackClientBuffers,
5715    };
5716    use crate::internal::congestion::CongestionWindow;
5717    use crate::internal::counters::TcpCountersWithoutSocket;
5718    use crate::internal::counters::testutil::{
5719        CounterExpectations, CounterExpectationsWithoutSocket,
5720    };
5721    use crate::internal::state::{Established, MSL, TimeWait};
5722
5723    pub(crate) trait TcpTestIpExt:
5724        DualStackIpExt + TestIpExt + IpDeviceStateIpExt + DualStackIpExt
5725    {
5726        type SingleStackConverter: SingleStackConverter<Self, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>;
5727        type DualStackConverter: DualStackConverter<Self, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>;
5728        fn recv_src_addr(addr: Self::Addr) -> Self::RecvSrcAddr;
5729
5730        fn converter() -> MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>;
5731    }
5732
5733    /// This trait anchors the timer DispatchId for our context implementations
5734    /// that require a core converter.
5735    ///
5736    /// This is required because we implement the traits on [`TcpCoreCtx`]
5737    /// abstracting away the bindings types, even though they're always
5738    /// [`TcpBindingsCtx`].
5739    trait TcpTestBindingsTypes<D: StrongDeviceIdentifier>:
5740        TcpBindingsTypes<DispatchId = TcpTimerId<D::Weak, Self>> + Sized
5741    {
5742    }
5743
5744    impl<D, BT> TcpTestBindingsTypes<D> for BT
5745    where
5746        BT: TcpBindingsTypes<DispatchId = TcpTimerId<D::Weak, Self>> + Sized,
5747        D: StrongDeviceIdentifier,
5748    {
5749    }
5750
5751    struct FakeTcpState<I: TcpTestIpExt, D: FakeStrongDeviceId, BT: TcpBindingsTypes> {
5752        isn_generator: Rc<IsnGenerator<BT::Instant>>,
5753        timestamp_offset_generator: Rc<TimestampOffsetGenerator<BT::Instant>>,
5754        demux: Rc<RefCell<DemuxState<I, D::Weak, BT>>>,
5755        // Always destroy all sockets last so the strong references in the demux
5756        // are gone.
5757        all_sockets: TcpSocketSet<I, D::Weak, BT>,
5758        counters_with_socket: TcpCountersWithSocket<I>,
5759        counters_without_socket: TcpCountersWithoutSocket<I>,
5760    }
5761
5762    impl<I, D, BT> Default for FakeTcpState<I, D, BT>
5763    where
5764        I: TcpTestIpExt,
5765        D: FakeStrongDeviceId,
5766        BT: TcpBindingsTypes,
5767        BT::Instant: Default,
5768    {
5769        fn default() -> Self {
5770            Self {
5771                isn_generator: Default::default(),
5772                timestamp_offset_generator: Default::default(),
5773                all_sockets: Default::default(),
5774                demux: Rc::new(RefCell::new(DemuxState { socketmap: Default::default() })),
5775                counters_with_socket: Default::default(),
5776                counters_without_socket: Default::default(),
5777            }
5778        }
5779    }
5780
5781    struct FakeDualStackTcpState<D: FakeStrongDeviceId, BT: TcpBindingsTypes> {
5782        v4: FakeTcpState<Ipv4, D, BT>,
5783        v6: FakeTcpState<Ipv6, D, BT>,
5784    }
5785
5786    impl<D, BT> Default for FakeDualStackTcpState<D, BT>
5787    where
5788        D: FakeStrongDeviceId,
5789        BT: TcpBindingsTypes,
5790        BT::Instant: Default,
5791    {
5792        fn default() -> Self {
5793            Self { v4: Default::default(), v6: Default::default() }
5794        }
5795    }
5796
5797    type InnerCoreCtx<D> =
5798        FakeCoreCtx<FakeDualStackIpSocketCtx<D>, DualStackSendIpPacketMeta<D>, D>;
5799
5800    pub(crate) struct TcpCoreCtx<D: FakeStrongDeviceId, BT: TcpBindingsTypes> {
5801        tcp: FakeDualStackTcpState<D, BT>,
5802        ip_socket_ctx: InnerCoreCtx<D>,
5803        // Marks to attach for incoming packets.
5804        recv_packet_marks: netstack3_base::Marks,
5805    }
5806
5807    impl<D: FakeStrongDeviceId, BT: TcpBindingsTypes> ContextProvider for TcpCoreCtx<D, BT> {
5808        type Context = Self;
5809
5810        fn context(&mut self) -> &mut Self::Context {
5811            self
5812        }
5813    }
5814
5815    impl<D, BT> DeviceIdContext<AnyDevice> for TcpCoreCtx<D, BT>
5816    where
5817        D: FakeStrongDeviceId,
5818        BT: TcpBindingsTypes,
5819    {
5820        type DeviceId = D;
5821        type WeakDeviceId = FakeWeakDeviceId<D>;
5822    }
5823
5824    pub(crate) type TcpCtx<D> = CtxPair<TcpCoreCtx<D, TcpBindingsCtx<D>>, TcpBindingsCtx<D>>;
5825
5826    struct FakeTcpNetworkSpec<D: FakeStrongDeviceId>(PhantomData<D>, Never);
5827    impl<D: FakeStrongDeviceId> FakeNetworkSpec for FakeTcpNetworkSpec<D> {
5828        type Context = TcpCtx<D>;
5829        type TimerId = TcpTimerId<D::Weak, TcpBindingsCtx<D>>;
5830        type SendMeta = DualStackSendIpPacketMeta<D>;
5831        type RecvMeta = DualStackSendIpPacketMeta<D>;
5832        fn handle_frame(ctx: &mut Self::Context, meta: Self::RecvMeta, buffer: Buf<Vec<u8>>) {
5833            let TcpCtx { core_ctx, bindings_ctx } = ctx;
5834            match meta {
5835                DualStackSendIpPacketMeta::V4(meta) => {
5836                    <TcpIpTransportContext as IpTransportContext<Ipv4, _, _>>::receive_ip_packet(
5837                        core_ctx,
5838                        bindings_ctx,
5839                        &meta.device,
5840                        Ipv4::recv_src_addr(*meta.src_ip),
5841                        meta.dst_ip,
5842                        buffer,
5843                        &LocalDeliveryPacketInfo {
5844                            marks: core_ctx.recv_packet_marks,
5845                            ..Default::default()
5846                        },
5847                    )
5848                    .expect("failed to deliver bytes");
5849                }
5850                DualStackSendIpPacketMeta::V6(meta) => {
5851                    <TcpIpTransportContext as IpTransportContext<Ipv6, _, _>>::receive_ip_packet(
5852                        core_ctx,
5853                        bindings_ctx,
5854                        &meta.device,
5855                        Ipv6::recv_src_addr(*meta.src_ip),
5856                        meta.dst_ip,
5857                        buffer,
5858                        &LocalDeliveryPacketInfo {
5859                            marks: core_ctx.recv_packet_marks,
5860                            ..Default::default()
5861                        },
5862                    )
5863                    .expect("failed to deliver bytes");
5864                }
5865            }
5866        }
5867        fn handle_timer(ctx: &mut Self::Context, dispatch: Self::TimerId, _: FakeTimerId) {
5868            match dispatch {
5869                TcpTimerId::V4(id) => ctx.tcp_api().handle_timer(id),
5870                TcpTimerId::V6(id) => ctx.tcp_api().handle_timer(id),
5871            }
5872        }
5873        fn process_queues(_ctx: &mut Self::Context) -> bool {
5874            false
5875        }
5876        fn fake_frames(ctx: &mut Self::Context) -> &mut impl WithFakeFrameContext<Self::SendMeta> {
5877            &mut ctx.core_ctx.ip_socket_ctx.frames
5878        }
5879    }
5880
5881    impl<D: FakeStrongDeviceId> WithFakeTimerContext<TcpTimerId<D::Weak, TcpBindingsCtx<D>>>
5882        for TcpCtx<D>
5883    {
5884        fn with_fake_timer_ctx<
5885            O,
5886            F: FnOnce(&FakeTimerCtx<TcpTimerId<D::Weak, TcpBindingsCtx<D>>>) -> O,
5887        >(
5888            &self,
5889            f: F,
5890        ) -> O {
5891            let Self { core_ctx: _, bindings_ctx } = self;
5892            f(&bindings_ctx.timers)
5893        }
5894
5895        fn with_fake_timer_ctx_mut<
5896            O,
5897            F: FnOnce(&mut FakeTimerCtx<TcpTimerId<D::Weak, TcpBindingsCtx<D>>>) -> O,
5898        >(
5899            &mut self,
5900            f: F,
5901        ) -> O {
5902            let Self { core_ctx: _, bindings_ctx } = self;
5903            f(&mut bindings_ctx.timers)
5904        }
5905    }
5906
5907    #[derive(Derivative)]
5908    #[derivative(Default(bound = ""))]
5909    pub(crate) struct TcpBindingsCtx<D: FakeStrongDeviceId> {
5910        rng: FakeCryptoRng,
5911        timers: FakeTimerCtx<TcpTimerId<D::Weak, Self>>,
5912    }
5913
5914    impl<D: FakeStrongDeviceId> ContextProvider for TcpBindingsCtx<D> {
5915        type Context = Self;
5916        fn context(&mut self) -> &mut Self::Context {
5917            self
5918        }
5919    }
5920
5921    impl<D: LinkDevice + FakeStrongDeviceId> LinkResolutionContext<D> for TcpBindingsCtx<D> {
5922        type Notifier = FakeLinkResolutionNotifier<D>;
5923    }
5924
5925    /// Delegate implementation to internal thing.
5926    impl<D: FakeStrongDeviceId> TimerBindingsTypes for TcpBindingsCtx<D> {
5927        type Timer = <FakeTimerCtx<TcpTimerId<D::Weak, Self>> as TimerBindingsTypes>::Timer;
5928        type DispatchId =
5929            <FakeTimerCtx<TcpTimerId<D::Weak, Self>> as TimerBindingsTypes>::DispatchId;
5930        type UniqueTimerId =
5931            <FakeTimerCtx<TcpTimerId<D::Weak, Self>> as TimerBindingsTypes>::UniqueTimerId;
5932    }
5933
5934    /// Delegate implementation to internal thing.
5935    impl<D: FakeStrongDeviceId> InstantBindingsTypes for TcpBindingsCtx<D> {
5936        type Instant = FakeInstant;
5937        type AtomicInstant = FakeAtomicInstant;
5938    }
5939
5940    impl<D: FakeStrongDeviceId> SocketOpsFilterBindingContext<D> for TcpBindingsCtx<D> {
5941        fn socket_ops_filter(&self) -> impl SocketOpsFilter<D> {
5942            NoOpSocketOpsFilter
5943        }
5944    }
5945
5946    /// Delegate implementation to internal thing.
5947    impl<D: FakeStrongDeviceId> InstantContext for TcpBindingsCtx<D> {
5948        fn now(&self) -> FakeInstant {
5949            self.timers.now()
5950        }
5951    }
5952
5953    /// Delegate implementation to internal thing.
5954    impl<D: FakeStrongDeviceId> TimerContext for TcpBindingsCtx<D> {
5955        fn new_timer(&mut self, id: Self::DispatchId) -> Self::Timer {
5956            self.timers.new_timer(id)
5957        }
5958
5959        fn schedule_timer_instant(
5960            &mut self,
5961            time: Self::Instant,
5962            timer: &mut Self::Timer,
5963        ) -> Option<Self::Instant> {
5964            self.timers.schedule_timer_instant(time, timer)
5965        }
5966
5967        fn cancel_timer(&mut self, timer: &mut Self::Timer) -> Option<Self::Instant> {
5968            self.timers.cancel_timer(timer)
5969        }
5970
5971        fn scheduled_instant(&self, timer: &mut Self::Timer) -> Option<Self::Instant> {
5972            self.timers.scheduled_instant(timer)
5973        }
5974
5975        fn unique_timer_id(&self, timer: &Self::Timer) -> Self::UniqueTimerId {
5976            self.timers.unique_timer_id(timer)
5977        }
5978    }
5979
5980    impl<D: FakeStrongDeviceId> ReferenceNotifiers for TcpBindingsCtx<D> {
5981        type ReferenceReceiver<T: 'static> = Never;
5982
5983        type ReferenceNotifier<T: Send + 'static> = Never;
5984
5985        fn new_reference_notifier<T: Send + 'static>(
5986            debug_references: DynDebugReferences,
5987        ) -> (Self::ReferenceNotifier<T>, Self::ReferenceReceiver<T>) {
5988            // We don't support deferred destruction, tests are single threaded.
5989            panic!(
5990                "can't create deferred reference notifiers for type {}: \
5991                debug_references={debug_references:?}",
5992                core::any::type_name::<T>()
5993            );
5994        }
5995    }
5996
5997    impl<D: FakeStrongDeviceId> DeferredResourceRemovalContext for TcpBindingsCtx<D> {
5998        fn defer_removal<T: Send + 'static>(&mut self, receiver: Self::ReferenceReceiver<T>) {
5999            match receiver {}
6000        }
6001    }
6002
6003    impl<D: FakeStrongDeviceId> RngContext for TcpBindingsCtx<D> {
6004        type Rng<'a> = &'a mut FakeCryptoRng;
6005        fn rng(&mut self) -> Self::Rng<'_> {
6006            &mut self.rng
6007        }
6008    }
6009
6010    impl<D: FakeStrongDeviceId> TxMetadataBindingsTypes for TcpBindingsCtx<D> {
6011        type TxMetadata = FakeTxMetadata;
6012    }
6013
6014    impl<D: FakeStrongDeviceId> MatcherBindingsTypes for TcpBindingsCtx<D> {
6015        type DeviceClass = ();
6016        type BindingsPacketMatcher = Never;
6017    }
6018
6019    impl<D: FakeStrongDeviceId> TcpBindingsTypes for TcpBindingsCtx<D> {
6020        type ReceiveBuffer = Arc<Mutex<RingBuffer>>;
6021        type SendBuffer = TestSendBuffer;
6022        type ReturnedBuffers = ClientBuffers;
6023        type ListenerNotifierOrProvidedBuffers = ProvidedBuffers;
6024
6025        fn new_passive_open_buffers(
6026            buffer_sizes: BufferSizes,
6027        ) -> (Self::ReceiveBuffer, Self::SendBuffer, Self::ReturnedBuffers) {
6028            let client = ClientBuffers::new(buffer_sizes);
6029            (
6030                Arc::clone(&client.receive),
6031                TestSendBuffer::new(Arc::clone(&client.send), RingBuffer::default()),
6032                client,
6033            )
6034        }
6035    }
6036
6037    impl<D: FakeStrongDeviceId> AlwaysDefaultsSettingsContext for TcpBindingsCtx<D> {}
6038
6039    const LINK_MTU: Mtu = Mtu::new(1500);
6040
6041    impl<I, D, BC> DeviceIpSocketHandler<I, BC> for TcpCoreCtx<D, BC>
6042    where
6043        I: TcpTestIpExt,
6044        D: FakeStrongDeviceId,
6045        BC: TcpTestBindingsTypes<D>,
6046    {
6047        fn get_mms<O>(
6048            &mut self,
6049            _bindings_ctx: &mut BC,
6050            _ip_sock: &IpSock<I, Self::WeakDeviceId>,
6051            _options: &O,
6052        ) -> Result<Mms, MmsError>
6053        where
6054            O: RouteResolutionOptions<I>,
6055        {
6056            Ok(Mms::from_mtu::<I>(LINK_MTU, 0).unwrap())
6057        }
6058    }
6059
6060    /// Delegate implementation to inner context.
6061    impl<I, D, BC> BaseTransportIpContext<I, BC> for TcpCoreCtx<D, BC>
6062    where
6063        I: TcpTestIpExt,
6064        D: FakeStrongDeviceId,
6065        BC: TcpTestBindingsTypes<D>,
6066    {
6067        type DevicesWithAddrIter<'a>
6068            = <InnerCoreCtx<D> as BaseTransportIpContext<I, BC>>::DevicesWithAddrIter<'a>
6069        where
6070            Self: 'a;
6071
6072        fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
6073            &mut self,
6074            addr: SpecifiedAddr<I::Addr>,
6075            cb: F,
6076        ) -> O {
6077            BaseTransportIpContext::<I, BC>::with_devices_with_assigned_addr(
6078                &mut self.ip_socket_ctx,
6079                addr,
6080                cb,
6081            )
6082        }
6083
6084        fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
6085            BaseTransportIpContext::<I, BC>::get_default_hop_limits(&mut self.ip_socket_ctx, device)
6086        }
6087
6088        fn get_original_destination(&mut self, tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
6089            BaseTransportIpContext::<I, BC>::get_original_destination(
6090                &mut self.ip_socket_ctx,
6091                tuple,
6092            )
6093        }
6094    }
6095
6096    /// Delegate implementation to inner context.
6097    impl<I: TcpTestIpExt, D: FakeStrongDeviceId, BC: TcpTestBindingsTypes<D>> IpSocketHandler<I, BC>
6098        for TcpCoreCtx<D, BC>
6099    {
6100        fn new_ip_socket<O>(
6101            &mut self,
6102            bindings_ctx: &mut BC,
6103            args: IpSocketArgs<'_, Self::DeviceId, I, O>,
6104        ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
6105        where
6106            O: RouteResolutionOptions<I>,
6107        {
6108            IpSocketHandler::<I, BC>::new_ip_socket(&mut self.ip_socket_ctx, bindings_ctx, args)
6109        }
6110
6111        fn send_ip_packet<S, O>(
6112            &mut self,
6113            bindings_ctx: &mut BC,
6114            socket: &IpSock<I, Self::WeakDeviceId>,
6115            body: S,
6116            options: &O,
6117            tx_meta: BC::TxMetadata,
6118        ) -> Result<(), IpSockSendError>
6119        where
6120            S: TransportPacketSerializer<I>,
6121            S::Buffer: BufferMut,
6122            O: SendOptions<I> + RouteResolutionOptions<I>,
6123        {
6124            self.ip_socket_ctx.send_ip_packet(bindings_ctx, socket, body, options, tx_meta)
6125        }
6126
6127        fn confirm_reachable<O>(
6128            &mut self,
6129            bindings_ctx: &mut BC,
6130            socket: &IpSock<I, Self::WeakDeviceId>,
6131            options: &O,
6132        ) where
6133            O: RouteResolutionOptions<I>,
6134        {
6135            self.ip_socket_ctx.confirm_reachable(bindings_ctx, socket, options)
6136        }
6137    }
6138
6139    impl<D, BC> TcpDemuxContext<Ipv4, D::Weak, BC> for TcpCoreCtx<D, BC>
6140    where
6141        D: FakeStrongDeviceId,
6142        BC: TcpTestBindingsTypes<D>,
6143    {
6144        type IpTransportCtx<'a> = Self;
6145        fn with_demux<O, F: FnOnce(&DemuxState<Ipv4, D::Weak, BC>) -> O>(&mut self, cb: F) -> O {
6146            cb(&self.tcp.v4.demux.borrow())
6147        }
6148
6149        fn with_demux_mut<O, F: FnOnce(&mut DemuxState<Ipv4, D::Weak, BC>) -> O>(
6150            &mut self,
6151            cb: F,
6152        ) -> O {
6153            cb(&mut self.tcp.v4.demux.borrow_mut())
6154        }
6155    }
6156
6157    impl<D, BC> TcpDemuxContext<Ipv6, D::Weak, BC> for TcpCoreCtx<D, BC>
6158    where
6159        D: FakeStrongDeviceId,
6160        BC: TcpTestBindingsTypes<D>,
6161    {
6162        type IpTransportCtx<'a> = Self;
6163        fn with_demux<O, F: FnOnce(&DemuxState<Ipv6, D::Weak, BC>) -> O>(&mut self, cb: F) -> O {
6164            cb(&self.tcp.v6.demux.borrow())
6165        }
6166
6167        fn with_demux_mut<O, F: FnOnce(&mut DemuxState<Ipv6, D::Weak, BC>) -> O>(
6168            &mut self,
6169            cb: F,
6170        ) -> O {
6171            cb(&mut self.tcp.v6.demux.borrow_mut())
6172        }
6173    }
6174
6175    impl<I, D, BT> CoreTimerContext<WeakTcpSocketId<I, D::Weak, BT>, BT> for TcpCoreCtx<D, BT>
6176    where
6177        I: DualStackIpExt,
6178        D: FakeStrongDeviceId,
6179        BT: TcpTestBindingsTypes<D>,
6180    {
6181        fn convert_timer(dispatch_id: WeakTcpSocketId<I, D::Weak, BT>) -> BT::DispatchId {
6182            dispatch_id.into()
6183        }
6184    }
6185
6186    impl<I, D, BC> CoreTxMetadataContext<TcpSocketTxMetadata<I, D::Weak, BC>, BC> for TcpCoreCtx<D, BC>
6187    where
6188        I: TcpTestIpExt,
6189        D: FakeStrongDeviceId,
6190        BC: TcpTestBindingsTypes<D>,
6191    {
6192        fn convert_tx_meta(&self, _tx_meta: TcpSocketTxMetadata<I, D::Weak, BC>) -> BC::TxMetadata {
6193            Default::default()
6194        }
6195    }
6196
6197    impl<D: FakeStrongDeviceId, BC: TcpTestBindingsTypes<D>> TcpContext<Ipv6, BC>
6198        for TcpCoreCtx<D, BC>
6199    {
6200        type ThisStackIpTransportAndDemuxCtx<'a> = Self;
6201        type SingleStackIpTransportAndDemuxCtx<'a> = UninstantiableWrapper<Self>;
6202        type SingleStackConverter = Uninstantiable;
6203        type DualStackIpTransportAndDemuxCtx<'a> = Self;
6204        type DualStackConverter = ();
6205        fn with_all_sockets_mut<
6206            O,
6207            F: FnOnce(&mut TcpSocketSet<Ipv6, Self::WeakDeviceId, BC>) -> O,
6208        >(
6209            &mut self,
6210            cb: F,
6211        ) -> O {
6212            cb(&mut self.tcp.v6.all_sockets)
6213        }
6214
6215        fn for_each_socket<
6216            F: FnMut(
6217                &TcpSocketId<Ipv6, Self::WeakDeviceId, BC>,
6218                &TcpSocketState<Ipv6, Self::WeakDeviceId, BC>,
6219            ),
6220        >(
6221            &mut self,
6222            mut cb: F,
6223        ) {
6224            for id in self.tcp.v6.all_sockets.keys() {
6225                cb(id, &id.get());
6226            }
6227        }
6228
6229        fn with_socket_mut_generators_transport_demux<
6230            O,
6231            F: for<'a> FnOnce(
6232                MaybeDualStack<
6233                    (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
6234                    (
6235                        &'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>,
6236                        Self::SingleStackConverter,
6237                    ),
6238                >,
6239                &mut TcpSocketState<Ipv6, Self::WeakDeviceId, BC>,
6240                &IsnGenerator<BC::Instant>,
6241                &TimestampOffsetGenerator<BC::Instant>,
6242            ) -> O,
6243        >(
6244            &mut self,
6245            id: &TcpSocketId<Ipv6, Self::WeakDeviceId, BC>,
6246            cb: F,
6247        ) -> O {
6248            let isn = Rc::clone(&self.tcp.v6.isn_generator);
6249            let timestamp_offset = Rc::clone(&self.tcp.v6.timestamp_offset_generator);
6250            cb(
6251                MaybeDualStack::DualStack((self, ())),
6252                id.get_mut().deref_mut(),
6253                isn.deref(),
6254                timestamp_offset.deref(),
6255            )
6256        }
6257
6258        fn with_socket_and_converter<
6259            O,
6260            F: FnOnce(
6261                &TcpSocketState<Ipv6, Self::WeakDeviceId, BC>,
6262                MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
6263            ) -> O,
6264        >(
6265            &mut self,
6266            id: &TcpSocketId<Ipv6, Self::WeakDeviceId, BC>,
6267            cb: F,
6268        ) -> O {
6269            cb(id.get_mut().deref_mut(), MaybeDualStack::DualStack(()))
6270        }
6271    }
6272
6273    impl<D: FakeStrongDeviceId, BC: TcpTestBindingsTypes<D>> TcpContext<Ipv4, BC>
6274        for TcpCoreCtx<D, BC>
6275    {
6276        type ThisStackIpTransportAndDemuxCtx<'a> = Self;
6277        type SingleStackIpTransportAndDemuxCtx<'a> = Self;
6278        type SingleStackConverter = ();
6279        type DualStackIpTransportAndDemuxCtx<'a> = UninstantiableWrapper<Self>;
6280        type DualStackConverter = Uninstantiable;
6281        fn with_all_sockets_mut<
6282            O,
6283            F: FnOnce(&mut TcpSocketSet<Ipv4, Self::WeakDeviceId, BC>) -> O,
6284        >(
6285            &mut self,
6286            cb: F,
6287        ) -> O {
6288            cb(&mut self.tcp.v4.all_sockets)
6289        }
6290
6291        fn for_each_socket<
6292            F: FnMut(
6293                &TcpSocketId<Ipv4, Self::WeakDeviceId, BC>,
6294                &TcpSocketState<Ipv4, Self::WeakDeviceId, BC>,
6295            ),
6296        >(
6297            &mut self,
6298            mut cb: F,
6299        ) {
6300            for id in self.tcp.v4.all_sockets.keys() {
6301                cb(id, &id.get());
6302            }
6303        }
6304
6305        fn with_socket_mut_generators_transport_demux<
6306            O,
6307            F: for<'a> FnOnce(
6308                MaybeDualStack<
6309                    (&'a mut Self::DualStackIpTransportAndDemuxCtx<'a>, Self::DualStackConverter),
6310                    (
6311                        &'a mut Self::SingleStackIpTransportAndDemuxCtx<'a>,
6312                        Self::SingleStackConverter,
6313                    ),
6314                >,
6315                &mut TcpSocketState<Ipv4, Self::WeakDeviceId, BC>,
6316                &IsnGenerator<BC::Instant>,
6317                &TimestampOffsetGenerator<BC::Instant>,
6318            ) -> O,
6319        >(
6320            &mut self,
6321            id: &TcpSocketId<Ipv4, Self::WeakDeviceId, BC>,
6322            cb: F,
6323        ) -> O {
6324            let isn: Rc<IsnGenerator<<BC as InstantBindingsTypes>::Instant>> =
6325                Rc::clone(&self.tcp.v4.isn_generator);
6326            let timestamp_offset: Rc<
6327                TimestampOffsetGenerator<<BC as InstantBindingsTypes>::Instant>,
6328            > = Rc::clone(&self.tcp.v4.timestamp_offset_generator);
6329            cb(
6330                MaybeDualStack::NotDualStack((self, ())),
6331                id.get_mut().deref_mut(),
6332                isn.deref(),
6333                timestamp_offset.deref(),
6334            )
6335        }
6336
6337        fn with_socket_and_converter<
6338            O,
6339            F: FnOnce(
6340                &TcpSocketState<Ipv4, Self::WeakDeviceId, BC>,
6341                MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter>,
6342            ) -> O,
6343        >(
6344            &mut self,
6345            id: &TcpSocketId<Ipv4, Self::WeakDeviceId, BC>,
6346            cb: F,
6347        ) -> O {
6348            cb(id.get_mut().deref_mut(), MaybeDualStack::NotDualStack(()))
6349        }
6350    }
6351
6352    impl<D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6353        TcpDualStackContext<Ipv6, FakeWeakDeviceId<D>, BT> for TcpCoreCtx<D, BT>
6354    {
6355        type DualStackIpTransportCtx<'a> = Self;
6356        fn other_demux_id_converter(&self) -> impl DualStackDemuxIdConverter<Ipv6> {
6357            Ipv6SocketIdToIpv4DemuxIdConverter
6358        }
6359        fn dual_stack_enabled(&self, ip_options: &Ipv6Options) -> bool {
6360            ip_options.dual_stack_enabled
6361        }
6362        fn set_dual_stack_enabled(&self, ip_options: &mut Ipv6Options, value: bool) {
6363            ip_options.dual_stack_enabled = value;
6364        }
6365        fn with_both_demux_mut<
6366            O,
6367            F: FnOnce(
6368                &mut DemuxState<Ipv6, FakeWeakDeviceId<D>, BT>,
6369                &mut DemuxState<Ipv4, FakeWeakDeviceId<D>, BT>,
6370            ) -> O,
6371        >(
6372            &mut self,
6373            cb: F,
6374        ) -> O {
6375            cb(&mut self.tcp.v6.demux.borrow_mut(), &mut self.tcp.v4.demux.borrow_mut())
6376        }
6377    }
6378
6379    impl<I: Ip, D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6380        CounterContext<TcpCountersWithSocket<I>> for TcpCoreCtx<D, BT>
6381    {
6382        fn counters(&self) -> &TcpCountersWithSocket<I> {
6383            I::map_ip(
6384                (),
6385                |()| &self.tcp.v4.counters_with_socket,
6386                |()| &self.tcp.v6.counters_with_socket,
6387            )
6388        }
6389    }
6390
6391    impl<I: Ip, D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6392        CounterContext<TcpCountersWithoutSocket<I>> for TcpCoreCtx<D, BT>
6393    {
6394        fn counters(&self) -> &TcpCountersWithoutSocket<I> {
6395            I::map_ip(
6396                (),
6397                |()| &self.tcp.v4.counters_without_socket,
6398                |()| &self.tcp.v6.counters_without_socket,
6399            )
6400        }
6401    }
6402
6403    impl<I: DualStackIpExt, D: FakeStrongDeviceId, BT: TcpTestBindingsTypes<D>>
6404        ResourceCounterContext<TcpSocketId<I, FakeWeakDeviceId<D>, BT>, TcpCountersWithSocket<I>>
6405        for TcpCoreCtx<D, BT>
6406    {
6407        fn per_resource_counters<'a>(
6408            &'a self,
6409            resource: &'a TcpSocketId<I, FakeWeakDeviceId<D>, BT>,
6410        ) -> &'a TcpCountersWithSocket<I> {
6411            resource.counters()
6412        }
6413    }
6414
6415    impl<D, BT> TcpCoreCtx<D, BT>
6416    where
6417        D: FakeStrongDeviceId,
6418        BT: TcpBindingsTypes,
6419        BT::Instant: Default,
6420    {
6421        fn with_ip_socket_ctx_state(state: FakeDualStackIpSocketCtx<D>) -> Self {
6422            Self {
6423                tcp: Default::default(),
6424                ip_socket_ctx: FakeCoreCtx::with_state(state),
6425                recv_packet_marks: Default::default(),
6426            }
6427        }
6428    }
6429
6430    impl TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>> {
6431        pub(crate) fn new<I: TcpTestIpExt>(
6432            addr: SpecifiedAddr<I::Addr>,
6433            peer: SpecifiedAddr<I::Addr>,
6434        ) -> Self {
6435            Self::with_ip_socket_ctx_state(FakeDualStackIpSocketCtx::new(core::iter::once(
6436                FakeDeviceConfig {
6437                    device: FakeDeviceId,
6438                    local_ips: vec![addr],
6439                    remote_ips: vec![peer],
6440                },
6441            )))
6442        }
6443    }
6444
6445    impl TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>> {
6446        fn new_multiple_devices() -> Self {
6447            Self::with_ip_socket_ctx_state(FakeDualStackIpSocketCtx::new(core::iter::empty::<
6448                FakeDeviceConfig<MultipleDevicesId, SpecifiedAddr<IpAddr>>,
6449            >()))
6450        }
6451    }
6452
6453    const LOCAL: &'static str = "local";
6454    const REMOTE: &'static str = "remote";
6455    pub(crate) const PORT_1: NonZeroU16 = NonZeroU16::new(42).unwrap();
6456    const PORT_2: NonZeroU16 = NonZeroU16::new(43).unwrap();
6457
6458    impl TcpTestIpExt for Ipv4 {
6459        type SingleStackConverter = ();
6460        type DualStackConverter = Uninstantiable;
6461        fn converter() -> MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter> {
6462            MaybeDualStack::NotDualStack(())
6463        }
6464        fn recv_src_addr(addr: Self::Addr) -> Self::RecvSrcAddr {
6465            Ipv4SourceAddr::new(addr).unwrap()
6466        }
6467    }
6468
6469    impl TcpTestIpExt for Ipv6 {
6470        type SingleStackConverter = Uninstantiable;
6471        type DualStackConverter = ();
6472        fn converter() -> MaybeDualStack<Self::DualStackConverter, Self::SingleStackConverter> {
6473            MaybeDualStack::DualStack(())
6474        }
6475        fn recv_src_addr(addr: Self::Addr) -> Self::RecvSrcAddr {
6476            Ipv6SourceAddr::new(addr).unwrap()
6477        }
6478    }
6479
6480    type TcpTestNetwork = FakeNetwork<
6481        FakeTcpNetworkSpec<FakeDeviceId>,
6482        &'static str,
6483        fn(
6484            &'static str,
6485            DualStackSendIpPacketMeta<FakeDeviceId>,
6486        ) -> Vec<(
6487            &'static str,
6488            DualStackSendIpPacketMeta<FakeDeviceId>,
6489            Option<core::time::Duration>,
6490        )>,
6491    >;
6492
6493    fn new_test_net<I: TcpTestIpExt>() -> TcpTestNetwork {
6494        FakeTcpNetworkSpec::new_network(
6495            [
6496                (
6497                    LOCAL,
6498                    TcpCtx {
6499                        core_ctx: TcpCoreCtx::new::<I>(
6500                            I::TEST_ADDRS.local_ip,
6501                            I::TEST_ADDRS.remote_ip,
6502                        ),
6503                        bindings_ctx: TcpBindingsCtx::default(),
6504                    },
6505                ),
6506                (
6507                    REMOTE,
6508                    TcpCtx {
6509                        core_ctx: TcpCoreCtx::new::<I>(
6510                            I::TEST_ADDRS.remote_ip,
6511                            I::TEST_ADDRS.local_ip,
6512                        ),
6513                        bindings_ctx: TcpBindingsCtx::default(),
6514                    },
6515                ),
6516            ],
6517            move |net, meta: DualStackSendIpPacketMeta<_>| {
6518                if net == LOCAL {
6519                    alloc::vec![(REMOTE, meta, None)]
6520                } else {
6521                    alloc::vec![(LOCAL, meta, None)]
6522                }
6523            },
6524        )
6525    }
6526
6527    /// Utilities for accessing locked internal state in tests.
6528    impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
6529        fn get(&self) -> impl Deref<Target = TcpSocketState<I, D, BT>> + '_ {
6530            let Self(rc) = self;
6531            rc.locked_state.read()
6532        }
6533
6534        fn get_mut(&self) -> impl DerefMut<Target = TcpSocketState<I, D, BT>> + '_ {
6535            let Self(rc) = self;
6536            rc.locked_state.write()
6537        }
6538    }
6539
6540    fn assert_this_stack_conn<
6541        'a,
6542        I: DualStackIpExt,
6543        BC: TcpBindingsContext<CC::DeviceId>,
6544        CC: TcpContext<I, BC>,
6545    >(
6546        conn: &'a I::ConnectionAndAddr<CC::WeakDeviceId, BC>,
6547        converter: &MaybeDualStack<CC::DualStackConverter, CC::SingleStackConverter>,
6548    ) -> &'a (
6549        Connection<I, I, CC::WeakDeviceId, BC>,
6550        ConnAddr<ConnIpAddr<I::Addr, NonZeroU16, NonZeroU16>, CC::WeakDeviceId>,
6551    ) {
6552        match converter {
6553            MaybeDualStack::NotDualStack(nds) => nds.convert(conn),
6554            MaybeDualStack::DualStack(ds) => {
6555                assert_matches!(ds.convert(conn), EitherStack::ThisStack(conn) => conn)
6556            }
6557        }
6558    }
6559
6560    /// A trait providing a shortcut to instantiate a [`TcpApi`] from a context.
6561    pub(crate) trait TcpApiExt: ContextPair + Sized {
6562        fn tcp_api<I: Ip>(&mut self) -> TcpApi<I, &mut Self> {
6563            TcpApi::new(self)
6564        }
6565    }
6566
6567    impl<O> TcpApiExt for O where O: ContextPair + Sized {}
6568
6569    /// How to bind the client socket in `bind_listen_connect_accept_inner`.
6570    struct BindConfig {
6571        /// Which port to bind the client to.
6572        client_port: Option<NonZeroU16>,
6573        /// Which port to bind the server to.
6574        server_port: NonZeroU16,
6575        /// Whether to set REUSE_ADDR for the client.
6576        client_reuse_addr: bool,
6577        /// Whether to send bidirectional test data after establishing the
6578        /// connection.
6579        send_test_data: bool,
6580    }
6581
6582    /// The following test sets up two connected testing context - one as the
6583    /// server and the other as the client. Tests if a connection can be
6584    /// established using `bind`, `listen`, `connect` and `accept`.
6585    ///
6586    /// # Arguments
6587    ///
6588    /// * `listen_addr` - The address to listen on.
6589    /// * `bind_config` - Specifics about how to bind the client socket.
6590    ///
6591    /// # Returns
6592    ///
6593    /// Returns a tuple of
6594    ///   - the created test network.
6595    ///   - the client socket from local.
6596    ///   - the send end of the client socket.
6597    ///   - the accepted socket from remote.
6598    fn bind_listen_connect_accept_inner<I: TcpTestIpExt>(
6599        listen_addr: I::Addr,
6600        BindConfig { client_port, server_port, client_reuse_addr, send_test_data }: BindConfig,
6601        seed: u128,
6602        drop_rate: f64,
6603    ) -> (
6604        TcpTestNetwork,
6605        TcpSocketId<I, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>,
6606        Arc<Mutex<Vec<u8>>>,
6607        TcpSocketId<I, FakeWeakDeviceId<FakeDeviceId>, TcpBindingsCtx<FakeDeviceId>>,
6608    )
6609    where
6610        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
6611                I,
6612                TcpBindingsCtx<FakeDeviceId>,
6613                SingleStackConverter = I::SingleStackConverter,
6614                DualStackConverter = I::DualStackConverter,
6615            >,
6616    {
6617        let mut net = new_test_net::<I>();
6618        let mut rng = new_rng(seed);
6619
6620        let mut maybe_drop_frame =
6621            |_: &mut TcpCtx<_>, meta: DualStackSendIpPacketMeta<_>, buffer: Buf<Vec<u8>>| {
6622                let x: f64 = rng.random();
6623                (x > drop_rate).then_some((meta, buffer))
6624            };
6625
6626        let backlog = NonZeroUsize::new(1).unwrap();
6627        let server = net.with_context(REMOTE, |ctx| {
6628            let mut api = ctx.tcp_api::<I>();
6629            let server = api.create(Default::default());
6630            api.bind(
6631                &server,
6632                SpecifiedAddr::new(listen_addr).map(|a| ZonedAddr::Unzoned(a)),
6633                Some(server_port),
6634            )
6635            .expect("failed to bind the server socket");
6636            api.listen(&server, backlog).expect("can listen");
6637            server
6638        });
6639
6640        let client_ends = WriteBackClientBuffers::default();
6641        let client = net.with_context(LOCAL, |ctx| {
6642            let mut api = ctx.tcp_api::<I>();
6643            let socket = api.create(ProvidedBuffers::Buffers(client_ends.clone()));
6644            if client_reuse_addr {
6645                api.set_reuseaddr(&socket, true).expect("can set");
6646            }
6647            if let Some(port) = client_port {
6648                api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(port))
6649                    .expect("failed to bind the client socket")
6650            }
6651            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), server_port)
6652                .expect("failed to connect");
6653            socket
6654        });
6655        // If drop rate is 0, the SYN is guaranteed to be delivered, so we can
6656        // look at the SYN queue deterministically.
6657        if drop_rate == 0.0 {
6658            // Step once for the SYN packet to be sent.
6659            let _: StepResult = net.step();
6660            // The listener should create a pending socket.
6661            assert_matches!(
6662                &server.get().deref().socket_state,
6663                TcpSocketStateInner::Bound(BoundSocketState::Listener((
6664                    MaybeListener::Listener(Listener {
6665                        accept_queue,
6666                        ..
6667                    }), ..))) => {
6668                    assert_eq!(accept_queue.ready_len(), 0);
6669                    assert_eq!(accept_queue.pending_len(), 1);
6670                }
6671            );
6672            // The handshake is not done, calling accept here should not succeed.
6673            net.with_context(REMOTE, |ctx| {
6674                let mut api = ctx.tcp_api::<I>();
6675                assert_matches!(api.accept(&server), Err(AcceptError::WouldBlock));
6676            });
6677        }
6678
6679        // Step the test network until the handshake is done.
6680        net.run_until_idle_with(&mut maybe_drop_frame);
6681        let (accepted, addr, accepted_ends) = net.with_context(REMOTE, |ctx| {
6682            ctx.tcp_api::<I>().accept(&server).expect("failed to accept")
6683        });
6684        if let Some(port) = client_port {
6685            assert_eq!(
6686                addr,
6687                SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip), port: port }
6688            );
6689        } else {
6690            assert_eq!(addr.ip, ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip));
6691        }
6692
6693        net.with_context(LOCAL, |ctx| {
6694            let mut api = ctx.tcp_api::<I>();
6695            assert_eq!(
6696                api.connect(
6697                    &client,
6698                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)),
6699                    server_port,
6700                ),
6701                Ok(())
6702            );
6703        });
6704
6705        let assert_connected = |conn_id: &TcpSocketId<I, _, _>| {
6706            assert_matches!(
6707            &conn_id.get().deref().socket_state,
6708            TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
6709                    let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
6710                    assert_matches!(
6711                        conn,
6712                        Connection {
6713                            accept_queue: None,
6714                            state: State::Established(_),
6715                            ip_sock: _,
6716                            defunct: false,
6717                            soft_error: None,
6718                            handshake_status: HandshakeStatus::Completed { reported: true },
6719                        }
6720                    );
6721                })
6722        };
6723
6724        assert_connected(&client);
6725        assert_connected(&accepted);
6726
6727        let ClientBuffers { send: client_snd_end, receive: client_rcv_end } =
6728            client_ends.0.as_ref().lock().take().unwrap();
6729        let ClientBuffers { send: accepted_snd_end, receive: accepted_rcv_end } = accepted_ends;
6730
6731        if send_test_data {
6732            for snd_end in [client_snd_end.clone(), accepted_snd_end] {
6733                snd_end.lock().extend_from_slice(b"Hello");
6734            }
6735
6736            for (c, id) in [(LOCAL, &client), (REMOTE, &accepted)] {
6737                net.with_context(c, |ctx| ctx.tcp_api::<I>().do_send(id))
6738            }
6739            net.run_until_idle_with(&mut maybe_drop_frame);
6740
6741            for rcv_end in [client_rcv_end, accepted_rcv_end] {
6742                assert_eq!(
6743                    rcv_end.lock().read_with(|avail| {
6744                        let avail = avail.concat();
6745                        assert_eq!(avail, b"Hello");
6746                        avail.len()
6747                    }),
6748                    5
6749                );
6750            }
6751        }
6752
6753        // Check the listener is in correct state.
6754        assert_matches!(
6755            &server.get().deref().socket_state,
6756            TcpSocketStateInner::Bound(BoundSocketState::Listener((MaybeListener::Listener(l),..))) => {
6757                assert_eq!(l, &Listener::new(
6758                    backlog,
6759                    BufferSizes::default(),
6760                    Default::default()
6761                ));
6762            }
6763        );
6764
6765        net.with_context(REMOTE, |ctx| {
6766            let mut api = ctx.tcp_api::<I>();
6767            assert_eq!(api.shutdown(&server, ShutdownType::Receive), Ok(false));
6768            api.close(server);
6769        });
6770
6771        (net, client, client_snd_end, accepted)
6772    }
6773
6774    #[test]
6775    fn test_socket_addr_display() {
6776        assert_eq!(
6777            format!(
6778                "{}",
6779                SocketAddr {
6780                    ip: maybe_zoned(
6781                        SpecifiedAddr::new(Ipv4Addr::new([192, 168, 0, 1]))
6782                            .expect("failed to create specified addr"),
6783                        &None::<usize>,
6784                    ),
6785                    port: NonZeroU16::new(1024).expect("failed to create NonZeroU16"),
6786                }
6787            ),
6788            String::from("192.168.0.1:1024"),
6789        );
6790        assert_eq!(
6791            format!(
6792                "{}",
6793                SocketAddr {
6794                    ip: maybe_zoned(
6795                        SpecifiedAddr::new(Ipv6Addr::new([0x2001, 0xDB8, 0, 0, 0, 0, 0, 1]))
6796                            .expect("failed to create specified addr"),
6797                        &None::<usize>,
6798                    ),
6799                    port: NonZeroU16::new(1024).expect("failed to create NonZeroU16"),
6800                }
6801            ),
6802            String::from("[2001:db8::1]:1024")
6803        );
6804        assert_eq!(
6805            format!(
6806                "{}",
6807                SocketAddr {
6808                    ip: maybe_zoned(
6809                        SpecifiedAddr::new(Ipv6Addr::new([0xFE80, 0, 0, 0, 0, 0, 0, 1]))
6810                            .expect("failed to create specified addr"),
6811                        &Some(42),
6812                    ),
6813                    port: NonZeroU16::new(1024).expect("failed to create NonZeroU16"),
6814                }
6815            ),
6816            String::from("[fe80::1%42]:1024")
6817        );
6818    }
6819
6820    #[ip_test(I)]
6821    #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
6822    #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
6823    #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
6824    #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, I::UNSPECIFIED_ADDRESS)]
6825    #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
6826    #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: false, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
6827    #[test_case(BindConfig { client_port: None, server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
6828    #[test_case(BindConfig { client_port: Some(PORT_1), server_port: PORT_1, client_reuse_addr: true, send_test_data: true }, *<I as TestIpExt>::TEST_ADDRS.remote_ip)]
6829    fn bind_listen_connect_accept<I: TcpTestIpExt>(bind_config: BindConfig, listen_addr: I::Addr)
6830    where
6831        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
6832                I,
6833                TcpBindingsCtx<FakeDeviceId>,
6834                SingleStackConverter = I::SingleStackConverter,
6835                DualStackConverter = I::DualStackConverter,
6836            >,
6837    {
6838        set_logger_for_test();
6839        let (mut net, client, _client_snd_end, accepted) =
6840            bind_listen_connect_accept_inner::<I>(listen_addr, bind_config, 0, 0.0);
6841
6842        let mut assert_counters =
6843            |context_name: &'static str,
6844             socket: &TcpSocketId<I, _, _>,
6845             expected: CounterExpectations,
6846             expected_without_socket: CounterExpectationsWithoutSocket,
6847             expected_per_socket: CounterExpectations| {
6848                net.with_context(context_name, |ctx| {
6849                    let counters =
6850                        CounterContext::<TcpCountersWithSocket<I>>::counters(&ctx.core_ctx);
6851                    let counters_without_socket =
6852                        CounterContext::<TcpCountersWithoutSocket<I>>::counters(&ctx.core_ctx);
6853                    let counters_per_socket = ctx.core_ctx.per_resource_counters(socket);
6854                    assert_eq!(expected, counters.as_ref().cast(), "{context_name}");
6855                    assert_eq!(
6856                        expected_without_socket,
6857                        counters_without_socket.as_ref().cast(),
6858                        "{context_name}"
6859                    );
6860                    assert_eq!(
6861                        expected_per_socket,
6862                        counters_per_socket.as_ref().cast(),
6863                        "{context_name}"
6864                    )
6865                })
6866            };
6867
6868        // Communication done by `bind_listen_connect_accept_inner`:
6869        //   LOCAL -> REMOTE: SYN to initiate the connection.
6870        //   LOCAL <- REMOTE: ACK the connection.
6871        //   LOCAL -> REMOTE: ACK the ACK.
6872        //   LOCAL -> REMOTE: Send "hello".
6873        //   LOCAL <- REMOTE: ACK "hello".
6874        //   LOCAL <- REMOTE: Send "hello".
6875        //   LOCAL -> REMOTE: ACK "hello".
6876        let local_with_socket_expects = || CounterExpectations {
6877            segments_sent: 4,
6878            received_segments_dispatched: 3,
6879            active_connection_openings: 1,
6880            syns_sent: 1,
6881            syns_received: 1,
6882            ..Default::default()
6883        };
6884        assert_counters(
6885            LOCAL,
6886            &client,
6887            local_with_socket_expects(),
6888            CounterExpectationsWithoutSocket { valid_segments_received: 3, ..Default::default() },
6889            // Note: The local side only has 1 socket, so the stack-wide and
6890            // per-socket expectations are identical.
6891            local_with_socket_expects(),
6892        );
6893
6894        assert_counters(
6895            REMOTE,
6896            &accepted,
6897            CounterExpectations {
6898                segments_sent: 3,
6899                received_segments_dispatched: 4,
6900                passive_connection_openings: 1,
6901                syns_sent: 1,
6902                syns_received: 1,
6903                ..Default::default()
6904            },
6905            CounterExpectationsWithoutSocket { valid_segments_received: 4, ..Default::default() },
6906            // Note: The remote side has a listener socket and the accepted
6907            // socket. The stack-wide counters are higher than the accepted
6908            // socket's counters, because some events are attributed to the
6909            // listener.
6910            CounterExpectations {
6911                segments_sent: 2,
6912                received_segments_dispatched: 3,
6913                ..Default::default()
6914            },
6915        );
6916    }
6917
6918    #[ip_test(I)]
6919    #[test_case(*<I as TestIpExt>::TEST_ADDRS.local_ip; "same addr")]
6920    #[test_case(I::UNSPECIFIED_ADDRESS; "any addr")]
6921    fn bind_conflict<I: TcpTestIpExt>(conflict_addr: I::Addr)
6922    where
6923        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
6924            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
6925    {
6926        set_logger_for_test();
6927        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
6928            I::TEST_ADDRS.local_ip,
6929            I::TEST_ADDRS.local_ip,
6930        ));
6931        let mut api = ctx.tcp_api::<I>();
6932        let s1 = api.create(Default::default());
6933        let s2 = api.create(Default::default());
6934
6935        api.bind(&s1, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
6936            .expect("first bind should succeed");
6937        assert_matches!(
6938            api.bind(&s2, SpecifiedAddr::new(conflict_addr).map(ZonedAddr::Unzoned), Some(PORT_1)),
6939            Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
6940        );
6941        api.bind(&s2, SpecifiedAddr::new(conflict_addr).map(ZonedAddr::Unzoned), Some(PORT_2))
6942            .expect("able to rebind to a free address");
6943    }
6944
6945    #[ip_test(I)]
6946    #[test_case(NonZeroU16::new(u16::MAX).unwrap(), Ok(NonZeroU16::new(u16::MAX).unwrap()); "ephemeral available")]
6947    #[test_case(NonZeroU16::new(100).unwrap(), Err(LocalAddressError::FailedToAllocateLocalPort);
6948                "no ephemeral available")]
6949    fn bind_picked_port_all_others_taken<I: TcpTestIpExt>(
6950        available_port: NonZeroU16,
6951        expected_result: Result<NonZeroU16, LocalAddressError>,
6952    ) where
6953        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
6954            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
6955    {
6956        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
6957            I::TEST_ADDRS.local_ip,
6958            I::TEST_ADDRS.local_ip,
6959        ));
6960        let mut api = ctx.tcp_api::<I>();
6961        for port in 1..=u16::MAX {
6962            let port = NonZeroU16::new(port).unwrap();
6963            if port == available_port {
6964                continue;
6965            }
6966            let socket = api.create(Default::default());
6967
6968            api.bind(&socket, None, Some(port)).expect("uncontested bind");
6969            api.listen(&socket, NonZeroUsize::new(1).unwrap()).expect("can listen");
6970        }
6971
6972        // Now that all but the LOCAL_PORT are occupied, ask the stack to
6973        // select a port.
6974        let socket = api.create(Default::default());
6975        let result = api.bind(&socket, None, None).map(|()| {
6976            assert_matches!(
6977                api.get_info(&socket),
6978                SocketInfo::Bound(bound) => bound.port
6979            )
6980        });
6981        assert_eq!(result, expected_result.map_err(From::from));
6982
6983        // Now close the socket and try a connect call to ourselves on the
6984        // available port. Self-connection protection should always prevent us
6985        // from doing that even when the port is in the ephemeral range.
6986        api.close(socket);
6987        let socket = api.create(Default::default());
6988        let result =
6989            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), available_port);
6990        assert_eq!(result, Err(ConnectError::NoPort));
6991    }
6992
6993    #[ip_test(I)]
6994    fn bind_to_non_existent_address<I: TcpTestIpExt>()
6995    where
6996        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
6997            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
6998    {
6999        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7000            I::TEST_ADDRS.local_ip,
7001            I::TEST_ADDRS.remote_ip,
7002        ));
7003        let mut api = ctx.tcp_api::<I>();
7004        let unbound = api.create(Default::default());
7005        assert_matches!(
7006            api.bind(&unbound, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), None),
7007            Err(BindError::LocalAddressError(LocalAddressError::AddressMismatch))
7008        );
7009
7010        assert_matches!(unbound.get().deref().socket_state, TcpSocketStateInner::Unbound(_));
7011    }
7012
7013    #[test]
7014    fn bind_addr_requires_zone() {
7015        let local_ip = LinkLocalAddr::new(net_ip_v6!("fe80::1")).unwrap().into_specified();
7016
7017        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(
7018            Ipv6::TEST_ADDRS.local_ip,
7019            Ipv6::TEST_ADDRS.remote_ip,
7020        ));
7021        let mut api = ctx.tcp_api::<Ipv6>();
7022        let unbound = api.create(Default::default());
7023        assert_matches!(
7024            api.bind(&unbound, Some(ZonedAddr::Unzoned(local_ip)), None),
7025            Err(BindError::LocalAddressError(LocalAddressError::Zone(
7026                ZonedAddressError::RequiredZoneNotProvided
7027            )))
7028        );
7029
7030        assert_matches!(unbound.get().deref().socket_state, TcpSocketStateInner::Unbound(_));
7031    }
7032
7033    #[test]
7034    fn connect_bound_requires_zone() {
7035        let ll_ip = LinkLocalAddr::new(net_ip_v6!("fe80::1")).unwrap().into_specified();
7036
7037        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(
7038            Ipv6::TEST_ADDRS.local_ip,
7039            Ipv6::TEST_ADDRS.remote_ip,
7040        ));
7041        let mut api = ctx.tcp_api::<Ipv6>();
7042        let socket = api.create(Default::default());
7043        api.bind(&socket, None, None).expect("bind succeeds");
7044        assert_matches!(
7045            api.connect(&socket, Some(ZonedAddr::Unzoned(ll_ip)), PORT_1,),
7046            Err(ConnectError::Zone(ZonedAddressError::RequiredZoneNotProvided))
7047        );
7048
7049        assert_matches!(socket.get().deref().socket_state, TcpSocketStateInner::Bound(_));
7050    }
7051
7052    // This is a regression test for https://fxbug.dev/361402347.
7053    #[ip_test(I)]
7054    fn bind_listen_on_same_port_different_addrs<I: TcpTestIpExt>()
7055    where
7056        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7057            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7058    {
7059        set_logger_for_test();
7060
7061        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7062            FakeDualStackIpSocketCtx::new(core::iter::once(FakeDeviceConfig {
7063                device: FakeDeviceId,
7064                local_ips: vec![I::TEST_ADDRS.local_ip, I::TEST_ADDRS.remote_ip],
7065                remote_ips: vec![],
7066            })),
7067        ));
7068        let mut api = ctx.tcp_api::<I>();
7069
7070        let s1 = api.create(Default::default());
7071        api.bind(&s1, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1)).unwrap();
7072        api.listen(&s1, NonZeroUsize::MIN).unwrap();
7073
7074        let s2 = api.create(Default::default());
7075        api.bind(&s2, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), Some(PORT_1)).unwrap();
7076        api.listen(&s2, NonZeroUsize::MIN).unwrap();
7077    }
7078
7079    #[ip_test(I)]
7080    #[test_case(None, None; "both any addr")]
7081    #[test_case(None, Some(<I as TestIpExt>::TEST_ADDRS.local_ip); "any then specified")]
7082    #[test_case(Some(<I as TestIpExt>::TEST_ADDRS.local_ip), None; "specified then any")]
7083    #[test_case(
7084        Some(<I as TestIpExt>::TEST_ADDRS.local_ip),
7085        Some(<I as TestIpExt>::TEST_ADDRS.local_ip);
7086        "both specified"
7087    )]
7088    fn cannot_listen_on_same_port_with_shadowed_address<I: TcpTestIpExt>(
7089        first: Option<SpecifiedAddr<I::Addr>>,
7090        second: Option<SpecifiedAddr<I::Addr>>,
7091    ) where
7092        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7093            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7094    {
7095        set_logger_for_test();
7096
7097        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7098            FakeDualStackIpSocketCtx::new(core::iter::once(FakeDeviceConfig {
7099                device: FakeDeviceId,
7100                local_ips: vec![I::TEST_ADDRS.local_ip],
7101                remote_ips: vec![],
7102            })),
7103        ));
7104        let mut api = ctx.tcp_api::<I>();
7105
7106        let s1 = api.create(Default::default());
7107        api.set_reuseaddr(&s1, true).unwrap();
7108        api.bind(&s1, first.map(ZonedAddr::Unzoned), Some(PORT_1)).unwrap();
7109
7110        let s2 = api.create(Default::default());
7111        api.set_reuseaddr(&s2, true).unwrap();
7112        api.bind(&s2, second.map(ZonedAddr::Unzoned), Some(PORT_1)).unwrap();
7113
7114        api.listen(&s1, NonZeroUsize::MIN).unwrap();
7115        assert_eq!(api.listen(&s2, NonZeroUsize::MIN), Err(ListenError::ListenerExists));
7116    }
7117
7118    #[test]
7119    fn connect_unbound_picks_link_local_source_addr() {
7120        set_logger_for_test();
7121        let client_ip = SpecifiedAddr::new(net_ip_v6!("fe80::1")).unwrap();
7122        let server_ip = SpecifiedAddr::new(net_ip_v6!("1:2:3:4::")).unwrap();
7123        let mut net = FakeTcpNetworkSpec::new_network(
7124            [
7125                (LOCAL, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(client_ip, server_ip))),
7126                (REMOTE, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(server_ip, client_ip))),
7127            ],
7128            |net, meta| {
7129                if net == LOCAL {
7130                    alloc::vec![(REMOTE, meta, None)]
7131                } else {
7132                    alloc::vec![(LOCAL, meta, None)]
7133                }
7134            },
7135        );
7136        const PORT: NonZeroU16 = NonZeroU16::new(100).unwrap();
7137        let client_connection = net.with_context(LOCAL, |ctx| {
7138            let mut api = ctx.tcp_api();
7139            let socket: TcpSocketId<Ipv6, _, _> = api.create(Default::default());
7140            api.connect(&socket, Some(ZonedAddr::Unzoned(server_ip)), PORT).expect("can connect");
7141            socket
7142        });
7143        net.with_context(REMOTE, |ctx| {
7144            let mut api = ctx.tcp_api::<Ipv6>();
7145            let socket = api.create(Default::default());
7146            api.bind(&socket, None, Some(PORT)).expect("failed to bind the client socket");
7147            let _listener = api.listen(&socket, NonZeroUsize::MIN).expect("can listen");
7148        });
7149
7150        // Advance until the connection is established.
7151        net.run_until_idle();
7152
7153        net.with_context(LOCAL, |ctx| {
7154            let mut api = ctx.tcp_api();
7155            assert_eq!(
7156                api.connect(&client_connection, Some(ZonedAddr::Unzoned(server_ip)), PORT),
7157                Ok(())
7158            );
7159
7160            let info = assert_matches!(
7161                api.get_info(&client_connection),
7162                SocketInfo::Connection(info) => info
7163            );
7164            // The local address picked for the connection is link-local, which
7165            // means the device for the connection must also be set (since the
7166            // address requires a zone).
7167            let (local_ip, remote_ip) = assert_matches!(
7168                info,
7169                ConnectionInfo {
7170                    local_addr: SocketAddr { ip: local_ip, port: _ },
7171                    remote_addr: SocketAddr { ip: remote_ip, port: PORT },
7172                    device: Some(FakeWeakDeviceId(FakeDeviceId))
7173                } => (local_ip, remote_ip)
7174            );
7175            assert_eq!(
7176                local_ip,
7177                ZonedAddr::Zoned(
7178                    AddrAndZone::new(client_ip, FakeWeakDeviceId(FakeDeviceId)).unwrap()
7179                )
7180            );
7181            assert_eq!(remote_ip, ZonedAddr::Unzoned(server_ip));
7182
7183            // Double-check that the bound device can't be changed after being set
7184            // implicitly.
7185            assert_matches!(
7186                api.set_device(&client_connection, None),
7187                Err(SetDeviceError::ZoneChange)
7188            );
7189        });
7190    }
7191
7192    #[test]
7193    fn accept_connect_picks_link_local_addr() {
7194        set_logger_for_test();
7195        let server_ip = SpecifiedAddr::new(net_ip_v6!("fe80::1")).unwrap();
7196        let client_ip = SpecifiedAddr::new(net_ip_v6!("1:2:3:4::")).unwrap();
7197        let mut net = FakeTcpNetworkSpec::new_network(
7198            [
7199                (LOCAL, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(server_ip, client_ip))),
7200                (REMOTE, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(client_ip, server_ip))),
7201            ],
7202            |net, meta| {
7203                if net == LOCAL {
7204                    alloc::vec![(REMOTE, meta, None)]
7205                } else {
7206                    alloc::vec![(LOCAL, meta, None)]
7207                }
7208            },
7209        );
7210        const PORT: NonZeroU16 = NonZeroU16::new(100).unwrap();
7211        let server_listener = net.with_context(LOCAL, |ctx| {
7212            let mut api = ctx.tcp_api::<Ipv6>();
7213            let socket: TcpSocketId<Ipv6, _, _> = api.create(Default::default());
7214            api.bind(&socket, None, Some(PORT)).expect("failed to bind the client socket");
7215            api.listen(&socket, NonZeroUsize::MIN).expect("can listen");
7216            socket
7217        });
7218        let client_connection = net.with_context(REMOTE, |ctx| {
7219            let mut api = ctx.tcp_api::<Ipv6>();
7220            let socket = api.create(Default::default());
7221            api.connect(
7222                &socket,
7223                Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, FakeDeviceId).unwrap())),
7224                PORT,
7225            )
7226            .expect("failed to open a connection");
7227            socket
7228        });
7229
7230        // Advance until the connection is established.
7231        net.run_until_idle();
7232
7233        net.with_context(LOCAL, |ctx| {
7234            let mut api = ctx.tcp_api();
7235            let (server_connection, _addr, _buffers) =
7236                api.accept(&server_listener).expect("connection is waiting");
7237
7238            let info = assert_matches!(
7239                api.get_info(&server_connection),
7240                SocketInfo::Connection(info) => info
7241            );
7242            // The local address picked for the connection is link-local, which
7243            // means the device for the connection must also be set (since the
7244            // address requires a zone).
7245            let (local_ip, remote_ip) = assert_matches!(
7246                info,
7247                ConnectionInfo {
7248                    local_addr: SocketAddr { ip: local_ip, port: PORT },
7249                    remote_addr: SocketAddr { ip: remote_ip, port: _ },
7250                    device: Some(FakeWeakDeviceId(FakeDeviceId))
7251                } => (local_ip, remote_ip)
7252            );
7253            assert_eq!(
7254                local_ip,
7255                ZonedAddr::Zoned(
7256                    AddrAndZone::new(server_ip, FakeWeakDeviceId(FakeDeviceId)).unwrap()
7257                )
7258            );
7259            assert_eq!(remote_ip, ZonedAddr::Unzoned(client_ip));
7260
7261            // Double-check that the bound device can't be changed after being set
7262            // implicitly.
7263            assert_matches!(
7264                api.set_device(&server_connection, None),
7265                Err(SetDeviceError::ZoneChange)
7266            );
7267        });
7268        net.with_context(REMOTE, |ctx| {
7269            assert_eq!(
7270                ctx.tcp_api().connect(
7271                    &client_connection,
7272                    Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, FakeDeviceId).unwrap())),
7273                    PORT,
7274                ),
7275                Ok(())
7276            );
7277        });
7278    }
7279
7280    // The test verifies that if client tries to connect to a closed port on
7281    // server, the connection is aborted and RST is received.
7282    #[ip_test(I)]
7283    fn connect_reset<I: TcpTestIpExt>()
7284    where
7285        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7286                I,
7287                TcpBindingsCtx<FakeDeviceId>,
7288                SingleStackConverter = I::SingleStackConverter,
7289                DualStackConverter = I::DualStackConverter,
7290            >,
7291    {
7292        set_logger_for_test();
7293        let mut net = new_test_net::<I>();
7294
7295        let client = net.with_context(LOCAL, |ctx| {
7296            let mut api = ctx.tcp_api::<I>();
7297            let conn = api.create(Default::default());
7298            api.bind(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
7299                .expect("failed to bind the client socket");
7300            api.connect(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
7301                .expect("failed to connect");
7302            conn
7303        });
7304
7305        // Step one time for SYN packet to be delivered.
7306        let _: StepResult = net.step();
7307        // Assert that we got a RST back.
7308        net.collect_frames();
7309        assert_matches!(
7310            &net.iter_pending_frames().collect::<Vec<_>>()[..],
7311            [InstantAndData(_instant, PendingFrameData {
7312                dst_context: _,
7313                meta,
7314                frame,
7315            })] => {
7316            let mut buffer = Buf::new(frame, ..);
7317            match I::VERSION {
7318                IpVersion::V4 => {
7319                    let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V4(v4) => v4);
7320                    let parsed = buffer.parse_with::<_, TcpSegment<_>>(
7321                        TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
7322                    ).expect("failed to parse");
7323                    assert!(parsed.rst())
7324                }
7325                IpVersion::V6 => {
7326                    let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V6(v6) => v6);
7327                    let parsed = buffer.parse_with::<_, TcpSegment<_>>(
7328                        TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
7329                    ).expect("failed to parse");
7330                    assert!(parsed.rst())
7331                }
7332            }
7333        });
7334
7335        net.run_until_idle();
7336        // Finally, the connection should be reset and bindings should have been
7337        // signaled.
7338        assert_matches!(
7339        &client.get().deref().socket_state,
7340        TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
7341                let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
7342                assert_matches!(
7343                    conn,
7344                    Connection {
7345                    accept_queue: None,
7346                    state: State::Closed(Closed {
7347                        reason: Some(ConnectionError::ConnectionRefused)
7348                    }),
7349                    ip_sock: _,
7350                    defunct: false,
7351                    soft_error: None,
7352                    handshake_status: HandshakeStatus::Aborted,
7353                    }
7354                );
7355            });
7356        net.with_context(LOCAL, |ctx| {
7357            assert_matches!(
7358                ctx.tcp_api().connect(
7359                    &client,
7360                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)),
7361                    PORT_1
7362                ),
7363                Err(ConnectError::Aborted)
7364            );
7365        });
7366    }
7367
7368    #[ip_test(I)]
7369    fn retransmission<I: TcpTestIpExt>()
7370    where
7371        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7372                I,
7373                TcpBindingsCtx<FakeDeviceId>,
7374                SingleStackConverter = I::SingleStackConverter,
7375                DualStackConverter = I::DualStackConverter,
7376            >,
7377    {
7378        set_logger_for_test();
7379        run_with_many_seeds(|seed| {
7380            let (_net, _client, _client_snd_end, _accepted) = bind_listen_connect_accept_inner::<I>(
7381                I::UNSPECIFIED_ADDRESS,
7382                BindConfig {
7383                    client_port: None,
7384                    server_port: PORT_1,
7385                    client_reuse_addr: false,
7386                    send_test_data: true,
7387                },
7388                seed,
7389                0.2,
7390            );
7391        });
7392    }
7393
7394    const LOCAL_PORT: NonZeroU16 = NonZeroU16::new(1845).unwrap();
7395
7396    #[ip_test(I)]
7397    fn listener_with_bound_device_conflict<I: TcpTestIpExt>()
7398    where
7399        TcpCoreCtx<MultipleDevicesId, TcpBindingsCtx<MultipleDevicesId>>:
7400            TcpContext<I, TcpBindingsCtx<MultipleDevicesId>>,
7401    {
7402        set_logger_for_test();
7403        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new_multiple_devices());
7404        let mut api = ctx.tcp_api::<I>();
7405        let sock_a = api.create(Default::default());
7406        assert_matches!(api.set_device(&sock_a, Some(MultipleDevicesId::A),), Ok(()));
7407        api.bind(&sock_a, None, Some(LOCAL_PORT)).expect("bind should succeed");
7408        api.listen(&sock_a, NonZeroUsize::new(10).unwrap()).expect("can listen");
7409
7410        let socket = api.create(Default::default());
7411        // Binding `socket` to the unspecified address should fail since the address
7412        // is shadowed by `sock_a`.
7413        assert_matches!(
7414            api.bind(&socket, None, Some(LOCAL_PORT)),
7415            Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
7416        );
7417
7418        // Once `socket` is bound to a different device, though, it no longer
7419        // conflicts.
7420        assert_matches!(api.set_device(&socket, Some(MultipleDevicesId::B),), Ok(()));
7421        api.bind(&socket, None, Some(LOCAL_PORT)).expect("no conflict");
7422    }
7423
7424    #[test_case(None)]
7425    #[test_case(Some(MultipleDevicesId::B); "other")]
7426    fn set_bound_device_listener_on_zoned_addr(set_device: Option<MultipleDevicesId>) {
7427        set_logger_for_test();
7428        let ll_addr = LinkLocalAddr::new(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network()).unwrap();
7429
7430        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7431            FakeDualStackIpSocketCtx::new(MultipleDevicesId::all().into_iter().map(|device| {
7432                FakeDeviceConfig {
7433                    device,
7434                    local_ips: vec![ll_addr.into_specified()],
7435                    remote_ips: vec![ll_addr.into_specified()],
7436                }
7437            })),
7438        ));
7439        let mut api = ctx.tcp_api::<Ipv6>();
7440        let socket = api.create(Default::default());
7441        api.bind(
7442            &socket,
7443            Some(ZonedAddr::Zoned(
7444                AddrAndZone::new(ll_addr.into_specified(), MultipleDevicesId::A).unwrap(),
7445            )),
7446            Some(LOCAL_PORT),
7447        )
7448        .expect("bind should succeed");
7449
7450        assert_matches!(api.set_device(&socket, set_device), Err(SetDeviceError::ZoneChange));
7451    }
7452
7453    #[test_case(None)]
7454    #[test_case(Some(MultipleDevicesId::B); "other")]
7455    fn set_bound_device_connected_to_zoned_addr(set_device: Option<MultipleDevicesId>) {
7456        set_logger_for_test();
7457        let ll_addr = LinkLocalAddr::new(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network()).unwrap();
7458
7459        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
7460            FakeDualStackIpSocketCtx::new(MultipleDevicesId::all().into_iter().map(|device| {
7461                FakeDeviceConfig {
7462                    device,
7463                    local_ips: vec![ll_addr.into_specified()],
7464                    remote_ips: vec![ll_addr.into_specified()],
7465                }
7466            })),
7467        ));
7468        let mut api = ctx.tcp_api::<Ipv6>();
7469        let socket = api.create(Default::default());
7470        api.connect(
7471            &socket,
7472            Some(ZonedAddr::Zoned(
7473                AddrAndZone::new(ll_addr.into_specified(), MultipleDevicesId::A).unwrap(),
7474            )),
7475            LOCAL_PORT,
7476        )
7477        .expect("connect should succeed");
7478
7479        assert_matches!(api.set_device(&socket, set_device), Err(SetDeviceError::ZoneChange));
7480    }
7481
7482    // Regression test for https://fxbug.dev/388656903.
7483    #[ip_test(I)]
7484    fn set_bound_to_device_after_connect_fails<I: TcpTestIpExt>()
7485    where
7486        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7487            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7488    {
7489        set_logger_for_test();
7490        let mut net = new_test_net::<I>();
7491        let socket = net.with_context(LOCAL, |ctx| {
7492            let mut api = ctx.tcp_api::<I>();
7493            let socket = api.create(Default::default());
7494            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
7495                .expect("bind should succeed");
7496            socket
7497        });
7498
7499        net.run_until_idle();
7500
7501        net.with_context(LOCAL, |ctx| {
7502            let mut api = ctx.tcp_api::<I>();
7503            assert_matches!(api.set_device(&socket, Some(FakeDeviceId)), Ok(()));
7504            let ConnectionInfo { local_addr: _, remote_addr, device } =
7505                assert_matches!(api.get_info(&socket), SocketInfo::Connection(c) => c);
7506            assert_eq!(
7507                remote_addr,
7508                SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip), port: PORT_1 }
7509            );
7510            assert_eq!(device, Some(FakeWeakDeviceId(FakeDeviceId)));
7511            api.close(socket);
7512        });
7513    }
7514
7515    #[ip_test(I)]
7516    #[test_case(*<I as TestIpExt>::TEST_ADDRS.local_ip, true; "specified bound")]
7517    #[test_case(I::UNSPECIFIED_ADDRESS, true; "unspecified bound")]
7518    #[test_case(*<I as TestIpExt>::TEST_ADDRS.local_ip, false; "specified listener")]
7519    #[test_case(I::UNSPECIFIED_ADDRESS, false; "unspecified listener")]
7520    fn bound_socket_info<I: TcpTestIpExt>(ip_addr: I::Addr, listen: bool)
7521    where
7522        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7523            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7524    {
7525        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7526            I::TEST_ADDRS.local_ip,
7527            I::TEST_ADDRS.remote_ip,
7528        ));
7529        let mut api = ctx.tcp_api::<I>();
7530        let socket = api.create(Default::default());
7531
7532        let (addr, port) = (SpecifiedAddr::new(ip_addr).map(ZonedAddr::Unzoned), PORT_1);
7533
7534        api.bind(&socket, addr, Some(port)).expect("bind should succeed");
7535        if listen {
7536            api.listen(&socket, NonZeroUsize::new(25).unwrap()).expect("can listen");
7537        }
7538        let info = api.get_info(&socket);
7539        assert_eq!(
7540            info,
7541            SocketInfo::Bound(BoundInfo {
7542                addr: addr.map(|a| a.map_zone(FakeWeakDeviceId)),
7543                port,
7544                device: None
7545            })
7546        );
7547    }
7548
7549    #[ip_test(I)]
7550    fn connection_info<I: TcpTestIpExt>()
7551    where
7552        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7553            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7554    {
7555        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7556            I::TEST_ADDRS.local_ip,
7557            I::TEST_ADDRS.remote_ip,
7558        ));
7559        let mut api = ctx.tcp_api::<I>();
7560        let local = SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip), port: PORT_1 };
7561        let remote = SocketAddr { ip: ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip), port: PORT_2 };
7562
7563        let socket = api.create(Default::default());
7564        api.bind(&socket, Some(local.ip), Some(local.port)).expect("bind should succeed");
7565
7566        api.connect(&socket, Some(remote.ip), remote.port).expect("connect should succeed");
7567
7568        assert_eq!(
7569            api.get_info(&socket),
7570            SocketInfo::Connection(ConnectionInfo {
7571                local_addr: local.map_zone(FakeWeakDeviceId),
7572                remote_addr: remote.map_zone(FakeWeakDeviceId),
7573                device: None,
7574            }),
7575        );
7576    }
7577
7578    #[test_case(Ipv6::get_multicast_addr(1).into(), PhantomData::<Ipv6>)]
7579    #[test_case(Ipv4::get_multicast_addr(1).into(), PhantomData::<Ipv4>)]
7580    #[test_case(Ipv4::LIMITED_BROADCAST_ADDRESS, PhantomData::<Ipv4>)]
7581    fn non_unicast_ip_bind<I>(local_ip: SpecifiedAddr<I::Addr>, _ip: PhantomData<I>)
7582    where
7583        I: TcpTestIpExt + Ip,
7584        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7585            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7586    {
7587        let mut ctx =
7588            TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(local_ip, I::TEST_ADDRS.remote_ip));
7589        let mut api = ctx.tcp_api::<I>();
7590        let local = SocketAddr { ip: ZonedAddr::Unzoned(local_ip), port: PORT_1 };
7591        let socket = api.create(Default::default());
7592
7593        assert_eq!(
7594            api.bind(&socket, Some(local.ip), Some(local.port))
7595                .expect_err("bind should fail for non-unicast address"),
7596            BindError::LocalAddressError(LocalAddressError::CannotBindToAddress)
7597        );
7598    }
7599
7600    #[test_case(Ipv6::get_multicast_addr(1).into(), PhantomData::<Ipv6>)]
7601    #[test_case(Ipv4::get_multicast_addr(1).into(), PhantomData::<Ipv4>)]
7602    #[test_case(Ipv4::LIMITED_BROADCAST_ADDRESS, PhantomData::<Ipv4>)]
7603    fn non_unicast_ip_peer<I>(remote_ip: SpecifiedAddr<I::Addr>, _ip: PhantomData<I>)
7604    where
7605        I: TcpTestIpExt + Ip,
7606        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7607            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7608    {
7609        let mut ctx =
7610            TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(I::TEST_ADDRS.local_ip, remote_ip));
7611        let mut api = ctx.tcp_api::<I>();
7612        let remote = SocketAddr { ip: ZonedAddr::Unzoned(remote_ip), port: PORT_2 };
7613        let socket = api.create(Default::default());
7614
7615        assert_eq!(
7616            api.connect(&socket, Some(remote.ip), remote.port)
7617                .expect_err("connect should fail for non-unicast peer"),
7618            ConnectError::NoRoute
7619        );
7620    }
7621
7622    #[test_case(true; "any")]
7623    #[test_case(false; "link local")]
7624    fn accepted_connection_info_zone(listen_any: bool) {
7625        set_logger_for_test();
7626        let client_ip = SpecifiedAddr::new(net_ip_v6!("fe80::1")).unwrap();
7627        let server_ip = SpecifiedAddr::new(net_ip_v6!("fe80::2")).unwrap();
7628        let mut net = FakeTcpNetworkSpec::new_network(
7629            [
7630                (LOCAL, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(server_ip, client_ip))),
7631                (REMOTE, TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(client_ip, server_ip))),
7632            ],
7633            move |net, meta: DualStackSendIpPacketMeta<_>| {
7634                if net == LOCAL {
7635                    alloc::vec![(REMOTE, meta, None)]
7636                } else {
7637                    alloc::vec![(LOCAL, meta, None)]
7638                }
7639            },
7640        );
7641
7642        let local_server = net.with_context(LOCAL, |ctx| {
7643            let mut api = ctx.tcp_api::<Ipv6>();
7644            let socket = api.create(Default::default());
7645            let device = FakeDeviceId;
7646            let bind_addr = match listen_any {
7647                true => None,
7648                false => Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, device).unwrap())),
7649            };
7650
7651            api.bind(&socket, bind_addr, Some(PORT_1)).expect("failed to bind the client socket");
7652            api.listen(&socket, NonZeroUsize::new(1).unwrap()).expect("can listen");
7653            socket
7654        });
7655
7656        let _remote_client = net.with_context(REMOTE, |ctx| {
7657            let mut api = ctx.tcp_api::<Ipv6>();
7658            let socket = api.create(Default::default());
7659            let device = FakeDeviceId;
7660            api.connect(
7661                &socket,
7662                Some(ZonedAddr::Zoned(AddrAndZone::new(server_ip, device).unwrap())),
7663                PORT_1,
7664            )
7665            .expect("failed to connect");
7666            socket
7667        });
7668
7669        net.run_until_idle();
7670
7671        let ConnectionInfo { remote_addr, local_addr, device } = net.with_context(LOCAL, |ctx| {
7672            let mut api = ctx.tcp_api();
7673            let (server_conn, _addr, _buffers) =
7674                api.accept(&local_server).expect("connection is available");
7675            assert_matches!(
7676                api.get_info(&server_conn),
7677                SocketInfo::Connection(info) => info
7678            )
7679        });
7680
7681        let device = assert_matches!(device, Some(device) => device);
7682        assert_eq!(
7683            local_addr,
7684            SocketAddr {
7685                ip: ZonedAddr::Zoned(AddrAndZone::new(server_ip, device).unwrap()),
7686                port: PORT_1
7687            }
7688        );
7689        let SocketAddr { ip: remote_ip, port: _ } = remote_addr;
7690        assert_eq!(remote_ip, ZonedAddr::Zoned(AddrAndZone::new(client_ip, device).unwrap()));
7691    }
7692
7693    #[test]
7694    fn bound_connection_info_zoned_addrs() {
7695        let local_ip = LinkLocalAddr::new(net_ip_v6!("fe80::1")).unwrap().into_specified();
7696        let remote_ip = LinkLocalAddr::new(net_ip_v6!("fe80::2")).unwrap().into_specified();
7697        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<Ipv6>(local_ip, remote_ip));
7698
7699        let local_addr = SocketAddr {
7700            ip: ZonedAddr::Zoned(AddrAndZone::new(local_ip, FakeDeviceId).unwrap()),
7701            port: PORT_1,
7702        };
7703        let remote_addr = SocketAddr {
7704            ip: ZonedAddr::Zoned(AddrAndZone::new(remote_ip, FakeDeviceId).unwrap()),
7705            port: PORT_2,
7706        };
7707        let mut api = ctx.tcp_api::<Ipv6>();
7708
7709        let socket = api.create(Default::default());
7710        api.bind(&socket, Some(local_addr.ip), Some(local_addr.port)).expect("bind should succeed");
7711
7712        assert_eq!(
7713            api.get_info(&socket),
7714            SocketInfo::Bound(BoundInfo {
7715                addr: Some(local_addr.ip.map_zone(FakeWeakDeviceId)),
7716                port: local_addr.port,
7717                device: Some(FakeWeakDeviceId(FakeDeviceId))
7718            })
7719        );
7720
7721        api.connect(&socket, Some(remote_addr.ip), remote_addr.port)
7722            .expect("connect should succeed");
7723
7724        assert_eq!(
7725            api.get_info(&socket),
7726            SocketInfo::Connection(ConnectionInfo {
7727                local_addr: local_addr.map_zone(FakeWeakDeviceId),
7728                remote_addr: remote_addr.map_zone(FakeWeakDeviceId),
7729                device: Some(FakeWeakDeviceId(FakeDeviceId))
7730            })
7731        );
7732    }
7733
7734    #[ip_test(I)]
7735    // Assuming instant delivery of segments:
7736    // - If peer calls close, then the timeout we need to wait is in
7737    // TIME_WAIT, which is 2MSL.
7738    #[test_case(true, 2 * MSL; "peer calls close")]
7739    // - If not, we will be in the FIN_WAIT2 state and waiting for its
7740    // timeout.
7741    #[test_case(false, DEFAULT_FIN_WAIT2_TIMEOUT; "peer doesn't call close")]
7742    fn connection_close_peer_calls_close<I: TcpTestIpExt>(
7743        peer_calls_close: bool,
7744        expected_time_to_close: Duration,
7745    ) where
7746        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7747                I,
7748                TcpBindingsCtx<FakeDeviceId>,
7749                SingleStackConverter = I::SingleStackConverter,
7750                DualStackConverter = I::DualStackConverter,
7751            >,
7752    {
7753        set_logger_for_test();
7754        let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
7755            I::UNSPECIFIED_ADDRESS,
7756            BindConfig {
7757                client_port: None,
7758                server_port: PORT_1,
7759                client_reuse_addr: false,
7760                send_test_data: false,
7761            },
7762            0,
7763            0.0,
7764        );
7765
7766        let weak_local = local.downgrade();
7767        let close_called = net.with_context(LOCAL, |ctx| {
7768            ctx.tcp_api().close(local);
7769            ctx.bindings_ctx.now()
7770        });
7771
7772        while {
7773            assert!(!net.step().is_idle());
7774            let is_fin_wait_2 = {
7775                let local = weak_local.upgrade().unwrap();
7776                let state = local.get();
7777                let state = assert_matches!(
7778                    &state.deref().socket_state,
7779                    TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
7780                    let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
7781                    assert_matches!(
7782                        conn,
7783                        Connection {
7784                            state,
7785                            ..
7786                        } => state
7787                    )
7788                }
7789                );
7790                matches!(state, State::FinWait2(_))
7791            };
7792            !is_fin_wait_2
7793        } {}
7794
7795        let weak_remote = remote.downgrade();
7796        if peer_calls_close {
7797            net.with_context(REMOTE, |ctx| {
7798                ctx.tcp_api().close(remote);
7799            });
7800        }
7801
7802        net.run_until_idle();
7803
7804        net.with_context(LOCAL, |TcpCtx { core_ctx: _, bindings_ctx }| {
7805            assert_eq!(
7806                bindings_ctx.now().checked_duration_since(close_called).unwrap(),
7807                expected_time_to_close
7808            );
7809            assert_eq!(weak_local.upgrade(), None);
7810        });
7811        if peer_calls_close {
7812            assert_eq!(weak_remote.upgrade(), None);
7813        }
7814    }
7815
7816    #[ip_test(I)]
7817    fn connection_shutdown_then_close_peer_doesnt_call_close<I: TcpTestIpExt>()
7818    where
7819        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7820                I,
7821                TcpBindingsCtx<FakeDeviceId>,
7822                SingleStackConverter = I::SingleStackConverter,
7823                DualStackConverter = I::DualStackConverter,
7824            >,
7825    {
7826        set_logger_for_test();
7827        let (mut net, local, _local_snd_end, _remote) = bind_listen_connect_accept_inner::<I>(
7828            I::UNSPECIFIED_ADDRESS,
7829            BindConfig {
7830                client_port: None,
7831                server_port: PORT_1,
7832                client_reuse_addr: false,
7833                send_test_data: false,
7834            },
7835            0,
7836            0.0,
7837        );
7838        net.with_context(LOCAL, |ctx| {
7839            assert_eq!(ctx.tcp_api().shutdown(&local, ShutdownType::Send), Ok(true));
7840        });
7841        loop {
7842            assert!(!net.step().is_idle());
7843            let is_fin_wait_2 = {
7844                let state = local.get();
7845                let state = assert_matches!(
7846                &state.deref().socket_state,
7847                TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
7848                let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
7849                assert_matches!(
7850                    conn,
7851                    Connection {
7852                        state, ..
7853                    } => state
7854                )});
7855                matches!(state, State::FinWait2(_))
7856            };
7857            if is_fin_wait_2 {
7858                break;
7859            }
7860        }
7861
7862        let weak_local = local.downgrade();
7863        net.with_context(LOCAL, |ctx| {
7864            ctx.tcp_api().close(local);
7865        });
7866        net.run_until_idle();
7867        assert_eq!(weak_local.upgrade(), None);
7868    }
7869
7870    #[ip_test(I)]
7871    fn connection_shutdown_then_close<I: TcpTestIpExt>()
7872    where
7873        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7874                I,
7875                TcpBindingsCtx<FakeDeviceId>,
7876                SingleStackConverter = I::SingleStackConverter,
7877                DualStackConverter = I::DualStackConverter,
7878            >,
7879    {
7880        set_logger_for_test();
7881        let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
7882            I::UNSPECIFIED_ADDRESS,
7883            BindConfig {
7884                client_port: None,
7885                server_port: PORT_1,
7886                client_reuse_addr: false,
7887                send_test_data: false,
7888            },
7889            0,
7890            0.0,
7891        );
7892
7893        for (name, id) in [(LOCAL, &local), (REMOTE, &remote)] {
7894            net.with_context(name, |ctx| {
7895                let mut api = ctx.tcp_api();
7896                assert_eq!(
7897                    api.shutdown(id,ShutdownType::Send),
7898                    Ok(true)
7899                );
7900                assert_matches!(
7901                    &id.get().deref().socket_state,
7902                    TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
7903                    let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
7904                    assert_matches!(
7905                        conn,
7906                        Connection {
7907                            state: State::FinWait1(_),
7908                            ..
7909                        }
7910                    );
7911                });
7912                assert_eq!(
7913                    api.shutdown(id,ShutdownType::Send),
7914                    Ok(true)
7915                );
7916            });
7917        }
7918        net.run_until_idle();
7919        for (name, id) in [(LOCAL, local), (REMOTE, remote)] {
7920            net.with_context(name, |ctx| {
7921                assert_matches!(
7922                    &id.get().deref().socket_state,
7923                    TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
7924                    let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
7925                    assert_matches!(
7926                        conn,
7927                        Connection {
7928                            state: State::Closed(_),
7929                            ..
7930                        }
7931                    );
7932                });
7933                let weak_id = id.downgrade();
7934                ctx.tcp_api().close(id);
7935                assert_eq!(weak_id.upgrade(), None)
7936            });
7937        }
7938    }
7939
7940    #[ip_test(I)]
7941    fn remove_unbound<I: TcpTestIpExt>()
7942    where
7943        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7944            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7945    {
7946        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7947            I::TEST_ADDRS.local_ip,
7948            I::TEST_ADDRS.remote_ip,
7949        ));
7950        let mut api = ctx.tcp_api::<I>();
7951        let unbound = api.create(Default::default());
7952        let weak_unbound = unbound.downgrade();
7953        api.close(unbound);
7954        assert_eq!(weak_unbound.upgrade(), None);
7955    }
7956
7957    #[ip_test(I)]
7958    fn remove_bound<I: TcpTestIpExt>()
7959    where
7960        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
7961            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
7962    {
7963        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
7964            I::TEST_ADDRS.local_ip,
7965            I::TEST_ADDRS.remote_ip,
7966        ));
7967        let mut api = ctx.tcp_api::<I>();
7968        let socket = api.create(Default::default());
7969        api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), None)
7970            .expect("bind should succeed");
7971        let weak_socket = socket.downgrade();
7972        api.close(socket);
7973        assert_eq!(weak_socket.upgrade(), None);
7974    }
7975
7976    #[ip_test(I)]
7977    fn shutdown_listener<I: TcpTestIpExt>()
7978    where
7979        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
7980                I,
7981                TcpBindingsCtx<FakeDeviceId>,
7982                SingleStackConverter = I::SingleStackConverter,
7983                DualStackConverter = I::DualStackConverter,
7984            >,
7985    {
7986        set_logger_for_test();
7987        let mut net = new_test_net::<I>();
7988        let local_listener = net.with_context(LOCAL, |ctx| {
7989            let mut api = ctx.tcp_api::<I>();
7990            let socket = api.create(Default::default());
7991            api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
7992                .expect("bind should succeed");
7993            api.listen(&socket, NonZeroUsize::new(5).unwrap()).expect("can listen");
7994            socket
7995        });
7996
7997        let remote_connection = net.with_context(REMOTE, |ctx| {
7998            let mut api = ctx.tcp_api::<I>();
7999            let socket = api.create(Default::default());
8000            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8001                .expect("connect should succeed");
8002            socket
8003        });
8004
8005        // After the following step, we should have one established connection
8006        // in the listener's accept queue, which ought to be aborted during
8007        // shutdown.
8008        net.run_until_idle();
8009
8010        // The incoming connection was signaled, and the remote end was notified
8011        // of connection establishment.
8012        net.with_context(REMOTE, |ctx| {
8013            assert_eq!(
8014                ctx.tcp_api().connect(
8015                    &remote_connection,
8016                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8017                    PORT_1
8018                ),
8019                Ok(())
8020            );
8021        });
8022
8023        // Create a second half-open connection so that we have one entry in the
8024        // pending queue.
8025        let second_connection = net.with_context(REMOTE, |ctx| {
8026            let mut api = ctx.tcp_api::<I>();
8027            let socket = api.create(Default::default());
8028            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8029                .expect("connect should succeed");
8030            socket
8031        });
8032
8033        let _: StepResult = net.step();
8034
8035        // We have a timer scheduled for the pending connection.
8036        net.with_context(LOCAL, |TcpCtx { core_ctx: _, bindings_ctx }| {
8037            assert_matches!(bindings_ctx.timers.timers().len(), 1);
8038        });
8039
8040        net.with_context(LOCAL, |ctx| {
8041            assert_eq!(ctx.tcp_api().shutdown(&local_listener, ShutdownType::Receive,), Ok(false));
8042        });
8043
8044        // The timer for the pending connection should be cancelled.
8045        net.with_context(LOCAL, |TcpCtx { core_ctx: _, bindings_ctx }| {
8046            assert_eq!(bindings_ctx.timers.timers().len(), 0);
8047        });
8048
8049        net.run_until_idle();
8050
8051        // Both remote sockets should now be reset to Closed state.
8052        net.with_context(REMOTE, |ctx| {
8053            for conn in [&remote_connection, &second_connection] {
8054                assert_eq!(
8055                    ctx.tcp_api().get_socket_error(conn),
8056                    Some(ConnectionError::ConnectionReset),
8057                )
8058            }
8059
8060            assert_matches!(
8061                &remote_connection.get().deref().socket_state,
8062                TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
8063                        let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8064                        assert_matches!(
8065                            conn,
8066                            Connection {
8067                                state: State::Closed(Closed {
8068                                    reason: Some(ConnectionError::ConnectionReset)
8069                                }),
8070                                ..
8071                            }
8072                        );
8073                    }
8074            );
8075        });
8076
8077        net.with_context(LOCAL, |ctx| {
8078            let mut api = ctx.tcp_api::<I>();
8079            let new_unbound = api.create(Default::default());
8080            assert_matches!(
8081                api.bind(
8082                    &new_unbound,
8083                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip,)),
8084                    Some(PORT_1),
8085                ),
8086                Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8087            );
8088            // Bring the already-shutdown listener back to listener again.
8089            api.listen(&local_listener, NonZeroUsize::new(5).unwrap()).expect("can listen again");
8090        });
8091
8092        let new_remote_connection = net.with_context(REMOTE, |ctx| {
8093            let mut api = ctx.tcp_api::<I>();
8094            let socket = api.create(Default::default());
8095            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8096                .expect("connect should succeed");
8097            socket
8098        });
8099
8100        net.run_until_idle();
8101
8102        net.with_context(REMOTE, |ctx| {
8103            assert_matches!(
8104                &new_remote_connection.get().deref().socket_state,
8105                TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
8106                    let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8107                    assert_matches!(
8108                        conn,
8109                        Connection {
8110                            state: State::Established(_),
8111                            ..
8112                        }
8113                    );
8114                    });
8115            assert_eq!(
8116                ctx.tcp_api().connect(
8117                    &new_remote_connection,
8118                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8119                    PORT_1,
8120                ),
8121                Ok(())
8122            );
8123        });
8124    }
8125
8126    #[ip_test(I)]
8127    fn clamp_buffer_size<I: TcpTestIpExt>()
8128    where
8129        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8130            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8131    {
8132        set_logger_for_test();
8133        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8134            I::TEST_ADDRS.local_ip,
8135            I::TEST_ADDRS.remote_ip,
8136        ));
8137        let mut api = ctx.tcp_api::<I>();
8138        let socket = api.create(Default::default());
8139
8140        let (min, max) =
8141            SettingsContext::<TcpSettings>::settings(&ctx.bindings_ctx).send_buffer.min_max();
8142        let mut api = ctx.tcp_api::<I>();
8143        api.set_send_buffer_size(&socket, min.get() - 1);
8144        assert_eq!(api.send_buffer_size(&socket), Some(min.get()));
8145        api.set_send_buffer_size(&socket, max.get() + 1);
8146        assert_eq!(api.send_buffer_size(&socket), Some(max.get()));
8147
8148        let (min, max) =
8149            SettingsContext::<TcpSettings>::settings(&ctx.bindings_ctx).receive_buffer.min_max();
8150        let mut api = ctx.tcp_api::<I>();
8151        api.set_receive_buffer_size(&socket, min.get() - 1);
8152        assert_eq!(api.receive_buffer_size(&socket), Some(min.get()));
8153        api.set_receive_buffer_size(&socket, max.get() + 1);
8154        assert_eq!(api.receive_buffer_size(&socket), Some(max.get()));
8155    }
8156
8157    #[ip_test(I)]
8158    fn set_reuseaddr_unbound<I: TcpTestIpExt>()
8159    where
8160        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8161            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8162    {
8163        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8164            I::TEST_ADDRS.local_ip,
8165            I::TEST_ADDRS.remote_ip,
8166        ));
8167        let mut api = ctx.tcp_api::<I>();
8168
8169        let first_bound = {
8170            let socket = api.create(Default::default());
8171            api.set_reuseaddr(&socket, true).expect("can set");
8172            api.bind(&socket, None, None).expect("bind succeeds");
8173            socket
8174        };
8175        let _second_bound = {
8176            let socket = api.create(Default::default());
8177            api.set_reuseaddr(&socket, true).expect("can set");
8178            api.bind(&socket, None, None).expect("bind succeeds");
8179            socket
8180        };
8181
8182        api.listen(&first_bound, NonZeroUsize::new(10).unwrap()).expect("can listen");
8183    }
8184
8185    #[ip_test(I)]
8186    #[test_case([true, true], Ok(()); "allowed with set")]
8187    #[test_case([false, true], Err(LocalAddressError::AddressInUse); "first unset")]
8188    #[test_case([true, false], Err(LocalAddressError::AddressInUse); "second unset")]
8189    #[test_case([false, false], Err(LocalAddressError::AddressInUse); "both unset")]
8190    fn reuseaddr_multiple_bound<I: TcpTestIpExt>(
8191        set_reuseaddr: [bool; 2],
8192        expected: Result<(), LocalAddressError>,
8193    ) where
8194        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8195            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8196    {
8197        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8198            I::TEST_ADDRS.local_ip,
8199            I::TEST_ADDRS.remote_ip,
8200        ));
8201        let mut api = ctx.tcp_api::<I>();
8202
8203        let first = api.create(Default::default());
8204        api.set_reuseaddr(&first, set_reuseaddr[0]).expect("can set");
8205        api.bind(&first, None, Some(PORT_1)).expect("bind succeeds");
8206
8207        let second = api.create(Default::default());
8208        api.set_reuseaddr(&second, set_reuseaddr[1]).expect("can set");
8209        let second_bind_result = api.bind(&second, None, Some(PORT_1));
8210
8211        assert_eq!(second_bind_result, expected.map_err(From::from));
8212    }
8213
8214    #[ip_test(I)]
8215    fn toggle_reuseaddr_bound_different_addrs<I: TcpTestIpExt>()
8216    where
8217        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8218            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8219    {
8220        let addrs = [1, 2].map(|i| I::get_other_ip_address(i));
8221        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::with_ip_socket_ctx_state(
8222            FakeDualStackIpSocketCtx::new(core::iter::once(FakeDeviceConfig {
8223                device: FakeDeviceId,
8224                local_ips: addrs.iter().cloned().map(SpecifiedAddr::<IpAddr>::from).collect(),
8225                remote_ips: Default::default(),
8226            })),
8227        ));
8228        let mut api = ctx.tcp_api::<I>();
8229
8230        let first = api.create(Default::default());
8231        api.bind(&first, Some(ZonedAddr::Unzoned(addrs[0])), Some(PORT_1)).unwrap();
8232
8233        let second = api.create(Default::default());
8234        api.bind(&second, Some(ZonedAddr::Unzoned(addrs[1])), Some(PORT_1)).unwrap();
8235        // Setting and un-setting ReuseAddr should be fine since these sockets
8236        // don't conflict.
8237        api.set_reuseaddr(&first, true).expect("can set");
8238        api.set_reuseaddr(&first, false).expect("can un-set");
8239    }
8240
8241    #[ip_test(I)]
8242    fn unset_reuseaddr_bound_unspecified_specified<I: TcpTestIpExt>()
8243    where
8244        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8245            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8246    {
8247        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8248            I::TEST_ADDRS.local_ip,
8249            I::TEST_ADDRS.remote_ip,
8250        ));
8251        let mut api = ctx.tcp_api::<I>();
8252        let first = api.create(Default::default());
8253        api.set_reuseaddr(&first, true).expect("can set");
8254        api.bind(&first, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1)).unwrap();
8255
8256        let second = api.create(Default::default());
8257        api.set_reuseaddr(&second, true).expect("can set");
8258        api.bind(&second, None, Some(PORT_1)).unwrap();
8259
8260        // Both sockets can be bound because they have ReuseAddr set. Since
8261        // removing it would introduce inconsistent state, that's not allowed.
8262        assert_matches!(api.set_reuseaddr(&first, false), Err(SetReuseAddrError::AddrInUse));
8263        assert_matches!(api.set_reuseaddr(&second, false), Err(SetReuseAddrError::AddrInUse));
8264    }
8265
8266    #[ip_test(I)]
8267    fn reuseaddr_allows_binding_under_connection<I: TcpTestIpExt>()
8268    where
8269        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8270            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8271    {
8272        set_logger_for_test();
8273        let mut net = new_test_net::<I>();
8274
8275        let server = net.with_context(LOCAL, |ctx| {
8276            let mut api = ctx.tcp_api::<I>();
8277            let server = api.create(Default::default());
8278            api.set_reuseaddr(&server, true).expect("can set");
8279            api.bind(&server, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
8280                .expect("failed to bind the client socket");
8281            api.listen(&server, NonZeroUsize::new(10).unwrap()).expect("can listen");
8282            server
8283        });
8284
8285        let client = net.with_context(REMOTE, |ctx| {
8286            let mut api = ctx.tcp_api::<I>();
8287            let client = api.create(Default::default());
8288            api.connect(&client, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), PORT_1)
8289                .expect("connect should succeed");
8290            client
8291        });
8292        // Finish the connection establishment.
8293        net.run_until_idle();
8294        net.with_context(REMOTE, |ctx| {
8295            assert_eq!(
8296                ctx.tcp_api().connect(
8297                    &client,
8298                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8299                    PORT_1
8300                ),
8301                Ok(())
8302            );
8303        });
8304
8305        // Now accept the connection and close the listening socket. Then
8306        // binding a new socket on the same local address should fail unless the
8307        // socket has SO_REUSEADDR set.
8308        net.with_context(LOCAL, |ctx| {
8309            let mut api = ctx.tcp_api();
8310            let (_server_conn, _, _): (_, SocketAddr<_, _>, ClientBuffers) =
8311                api.accept(&server).expect("pending connection");
8312
8313            assert_eq!(api.shutdown(&server, ShutdownType::Receive), Ok(false));
8314            api.close(server);
8315
8316            let unbound = api.create(Default::default());
8317            assert_eq!(
8318                api.bind(&unbound, None, Some(PORT_1)),
8319                Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8320            );
8321
8322            // Binding should succeed after setting ReuseAddr.
8323            api.set_reuseaddr(&unbound, true).expect("can set");
8324            api.bind(&unbound, None, Some(PORT_1)).expect("bind succeeds");
8325        });
8326    }
8327
8328    #[ip_test(I)]
8329    #[test_case([true, true]; "specified specified")]
8330    #[test_case([false, true]; "any specified")]
8331    #[test_case([true, false]; "specified any")]
8332    #[test_case([false, false]; "any any")]
8333    fn set_reuseaddr_bound_allows_other_bound<I: TcpTestIpExt>(bind_specified: [bool; 2])
8334    where
8335        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8336            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8337    {
8338        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8339            I::TEST_ADDRS.local_ip,
8340            I::TEST_ADDRS.remote_ip,
8341        ));
8342        let mut api = ctx.tcp_api::<I>();
8343
8344        let [first_addr, second_addr] =
8345            bind_specified.map(|b| b.then_some(I::TEST_ADDRS.local_ip).map(ZonedAddr::Unzoned));
8346        let first_bound = {
8347            let socket = api.create(Default::default());
8348            api.bind(&socket, first_addr, Some(PORT_1)).expect("bind succeeds");
8349            socket
8350        };
8351
8352        let second = api.create(Default::default());
8353
8354        // Binding the second socket will fail because the first doesn't have
8355        // SO_REUSEADDR set.
8356        assert_matches!(
8357            api.bind(&second, second_addr, Some(PORT_1)),
8358            Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8359        );
8360
8361        // Setting SO_REUSEADDR for the second socket isn't enough.
8362        api.set_reuseaddr(&second, true).expect("can set");
8363        assert_matches!(
8364            api.bind(&second, second_addr, Some(PORT_1)),
8365            Err(BindError::LocalAddressError(LocalAddressError::AddressInUse))
8366        );
8367
8368        // Setting SO_REUSEADDR for the first socket lets the second bind.
8369        api.set_reuseaddr(&first_bound, true).expect("only socket");
8370        api.bind(&second, second_addr, Some(PORT_1)).expect("can bind");
8371    }
8372
8373    #[ip_test(I)]
8374    fn clear_reuseaddr_listener<I: TcpTestIpExt>()
8375    where
8376        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
8377            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
8378    {
8379        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8380            I::TEST_ADDRS.local_ip,
8381            I::TEST_ADDRS.remote_ip,
8382        ));
8383        let mut api = ctx.tcp_api::<I>();
8384
8385        let bound = {
8386            let socket = api.create(Default::default());
8387            api.set_reuseaddr(&socket, true).expect("can set");
8388            api.bind(&socket, None, Some(PORT_1)).expect("bind succeeds");
8389            socket
8390        };
8391
8392        let listener = {
8393            let socket = api.create(Default::default());
8394            api.set_reuseaddr(&socket, true).expect("can set");
8395
8396            api.bind(&socket, None, Some(PORT_1)).expect("bind succeeds");
8397            api.listen(&socket, NonZeroUsize::new(5).unwrap()).expect("can listen");
8398            socket
8399        };
8400
8401        // We can't clear SO_REUSEADDR on the listener because it's sharing with
8402        // the bound socket.
8403        assert_matches!(api.set_reuseaddr(&listener, false), Err(SetReuseAddrError::AddrInUse));
8404
8405        // We can, however, connect to the listener with the bound socket. Then
8406        // the unencumbered listener can clear SO_REUSEADDR.
8407        api.connect(&bound, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
8408            .expect("can connect");
8409        api.set_reuseaddr(&listener, false).expect("can unset")
8410    }
8411
8412    fn deliver_icmp_error<
8413        I: TcpTestIpExt + IcmpIpExt,
8414        CC: TcpContext<I, BC, DeviceId = FakeDeviceId>
8415            + TcpContext<I::OtherVersion, BC, DeviceId = FakeDeviceId>,
8416        BC: TcpBindingsContext<CC::DeviceId>,
8417    >(
8418        core_ctx: &mut CC,
8419        bindings_ctx: &mut BC,
8420        original_src_ip: SpecifiedAddr<I::Addr>,
8421        original_dst_ip: SpecifiedAddr<I::Addr>,
8422        original_body: &[u8],
8423        err: I::ErrorCode,
8424    ) {
8425        <TcpIpTransportContext as IpTransportContext<I, _, _>>::receive_icmp_error(
8426            core_ctx,
8427            bindings_ctx,
8428            &FakeDeviceId,
8429            Some(original_src_ip),
8430            original_dst_ip,
8431            original_body,
8432            err,
8433        );
8434    }
8435
8436    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnreachable, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8437    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnreachable, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8438    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestProtocolUnreachable, IcmpDestUnreachable::default()) => ConnectionError::ProtocolUnreachable)]
8439    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestPortUnreachable, IcmpDestUnreachable::default()) => ConnectionError::PortUnreachable)]
8440    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceRouteFailed, IcmpDestUnreachable::default()) => ConnectionError::SourceRouteFailed)]
8441    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnknown, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8442    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnknown, IcmpDestUnreachable::default()) => ConnectionError::DestinationHostDown)]
8443    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceHostIsolated, IcmpDestUnreachable::default()) => ConnectionError::SourceHostIsolated)]
8444    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8445    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8446    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8447    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8448    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::CommAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8449    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostPrecedenceViolation, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8450    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::PrecedenceCutoffInEffect, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8451    #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::PointerIndicatesError) => ConnectionError::ProtocolError)]
8452    #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::MissingRequiredOption) => ConnectionError::ProtocolError)]
8453    #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::BadLength) => ConnectionError::ProtocolError)]
8454    #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired) => ConnectionError::HostUnreachable)]
8455    #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::TimedOut)]
8456    fn icmp_destination_unreachable_connect_v4(error: Icmpv4ErrorCode) -> ConnectionError {
8457        icmp_destination_unreachable_connect_inner::<Ipv4>(error)
8458    }
8459
8460    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute) => ConnectionError::NetworkUnreachable)]
8461    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::CommAdministrativelyProhibited) => ConnectionError::PermissionDenied)]
8462    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::BeyondScope) => ConnectionError::HostUnreachable)]
8463    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::AddrUnreachable) => ConnectionError::HostUnreachable)]
8464    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::PortUnreachable) => ConnectionError::PortUnreachable)]
8465    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::SrcAddrFailedPolicy) => ConnectionError::PermissionDenied)]
8466    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::RejectRoute) => ConnectionError::PermissionDenied)]
8467    #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::ErroneousHeaderField) => ConnectionError::ProtocolError)]
8468    #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType) => ConnectionError::ProtocolError)]
8469    #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedIpv6Option) => ConnectionError::ProtocolError)]
8470    #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded) => ConnectionError::HostUnreachable)]
8471    #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::HostUnreachable)]
8472    fn icmp_destination_unreachable_connect_v6(error: Icmpv6ErrorCode) -> ConnectionError {
8473        icmp_destination_unreachable_connect_inner::<Ipv6>(error)
8474    }
8475
8476    fn icmp_destination_unreachable_connect_inner<I: TcpTestIpExt + IcmpIpExt>(
8477        icmp_error: I::ErrorCode,
8478    ) -> ConnectionError
8479    where
8480        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<I, TcpBindingsCtx<FakeDeviceId>>
8481            + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>,
8482    {
8483        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
8484            I::TEST_ADDRS.local_ip,
8485            I::TEST_ADDRS.remote_ip,
8486        ));
8487        let mut api = ctx.tcp_api::<I>();
8488
8489        let connection = api.create(Default::default());
8490        api.connect(&connection, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
8491            .expect("failed to create a connection socket");
8492
8493        let (core_ctx, bindings_ctx) = api.contexts();
8494        let frames = core_ctx.ip_socket_ctx.take_frames();
8495        let frame = assert_matches!(&frames[..], [(_meta, frame)] => frame);
8496
8497        deliver_icmp_error::<I, _, _>(
8498            core_ctx,
8499            bindings_ctx,
8500            I::TEST_ADDRS.local_ip,
8501            I::TEST_ADDRS.remote_ip,
8502            &frame[0..8],
8503            icmp_error,
8504        );
8505        // The TCP handshake should be aborted.
8506        assert_eq!(
8507            api.connect(&connection, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1),
8508            Err(ConnectError::Aborted)
8509        );
8510        api.get_socket_error(&connection).unwrap()
8511    }
8512
8513    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnreachable, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8514    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnreachable, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8515    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestProtocolUnreachable, IcmpDestUnreachable::default()) => ConnectionError::ProtocolUnreachable)]
8516    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestPortUnreachable, IcmpDestUnreachable::default()) => ConnectionError::PortUnreachable)]
8517    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceRouteFailed, IcmpDestUnreachable::default()) => ConnectionError::SourceRouteFailed)]
8518    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestNetworkUnknown, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8519    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::DestHostUnknown, IcmpDestUnreachable::default()) => ConnectionError::DestinationHostDown)]
8520    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::SourceHostIsolated, IcmpDestUnreachable::default()) => ConnectionError::SourceHostIsolated)]
8521    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8522    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8523    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::NetworkUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::NetworkUnreachable)]
8524    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostUnreachableForToS, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8525    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::CommAdministrativelyProhibited, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8526    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::HostPrecedenceViolation, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8527    #[test_case(Icmpv4ErrorCode::DestUnreachable(Icmpv4DestUnreachableCode::PrecedenceCutoffInEffect, IcmpDestUnreachable::default()) => ConnectionError::HostUnreachable)]
8528    #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::PointerIndicatesError) => ConnectionError::ProtocolError)]
8529    #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::MissingRequiredOption) => ConnectionError::ProtocolError)]
8530    #[test_case(Icmpv4ErrorCode::ParameterProblem(Icmpv4ParameterProblemCode::BadLength) => ConnectionError::ProtocolError)]
8531    #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::TtlExpired) => ConnectionError::HostUnreachable)]
8532    #[test_case(Icmpv4ErrorCode::TimeExceeded(Icmpv4TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::TimedOut)]
8533    fn icmp_destination_unreachable_established_v4(error: Icmpv4ErrorCode) -> ConnectionError {
8534        icmp_destination_unreachable_established_inner::<Ipv4>(error)
8535    }
8536
8537    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::NoRoute) => ConnectionError::NetworkUnreachable)]
8538    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::CommAdministrativelyProhibited) => ConnectionError::PermissionDenied)]
8539    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::BeyondScope) => ConnectionError::HostUnreachable)]
8540    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::AddrUnreachable) => ConnectionError::HostUnreachable)]
8541    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::PortUnreachable) => ConnectionError::PortUnreachable)]
8542    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::SrcAddrFailedPolicy) => ConnectionError::PermissionDenied)]
8543    #[test_case(Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::RejectRoute) => ConnectionError::PermissionDenied)]
8544    #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::ErroneousHeaderField) => ConnectionError::ProtocolError)]
8545    #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedNextHeaderType) => ConnectionError::ProtocolError)]
8546    #[test_case(Icmpv6ErrorCode::ParameterProblem(Icmpv6ParameterProblemCode::UnrecognizedIpv6Option) => ConnectionError::ProtocolError)]
8547    #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::HopLimitExceeded) => ConnectionError::HostUnreachable)]
8548    #[test_case(Icmpv6ErrorCode::TimeExceeded(Icmpv6TimeExceededCode::FragmentReassemblyTimeExceeded) => ConnectionError::HostUnreachable)]
8549    fn icmp_destination_unreachable_established_v6(error: Icmpv6ErrorCode) -> ConnectionError {
8550        icmp_destination_unreachable_established_inner::<Ipv6>(error)
8551    }
8552
8553    fn icmp_destination_unreachable_established_inner<I: TcpTestIpExt + IcmpIpExt>(
8554        icmp_error: I::ErrorCode,
8555    ) -> ConnectionError
8556    where
8557        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
8558                I,
8559                TcpBindingsCtx<FakeDeviceId>,
8560                SingleStackConverter = I::SingleStackConverter,
8561                DualStackConverter = I::DualStackConverter,
8562            > + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>,
8563    {
8564        let (mut net, local, local_snd_end, _remote) = bind_listen_connect_accept_inner::<I>(
8565            I::UNSPECIFIED_ADDRESS,
8566            BindConfig {
8567                client_port: None,
8568                server_port: PORT_1,
8569                client_reuse_addr: false,
8570                send_test_data: false,
8571            },
8572            0,
8573            0.0,
8574        );
8575        local_snd_end.lock().extend_from_slice(b"Hello");
8576        net.with_context(LOCAL, |ctx| {
8577            ctx.tcp_api().do_send(&local);
8578        });
8579        net.collect_frames();
8580        let original_body = assert_matches!(
8581            &net.iter_pending_frames().collect::<Vec<_>>()[..],
8582            [InstantAndData(_instant, PendingFrameData {
8583                dst_context: _,
8584                meta: _,
8585                frame,
8586            })] => {
8587            frame.clone()
8588        });
8589        net.with_context(LOCAL, |ctx| {
8590            let TcpCtx { core_ctx, bindings_ctx } = ctx;
8591            deliver_icmp_error::<I, _, _>(
8592                core_ctx,
8593                bindings_ctx,
8594                I::TEST_ADDRS.local_ip,
8595                I::TEST_ADDRS.remote_ip,
8596                &original_body[..],
8597                icmp_error,
8598            );
8599            // An error should be posted on the connection.
8600            let error = assert_matches!(
8601                ctx.tcp_api().get_socket_error(&local),
8602                Some(error) => error
8603            );
8604            // But it should stay established.
8605            assert_matches!(
8606                &local.get().deref().socket_state,
8607                TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
8608                    let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8609                    assert_matches!(
8610                        conn,
8611                        Connection {
8612                            state: State::Established(_),
8613                            ..
8614                        }
8615                    );
8616                }
8617            );
8618            error
8619        })
8620    }
8621
8622    #[ip_test(I)]
8623    fn icmp_destination_unreachable_listener<I: TcpTestIpExt + IcmpIpExt>()
8624    where
8625        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<I, TcpBindingsCtx<FakeDeviceId>>
8626            + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>
8627            + CounterContext<TcpCountersWithSocket<I>>,
8628    {
8629        let mut net = new_test_net::<I>();
8630
8631        let backlog = NonZeroUsize::new(1).unwrap();
8632        let server = net.with_context(REMOTE, |ctx| {
8633            let mut api = ctx.tcp_api::<I>();
8634            let server = api.create(Default::default());
8635            api.bind(&server, None, Some(PORT_1)).expect("failed to bind the server socket");
8636            api.listen(&server, backlog).expect("can listen");
8637            server
8638        });
8639
8640        net.with_context(LOCAL, |ctx| {
8641            let mut api = ctx.tcp_api::<I>();
8642            let conn = api.create(Default::default());
8643            api.connect(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
8644                .expect("failed to connect");
8645        });
8646
8647        assert!(!net.step().is_idle());
8648
8649        net.collect_frames();
8650        let original_body = assert_matches!(
8651            &net.iter_pending_frames().collect::<Vec<_>>()[..],
8652            [InstantAndData(_instant, PendingFrameData {
8653                dst_context: _,
8654                meta: _,
8655                frame,
8656            })] => {
8657            frame.clone()
8658        });
8659        let icmp_error = I::map_ip(
8660            (),
8661            |()| {
8662                Icmpv4ErrorCode::DestUnreachable(
8663                    Icmpv4DestUnreachableCode::DestPortUnreachable,
8664                    IcmpDestUnreachable::default(),
8665                )
8666            },
8667            |()| Icmpv6ErrorCode::DestUnreachable(Icmpv6DestUnreachableCode::PortUnreachable),
8668        );
8669        net.with_context(REMOTE, |TcpCtx { core_ctx, bindings_ctx }| {
8670            let in_queue = {
8671                let state = server.get();
8672                let accept_queue = assert_matches!(
8673                    &state.deref().socket_state,
8674                    TcpSocketStateInner::Bound(BoundSocketState::Listener((
8675                        MaybeListener::Listener(Listener { accept_queue, .. }),
8676                        ..
8677                    ))) => accept_queue
8678                );
8679                assert_eq!(accept_queue.len(), 1);
8680                accept_queue.collect_pending().first().unwrap().downgrade()
8681            };
8682            deliver_icmp_error::<I, _, _>(
8683                core_ctx,
8684                bindings_ctx,
8685                I::TEST_ADDRS.remote_ip,
8686                I::TEST_ADDRS.local_ip,
8687                &original_body[..],
8688                icmp_error,
8689            );
8690            {
8691                let state = server.get();
8692                let queue_len = assert_matches!(
8693                    &state.deref().socket_state,
8694                    TcpSocketStateInner::Bound(BoundSocketState::Listener((
8695                        MaybeListener::Listener(Listener { accept_queue, .. }),
8696                        ..
8697                    ))) => accept_queue.len()
8698                );
8699                assert_eq!(queue_len, 0);
8700            }
8701            // Socket must've been destroyed.
8702            assert_eq!(in_queue.upgrade(), None);
8703        });
8704    }
8705
8706    #[ip_test(I)]
8707    fn time_wait_reuse<I: TcpTestIpExt>()
8708    where
8709        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
8710                I,
8711                TcpBindingsCtx<FakeDeviceId>,
8712                SingleStackConverter = I::SingleStackConverter,
8713                DualStackConverter = I::DualStackConverter,
8714            >,
8715    {
8716        set_logger_for_test();
8717        const CLIENT_PORT: NonZeroU16 = NonZeroU16::new(2).unwrap();
8718        const SERVER_PORT: NonZeroU16 = NonZeroU16::new(1).unwrap();
8719        let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
8720            I::UNSPECIFIED_ADDRESS,
8721            BindConfig {
8722                client_port: Some(CLIENT_PORT),
8723                server_port: SERVER_PORT,
8724                client_reuse_addr: true,
8725                send_test_data: false,
8726            },
8727            0,
8728            0.0,
8729        );
8730        // Locally, we create a connection with a full accept queue.
8731        let listener = net.with_context(LOCAL, |ctx| {
8732            let mut api = ctx.tcp_api::<I>();
8733            let listener = api.create(Default::default());
8734            api.set_reuseaddr(&listener, true).expect("can set");
8735            api.bind(
8736                &listener,
8737                Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8738                Some(CLIENT_PORT),
8739            )
8740            .expect("failed to bind");
8741            api.listen(&listener, NonZeroUsize::new(1).unwrap()).expect("failed to listen");
8742            listener
8743        });
8744        // This connection is never used, just to keep accept queue full.
8745        let extra_conn = net.with_context(REMOTE, |ctx| {
8746            let mut api = ctx.tcp_api::<I>();
8747            let extra_conn = api.create(Default::default());
8748            api.connect(&extra_conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), CLIENT_PORT)
8749                .expect("failed to connect");
8750            extra_conn
8751        });
8752        net.run_until_idle();
8753
8754        net.with_context(REMOTE, |ctx| {
8755            assert_eq!(
8756                ctx.tcp_api().connect(
8757                    &extra_conn,
8758                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8759                    CLIENT_PORT,
8760                ),
8761                Ok(())
8762            );
8763        });
8764
8765        // Now we shutdown the sockets and try to bring the local socket to
8766        // TIME-WAIT.
8767        let weak_local = local.downgrade();
8768        net.with_context(LOCAL, |ctx| {
8769            ctx.tcp_api().close(local);
8770        });
8771        assert!(!net.step().is_idle());
8772        assert!(!net.step().is_idle());
8773        net.with_context(REMOTE, |ctx| {
8774            ctx.tcp_api().close(remote);
8775        });
8776        assert!(!net.step().is_idle());
8777        assert!(!net.step().is_idle());
8778        // The connection should go to TIME-WAIT.
8779        let (tw_last_seq, tw_last_ack, tw_expiry) = {
8780            assert_matches!(
8781                &weak_local.upgrade().unwrap().get().deref().socket_state,
8782                TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
8783                    let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8784                    assert_matches!(
8785                        conn,
8786                        Connection {
8787                        state: State::TimeWait(TimeWait {
8788                            last_seq,
8789                            closed_rcv,
8790                            expiry,
8791                            ..
8792                        }), ..
8793                        } => (*last_seq, closed_rcv.ack, *expiry)
8794                    )
8795                }
8796            )
8797        };
8798
8799        // Try to initiate a connection from the remote since we have an active
8800        // listener locally.
8801        let conn = net.with_context(REMOTE, |ctx| {
8802            let mut api = ctx.tcp_api::<I>();
8803            let conn = api.create(Default::default());
8804            api.connect(&conn, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), CLIENT_PORT)
8805                .expect("failed to connect");
8806            conn
8807        });
8808        while net.next_step() != Some(tw_expiry) {
8809            assert!(!net.step().is_idle());
8810        }
8811        // This attempt should fail due the full accept queue at the listener.
8812        assert_matches!(
8813        &conn.get().deref().socket_state,
8814        TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
8815                let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(conn, &I::converter());
8816                assert_matches!(
8817                    conn,
8818                Connection {
8819                    state: State::Closed(Closed { reason: Some(ConnectionError::TimedOut) }),
8820                    ..
8821                }
8822                );
8823            });
8824
8825        // Now free up the accept queue by accepting the connection.
8826        net.with_context(LOCAL, |ctx| {
8827            let _accepted =
8828                ctx.tcp_api().accept(&listener).expect("failed to accept a new connection");
8829        });
8830        let conn = net.with_context(REMOTE, |ctx| {
8831            let mut api = ctx.tcp_api::<I>();
8832            let socket = api.create(Default::default());
8833            api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), Some(SERVER_PORT))
8834                .expect("failed to bind");
8835            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), CLIENT_PORT)
8836                .expect("failed to connect");
8837            socket
8838        });
8839        net.collect_frames();
8840        assert_matches!(
8841            &net.iter_pending_frames().collect::<Vec<_>>()[..],
8842            [InstantAndData(_instant, PendingFrameData {
8843                dst_context: _,
8844                meta,
8845                frame,
8846            })] => {
8847            let mut buffer = Buf::new(frame, ..);
8848            let iss = match I::VERSION {
8849                IpVersion::V4 => {
8850                    let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V4(meta) => meta);
8851                    let parsed = buffer.parse_with::<_, TcpSegment<_>>(
8852                        TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
8853                    ).expect("failed to parse");
8854                    assert!(parsed.syn());
8855                    SeqNum::new(parsed.seq_num())
8856                }
8857                IpVersion::V6 => {
8858                    let meta = assert_matches!(meta, DualStackSendIpPacketMeta::V6(meta) => meta);
8859                    let parsed = buffer.parse_with::<_, TcpSegment<_>>(
8860                        TcpParseArgs::new(*meta.src_ip, *meta.dst_ip)
8861                    ).expect("failed to parse");
8862                    assert!(parsed.syn());
8863                    SeqNum::new(parsed.seq_num())
8864                }
8865            };
8866            assert!(iss.after(tw_last_ack) && iss.before(tw_last_seq));
8867        });
8868        // The TIME-WAIT socket should be reused to establish the connection.
8869        net.run_until_idle();
8870        net.with_context(REMOTE, |ctx| {
8871            assert_eq!(
8872                ctx.tcp_api().connect(
8873                    &conn,
8874                    Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)),
8875                    CLIENT_PORT
8876                ),
8877                Ok(())
8878            );
8879        });
8880    }
8881
8882    #[ip_test(I)]
8883    fn conn_addr_not_available<I: TcpTestIpExt + IcmpIpExt>()
8884    where
8885        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
8886                I,
8887                TcpBindingsCtx<FakeDeviceId>,
8888                SingleStackConverter = I::SingleStackConverter,
8889                DualStackConverter = I::DualStackConverter,
8890            >,
8891    {
8892        set_logger_for_test();
8893        let (mut net, _local, _local_snd_end, _remote) = bind_listen_connect_accept_inner::<I>(
8894            I::UNSPECIFIED_ADDRESS,
8895            BindConfig {
8896                client_port: Some(PORT_1),
8897                server_port: PORT_1,
8898                client_reuse_addr: true,
8899                send_test_data: false,
8900            },
8901            0,
8902            0.0,
8903        );
8904        // Now we are using the same 4-tuple again to try to create a new
8905        // connection, this should fail.
8906        net.with_context(LOCAL, |ctx| {
8907            let mut api = ctx.tcp_api::<I>();
8908            let socket = api.create(Default::default());
8909            api.set_reuseaddr(&socket, true).expect("can set");
8910            api.bind(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.local_ip)), Some(PORT_1))
8911                .expect("failed to bind");
8912            assert_eq!(
8913                api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1),
8914                Err(ConnectError::ConnectionExists),
8915            )
8916        });
8917    }
8918
8919    #[test_case::test_matrix(
8920        [None, Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped()))],
8921        [None, Some(PORT_1)],
8922        [true, false]
8923    )]
8924    fn dual_stack_connect(
8925        server_bind_ip: Option<ZonedAddr<SpecifiedAddr<Ipv6Addr>, FakeDeviceId>>,
8926        server_bind_port: Option<NonZeroU16>,
8927        bind_client: bool,
8928    ) {
8929        set_logger_for_test();
8930        let mut net = new_test_net::<Ipv4>();
8931        let backlog = NonZeroUsize::new(1).unwrap();
8932        let (server, listen_port) = net.with_context(REMOTE, |ctx| {
8933            let mut api = ctx.tcp_api::<Ipv6>();
8934            let server = api.create(Default::default());
8935            api.bind(&server, server_bind_ip, server_bind_port)
8936                .expect("failed to bind the server socket");
8937            api.listen(&server, backlog).expect("can listen");
8938            let port = assert_matches!(
8939                api.get_info(&server),
8940                SocketInfo::Bound(info) => info.port
8941            );
8942            (server, port)
8943        });
8944
8945        let client_ends = WriteBackClientBuffers::default();
8946        let client = net.with_context(LOCAL, |ctx| {
8947            let mut api = ctx.tcp_api::<Ipv6>();
8948            let socket = api.create(ProvidedBuffers::Buffers(client_ends.clone()));
8949            if bind_client {
8950                api.bind(&socket, None, None).expect("failed to bind");
8951            }
8952            api.connect(
8953                &socket,
8954                Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped())),
8955                listen_port,
8956            )
8957            .expect("failed to connect");
8958            socket
8959        });
8960
8961        // Step the test network until the handshake is done.
8962        net.run_until_idle();
8963        let (accepted, addr, accepted_ends) = net
8964            .with_context(REMOTE, |ctx| ctx.tcp_api().accept(&server).expect("failed to accept"));
8965        assert_eq!(addr.ip, ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.local_ip).to_ipv6_mapped()));
8966
8967        let ClientBuffers { send: client_snd_end, receive: client_rcv_end } =
8968            client_ends.0.as_ref().lock().take().unwrap();
8969        let ClientBuffers { send: accepted_snd_end, receive: accepted_rcv_end } = accepted_ends;
8970        for snd_end in [client_snd_end, accepted_snd_end] {
8971            snd_end.lock().extend_from_slice(b"Hello");
8972        }
8973        net.with_context(LOCAL, |ctx| ctx.tcp_api().do_send(&client));
8974        net.with_context(REMOTE, |ctx| ctx.tcp_api().do_send(&accepted));
8975        net.run_until_idle();
8976
8977        for rcv_end in [client_rcv_end, accepted_rcv_end] {
8978            assert_eq!(
8979                rcv_end.lock().read_with(|avail| {
8980                    let avail = avail.concat();
8981                    assert_eq!(avail, b"Hello");
8982                    avail.len()
8983                }),
8984                5
8985            );
8986        }
8987
8988        // Verify that the client is connected to the IPv4 remote and has been
8989        // assigned an IPv4 local IP.
8990        let info = assert_matches!(
8991            net.with_context(LOCAL, |ctx| ctx.tcp_api().get_info(&client)),
8992            SocketInfo::Connection(info) => info
8993        );
8994        let (local_ip, remote_ip, port) = assert_matches!(
8995            info,
8996            ConnectionInfo {
8997                local_addr: SocketAddr { ip: local_ip, port: _ },
8998                remote_addr: SocketAddr { ip: remote_ip, port },
8999                device: _
9000            } => (local_ip.addr(), remote_ip.addr(), port)
9001        );
9002        assert_eq!(remote_ip, Ipv4::TEST_ADDRS.remote_ip.to_ipv6_mapped());
9003        assert_matches!(local_ip.to_ipv4_mapped(), Some(_));
9004        assert_eq!(port, listen_port);
9005    }
9006
9007    #[test]
9008    fn ipv6_dual_stack_enabled() {
9009        set_logger_for_test();
9010        let mut net = new_test_net::<Ipv4>();
9011        net.with_context(LOCAL, |ctx| {
9012            let mut api = ctx.tcp_api::<Ipv6>();
9013            let socket = api.create(Default::default());
9014            assert_eq!(api.dual_stack_enabled(&socket), Ok(true));
9015            api.set_dual_stack_enabled(&socket, false).expect("failed to disable dual stack");
9016            assert_eq!(api.dual_stack_enabled(&socket), Ok(false));
9017            assert_eq!(
9018                api.bind(
9019                    &socket,
9020                    Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.local_ip).to_ipv6_mapped())),
9021                    Some(PORT_1),
9022                ),
9023                Err(BindError::LocalAddressError(LocalAddressError::CannotBindToAddress))
9024            );
9025            assert_eq!(
9026                api.connect(
9027                    &socket,
9028                    Some(ZonedAddr::Unzoned((*Ipv4::TEST_ADDRS.remote_ip).to_ipv6_mapped())),
9029                    PORT_1,
9030                ),
9031                Err(ConnectError::NoRoute)
9032            );
9033        });
9034    }
9035
9036    #[test]
9037    fn ipv4_dual_stack_enabled() {
9038        set_logger_for_test();
9039        let mut net = new_test_net::<Ipv4>();
9040        net.with_context(LOCAL, |ctx| {
9041            let mut api = ctx.tcp_api::<Ipv4>();
9042            let socket = api.create(Default::default());
9043            assert_eq!(api.dual_stack_enabled(&socket), Err(NotDualStackCapableError));
9044            assert_eq!(
9045                api.set_dual_stack_enabled(&socket, true),
9046                Err(NotDualStackCapableError.into())
9047            );
9048        });
9049    }
9050
9051    #[ip_test(I)]
9052    fn closed_not_in_demux<I: TcpTestIpExt>()
9053    where
9054        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9055                I,
9056                TcpBindingsCtx<FakeDeviceId>,
9057                SingleStackConverter = I::SingleStackConverter,
9058                DualStackConverter = I::DualStackConverter,
9059            >,
9060    {
9061        let (mut net, local, _local_snd_end, remote) = bind_listen_connect_accept_inner::<I>(
9062            I::UNSPECIFIED_ADDRESS,
9063            BindConfig {
9064                client_port: None,
9065                server_port: PORT_1,
9066                client_reuse_addr: false,
9067                send_test_data: false,
9068            },
9069            0,
9070            0.0,
9071        );
9072        // Assert that the sockets are bound in the socketmap.
9073        for ctx_name in [LOCAL, REMOTE] {
9074            net.with_context(ctx_name, |CtxPair { core_ctx, bindings_ctx: _ }| {
9075                TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9076                    assert_eq!(socketmap.len(), 1);
9077                })
9078            });
9079        }
9080        for (ctx_name, socket) in [(LOCAL, &local), (REMOTE, &remote)] {
9081            net.with_context(ctx_name, |ctx| {
9082                assert_eq!(ctx.tcp_api().shutdown(socket, ShutdownType::SendAndReceive), Ok(true));
9083            });
9084        }
9085        net.run_until_idle();
9086        // Both sockets are closed by now, but they are not defunct because we
9087        // never called `close` on them, but they should not be in the demuxer
9088        // regardless.
9089        for ctx_name in [LOCAL, REMOTE] {
9090            net.with_context(ctx_name, |CtxPair { core_ctx, bindings_ctx: _ }| {
9091                TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9092                    assert_eq!(socketmap.len(), 0);
9093                })
9094            });
9095        }
9096    }
9097
9098    #[ip_test(I)]
9099    fn tcp_accept_queue_clean_up_closed<I: TcpTestIpExt>()
9100    where
9101        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
9102            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
9103    {
9104        let mut net = new_test_net::<I>();
9105        let backlog = NonZeroUsize::new(1).unwrap();
9106        let server_port = NonZeroU16::new(1024).unwrap();
9107        let server = net.with_context(REMOTE, |ctx| {
9108            let mut api = ctx.tcp_api::<I>();
9109            let server = api.create(Default::default());
9110            api.bind(&server, None, Some(server_port)).expect("failed to bind the server socket");
9111            api.listen(&server, backlog).expect("can listen");
9112            server
9113        });
9114
9115        let client = net.with_context(LOCAL, |ctx| {
9116            let mut api = ctx.tcp_api::<I>();
9117            let socket = api.create(ProvidedBuffers::Buffers(WriteBackClientBuffers::default()));
9118            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), server_port)
9119                .expect("failed to connect");
9120            socket
9121        });
9122        // Step so that SYN is received by the server.
9123        assert!(!net.step().is_idle());
9124        // Make sure the server now has a pending socket in the accept queue.
9125        assert_matches!(
9126            &server.get().deref().socket_state,
9127            TcpSocketStateInner::Bound(BoundSocketState::Listener((
9128                MaybeListener::Listener(Listener {
9129                    accept_queue,
9130                    ..
9131                }), ..))) => {
9132                assert_eq!(accept_queue.ready_len(), 0);
9133                assert_eq!(accept_queue.pending_len(), 1);
9134            }
9135        );
9136        // Now close the client socket.
9137        net.with_context(LOCAL, |ctx| {
9138            let mut api = ctx.tcp_api::<I>();
9139            api.close(client);
9140        });
9141        // Server's SYN-ACK will get a RST response because the connection is
9142        // no longer there.
9143        net.run_until_idle();
9144        // We verify that no lingering socket in the accept_queue.
9145        assert_matches!(
9146            &server.get().deref().socket_state,
9147            TcpSocketStateInner::Bound(BoundSocketState::Listener((
9148                MaybeListener::Listener(Listener {
9149                    accept_queue,
9150                    ..
9151                }), ..))) => {
9152                assert_eq!(accept_queue.ready_len(), 0);
9153                assert_eq!(accept_queue.pending_len(), 0);
9154            }
9155        );
9156        // Server should be the only socket in `all_sockets`.
9157        net.with_context(REMOTE, |ctx| {
9158            ctx.core_ctx.with_all_sockets_mut(|all_sockets| {
9159                assert_eq!(all_sockets.keys().collect::<Vec<_>>(), [&server]);
9160            })
9161        })
9162    }
9163
9164    #[ip_test(I)]
9165    #[test_case::test_matrix(
9166        [MarkDomain::Mark1, MarkDomain::Mark2],
9167        [None, Some(0), Some(1)]
9168    )]
9169    fn tcp_socket_marks<I: TcpTestIpExt>(domain: MarkDomain, mark: Option<u32>)
9170    where
9171        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>:
9172            TcpContext<I, TcpBindingsCtx<FakeDeviceId>>,
9173    {
9174        let mut ctx = TcpCtx::with_core_ctx(TcpCoreCtx::new::<I>(
9175            I::TEST_ADDRS.local_ip,
9176            I::TEST_ADDRS.remote_ip,
9177        ));
9178        let mut api = ctx.tcp_api::<I>();
9179        let socket = api.create(Default::default());
9180
9181        // Doesn't have a mark by default.
9182        assert_eq!(api.get_mark(&socket, domain), Mark(None));
9183
9184        let mark = Mark(mark);
9185        // We can set and get back the mark.
9186        api.set_mark(&socket, domain, mark);
9187        assert_eq!(api.get_mark(&socket, domain), mark);
9188    }
9189
9190    #[ip_test(I)]
9191    fn tcp_marks_for_accepted_sockets<I: TcpTestIpExt>()
9192    where
9193        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9194                I,
9195                TcpBindingsCtx<FakeDeviceId>,
9196                SingleStackConverter = I::SingleStackConverter,
9197                DualStackConverter = I::DualStackConverter,
9198            >,
9199    {
9200        // We want the accepted socket to be marked 101 for MARK_1 and 102 for MARK_2.
9201        let expected_marks = [(MarkDomain::Mark1, 101), (MarkDomain::Mark2, 102)];
9202        let marks = netstack3_base::Marks::new(expected_marks);
9203        let mut net = new_test_net::<I>();
9204
9205        for c in [LOCAL, REMOTE] {
9206            net.with_context(c, |ctx| {
9207                ctx.core_ctx.recv_packet_marks = marks;
9208            })
9209        }
9210
9211        let backlog = NonZeroUsize::new(1).unwrap();
9212        let server_port = NonZeroU16::new(1234).unwrap();
9213
9214        let server = net.with_context(REMOTE, |ctx| {
9215            let mut api = ctx.tcp_api::<I>();
9216            let server = api.create(Default::default());
9217            api.set_mark(&server, MarkDomain::Mark1, Mark(Some(1)));
9218            api.bind(&server, None, Some(server_port)).expect("failed to bind the server socket");
9219            api.listen(&server, backlog).expect("can listen");
9220            server
9221        });
9222
9223        let client_ends = WriteBackClientBuffers::default();
9224        let _client = net.with_context(LOCAL, |ctx| {
9225            let mut api = ctx.tcp_api::<I>();
9226            let socket = api.create(ProvidedBuffers::Buffers(client_ends.clone()));
9227            api.connect(&socket, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), server_port)
9228                .expect("failed to connect");
9229            socket
9230        });
9231        net.run_until_idle();
9232        net.with_context(REMOTE, |ctx| {
9233            let (accepted, _addr, _accepted_ends) =
9234                ctx.tcp_api::<I>().accept(&server).expect("failed to accept");
9235            for (domain, expected) in expected_marks {
9236                assert_eq!(ctx.tcp_api::<I>().get_mark(&accepted, domain), Mark(Some(expected)));
9237            }
9238        });
9239    }
9240
9241    #[ip_test(I)]
9242    fn do_send_can_remove_sockets_from_demux_state<I: TcpTestIpExt>()
9243    where
9244        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9245                I,
9246                TcpBindingsCtx<FakeDeviceId>,
9247                SingleStackConverter = I::SingleStackConverter,
9248                DualStackConverter = I::DualStackConverter,
9249            >,
9250    {
9251        let (mut net, client, _client_snd_end, accepted) = bind_listen_connect_accept_inner(
9252            I::UNSPECIFIED_ADDRESS,
9253            BindConfig {
9254                client_port: None,
9255                server_port: PORT_1,
9256                client_reuse_addr: false,
9257                send_test_data: false,
9258            },
9259            0,
9260            0.0,
9261        );
9262        net.with_context(LOCAL, |ctx| {
9263            let mut api = ctx.tcp_api::<I>();
9264            assert_eq!(api.shutdown(&client, ShutdownType::Send), Ok(true));
9265        });
9266        // client -> accepted FIN.
9267        assert!(!net.step().is_idle());
9268        // accepted -> client ACK.
9269        assert!(!net.step().is_idle());
9270        net.with_context(REMOTE, |ctx| {
9271            let mut api = ctx.tcp_api::<I>();
9272            assert_eq!(api.shutdown(&accepted, ShutdownType::Send), Ok(true));
9273        });
9274        // accepted -> client FIN.
9275        assert!(!net.step().is_idle());
9276        // client -> accepted ACK.
9277        assert!(!net.step().is_idle());
9278
9279        // client is now in TIME_WAIT
9280        net.with_context(LOCAL, |CtxPair { core_ctx, bindings_ctx: _ }| {
9281            TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9282                assert_eq!(socketmap.len(), 1);
9283            })
9284        });
9285        assert_matches!(
9286            &client.get().deref().socket_state,
9287            TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
9288                let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(
9289                    conn,
9290                    &I::converter()
9291                );
9292                assert_matches!(
9293                    conn,
9294                    Connection {
9295                        state: State::TimeWait(_),
9296                        ..
9297                    }
9298                );
9299            }
9300        );
9301        net.with_context(LOCAL, |ctx| {
9302            // Advance the current time but don't fire the timer.
9303            ctx.with_fake_timer_ctx_mut(|ctx| {
9304                ctx.instant.time =
9305                    ctx.instant.time.checked_add(Duration::from_secs(120 * 60)).unwrap()
9306            });
9307            // Race with `do_send`.
9308            let mut api = ctx.tcp_api::<I>();
9309            api.do_send(&client);
9310        });
9311        assert_matches!(
9312            &client.get().deref().socket_state,
9313            TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
9314                let (conn, _addr) = assert_this_stack_conn::<I, _, TcpCoreCtx<_, _>>(
9315                    conn,
9316                    &I::converter()
9317                );
9318                assert_matches!(
9319                    conn,
9320                    Connection {
9321                        state: State::Closed(_),
9322                        ..
9323                    }
9324                );
9325            }
9326        );
9327        net.with_context(LOCAL, |CtxPair { core_ctx, bindings_ctx: _ }| {
9328            TcpDemuxContext::<I, _, _>::with_demux(core_ctx, |DemuxState { socketmap }| {
9329                assert_eq!(socketmap.len(), 0);
9330            })
9331        });
9332    }
9333
9334    #[ip_test(I)]
9335    #[test_case(true; "server read over mss")]
9336    #[test_case(false; "server read under mss")]
9337    fn tcp_data_dequeue_sends_window_update<I: TcpTestIpExt>(server_read_over_mss: bool)
9338    where
9339        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<
9340                I,
9341                TcpBindingsCtx<FakeDeviceId>,
9342                SingleStackConverter = I::SingleStackConverter,
9343                DualStackConverter = I::DualStackConverter,
9344            >,
9345    {
9346        const EXTRA_DATA_AMOUNT: usize = 128;
9347        set_logger_for_test();
9348
9349        let (mut net, client, client_snd_end, accepted) = bind_listen_connect_accept_inner(
9350            I::UNSPECIFIED_ADDRESS,
9351            BindConfig {
9352                client_port: None,
9353                server_port: PORT_1,
9354                client_reuse_addr: false,
9355                send_test_data: false,
9356            },
9357            0,
9358            0.0,
9359        );
9360
9361        let accepted_rcv_bufsize = net
9362            .with_context(REMOTE, |ctx| ctx.tcp_api::<I>().receive_buffer_size(&accepted).unwrap());
9363
9364        // Send enough data to the server to fill up its receive buffer.
9365        client_snd_end.lock().extend(core::iter::repeat(0xAB).take(accepted_rcv_bufsize));
9366        net.with_context(LOCAL, |ctx| {
9367            ctx.tcp_api().do_send(&client);
9368        });
9369        net.run_until_idle();
9370
9371        // From now on, we don't want to trigger timers
9372        // because that would result in either:
9373        // 1. The client to time out, since the server isn't going to read any
9374        //    data from its buffer.
9375        // 2. ZWP from the client, which would make this test pointless.
9376
9377        // Push extra data into the send buffer that won't be sent because the
9378        // receive window is zero.
9379        client_snd_end.lock().extend(core::iter::repeat(0xAB).take(EXTRA_DATA_AMOUNT));
9380        net.with_context(LOCAL, |ctx| {
9381            ctx.tcp_api().do_send(&client);
9382        });
9383        let _ = net.step_deliver_frames();
9384
9385        let send_buf_len = net
9386            .with_context(LOCAL, |ctx| {
9387                ctx.tcp_api::<I>().with_send_buffer(&client, |buf| {
9388                    let BufferLimits { len, capacity: _ } = buf.limits();
9389                    len
9390                })
9391            })
9392            .unwrap();
9393        assert_eq!(send_buf_len, EXTRA_DATA_AMOUNT);
9394
9395        if server_read_over_mss {
9396            // Clear out the receive buffer
9397            let nread = net
9398                .with_context(REMOTE, |ctx| {
9399                    ctx.tcp_api::<I>().with_receive_buffer(&accepted, |buf| {
9400                        buf.lock()
9401                            .read_with(|readable| readable.into_iter().map(|buf| buf.len()).sum())
9402                    })
9403                })
9404                .unwrap();
9405            assert_eq!(nread, accepted_rcv_bufsize);
9406
9407            // The server sends a window update because the window went from 0 to
9408            // larger than MSS.
9409            net.with_context(REMOTE, |ctx| ctx.tcp_api::<I>().on_receive_buffer_read(&accepted));
9410
9411            let (server_snd_max, server_acknum) = {
9412                let socket = accepted.get();
9413                let state = assert_matches!(
9414                    &socket.deref().socket_state,
9415                    TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
9416                        assert_matches!(I::get_state(conn), State::Established(e) => e)
9417                    }
9418                );
9419
9420                (state.snd.max, state.rcv.nxt())
9421            };
9422
9423            // Deliver the window update to the client.
9424            assert_eq!(
9425                net.step_deliver_frames_with(|_, meta, frame| {
9426                    let mut buffer = Buf::new(frame.clone(), ..);
9427
9428                    let (packet_seq, packet_ack, window_size, body_len) = match I::VERSION {
9429                        IpVersion::V4 => {
9430                            let meta =
9431                                assert_matches!(&meta, DualStackSendIpPacketMeta::V4(v4) => v4);
9432
9433                            // Server -> Client.
9434                            assert_eq!(*meta.src_ip, Ipv4::TEST_ADDRS.remote_ip.into_addr());
9435                            assert_eq!(*meta.dst_ip, Ipv4::TEST_ADDRS.local_ip.into_addr());
9436
9437                            let parsed = buffer
9438                                .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9439                                    *meta.src_ip,
9440                                    *meta.dst_ip,
9441                                ))
9442                                .expect("failed to parse");
9443
9444                            (
9445                                parsed.seq_num(),
9446                                parsed.ack_num().unwrap(),
9447                                parsed.window_size(),
9448                                parsed.body().len(),
9449                            )
9450                        }
9451                        IpVersion::V6 => {
9452                            let meta =
9453                                assert_matches!(&meta, DualStackSendIpPacketMeta::V6(v6) => v6);
9454
9455                            // Server -> Client.
9456                            assert_eq!(*meta.src_ip, Ipv6::TEST_ADDRS.remote_ip.into_addr());
9457                            assert_eq!(*meta.dst_ip, Ipv6::TEST_ADDRS.local_ip.into_addr());
9458
9459                            let parsed = buffer
9460                                .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9461                                    *meta.src_ip,
9462                                    *meta.dst_ip,
9463                                ))
9464                                .expect("failed to parse");
9465
9466                            (
9467                                parsed.seq_num(),
9468                                parsed.ack_num().unwrap(),
9469                                parsed.window_size(),
9470                                parsed.body().len(),
9471                            )
9472                        }
9473                    };
9474
9475                    // Ensure that this is actually a window update, and no data
9476                    // is being sent or ACKed.
9477                    assert_eq!(packet_seq, u32::from(server_snd_max));
9478                    assert_eq!(packet_ack, u32::from(server_acknum));
9479                    assert_eq!(window_size, 65535);
9480                    assert_eq!(body_len, 0);
9481
9482                    Some((meta, frame))
9483                })
9484                .frames_sent,
9485                1
9486            );
9487
9488            // Deliver the data send to the server.
9489            assert_eq!(
9490                net.step_deliver_frames_with(|_, meta, frame| {
9491                    let mut buffer = Buf::new(frame.clone(), ..);
9492
9493                    let body_len = match I::VERSION {
9494                        IpVersion::V4 => {
9495                            let meta =
9496                                assert_matches!(&meta, DualStackSendIpPacketMeta::V4(v4) => v4);
9497
9498                            // Client -> Server.
9499                            assert_eq!(*meta.src_ip, Ipv4::TEST_ADDRS.local_ip.into_addr());
9500                            assert_eq!(*meta.dst_ip, Ipv4::TEST_ADDRS.remote_ip.into_addr());
9501
9502                            let parsed = buffer
9503                                .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9504                                    *meta.src_ip,
9505                                    *meta.dst_ip,
9506                                ))
9507                                .expect("failed to parse");
9508
9509                            parsed.body().len()
9510                        }
9511                        IpVersion::V6 => {
9512                            let meta =
9513                                assert_matches!(&meta, DualStackSendIpPacketMeta::V6(v6) => v6);
9514
9515                            // Client -> Server.
9516                            assert_eq!(*meta.src_ip, Ipv6::TEST_ADDRS.local_ip.into_addr());
9517                            assert_eq!(*meta.dst_ip, Ipv6::TEST_ADDRS.remote_ip.into_addr());
9518
9519                            let parsed = buffer
9520                                .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9521                                    *meta.src_ip,
9522                                    *meta.dst_ip,
9523                                ))
9524                                .expect("failed to parse");
9525
9526                            parsed.body().len()
9527                        }
9528                    };
9529
9530                    assert_eq!(body_len, EXTRA_DATA_AMOUNT);
9531
9532                    Some((meta, frame))
9533                })
9534                .frames_sent,
9535                1
9536            );
9537
9538            // Deliver the ACK of the data send to the client so it will flush the
9539            // data from its buffers.
9540            assert_eq!(
9541                net.step_deliver_frames_with(|_, meta, frame| {
9542                    let mut buffer = Buf::new(frame.clone(), ..);
9543
9544                    let (packet_seq, packet_ack, body_len) = match I::VERSION {
9545                        IpVersion::V4 => {
9546                            let meta =
9547                                assert_matches!(&meta, DualStackSendIpPacketMeta::V4(v4) => v4);
9548
9549                            // Server -> Client.
9550                            assert_eq!(*meta.src_ip, Ipv4::TEST_ADDRS.remote_ip.into_addr());
9551                            assert_eq!(*meta.dst_ip, Ipv4::TEST_ADDRS.local_ip.into_addr());
9552
9553                            let parsed = buffer
9554                                .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9555                                    *meta.src_ip,
9556                                    *meta.dst_ip,
9557                                ))
9558                                .expect("failed to parse");
9559
9560                            (parsed.seq_num(), parsed.ack_num().unwrap(), parsed.body().len())
9561                        }
9562                        IpVersion::V6 => {
9563                            let meta =
9564                                assert_matches!(&meta, DualStackSendIpPacketMeta::V6(v6) => v6);
9565
9566                            // Server -> Client.
9567                            assert_eq!(*meta.src_ip, Ipv6::TEST_ADDRS.remote_ip.into_addr());
9568                            assert_eq!(*meta.dst_ip, Ipv6::TEST_ADDRS.local_ip.into_addr());
9569
9570                            let parsed = buffer
9571                                .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
9572                                    *meta.src_ip,
9573                                    *meta.dst_ip,
9574                                ))
9575                                .expect("failed to parse");
9576
9577                            (parsed.seq_num(), parsed.ack_num().unwrap(), parsed.body().len())
9578                        }
9579                    };
9580
9581                    assert_eq!(packet_seq, u32::from(server_snd_max));
9582                    assert_eq!(
9583                        packet_ack,
9584                        u32::from(server_acknum) + u32::try_from(EXTRA_DATA_AMOUNT).unwrap()
9585                    );
9586                    assert_eq!(body_len, 0);
9587
9588                    Some((meta, frame))
9589                })
9590                .frames_sent,
9591                1
9592            );
9593
9594            let send_buf_len = net
9595                .with_context(LOCAL, |ctx| {
9596                    ctx.tcp_api::<I>().with_send_buffer(&client, |buf| {
9597                        let BufferLimits { len, capacity: _ } = buf.limits();
9598                        len
9599                    })
9600                })
9601                .unwrap();
9602            assert_eq!(send_buf_len, 0);
9603        } else {
9604            // Read a single byte out of the receive buffer, which is guaranteed
9605            // to be less than MSS.
9606            let nread = net
9607                .with_context(REMOTE, |ctx| {
9608                    ctx.tcp_api::<I>()
9609                        .with_receive_buffer(&accepted, |buf| buf.lock().read_with(|_readable| 1))
9610                })
9611                .unwrap();
9612            assert_eq!(nread, 1);
9613
9614            // The server won't send a window update because it wouldn't be
9615            // advertising a window that's larger than the MSS.
9616            net.with_context(REMOTE, |ctx| ctx.tcp_api::<I>().on_receive_buffer_read(&accepted));
9617            assert_eq!(net.step_deliver_frames().frames_sent, 0);
9618
9619            let send_buf_len = net
9620                .with_context(LOCAL, |ctx| {
9621                    ctx.tcp_api::<I>().with_send_buffer(&client, |buf| {
9622                        let BufferLimits { len, capacity: _ } = buf.limits();
9623                        len
9624                    })
9625                })
9626                .unwrap();
9627            // The client didn't hear about the data being read, since no window
9628            // update was sent.
9629            assert_eq!(send_buf_len, EXTRA_DATA_AMOUNT);
9630        }
9631    }
9632
9633    impl<I: DualStackIpExt, D: WeakDeviceIdentifier, BT: TcpBindingsTypes> TcpSocketId<I, D, BT> {
9634        fn established_state(
9635            state: &impl Deref<Target = TcpSocketState<I, D, BT>>,
9636        ) -> &Established<BT::Instant, BT::ReceiveBuffer, BT::SendBuffer> {
9637            assert_matches!(
9638                &state.deref().socket_state,
9639                TcpSocketStateInner::Bound(BoundSocketState::Connected { conn, .. }) => {
9640                    assert_matches!(I::get_state(conn), State::Established(e) => e)
9641                }
9642            )
9643        }
9644
9645        fn mss(&self) -> Mss {
9646            *Self::established_state(&self.get()).snd.congestion_control().mss().mss()
9647        }
9648
9649        fn cwnd(&self) -> CongestionWindow {
9650            Self::established_state(&self.get()).snd.congestion_control().inspect_cwnd()
9651        }
9652    }
9653
9654    #[derive(PartialEq)]
9655    enum MssUpdate {
9656        Decrease,
9657        DecreaseBelowMin,
9658        Same,
9659        Increase,
9660    }
9661
9662    #[ip_test(I)]
9663    #[test_case(MssUpdate::Decrease; "update if decrease")]
9664    #[test_case(MssUpdate::DecreaseBelowMin; "update to min if decreased below min")]
9665    #[test_case(MssUpdate::Same; "ignore if same")]
9666    #[test_case(MssUpdate::Increase; "ignore if increase")]
9667    fn pmtu_update_mss<I: TcpTestIpExt + IcmpIpExt>(mss_update: MssUpdate)
9668    where
9669        TcpCoreCtx<FakeDeviceId, TcpBindingsCtx<FakeDeviceId>>: TcpContext<I, TcpBindingsCtx<FakeDeviceId>>
9670            + TcpContext<I::OtherVersion, TcpBindingsCtx<FakeDeviceId>>,
9671    {
9672        let mut net = new_test_net::<I>();
9673
9674        let server = net.with_context(REMOTE, |ctx| {
9675            let mut api = ctx.tcp_api::<I>();
9676            let server = api.create(Default::default());
9677            api.bind(&server, None, Some(PORT_1)).expect("bind to port");
9678            api.listen(&server, NonZeroUsize::MIN).expect("can listen");
9679            server
9680        });
9681
9682        let client_buffers = WriteBackClientBuffers::default();
9683        let client = net.with_context(LOCAL, |ctx| {
9684            let mut api = ctx.tcp_api::<I>();
9685            let client = api.create(ProvidedBuffers::Buffers(client_buffers.clone()));
9686            api.connect(&client, Some(ZonedAddr::Unzoned(I::TEST_ADDRS.remote_ip)), PORT_1)
9687                .expect("connect to server");
9688            client
9689        });
9690
9691        // Allow the connection to be established.
9692        net.run_until_idle();
9693        let (_accepted, accepted_buffers) = net.with_context(REMOTE, |ctx| {
9694            let (accepted, _addr, accepted_ends) =
9695                ctx.tcp_api::<I>().accept(&server).expect("accept incoming connection");
9696            (accepted, accepted_ends)
9697        });
9698
9699        let initial_mss = client.mss();
9700
9701        // The minimum link MTU needed to support TCP connections.
9702        let min_mtu = u32::from(Mss::MIN)
9703            + I::IP_HEADER_LENGTH.get()
9704            + packet_formats::tcp::HDR_PREFIX_LEN as u32;
9705
9706        let pmtu_update = match mss_update {
9707            MssUpdate::DecreaseBelowMin => Mtu::new(min_mtu - 1),
9708            MssUpdate::Decrease => Mtu::new(min_mtu),
9709            MssUpdate::Same => LINK_MTU,
9710            MssUpdate::Increase => Mtu::max(),
9711        };
9712        let icmp_error = I::map_ip(
9713            (),
9714            |()| {
9715                let mtu = u16::try_from(pmtu_update.get()).unwrap_or(u16::MAX);
9716                let mtu = NonZeroU16::new(mtu).unwrap();
9717                Icmpv4ErrorCode::DestUnreachable(
9718                    Icmpv4DestUnreachableCode::FragmentationRequired,
9719                    IcmpDestUnreachable::new_for_frag_req(mtu),
9720                )
9721            },
9722            |()| Icmpv6ErrorCode::PacketTooBig(pmtu_update),
9723        );
9724
9725        // Send a payload that is large enough that it will need to be re-segmented if
9726        // the PMTU decreases, and deliver a PMTU update.
9727        let ClientBuffers { send: client_snd_end, receive: _ } =
9728            client_buffers.0.as_ref().lock().take().unwrap();
9729        let payload = vec![0xFF; min_mtu.try_into().unwrap()];
9730        client_snd_end.lock().extend_from_slice(&payload);
9731        net.with_context(LOCAL, |ctx| {
9732            ctx.tcp_api().do_send(&client);
9733            let (core_ctx, bindings_ctx) = ctx.contexts();
9734            let frames = core_ctx.ip_socket_ctx.take_frames();
9735            let frame = assert_matches!(&frames[..], [(_meta, frame)] => frame);
9736
9737            deliver_icmp_error::<I, _, _>(
9738                core_ctx,
9739                bindings_ctx,
9740                I::TEST_ADDRS.local_ip,
9741                I::TEST_ADDRS.remote_ip,
9742                &frame[0..8],
9743                icmp_error,
9744            );
9745        });
9746
9747        let requested_mms = Mms::from_mtu::<I>(pmtu_update, 0 /* no IP options */).unwrap();
9748        let requested_mss = Mss::from_mms(requested_mms);
9749        match mss_update {
9750            MssUpdate::DecreaseBelowMin => {
9751                // NB: The requested MSS is invalid.
9752                assert_eq!(requested_mss, None);
9753            }
9754            MssUpdate::Decrease => {
9755                assert_matches!(requested_mss, Some(mss) if mss < initial_mss);
9756            }
9757            MssUpdate::Same => {
9758                assert_eq!(requested_mss, Some(initial_mss));
9759            }
9760            MssUpdate::Increase => {
9761                assert_matches!(requested_mss, Some(mss) if mss > initial_mss);
9762            }
9763        };
9764
9765        // The socket should only update its MSS if the new MSS is a decrease.
9766        match mss_update {
9767            MssUpdate::Decrease | MssUpdate::DecreaseBelowMin => {}
9768            MssUpdate::Same | MssUpdate::Increase => {
9769                assert_eq!(client.mss(), initial_mss);
9770                return;
9771            }
9772        }
9773
9774        // Note the MSS & MMS used by the stack will be clamped to minimum valid
9775        // value.
9776        let expected_mss = requested_mss.unwrap_or(Mss::MIN);
9777        let expected_mms = usize::from(expected_mss) + packet_formats::tcp::HDR_PREFIX_LEN;
9778
9779        assert_eq!(client.mss(), expected_mss);
9780        // The PMTU update should not represent a congestion event.
9781        assert_gt!(client.cwnd().cwnd(), u32::from(expected_mss));
9782
9783        // The segment that was too large should be eagerly retransmitted.
9784        net.with_context(LOCAL, |ctx| {
9785            let frames = ctx.core_ctx().ip_socket_ctx.frames();
9786            let frame = assert_matches!(&frames[..], [(_meta, frame)] => frame);
9787            assert_eq!(frame.len(), expected_mms);
9788        });
9789
9790        // The remaining in-flight segment(s) are retransmitted via the retransmission
9791        // timer (rather than immediately).
9792        net.run_until_idle();
9793        let ClientBuffers { send: _, receive: accepted_rcv_end } = accepted_buffers;
9794        let read = accepted_rcv_end.lock().read_with(|avail| {
9795            let avail = avail.concat();
9796            assert_eq!(avail, payload);
9797            avail.len()
9798        });
9799        assert_eq!(read, payload.len());
9800    }
9801}