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