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