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