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