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