netstack3_tcp/
socket.rs

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