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