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