netstack3_tcp/
socket.rs

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