Skip to main content

fdomain_fuchsia_net_stack/
fdomain_fuchsia_net_stack.rs

1// WARNING: This file is machine generated by fidlgen.
2
3#![warn(clippy::all)]
4#![allow(unused_parens, unused_mut, unused_imports, nonstandard_style)]
5
6use bitflags::bitflags;
7use fdomain_client::fidl::{ControlHandle as _, FDomainFlexibleIntoResult as _, Responder as _};
8use fidl::encoding::{MessageBufFor, ProxyChannelBox, ResourceDialect};
9pub use fidl_fuchsia_net_stack_common::*;
10use futures::future::{self, MaybeDone, TryFutureExt};
11use zx_status;
12
13#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
14pub struct StackBridgeInterfacesRequest {
15    pub interfaces: Vec<u64>,
16    pub bridge:
17        fdomain_client::fidl::ServerEnd<fdomain_fuchsia_net_interfaces_admin::ControlMarker>,
18}
19
20impl fidl::Standalone<fdomain_client::fidl::FDomainResourceDialect>
21    for StackBridgeInterfacesRequest
22{
23}
24
25#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
26pub struct StackSetDhcpClientEnabledRequest {
27    pub id: u64,
28    pub enable: bool,
29}
30
31impl fidl::Standalone<fdomain_client::fidl::FDomainResourceDialect>
32    for StackSetDhcpClientEnabledRequest
33{
34}
35
36#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
37pub struct LogMarker;
38
39impl fdomain_client::fidl::ProtocolMarker for LogMarker {
40    type Proxy = LogProxy;
41    type RequestStream = LogRequestStream;
42
43    const DEBUG_NAME: &'static str = "fuchsia.net.stack.Log";
44}
45impl fdomain_client::fidl::DiscoverableProtocolMarker for LogMarker {}
46
47pub trait LogProxyInterface: Send + Sync {
48    type SetLogPacketsResponseFut: std::future::Future<Output = Result<(), fidl::Error>> + Send;
49    fn r#set_log_packets(&self, enabled: bool) -> Self::SetLogPacketsResponseFut;
50}
51
52#[derive(Debug, Clone)]
53pub struct LogProxy {
54    client: fidl::client::Client<fdomain_client::fidl::FDomainResourceDialect>,
55}
56
57impl fdomain_client::fidl::Proxy for LogProxy {
58    type Protocol = LogMarker;
59
60    fn from_channel(inner: fdomain_client::Channel) -> Self {
61        Self::new(inner)
62    }
63
64    fn into_channel(self) -> Result<fdomain_client::Channel, Self> {
65        self.client.into_channel().map_err(|client| Self { client })
66    }
67
68    fn as_channel(&self) -> &fdomain_client::Channel {
69        self.client.as_channel()
70    }
71}
72
73impl LogProxy {
74    /// Create a new Proxy for fuchsia.net.stack/Log.
75    pub fn new(channel: fdomain_client::Channel) -> Self {
76        let protocol_name = <LogMarker as fdomain_client::fidl::ProtocolMarker>::DEBUG_NAME;
77        Self { client: fidl::client::Client::new(channel, protocol_name) }
78    }
79
80    /// Get a Stream of events from the remote end of the protocol.
81    ///
82    /// # Panics
83    ///
84    /// Panics if the event stream was already taken.
85    pub fn take_event_stream(&self) -> LogEventStream {
86        LogEventStream { event_receiver: self.client.take_event_receiver() }
87    }
88
89    /// Dynamically set packet logging.
90    pub fn r#set_log_packets(
91        &self,
92        mut enabled: bool,
93    ) -> fidl::client::QueryResponseFut<(), fdomain_client::fidl::FDomainResourceDialect> {
94        LogProxyInterface::r#set_log_packets(self, enabled)
95    }
96}
97
98impl LogProxyInterface for LogProxy {
99    type SetLogPacketsResponseFut =
100        fidl::client::QueryResponseFut<(), fdomain_client::fidl::FDomainResourceDialect>;
101    fn r#set_log_packets(&self, mut enabled: bool) -> Self::SetLogPacketsResponseFut {
102        fn _decode(
103            mut _buf: Result<<fdomain_client::fidl::FDomainResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc, fidl::Error>,
104        ) -> Result<(), fidl::Error> {
105            let _response = fidl::client::decode_transaction_body::<
106                fidl::encoding::EmptyPayload,
107                fdomain_client::fidl::FDomainResourceDialect,
108                0x2176044cba5f378e,
109            >(_buf?)?;
110            Ok(_response)
111        }
112        self.client.send_query_and_decode::<LogSetLogPacketsRequest, ()>(
113            (enabled,),
114            0x2176044cba5f378e,
115            fidl::encoding::DynamicFlags::empty(),
116            _decode,
117        )
118    }
119}
120
121pub struct LogEventStream {
122    event_receiver: fidl::client::EventReceiver<fdomain_client::fidl::FDomainResourceDialect>,
123}
124
125impl std::marker::Unpin for LogEventStream {}
126
127impl futures::stream::FusedStream for LogEventStream {
128    fn is_terminated(&self) -> bool {
129        self.event_receiver.is_terminated()
130    }
131}
132
133impl futures::Stream for LogEventStream {
134    type Item = Result<LogEvent, fidl::Error>;
135
136    fn poll_next(
137        mut self: std::pin::Pin<&mut Self>,
138        cx: &mut std::task::Context<'_>,
139    ) -> std::task::Poll<Option<Self::Item>> {
140        match futures::ready!(futures::stream::StreamExt::poll_next_unpin(
141            &mut self.event_receiver,
142            cx
143        )?) {
144            Some(buf) => std::task::Poll::Ready(Some(LogEvent::decode(buf))),
145            None => std::task::Poll::Ready(None),
146        }
147    }
148}
149
150#[derive(Debug)]
151pub enum LogEvent {}
152
153impl LogEvent {
154    /// Decodes a message buffer as a [`LogEvent`].
155    fn decode(
156        mut buf: <fdomain_client::fidl::FDomainResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc,
157    ) -> Result<LogEvent, fidl::Error> {
158        let (bytes, _handles) = buf.split_mut();
159        let (tx_header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
160        debug_assert_eq!(tx_header.tx_id, 0);
161        match tx_header.ordinal {
162            _ => Err(fidl::Error::UnknownOrdinal {
163                ordinal: tx_header.ordinal,
164                protocol_name: <LogMarker as fdomain_client::fidl::ProtocolMarker>::DEBUG_NAME,
165            }),
166        }
167    }
168}
169
170/// A Stream of incoming requests for fuchsia.net.stack/Log.
171pub struct LogRequestStream {
172    inner: std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>,
173    is_terminated: bool,
174}
175
176impl std::marker::Unpin for LogRequestStream {}
177
178impl futures::stream::FusedStream for LogRequestStream {
179    fn is_terminated(&self) -> bool {
180        self.is_terminated
181    }
182}
183
184impl fdomain_client::fidl::RequestStream for LogRequestStream {
185    type Protocol = LogMarker;
186    type ControlHandle = LogControlHandle;
187
188    fn from_channel(channel: fdomain_client::Channel) -> Self {
189        Self { inner: std::sync::Arc::new(fidl::ServeInner::new(channel)), is_terminated: false }
190    }
191
192    fn control_handle(&self) -> Self::ControlHandle {
193        LogControlHandle { inner: self.inner.clone() }
194    }
195
196    fn into_inner(
197        self,
198    ) -> (::std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>, bool)
199    {
200        (self.inner, self.is_terminated)
201    }
202
203    fn from_inner(
204        inner: std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>,
205        is_terminated: bool,
206    ) -> Self {
207        Self { inner, is_terminated }
208    }
209}
210
211impl futures::Stream for LogRequestStream {
212    type Item = Result<LogRequest, fidl::Error>;
213
214    fn poll_next(
215        mut self: std::pin::Pin<&mut Self>,
216        cx: &mut std::task::Context<'_>,
217    ) -> std::task::Poll<Option<Self::Item>> {
218        let this = &mut *self;
219        if this.inner.check_shutdown(cx) {
220            this.is_terminated = true;
221            return std::task::Poll::Ready(None);
222        }
223        if this.is_terminated {
224            panic!("polled LogRequestStream after completion");
225        }
226        fidl::encoding::with_tls_decode_buf::<_, fdomain_client::fidl::FDomainResourceDialect>(
227            |bytes, handles| {
228                match this.inner.channel().read_etc(cx, bytes, handles) {
229                    std::task::Poll::Ready(Ok(())) => {}
230                    std::task::Poll::Pending => return std::task::Poll::Pending,
231                    std::task::Poll::Ready(Err(None)) => {
232                        this.is_terminated = true;
233                        return std::task::Poll::Ready(None);
234                    }
235                    std::task::Poll::Ready(Err(Some(e))) => {
236                        return std::task::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(
237                            e.into(),
238                        ))));
239                    }
240                }
241
242                // A message has been received from the channel
243                let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
244
245                std::task::Poll::Ready(Some(match header.ordinal {
246                    0x2176044cba5f378e => {
247                        header.validate_request_tx_id(fidl::MethodType::TwoWay)?;
248                        let mut req = fidl::new_empty!(
249                            LogSetLogPacketsRequest,
250                            fdomain_client::fidl::FDomainResourceDialect
251                        );
252                        fidl::encoding::Decoder::<fdomain_client::fidl::FDomainResourceDialect>::decode_into::<LogSetLogPacketsRequest>(&header, _body_bytes, handles, &mut req)?;
253                        let control_handle = LogControlHandle { inner: this.inner.clone() };
254                        Ok(LogRequest::SetLogPackets {
255                            enabled: req.enabled,
256
257                            responder: LogSetLogPacketsResponder {
258                                control_handle: std::mem::ManuallyDrop::new(control_handle),
259                                tx_id: header.tx_id,
260                            },
261                        })
262                    }
263                    _ => Err(fidl::Error::UnknownOrdinal {
264                        ordinal: header.ordinal,
265                        protocol_name:
266                            <LogMarker as fdomain_client::fidl::ProtocolMarker>::DEBUG_NAME,
267                    }),
268                }))
269            },
270        )
271    }
272}
273
274#[derive(Debug)]
275pub enum LogRequest {
276    /// Dynamically set packet logging.
277    SetLogPackets { enabled: bool, responder: LogSetLogPacketsResponder },
278}
279
280impl LogRequest {
281    #[allow(irrefutable_let_patterns)]
282    pub fn into_set_log_packets(self) -> Option<(bool, LogSetLogPacketsResponder)> {
283        if let LogRequest::SetLogPackets { enabled, responder } = self {
284            Some((enabled, responder))
285        } else {
286            None
287        }
288    }
289
290    /// Name of the method defined in FIDL
291    pub fn method_name(&self) -> &'static str {
292        match *self {
293            LogRequest::SetLogPackets { .. } => "set_log_packets",
294        }
295    }
296}
297
298#[derive(Debug, Clone)]
299pub struct LogControlHandle {
300    inner: std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>,
301}
302
303impl LogControlHandle {
304    pub fn shutdown_with_epitaph(&self, status: impl Into<fidl::Epitaph>) {
305        self.inner.shutdown_with_epitaph(status.into())
306    }
307}
308
309impl fdomain_client::fidl::ControlHandle for LogControlHandle {
310    fn shutdown(&self) {
311        self.inner.shutdown()
312    }
313
314    fn shutdown_with_epitaph(&self, status: fidl::Epitaph) {
315        self.inner.shutdown_with_epitaph(status)
316    }
317
318    fn is_closed(&self) -> bool {
319        self.inner.channel().is_closed()
320    }
321    fn on_closed(&self) -> fdomain_client::OnFDomainSignals {
322        self.inner.channel().on_closed()
323    }
324}
325
326impl LogControlHandle {}
327
328#[must_use = "FIDL methods require a response to be sent"]
329#[derive(Debug)]
330pub struct LogSetLogPacketsResponder {
331    control_handle: std::mem::ManuallyDrop<LogControlHandle>,
332    tx_id: u32,
333}
334
335/// Set the the channel to be shutdown (see [`LogControlHandle::shutdown`])
336/// if the responder is dropped without sending a response, so that the client
337/// doesn't hang. To prevent this behavior, call `drop_without_shutdown`.
338impl std::ops::Drop for LogSetLogPacketsResponder {
339    fn drop(&mut self) {
340        self.control_handle.shutdown();
341        // Safety: drops once, never accessed again
342        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
343    }
344}
345
346impl fdomain_client::fidl::Responder for LogSetLogPacketsResponder {
347    type ControlHandle = LogControlHandle;
348
349    fn control_handle(&self) -> &LogControlHandle {
350        &self.control_handle
351    }
352
353    fn drop_without_shutdown(mut self) {
354        // Safety: drops once, never accessed again due to mem::forget
355        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
356        // Prevent Drop from running (which would shut down the channel)
357        std::mem::forget(self);
358    }
359}
360
361impl LogSetLogPacketsResponder {
362    /// Sends a response to the FIDL transaction.
363    ///
364    /// Sets the channel to shutdown if an error occurs.
365    pub fn send(self) -> Result<(), fidl::Error> {
366        let _result = self.send_raw();
367        if _result.is_err() {
368            self.control_handle.shutdown();
369        }
370        self.drop_without_shutdown();
371        _result
372    }
373
374    /// Similar to "send" but does not shutdown the channel if an error occurs.
375    pub fn send_no_shutdown_on_err(self) -> Result<(), fidl::Error> {
376        let _result = self.send_raw();
377        self.drop_without_shutdown();
378        _result
379    }
380
381    fn send_raw(&self) -> Result<(), fidl::Error> {
382        self.control_handle.inner.send::<fidl::encoding::EmptyPayload>(
383            (),
384            self.tx_id,
385            0x2176044cba5f378e,
386            fidl::encoding::DynamicFlags::empty(),
387        )
388    }
389}
390
391#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
392pub struct StackMarker;
393
394impl fdomain_client::fidl::ProtocolMarker for StackMarker {
395    type Proxy = StackProxy;
396    type RequestStream = StackRequestStream;
397
398    const DEBUG_NAME: &'static str = "fuchsia.net.stack.Stack";
399}
400impl fdomain_client::fidl::DiscoverableProtocolMarker for StackMarker {}
401pub type StackSetDhcpClientEnabledResult = Result<(), Error>;
402
403pub trait StackProxyInterface: Send + Sync {
404    type SetDhcpClientEnabledResponseFut: std::future::Future<Output = Result<StackSetDhcpClientEnabledResult, fidl::Error>>
405        + Send;
406    fn r#set_dhcp_client_enabled(
407        &self,
408        id: u64,
409        enable: bool,
410    ) -> Self::SetDhcpClientEnabledResponseFut;
411    fn r#bridge_interfaces(
412        &self,
413        interfaces: &[u64],
414        bridge: fdomain_client::fidl::ServerEnd<
415            fdomain_fuchsia_net_interfaces_admin::ControlMarker,
416        >,
417    ) -> Result<(), fidl::Error>;
418}
419
420#[derive(Debug, Clone)]
421pub struct StackProxy {
422    client: fidl::client::Client<fdomain_client::fidl::FDomainResourceDialect>,
423}
424
425impl fdomain_client::fidl::Proxy for StackProxy {
426    type Protocol = StackMarker;
427
428    fn from_channel(inner: fdomain_client::Channel) -> Self {
429        Self::new(inner)
430    }
431
432    fn into_channel(self) -> Result<fdomain_client::Channel, Self> {
433        self.client.into_channel().map_err(|client| Self { client })
434    }
435
436    fn as_channel(&self) -> &fdomain_client::Channel {
437        self.client.as_channel()
438    }
439}
440
441impl StackProxy {
442    /// Create a new Proxy for fuchsia.net.stack/Stack.
443    pub fn new(channel: fdomain_client::Channel) -> Self {
444        let protocol_name = <StackMarker as fdomain_client::fidl::ProtocolMarker>::DEBUG_NAME;
445        Self { client: fidl::client::Client::new(channel, protocol_name) }
446    }
447
448    /// Get a Stream of events from the remote end of the protocol.
449    ///
450    /// # Panics
451    ///
452    /// Panics if the event stream was already taken.
453    pub fn take_event_stream(&self) -> StackEventStream {
454        StackEventStream { event_receiver: self.client.take_event_receiver() }
455    }
456
457    /// Enables or disables the DHCP client on an interface.
458    /// TODO(https://fxbug.dev/42162065): Remove this once the DHCP client is moved
459    /// out of the netstack.
460    pub fn r#set_dhcp_client_enabled(
461        &self,
462        mut id: u64,
463        mut enable: bool,
464    ) -> fidl::client::QueryResponseFut<
465        StackSetDhcpClientEnabledResult,
466        fdomain_client::fidl::FDomainResourceDialect,
467    > {
468        StackProxyInterface::r#set_dhcp_client_enabled(self, id, enable)
469    }
470
471    /// Creates a bridge over the provided `interfaces`.
472    ///
473    /// If the bridge can't be created, `bridge` is closed with a `BAD_PORT`
474    /// termination reason.
475    ///
476    /// NOTE: We're shoehorning bridging into the `admin/Control` API and
477    /// reassigning meaning to `BAD_PORT` because we don't want to leak
478    /// bridging-specific errors there. The POR is that bridging is going to get
479    /// its own API at some point.
480    ///
481    /// Bridge lifetime is controlled through the `bridge` handle.
482    pub fn r#bridge_interfaces(
483        &self,
484        mut interfaces: &[u64],
485        mut bridge: fdomain_client::fidl::ServerEnd<
486            fdomain_fuchsia_net_interfaces_admin::ControlMarker,
487        >,
488    ) -> Result<(), fidl::Error> {
489        StackProxyInterface::r#bridge_interfaces(self, interfaces, bridge)
490    }
491}
492
493impl StackProxyInterface for StackProxy {
494    type SetDhcpClientEnabledResponseFut = fidl::client::QueryResponseFut<
495        StackSetDhcpClientEnabledResult,
496        fdomain_client::fidl::FDomainResourceDialect,
497    >;
498    fn r#set_dhcp_client_enabled(
499        &self,
500        mut id: u64,
501        mut enable: bool,
502    ) -> Self::SetDhcpClientEnabledResponseFut {
503        fn _decode(
504            mut _buf: Result<<fdomain_client::fidl::FDomainResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc, fidl::Error>,
505        ) -> Result<StackSetDhcpClientEnabledResult, fidl::Error> {
506            let _response = fidl::client::decode_transaction_body::<
507                fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>,
508                fdomain_client::fidl::FDomainResourceDialect,
509                0x6dead3a6025b0543,
510            >(_buf?)?;
511            Ok(_response.map(|x| x))
512        }
513        self.client.send_query_and_decode::<
514            StackSetDhcpClientEnabledRequest,
515            StackSetDhcpClientEnabledResult,
516        >(
517            (id, enable,),
518            0x6dead3a6025b0543,
519            fidl::encoding::DynamicFlags::empty(),
520            _decode,
521        )
522    }
523
524    fn r#bridge_interfaces(
525        &self,
526        mut interfaces: &[u64],
527        mut bridge: fdomain_client::fidl::ServerEnd<
528            fdomain_fuchsia_net_interfaces_admin::ControlMarker,
529        >,
530    ) -> Result<(), fidl::Error> {
531        self.client.send::<StackBridgeInterfacesRequest>(
532            (interfaces, bridge),
533            0x60509044a41ac976,
534            fidl::encoding::DynamicFlags::empty(),
535        )
536    }
537}
538
539pub struct StackEventStream {
540    event_receiver: fidl::client::EventReceiver<fdomain_client::fidl::FDomainResourceDialect>,
541}
542
543impl std::marker::Unpin for StackEventStream {}
544
545impl futures::stream::FusedStream for StackEventStream {
546    fn is_terminated(&self) -> bool {
547        self.event_receiver.is_terminated()
548    }
549}
550
551impl futures::Stream for StackEventStream {
552    type Item = Result<StackEvent, fidl::Error>;
553
554    fn poll_next(
555        mut self: std::pin::Pin<&mut Self>,
556        cx: &mut std::task::Context<'_>,
557    ) -> std::task::Poll<Option<Self::Item>> {
558        match futures::ready!(futures::stream::StreamExt::poll_next_unpin(
559            &mut self.event_receiver,
560            cx
561        )?) {
562            Some(buf) => std::task::Poll::Ready(Some(StackEvent::decode(buf))),
563            None => std::task::Poll::Ready(None),
564        }
565    }
566}
567
568#[derive(Debug)]
569pub enum StackEvent {}
570
571impl StackEvent {
572    /// Decodes a message buffer as a [`StackEvent`].
573    fn decode(
574        mut buf: <fdomain_client::fidl::FDomainResourceDialect as fidl::encoding::ResourceDialect>::MessageBufEtc,
575    ) -> Result<StackEvent, fidl::Error> {
576        let (bytes, _handles) = buf.split_mut();
577        let (tx_header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
578        debug_assert_eq!(tx_header.tx_id, 0);
579        match tx_header.ordinal {
580            _ => Err(fidl::Error::UnknownOrdinal {
581                ordinal: tx_header.ordinal,
582                protocol_name: <StackMarker as fdomain_client::fidl::ProtocolMarker>::DEBUG_NAME,
583            }),
584        }
585    }
586}
587
588/// A Stream of incoming requests for fuchsia.net.stack/Stack.
589pub struct StackRequestStream {
590    inner: std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>,
591    is_terminated: bool,
592}
593
594impl std::marker::Unpin for StackRequestStream {}
595
596impl futures::stream::FusedStream for StackRequestStream {
597    fn is_terminated(&self) -> bool {
598        self.is_terminated
599    }
600}
601
602impl fdomain_client::fidl::RequestStream for StackRequestStream {
603    type Protocol = StackMarker;
604    type ControlHandle = StackControlHandle;
605
606    fn from_channel(channel: fdomain_client::Channel) -> Self {
607        Self { inner: std::sync::Arc::new(fidl::ServeInner::new(channel)), is_terminated: false }
608    }
609
610    fn control_handle(&self) -> Self::ControlHandle {
611        StackControlHandle { inner: self.inner.clone() }
612    }
613
614    fn into_inner(
615        self,
616    ) -> (::std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>, bool)
617    {
618        (self.inner, self.is_terminated)
619    }
620
621    fn from_inner(
622        inner: std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>,
623        is_terminated: bool,
624    ) -> Self {
625        Self { inner, is_terminated }
626    }
627}
628
629impl futures::Stream for StackRequestStream {
630    type Item = Result<StackRequest, fidl::Error>;
631
632    fn poll_next(
633        mut self: std::pin::Pin<&mut Self>,
634        cx: &mut std::task::Context<'_>,
635    ) -> std::task::Poll<Option<Self::Item>> {
636        let this = &mut *self;
637        if this.inner.check_shutdown(cx) {
638            this.is_terminated = true;
639            return std::task::Poll::Ready(None);
640        }
641        if this.is_terminated {
642            panic!("polled StackRequestStream after completion");
643        }
644        fidl::encoding::with_tls_decode_buf::<_, fdomain_client::fidl::FDomainResourceDialect>(
645            |bytes, handles| {
646                match this.inner.channel().read_etc(cx, bytes, handles) {
647                    std::task::Poll::Ready(Ok(())) => {}
648                    std::task::Poll::Pending => return std::task::Poll::Pending,
649                    std::task::Poll::Ready(Err(None)) => {
650                        this.is_terminated = true;
651                        return std::task::Poll::Ready(None);
652                    }
653                    std::task::Poll::Ready(Err(Some(e))) => {
654                        return std::task::Poll::Ready(Some(Err(fidl::Error::ServerRequestRead(
655                            e.into(),
656                        ))));
657                    }
658                }
659
660                // A message has been received from the channel
661                let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
662
663                std::task::Poll::Ready(Some(match header.ordinal {
664                    0x6dead3a6025b0543 => {
665                        header.validate_request_tx_id(fidl::MethodType::TwoWay)?;
666                        let mut req = fidl::new_empty!(
667                            StackSetDhcpClientEnabledRequest,
668                            fdomain_client::fidl::FDomainResourceDialect
669                        );
670                        fidl::encoding::Decoder::<fdomain_client::fidl::FDomainResourceDialect>::decode_into::<StackSetDhcpClientEnabledRequest>(&header, _body_bytes, handles, &mut req)?;
671                        let control_handle = StackControlHandle { inner: this.inner.clone() };
672                        Ok(StackRequest::SetDhcpClientEnabled {
673                            id: req.id,
674                            enable: req.enable,
675
676                            responder: StackSetDhcpClientEnabledResponder {
677                                control_handle: std::mem::ManuallyDrop::new(control_handle),
678                                tx_id: header.tx_id,
679                            },
680                        })
681                    }
682                    0x60509044a41ac976 => {
683                        header.validate_request_tx_id(fidl::MethodType::OneWay)?;
684                        let mut req = fidl::new_empty!(
685                            StackBridgeInterfacesRequest,
686                            fdomain_client::fidl::FDomainResourceDialect
687                        );
688                        fidl::encoding::Decoder::<fdomain_client::fidl::FDomainResourceDialect>::decode_into::<StackBridgeInterfacesRequest>(&header, _body_bytes, handles, &mut req)?;
689                        let control_handle = StackControlHandle { inner: this.inner.clone() };
690                        Ok(StackRequest::BridgeInterfaces {
691                            interfaces: req.interfaces,
692                            bridge: req.bridge,
693
694                            control_handle,
695                        })
696                    }
697                    _ => Err(fidl::Error::UnknownOrdinal {
698                        ordinal: header.ordinal,
699                        protocol_name:
700                            <StackMarker as fdomain_client::fidl::ProtocolMarker>::DEBUG_NAME,
701                    }),
702                }))
703            },
704        )
705    }
706}
707
708#[derive(Debug)]
709pub enum StackRequest {
710    /// Enables or disables the DHCP client on an interface.
711    /// TODO(https://fxbug.dev/42162065): Remove this once the DHCP client is moved
712    /// out of the netstack.
713    SetDhcpClientEnabled { id: u64, enable: bool, responder: StackSetDhcpClientEnabledResponder },
714    /// Creates a bridge over the provided `interfaces`.
715    ///
716    /// If the bridge can't be created, `bridge` is closed with a `BAD_PORT`
717    /// termination reason.
718    ///
719    /// NOTE: We're shoehorning bridging into the `admin/Control` API and
720    /// reassigning meaning to `BAD_PORT` because we don't want to leak
721    /// bridging-specific errors there. The POR is that bridging is going to get
722    /// its own API at some point.
723    ///
724    /// Bridge lifetime is controlled through the `bridge` handle.
725    BridgeInterfaces {
726        interfaces: Vec<u64>,
727        bridge:
728            fdomain_client::fidl::ServerEnd<fdomain_fuchsia_net_interfaces_admin::ControlMarker>,
729        control_handle: StackControlHandle,
730    },
731}
732
733impl StackRequest {
734    #[allow(irrefutable_let_patterns)]
735    pub fn into_set_dhcp_client_enabled(
736        self,
737    ) -> Option<(u64, bool, StackSetDhcpClientEnabledResponder)> {
738        if let StackRequest::SetDhcpClientEnabled { id, enable, responder } = self {
739            Some((id, enable, responder))
740        } else {
741            None
742        }
743    }
744
745    #[allow(irrefutable_let_patterns)]
746    pub fn into_bridge_interfaces(
747        self,
748    ) -> Option<(
749        Vec<u64>,
750        fdomain_client::fidl::ServerEnd<fdomain_fuchsia_net_interfaces_admin::ControlMarker>,
751        StackControlHandle,
752    )> {
753        if let StackRequest::BridgeInterfaces { interfaces, bridge, control_handle } = self {
754            Some((interfaces, bridge, control_handle))
755        } else {
756            None
757        }
758    }
759
760    /// Name of the method defined in FIDL
761    pub fn method_name(&self) -> &'static str {
762        match *self {
763            StackRequest::SetDhcpClientEnabled { .. } => "set_dhcp_client_enabled",
764            StackRequest::BridgeInterfaces { .. } => "bridge_interfaces",
765        }
766    }
767}
768
769#[derive(Debug, Clone)]
770pub struct StackControlHandle {
771    inner: std::sync::Arc<fidl::ServeInner<fdomain_client::fidl::FDomainResourceDialect>>,
772}
773
774impl StackControlHandle {
775    pub fn shutdown_with_epitaph(&self, status: impl Into<fidl::Epitaph>) {
776        self.inner.shutdown_with_epitaph(status.into())
777    }
778}
779
780impl fdomain_client::fidl::ControlHandle for StackControlHandle {
781    fn shutdown(&self) {
782        self.inner.shutdown()
783    }
784
785    fn shutdown_with_epitaph(&self, status: fidl::Epitaph) {
786        self.inner.shutdown_with_epitaph(status)
787    }
788
789    fn is_closed(&self) -> bool {
790        self.inner.channel().is_closed()
791    }
792    fn on_closed(&self) -> fdomain_client::OnFDomainSignals {
793        self.inner.channel().on_closed()
794    }
795}
796
797impl StackControlHandle {}
798
799#[must_use = "FIDL methods require a response to be sent"]
800#[derive(Debug)]
801pub struct StackSetDhcpClientEnabledResponder {
802    control_handle: std::mem::ManuallyDrop<StackControlHandle>,
803    tx_id: u32,
804}
805
806/// Set the the channel to be shutdown (see [`StackControlHandle::shutdown`])
807/// if the responder is dropped without sending a response, so that the client
808/// doesn't hang. To prevent this behavior, call `drop_without_shutdown`.
809impl std::ops::Drop for StackSetDhcpClientEnabledResponder {
810    fn drop(&mut self) {
811        self.control_handle.shutdown();
812        // Safety: drops once, never accessed again
813        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
814    }
815}
816
817impl fdomain_client::fidl::Responder for StackSetDhcpClientEnabledResponder {
818    type ControlHandle = StackControlHandle;
819
820    fn control_handle(&self) -> &StackControlHandle {
821        &self.control_handle
822    }
823
824    fn drop_without_shutdown(mut self) {
825        // Safety: drops once, never accessed again due to mem::forget
826        unsafe { std::mem::ManuallyDrop::drop(&mut self.control_handle) };
827        // Prevent Drop from running (which would shut down the channel)
828        std::mem::forget(self);
829    }
830}
831
832impl StackSetDhcpClientEnabledResponder {
833    /// Sends a response to the FIDL transaction.
834    ///
835    /// Sets the channel to shutdown if an error occurs.
836    pub fn send(self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
837        let _result = self.send_raw(result);
838        if _result.is_err() {
839            self.control_handle.shutdown();
840        }
841        self.drop_without_shutdown();
842        _result
843    }
844
845    /// Similar to "send" but does not shutdown the channel if an error occurs.
846    pub fn send_no_shutdown_on_err(self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
847        let _result = self.send_raw(result);
848        self.drop_without_shutdown();
849        _result
850    }
851
852    fn send_raw(&self, mut result: Result<(), Error>) -> Result<(), fidl::Error> {
853        self.control_handle
854            .inner
855            .send::<fidl::encoding::ResultType<fidl::encoding::EmptyStruct, Error>>(
856                result,
857                self.tx_id,
858                0x6dead3a6025b0543,
859                fidl::encoding::DynamicFlags::empty(),
860            )
861    }
862}
863
864mod internal {
865    use super::*;
866
867    impl fidl::encoding::ResourceTypeMarker for StackBridgeInterfacesRequest {
868        type Borrowed<'a> = &'a mut Self;
869        fn take_or_borrow<'a>(
870            value: &'a mut <Self as fidl::encoding::TypeMarker>::Owned,
871        ) -> Self::Borrowed<'a> {
872            value
873        }
874    }
875
876    unsafe impl fidl::encoding::TypeMarker for StackBridgeInterfacesRequest {
877        type Owned = Self;
878
879        #[inline(always)]
880        fn inline_align(_context: fidl::encoding::Context) -> usize {
881            8
882        }
883
884        #[inline(always)]
885        fn inline_size(_context: fidl::encoding::Context) -> usize {
886            24
887        }
888    }
889
890    unsafe impl
891        fidl::encoding::Encode<
892            StackBridgeInterfacesRequest,
893            fdomain_client::fidl::FDomainResourceDialect,
894        > for &mut StackBridgeInterfacesRequest
895    {
896        #[inline]
897        unsafe fn encode(
898            self,
899            encoder: &mut fidl::encoding::Encoder<'_, fdomain_client::fidl::FDomainResourceDialect>,
900            offset: usize,
901            _depth: fidl::encoding::Depth,
902        ) -> fidl::Result<()> {
903            encoder.debug_check_bounds::<StackBridgeInterfacesRequest>(offset);
904            // Delegate to tuple encoding.
905            fidl::encoding::Encode::<StackBridgeInterfacesRequest, fdomain_client::fidl::FDomainResourceDialect>::encode(
906                (
907                    <fidl::encoding::UnboundedVector<u64> as fidl::encoding::ValueTypeMarker>::borrow(&self.interfaces),
908                    <fidl::encoding::Endpoint<fdomain_client::fidl::ServerEnd<fdomain_fuchsia_net_interfaces_admin::ControlMarker>> as fidl::encoding::ResourceTypeMarker>::take_or_borrow(&mut self.bridge),
909                ),
910                encoder, offset, _depth
911            )
912        }
913    }
914    unsafe impl<
915        T0: fidl::encoding::Encode<
916                fidl::encoding::UnboundedVector<u64>,
917                fdomain_client::fidl::FDomainResourceDialect,
918            >,
919        T1: fidl::encoding::Encode<
920                fidl::encoding::Endpoint<
921                    fdomain_client::fidl::ServerEnd<
922                        fdomain_fuchsia_net_interfaces_admin::ControlMarker,
923                    >,
924                >,
925                fdomain_client::fidl::FDomainResourceDialect,
926            >,
927    >
928        fidl::encoding::Encode<
929            StackBridgeInterfacesRequest,
930            fdomain_client::fidl::FDomainResourceDialect,
931        > for (T0, T1)
932    {
933        #[inline]
934        unsafe fn encode(
935            self,
936            encoder: &mut fidl::encoding::Encoder<'_, fdomain_client::fidl::FDomainResourceDialect>,
937            offset: usize,
938            depth: fidl::encoding::Depth,
939        ) -> fidl::Result<()> {
940            encoder.debug_check_bounds::<StackBridgeInterfacesRequest>(offset);
941            // Zero out padding regions. There's no need to apply masks
942            // because the unmasked parts will be overwritten by fields.
943            unsafe {
944                let ptr = encoder.buf.as_mut_ptr().add(offset).offset(16);
945                (ptr as *mut u64).write_unaligned(0);
946            }
947            // Write the fields.
948            self.0.encode(encoder, offset + 0, depth)?;
949            self.1.encode(encoder, offset + 16, depth)?;
950            Ok(())
951        }
952    }
953
954    impl fidl::encoding::Decode<Self, fdomain_client::fidl::FDomainResourceDialect>
955        for StackBridgeInterfacesRequest
956    {
957        #[inline(always)]
958        fn new_empty() -> Self {
959            Self {
960                interfaces: fidl::new_empty!(
961                    fidl::encoding::UnboundedVector<u64>,
962                    fdomain_client::fidl::FDomainResourceDialect
963                ),
964                bridge: fidl::new_empty!(
965                    fidl::encoding::Endpoint<
966                        fdomain_client::fidl::ServerEnd<
967                            fdomain_fuchsia_net_interfaces_admin::ControlMarker,
968                        >,
969                    >,
970                    fdomain_client::fidl::FDomainResourceDialect
971                ),
972            }
973        }
974
975        #[inline]
976        unsafe fn decode(
977            &mut self,
978            decoder: &mut fidl::encoding::Decoder<'_, fdomain_client::fidl::FDomainResourceDialect>,
979            offset: usize,
980            _depth: fidl::encoding::Depth,
981        ) -> fidl::Result<()> {
982            decoder.debug_check_bounds::<Self>(offset);
983            // Verify that padding bytes are zero.
984            let ptr = unsafe { decoder.buf.as_ptr().add(offset).offset(16) };
985            let padval = unsafe { (ptr as *const u64).read_unaligned() };
986            let mask = 0xffffffff00000000u64;
987            let maskedval = padval & mask;
988            if maskedval != 0 {
989                return Err(fidl::Error::NonZeroPadding {
990                    padding_start: offset + 16 + ((mask as u64).trailing_zeros() / 8) as usize,
991                });
992            }
993            fidl::decode!(
994                fidl::encoding::UnboundedVector<u64>,
995                fdomain_client::fidl::FDomainResourceDialect,
996                &mut self.interfaces,
997                decoder,
998                offset + 0,
999                _depth
1000            )?;
1001            fidl::decode!(
1002                fidl::encoding::Endpoint<
1003                    fdomain_client::fidl::ServerEnd<
1004                        fdomain_fuchsia_net_interfaces_admin::ControlMarker,
1005                    >,
1006                >,
1007                fdomain_client::fidl::FDomainResourceDialect,
1008                &mut self.bridge,
1009                decoder,
1010                offset + 16,
1011                _depth
1012            )?;
1013            Ok(())
1014        }
1015    }
1016
1017    impl fidl::encoding::ResourceTypeMarker for StackSetDhcpClientEnabledRequest {
1018        type Borrowed<'a> = &'a mut Self;
1019        fn take_or_borrow<'a>(
1020            value: &'a mut <Self as fidl::encoding::TypeMarker>::Owned,
1021        ) -> Self::Borrowed<'a> {
1022            value
1023        }
1024    }
1025
1026    unsafe impl fidl::encoding::TypeMarker for StackSetDhcpClientEnabledRequest {
1027        type Owned = Self;
1028
1029        #[inline(always)]
1030        fn inline_align(_context: fidl::encoding::Context) -> usize {
1031            8
1032        }
1033
1034        #[inline(always)]
1035        fn inline_size(_context: fidl::encoding::Context) -> usize {
1036            16
1037        }
1038    }
1039
1040    unsafe impl
1041        fidl::encoding::Encode<
1042            StackSetDhcpClientEnabledRequest,
1043            fdomain_client::fidl::FDomainResourceDialect,
1044        > for &mut StackSetDhcpClientEnabledRequest
1045    {
1046        #[inline]
1047        unsafe fn encode(
1048            self,
1049            encoder: &mut fidl::encoding::Encoder<'_, fdomain_client::fidl::FDomainResourceDialect>,
1050            offset: usize,
1051            _depth: fidl::encoding::Depth,
1052        ) -> fidl::Result<()> {
1053            encoder.debug_check_bounds::<StackSetDhcpClientEnabledRequest>(offset);
1054            // Delegate to tuple encoding.
1055            fidl::encoding::Encode::<
1056                StackSetDhcpClientEnabledRequest,
1057                fdomain_client::fidl::FDomainResourceDialect,
1058            >::encode(
1059                (
1060                    <u64 as fidl::encoding::ValueTypeMarker>::borrow(&self.id),
1061                    <bool as fidl::encoding::ValueTypeMarker>::borrow(&self.enable),
1062                ),
1063                encoder,
1064                offset,
1065                _depth,
1066            )
1067        }
1068    }
1069    unsafe impl<
1070        T0: fidl::encoding::Encode<u64, fdomain_client::fidl::FDomainResourceDialect>,
1071        T1: fidl::encoding::Encode<bool, fdomain_client::fidl::FDomainResourceDialect>,
1072    >
1073        fidl::encoding::Encode<
1074            StackSetDhcpClientEnabledRequest,
1075            fdomain_client::fidl::FDomainResourceDialect,
1076        > for (T0, T1)
1077    {
1078        #[inline]
1079        unsafe fn encode(
1080            self,
1081            encoder: &mut fidl::encoding::Encoder<'_, fdomain_client::fidl::FDomainResourceDialect>,
1082            offset: usize,
1083            depth: fidl::encoding::Depth,
1084        ) -> fidl::Result<()> {
1085            encoder.debug_check_bounds::<StackSetDhcpClientEnabledRequest>(offset);
1086            // Zero out padding regions. There's no need to apply masks
1087            // because the unmasked parts will be overwritten by fields.
1088            unsafe {
1089                let ptr = encoder.buf.as_mut_ptr().add(offset).offset(8);
1090                (ptr as *mut u64).write_unaligned(0);
1091            }
1092            // Write the fields.
1093            self.0.encode(encoder, offset + 0, depth)?;
1094            self.1.encode(encoder, offset + 8, depth)?;
1095            Ok(())
1096        }
1097    }
1098
1099    impl fidl::encoding::Decode<Self, fdomain_client::fidl::FDomainResourceDialect>
1100        for StackSetDhcpClientEnabledRequest
1101    {
1102        #[inline(always)]
1103        fn new_empty() -> Self {
1104            Self {
1105                id: fidl::new_empty!(u64, fdomain_client::fidl::FDomainResourceDialect),
1106                enable: fidl::new_empty!(bool, fdomain_client::fidl::FDomainResourceDialect),
1107            }
1108        }
1109
1110        #[inline]
1111        unsafe fn decode(
1112            &mut self,
1113            decoder: &mut fidl::encoding::Decoder<'_, fdomain_client::fidl::FDomainResourceDialect>,
1114            offset: usize,
1115            _depth: fidl::encoding::Depth,
1116        ) -> fidl::Result<()> {
1117            decoder.debug_check_bounds::<Self>(offset);
1118            // Verify that padding bytes are zero.
1119            let ptr = unsafe { decoder.buf.as_ptr().add(offset).offset(8) };
1120            let padval = unsafe { (ptr as *const u64).read_unaligned() };
1121            let mask = 0xffffffffffffff00u64;
1122            let maskedval = padval & mask;
1123            if maskedval != 0 {
1124                return Err(fidl::Error::NonZeroPadding {
1125                    padding_start: offset + 8 + ((mask as u64).trailing_zeros() / 8) as usize,
1126                });
1127            }
1128            fidl::decode!(
1129                u64,
1130                fdomain_client::fidl::FDomainResourceDialect,
1131                &mut self.id,
1132                decoder,
1133                offset + 0,
1134                _depth
1135            )?;
1136            fidl::decode!(
1137                bool,
1138                fdomain_client::fidl::FDomainResourceDialect,
1139                &mut self.enable,
1140                decoder,
1141                offset + 8,
1142                _depth
1143            )?;
1144            Ok(())
1145        }
1146    }
1147}