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: &CC,
197    ) -> MaybeDualStack<&Self::DualStackContext, &Self::NonDualStackContext>;
198
199    fn dual_stack_context_mut(
200        core_ctx: &mut CC,
201    ) -> MaybeDualStack<&mut Self::DualStackContext, &mut Self::NonDualStackContext>;
202
203    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
204        core_ctx: &mut CC,
205        cb: F,
206    ) -> O;
207}
208
209impl<I, CC, BC, S> DatagramBoundStateContext<I, BC, S> for CC
210where
211    I: IpExt + DualStackIpExt,
212    CC: DeviceIdContext<AnyDevice>,
213    BC: DatagramBindingsTypes,
214    S: DatagramSpecBoundStateContext<I, CC, BC>,
215{
216    type IpSocketsCtx<'a> = S::IpSocketsCtx<'a>;
217    type DualStackContext = S::DualStackContext;
218    type NonDualStackContext = S::NonDualStackContext;
219
220    fn with_bound_sockets<
221        O,
222        F: FnOnce(&mut Self::IpSocketsCtx<'_>, &BoundSocketsFromSpec<I, CC, S>) -> O,
223    >(
224        &mut self,
225        cb: F,
226    ) -> O {
227        S::with_bound_sockets(self, cb)
228    }
229
230    fn with_bound_sockets_mut<
231        O,
232        F: FnOnce(&mut Self::IpSocketsCtx<'_>, &mut BoundSocketsFromSpec<I, CC, S>) -> O,
233    >(
234        &mut self,
235        cb: F,
236    ) -> O {
237        S::with_bound_sockets_mut(self, cb)
238    }
239
240    fn dual_stack_context(
241        &self,
242    ) -> MaybeDualStack<&Self::DualStackContext, &Self::NonDualStackContext> {
243        S::dual_stack_context(self)
244    }
245
246    fn dual_stack_context_mut(
247        &mut self,
248    ) -> MaybeDualStack<&mut Self::DualStackContext, &mut Self::NonDualStackContext> {
249        S::dual_stack_context_mut(self)
250    }
251
252    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
253        &mut self,
254        cb: F,
255    ) -> O {
256        S::with_transport_context(self, cb)
257    }
258}
259
260/// A mirror trait of [`DualStackDatagramBoundStateContext`] allowing foreign
261/// crates to provide blanket impls for it.
262///
263/// This trait repeats all the definitions in
264/// [`DualStackDatagramBoundStateContext`] to provide blanket impls from an
265/// implementation on the type implementing [`DatagramSocketSpec`], which is
266/// local for foreign implementers.
267///
268/// See [`DualStackDatagramBoundStateContext`] for details.
269#[allow(missing_docs)]
270pub trait DualStackDatagramSpecBoundStateContext<
271    I: IpExt,
272    CC: DeviceIdContext<AnyDevice>,
273    BC: DatagramBindingsTypes,
274>: DatagramSocketSpec
275{
276    type IpSocketsCtx<'a>: TransportIpContext<I, BC>
277        + CoreTxMetadataContext<TxMetadata<I, CC::WeakDeviceId, Self>, BC>
278        + DeviceIdContext<AnyDevice, DeviceId = CC::DeviceId, WeakDeviceId = CC::WeakDeviceId>
279        + TransportIpContext<I::OtherVersion, BC>
280        + CoreTxMetadataContext<TxMetadata<I::OtherVersion, CC::WeakDeviceId, Self>, BC>;
281
282    fn dual_stack_enabled(core_ctx: &CC, ip_options: &IpOptions<I, CC::WeakDeviceId, Self>)
283    -> bool;
284
285    fn to_other_socket_options<'a>(
286        core_ctx: &CC,
287        state: &'a IpOptions<I, CC::WeakDeviceId, Self>,
288    ) -> &'a DatagramIpSpecificSocketOptions<I::OtherVersion, CC::WeakDeviceId>;
289
290    fn ds_converter(core_ctx: &CC) -> impl DualStackConverter<I, CC::WeakDeviceId, Self>;
291
292    fn to_other_bound_socket_id(
293        core_ctx: &CC,
294        id: &Self::SocketId<I, CC::WeakDeviceId>,
295    ) -> <Self::SocketMapSpec<I::OtherVersion, CC::WeakDeviceId> as DatagramSocketMapSpec<
296        I::OtherVersion,
297        CC::WeakDeviceId,
298        Self::AddrSpec,
299    >>::BoundSocketId;
300
301    fn with_both_bound_sockets_mut<
302        O,
303        F: FnOnce(
304            &mut Self::IpSocketsCtx<'_>,
305            &mut BoundSocketsFromSpec<I, CC, Self>,
306            &mut BoundSocketsFromSpec<I::OtherVersion, CC, Self>,
307        ) -> O,
308    >(
309        core_ctx: &mut CC,
310        cb: F,
311    ) -> O;
312
313    fn with_other_bound_sockets_mut<
314        O,
315        F: FnOnce(
316            &mut Self::IpSocketsCtx<'_>,
317            &mut BoundSocketsFromSpec<I::OtherVersion, CC, Self>,
318        ) -> O,
319    >(
320        core_ctx: &mut CC,
321        cb: F,
322    ) -> O;
323
324    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
325        core_ctx: &mut CC,
326        cb: F,
327    ) -> O;
328}
329
330impl<I, CC, BC, S> DualStackDatagramBoundStateContext<I, BC, S> for CC
331where
332    I: IpExt,
333    CC: DeviceIdContext<AnyDevice>,
334    BC: DatagramBindingsTypes,
335    S: DualStackDatagramSpecBoundStateContext<I, CC, BC>,
336{
337    type IpSocketsCtx<'a> = S::IpSocketsCtx<'a>;
338
339    fn dual_stack_enabled(&self, ip_options: &IpOptions<I, Self::WeakDeviceId, S>) -> bool {
340        S::dual_stack_enabled(self, ip_options)
341    }
342
343    fn to_other_socket_options<'a>(
344        &self,
345        ip_options: &'a IpOptions<I, Self::WeakDeviceId, S>,
346    ) -> &'a DatagramIpSpecificSocketOptions<I::OtherVersion, Self::WeakDeviceId> {
347        S::to_other_socket_options(self, ip_options)
348    }
349
350    fn ds_converter(&self) -> impl DualStackConverter<I, Self::WeakDeviceId, S> {
351        S::ds_converter(self)
352    }
353
354    fn to_other_bound_socket_id(
355        &self,
356        id: &S::SocketId<I, Self::WeakDeviceId>,
357    ) -> <S::SocketMapSpec<I::OtherVersion, Self::WeakDeviceId> as DatagramSocketMapSpec<
358        I::OtherVersion,
359        Self::WeakDeviceId,
360        S::AddrSpec,
361    >>::BoundSocketId {
362        S::to_other_bound_socket_id(self, id)
363    }
364
365    fn with_both_bound_sockets_mut<
366        O,
367        F: FnOnce(
368            &mut Self::IpSocketsCtx<'_>,
369            &mut BoundSocketsFromSpec<I, Self, S>,
370            &mut BoundSocketsFromSpec<I::OtherVersion, Self, S>,
371        ) -> O,
372    >(
373        &mut self,
374        cb: F,
375    ) -> O {
376        S::with_both_bound_sockets_mut(self, cb)
377    }
378
379    fn with_other_bound_sockets_mut<
380        O,
381        F: FnOnce(
382            &mut Self::IpSocketsCtx<'_>,
383            &mut BoundSocketsFromSpec<I::OtherVersion, Self, S>,
384        ) -> O,
385    >(
386        &mut self,
387        cb: F,
388    ) -> O {
389        S::with_other_bound_sockets_mut(self, cb)
390    }
391
392    fn with_transport_context<O, F: FnOnce(&mut Self::IpSocketsCtx<'_>) -> O>(
393        &mut self,
394        cb: F,
395    ) -> O {
396        S::with_transport_context(self, cb)
397    }
398}
399
400/// A mirror trait of [`NonDualStackDatagramBoundStateContext`] allowing foreign
401/// crates to provide blanket impls for it.
402///
403/// This trait repeats all the definitions in
404/// [`NonDualStackDatagramBoundStateContext`] to provide blanket impls from an
405/// implementation on the type implementing [`DatagramSocketSpec`], which is
406/// local for foreign implementers.
407///
408/// See [`NonDualStackDatagramBoundStateContext`] for details.
409#[allow(missing_docs)]
410pub trait NonDualStackDatagramSpecBoundStateContext<I: IpExt, CC: DeviceIdContext<AnyDevice>, BC>:
411    DatagramSocketSpec
412{
413    fn nds_converter(core_ctx: &CC) -> impl NonDualStackConverter<I, CC::WeakDeviceId, Self>;
414}
415
416impl<I, CC, BC, S> NonDualStackDatagramBoundStateContext<I, BC, S> for CC
417where
418    I: IpExt,
419    CC: DeviceIdContext<AnyDevice>,
420    S: NonDualStackDatagramSpecBoundStateContext<I, CC, BC>,
421{
422    fn nds_converter(&self) -> impl NonDualStackConverter<I, CC::WeakDeviceId, S> {
423        S::nds_converter(self)
424    }
425}