Skip to main content

netstack3_tcp/
socket.rs

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