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