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