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