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