netstack3_tcp/
socket.rs

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