netstack3_datagram/
spec_context.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Datagram spec context definitions.
6//!
7//! This module contains the mirror traits for the datagram core context traits.
8//! They exist in a separate module so that:
9//!
10//! * They're not in scope in the main datagram module, avoiding conflicting
11//!   names.
12//! * The boilerplate around the mirror traits is mostly out of the way.
13
14use netstack3_base::socket::MaybeDualStack;
15use netstack3_base::{AnyDevice, CoreTxMetadataContext, DeviceIdContext};
16use netstack3_ip::{MulticastMembershipHandler, TransportIpContext};
17
18use crate::internal::datagram::{
19    BoundSocketsFromSpec, DatagramBindingsTypes, DatagramBoundStateContext,
20    DatagramIpSpecificSocketOptions, DatagramSocketMapSpec, DatagramSocketSet, DatagramSocketSpec,
21    DatagramStateContext, DualStackConverter, DualStackDatagramBoundStateContext, DualStackIpExt,
22    IpExt, IpOptions, NonDualStackConverter, NonDualStackDatagramBoundStateContext, SocketState,
23};
24use crate::internal::sndbuf::TxMetadata;
25
26/// A mirror trait of [`DatagramStateContext`] allowing foreign crates to
27/// provide blanket impls for it.
28///
29/// This trait repeats all the definitions in [`DatagramStateContext`] to
30/// provide blanket impls from an implementation on the type implementing
31/// [`DatagramSocketSpec`], which is local for foreign implementers.
32///
33/// See [`DatagramStateContext`] for details.
34#[allow(missing_docs)]
35pub trait DatagramSpecStateContext<
36    I: IpExt,
37    CC: DeviceIdContext<AnyDevice>,
38    BC: DatagramBindingsTypes,
39>: DatagramSocketSpec
40{
41    type SocketsStateCtx<'a>: DatagramBoundStateContext<I, BC, Self>
42        + DeviceIdContext<AnyDevice, DeviceId = CC::DeviceId, WeakDeviceId = CC::WeakDeviceId>;
43
44    fn with_all_sockets_mut<O, F: FnOnce(&mut DatagramSocketSet<I, CC::WeakDeviceId, Self>) -> O>(
45        core_ctx: &mut CC,
46        cb: F,
47    ) -> O;
48
49    fn with_all_sockets<O, F: FnOnce(&DatagramSocketSet<I, CC::WeakDeviceId, Self>) -> O>(
50        core_ctx: &mut CC,
51        cb: F,
52    ) -> O;
53
54    fn with_socket_state<
55        O,
56        F: FnOnce(&mut Self::SocketsStateCtx<'_>, &SocketState<I, CC::WeakDeviceId, Self>) -> O,
57    >(
58        core_ctx: &mut CC,
59        id: &Self::SocketId<I, CC::WeakDeviceId>,
60        cb: F,
61    ) -> O;
62
63    fn with_socket_state_mut<
64        O,
65        F: FnOnce(&mut Self::SocketsStateCtx<'_>, &mut SocketState<I, CC::WeakDeviceId, Self>) -> O,
66    >(
67        core_ctx: &mut CC,
68        id: &Self::SocketId<I, CC::WeakDeviceId>,
69        cb: F,
70    ) -> O;
71
72    fn for_each_socket<
73        F: FnMut(
74            &mut Self::SocketsStateCtx<'_>,
75            &Self::SocketId<I, CC::WeakDeviceId>,
76            &SocketState<I, CC::WeakDeviceId, Self>,
77        ),
78    >(
79        core_ctx: &mut CC,
80        cb: F,
81    );
82}
83
84impl<I, CC, BC, S> DatagramStateContext<I, BC, S> for CC
85where
86    I: IpExt,
87    BC: DatagramBindingsTypes,
88    CC: DeviceIdContext<AnyDevice>,
89    S: DatagramSpecStateContext<I, CC, BC>,
90{
91    type SocketsStateCtx<'a> = S::SocketsStateCtx<'a>;
92
93    fn with_all_sockets_mut<O, F: FnOnce(&mut DatagramSocketSet<I, Self::WeakDeviceId, S>) -> O>(
94        &mut self,
95        cb: F,
96    ) -> O {
97        S::with_all_sockets_mut(self, cb)
98    }
99
100    fn with_all_sockets<O, F: FnOnce(&DatagramSocketSet<I, Self::WeakDeviceId, S>) -> O>(
101        &mut self,
102        cb: F,
103    ) -> O {
104        S::with_all_sockets(self, cb)
105    }
106
107    fn with_socket_state<
108        O,
109        F: FnOnce(&mut Self::SocketsStateCtx<'_>, &SocketState<I, Self::WeakDeviceId, S>) -> O,
110    >(
111        &mut self,
112        id: &S::SocketId<I, Self::WeakDeviceId>,
113        cb: F,
114    ) -> O {
115        S::with_socket_state(self, id, cb)
116    }
117
118    fn with_socket_state_mut<
119        O,
120        F: FnOnce(&mut Self::SocketsStateCtx<'_>, &mut SocketState<I, Self::WeakDeviceId, S>) -> O,
121    >(
122        &mut self,
123        id: &S::SocketId<I, Self::WeakDeviceId>,
124        cb: F,
125    ) -> O {
126        S::with_socket_state_mut(self, id, cb)
127    }
128
129    fn for_each_socket<
130        F: FnMut(
131            &mut Self::SocketsStateCtx<'_>,
132            &S::SocketId<I, Self::WeakDeviceId>,
133            &SocketState<I, Self::WeakDeviceId, S>,
134        ),
135    >(
136        &mut self,
137        cb: F,
138    ) {
139        S::for_each_socket(self, cb)
140    }
141}
142
143/// A mirror trait of [`DatagramBoundStateContext`] allowing foreign crates to
144/// provide blanket impls for it.
145///
146/// This trait repeats all the definitions in [`DatagramBoundStateContext`] to
147/// provide blanket impls from an implementation on the type implementing
148/// [`DatagramSocketSpec`], which is local for foreign implementers.
149///
150/// See [`DatagramBoundStateContext`] for details.
151#[allow(missing_docs)]
152pub trait DatagramSpecBoundStateContext<
153    I: IpExt + DualStackIpExt,
154    CC: DeviceIdContext<AnyDevice>,
155    BC: DatagramBindingsTypes,
156>: DatagramSocketSpec
157{
158    type IpSocketsCtx<'a>: TransportIpContext<I, BC>
159        + CoreTxMetadataContext<TxMetadata<I, CC::WeakDeviceId, Self>, BC>
160        + MulticastMembershipHandler<I, BC>
161        + DeviceIdContext<AnyDevice, DeviceId = CC::DeviceId, WeakDeviceId = CC::WeakDeviceId>;
162
163    type DualStackContext: DualStackDatagramBoundStateContext<
164        I,
165        BC,
166        Self,
167        DeviceId = CC::DeviceId,
168        WeakDeviceId = CC::WeakDeviceId,
169    >;
170
171    type NonDualStackContext: NonDualStackDatagramBoundStateContext<
172        I,
173        BC,
174        Self,
175        DeviceId = CC::DeviceId,
176        WeakDeviceId = CC::WeakDeviceId,
177    >;
178
179    fn with_bound_sockets<
180        O,
181        F: FnOnce(&mut Self::IpSocketsCtx<'_>, &BoundSocketsFromSpec<I, CC, Self>) -> O,
182    >(
183        core_ctx: &mut CC,
184        cb: F,
185    ) -> O;
186
187    fn with_bound_sockets_mut<
188        O,
189        F: FnOnce(&mut Self::IpSocketsCtx<'_>, &mut BoundSocketsFromSpec<I, CC, Self>) -> O,
190    >(
191        core_ctx: &mut CC,
192        cb: F,
193    ) -> O;
194
195    fn dual_stack_context(
196        core_ctx: &mut CC,
197    ) -> MaybeDualStack<&mut Self::DualStackContext, &mut Self::NonDualStackContext>;
198
199    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
200        core_ctx: &mut CC,
201        cb: F,
202    ) -> O;
203}
204
205impl<I, CC, BC, S> DatagramBoundStateContext<I, BC, S> for CC
206where
207    I: IpExt + DualStackIpExt,
208    CC: DeviceIdContext<AnyDevice>,
209    BC: DatagramBindingsTypes,
210    S: DatagramSpecBoundStateContext<I, CC, BC>,
211{
212    type IpSocketsCtx<'a> = S::IpSocketsCtx<'a>;
213    type DualStackContext = S::DualStackContext;
214    type NonDualStackContext = S::NonDualStackContext;
215
216    fn with_bound_sockets<
217        O,
218        F: FnOnce(&mut Self::IpSocketsCtx<'_>, &BoundSocketsFromSpec<I, CC, S>) -> O,
219    >(
220        &mut self,
221        cb: F,
222    ) -> O {
223        S::with_bound_sockets(self, cb)
224    }
225
226    fn with_bound_sockets_mut<
227        O,
228        F: FnOnce(&mut Self::IpSocketsCtx<'_>, &mut BoundSocketsFromSpec<I, CC, S>) -> O,
229    >(
230        &mut self,
231        cb: F,
232    ) -> O {
233        S::with_bound_sockets_mut(self, cb)
234    }
235
236    fn dual_stack_context(
237        &mut self,
238    ) -> MaybeDualStack<&mut Self::DualStackContext, &mut Self::NonDualStackContext> {
239        S::dual_stack_context(self)
240    }
241
242    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
243        &mut self,
244        cb: F,
245    ) -> O {
246        S::with_transport_context(self, cb)
247    }
248}
249
250/// A mirror trait of [`DualStackDatagramBoundStateContext`] allowing foreign
251/// crates to provide blanket impls for it.
252///
253/// This trait repeats all the definitions in
254/// [`DualStackDatagramBoundStateContext`] to provide blanket impls from an
255/// implementation on the type implementing [`DatagramSocketSpec`], which is
256/// local for foreign implementers.
257///
258/// See [`DualStackDatagramBoundStateContext`] for details.
259#[allow(missing_docs)]
260pub trait DualStackDatagramSpecBoundStateContext<
261    I: IpExt,
262    CC: DeviceIdContext<AnyDevice>,
263    BC: DatagramBindingsTypes,
264>: DatagramSocketSpec
265{
266    type IpSocketsCtx<'a>: TransportIpContext<I, BC>
267        + CoreTxMetadataContext<TxMetadata<I, CC::WeakDeviceId, Self>, BC>
268        + DeviceIdContext<AnyDevice, DeviceId = CC::DeviceId, WeakDeviceId = CC::WeakDeviceId>
269        + TransportIpContext<I::OtherVersion, BC>
270        + CoreTxMetadataContext<TxMetadata<I::OtherVersion, CC::WeakDeviceId, Self>, BC>;
271
272    fn dual_stack_enabled(
273        core_ctx: &CC,
274        state: &impl AsRef<IpOptions<I, CC::WeakDeviceId, Self>>,
275    ) -> bool;
276
277    fn to_other_socket_options<'a>(
278        core_ctx: &CC,
279        state: &'a IpOptions<I, CC::WeakDeviceId, Self>,
280    ) -> &'a DatagramIpSpecificSocketOptions<I::OtherVersion, CC::WeakDeviceId>;
281
282    fn ds_converter(core_ctx: &CC) -> impl DualStackConverter<I, CC::WeakDeviceId, Self>;
283
284    fn to_other_bound_socket_id(
285        core_ctx: &CC,
286        id: &Self::SocketId<I, CC::WeakDeviceId>,
287    ) -> <Self::SocketMapSpec<I::OtherVersion, CC::WeakDeviceId> as DatagramSocketMapSpec<
288        I::OtherVersion,
289        CC::WeakDeviceId,
290        Self::AddrSpec,
291    >>::BoundSocketId;
292
293    fn with_both_bound_sockets_mut<
294        O,
295        F: FnOnce(
296            &mut Self::IpSocketsCtx<'_>,
297            &mut BoundSocketsFromSpec<I, CC, Self>,
298            &mut BoundSocketsFromSpec<I::OtherVersion, CC, Self>,
299        ) -> O,
300    >(
301        core_ctx: &mut CC,
302        cb: F,
303    ) -> O;
304
305    fn with_other_bound_sockets_mut<
306        O,
307        F: FnOnce(
308            &mut Self::IpSocketsCtx<'_>,
309            &mut BoundSocketsFromSpec<I::OtherVersion, CC, Self>,
310        ) -> O,
311    >(
312        core_ctx: &mut CC,
313        cb: F,
314    ) -> O;
315
316    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
317        core_ctx: &mut CC,
318        cb: F,
319    ) -> O;
320}
321
322impl<I, CC, BC, S> DualStackDatagramBoundStateContext<I, BC, S> for CC
323where
324    I: IpExt,
325    CC: DeviceIdContext<AnyDevice>,
326    BC: DatagramBindingsTypes,
327    S: DualStackDatagramSpecBoundStateContext<I, CC, BC>,
328{
329    type IpSocketsCtx<'a> = S::IpSocketsCtx<'a>;
330
331    fn dual_stack_enabled(&self, state: &impl AsRef<IpOptions<I, Self::WeakDeviceId, S>>) -> bool {
332        S::dual_stack_enabled(self, state)
333    }
334
335    fn to_other_socket_options<'a>(
336        &self,
337        state: &'a IpOptions<I, Self::WeakDeviceId, S>,
338    ) -> &'a DatagramIpSpecificSocketOptions<I::OtherVersion, Self::WeakDeviceId> {
339        S::to_other_socket_options(self, state)
340    }
341
342    fn ds_converter(&self) -> impl DualStackConverter<I, Self::WeakDeviceId, S> {
343        S::ds_converter(self)
344    }
345
346    fn to_other_bound_socket_id(
347        &self,
348        id: &S::SocketId<I, Self::WeakDeviceId>,
349    ) -> <S::SocketMapSpec<I::OtherVersion, Self::WeakDeviceId> as DatagramSocketMapSpec<
350        I::OtherVersion,
351        Self::WeakDeviceId,
352        S::AddrSpec,
353    >>::BoundSocketId {
354        S::to_other_bound_socket_id(self, id)
355    }
356
357    fn with_both_bound_sockets_mut<
358        O,
359        F: FnOnce(
360            &mut Self::IpSocketsCtx<'_>,
361            &mut BoundSocketsFromSpec<I, Self, S>,
362            &mut BoundSocketsFromSpec<I::OtherVersion, Self, S>,
363        ) -> O,
364    >(
365        &mut self,
366        cb: F,
367    ) -> O {
368        S::with_both_bound_sockets_mut(self, cb)
369    }
370
371    fn with_other_bound_sockets_mut<
372        O,
373        F: FnOnce(
374            &mut Self::IpSocketsCtx<'_>,
375            &mut BoundSocketsFromSpec<I::OtherVersion, Self, S>,
376        ) -> O,
377    >(
378        &mut self,
379        cb: F,
380    ) -> O {
381        S::with_other_bound_sockets_mut(self, cb)
382    }
383
384    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
385        &mut self,
386        cb: F,
387    ) -> O {
388        S::with_transport_context(self, cb)
389    }
390}
391
392/// A mirror trait of [`NonDualStackDatagramBoundStateContext`] allowing foreign
393/// crates to provide blanket impls for it.
394///
395/// This trait repeats all the definitions in
396/// [`NonDualStackDatagramBoundStateContext`] to provide blanket impls from an
397/// implementation on the type implementing [`DatagramSocketSpec`], which is
398/// local for foreign implementers.
399///
400/// See [`NonDualStackDatagramBoundStateContext`] for details.
401#[allow(missing_docs)]
402pub trait NonDualStackDatagramSpecBoundStateContext<I: IpExt, CC: DeviceIdContext<AnyDevice>, BC>:
403    DatagramSocketSpec
404{
405    fn nds_converter(core_ctx: &CC) -> impl NonDualStackConverter<I, CC::WeakDeviceId, Self>;
406}
407
408impl<I, CC, BC, S> NonDualStackDatagramBoundStateContext<I, BC, S> for CC
409where
410    I: IpExt,
411    CC: DeviceIdContext<AnyDevice>,
412    S: NonDualStackDatagramSpecBoundStateContext<I, CC, BC>,
413{
414    fn nds_converter(&self) -> impl NonDualStackConverter<I, CC::WeakDeviceId, S> {
415        S::nds_converter(self)
416    }
417}