1use crate::encoding::{
8 DefaultFuchsiaResourceDialect, DynamicFlags, EmptyStruct, Encode, Encoder, Flexible,
9 FlexibleType, FrameworkErr, HandleFor, ProxyChannelBox, ProxyChannelFor, ResourceDialect,
10 TransactionHeader, TransactionMessage, TransactionMessageType, TypeMarker,
11};
12use crate::{Error, epitaph};
13use futures::task::{AtomicWaker, Context};
14use std::sync::atomic::{self, AtomicBool};
15use zx_status;
16
17#[derive(Debug)]
19pub struct ServeInner<D: ResourceDialect = DefaultFuchsiaResourceDialect> {
20 waker: AtomicWaker,
21 shutdown: AtomicBool,
22 channel: <D::ProxyChannel as ProxyChannelFor<D>>::Boxed,
23}
24
25impl<D: ResourceDialect> ServeInner<D> {
26 pub fn new(channel: D::ProxyChannel) -> Self {
28 let waker = AtomicWaker::new();
29 let shutdown = AtomicBool::new(false);
30 ServeInner { waker, shutdown, channel: channel.boxed() }
31 }
32
33 pub fn channel(&self) -> &<D::ProxyChannel as ProxyChannelFor<D>>::Boxed {
35 &self.channel
36 }
37
38 pub fn into_channel(self) -> D::ProxyChannel {
43 self.channel.unbox()
44 }
45
46 pub fn shutdown(&self) {
52 self.shutdown.store(true, atomic::Ordering::Relaxed);
53 self.waker.wake();
54 }
55
56 pub fn shutdown_with_epitaph(&self, status: impl Into<crate::Epitaph>) {
62 let already_shutting_down = self.shutdown.swap(true, atomic::Ordering::Relaxed);
63 if !already_shutting_down {
64 let status = match status.into() {
66 crate::Epitaph::Explicit(res) => res,
67 crate::Epitaph::PeerClosed => Err(zx_status::Status::PEER_CLOSED),
68 };
69 let _ = epitaph::write_epitaph_impl(self.channel.as_channel(), status);
70 self.waker.wake();
71 }
72 }
73
74 pub fn check_shutdown(&self, cx: &Context<'_>) -> bool {
76 if self.shutdown.load(atomic::Ordering::Relaxed) {
77 return true;
78 }
79 self.waker.register(cx.waker());
80 self.shutdown.load(atomic::Ordering::Relaxed)
81 }
82
83 #[inline]
85 pub fn send<T: TypeMarker>(
86 &self,
87 body: impl Encode<T, D>,
88 tx_id: u32,
89 ordinal: u64,
90 dynamic_flags: DynamicFlags,
91 ) -> Result<(), Error> {
92 let msg = TransactionMessage {
93 header: TransactionHeader::new(tx_id, ordinal, dynamic_flags),
94 body,
95 };
96 crate::encoding::with_tls_encoded::<TransactionMessageType<T>, D, ()>(
97 msg,
98 |bytes, handles| self.send_raw_msg(bytes, handles),
99 )
100 }
101
102 #[inline]
107 pub fn send_framework_err(
108 &self,
109 framework_err: FrameworkErr,
110 tx_id: u32,
111 ordinal: u64,
112 dynamic_flags: DynamicFlags,
113 tls_decode_buf: (&mut Vec<u8>, &mut Vec<<D::Handle as HandleFor<D>>::HandleInfo>),
114 ) -> Result<(), Error> {
115 type Msg = TransactionMessageType<FlexibleType<EmptyStruct>>;
116 let msg = TransactionMessage {
117 header: TransactionHeader::new(tx_id, ordinal, dynamic_flags),
118 body: Flexible::<()>::FrameworkErr(framework_err),
119 };
120
121 let (bytes, handle_infos) = tls_decode_buf;
123 handle_infos.clear();
124 let mut handle_dispositions = Vec::new();
127 Encoder::<D>::encode::<Msg>(bytes, &mut handle_dispositions, msg)?;
128 debug_assert!(handle_dispositions.is_empty());
129 self.send_raw_msg(&*bytes, &mut [])
130 }
131
132 fn send_raw_msg(
134 &self,
135 bytes: &[u8],
136 handles: &mut [<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition],
137 ) -> Result<(), Error> {
138 match self.channel.write_etc(bytes, handles) {
139 Ok(()) | Err(None) => Ok(()),
140 Err(Some(e)) => Err(Error::ServerResponseWrite(e.into())),
141 }
142 }
143}