Skip to main content

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