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