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