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