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