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::{epitaph, Error};
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: zx_status::Status) {
62 let already_shutting_down = self.shutdown.swap(true, atomic::Ordering::Relaxed);
63 if !already_shutting_down {
64 let _ = epitaph::write_epitaph_impl(self.channel.as_channel(), status);
66 self.waker.wake();
67 }
68 }
69
70 pub fn check_shutdown(&self, cx: &Context<'_>) -> bool {
72 if self.shutdown.load(atomic::Ordering::Relaxed) {
73 return true;
74 }
75 self.waker.register(cx.waker());
76 self.shutdown.load(atomic::Ordering::Relaxed)
77 }
78
79 #[inline]
81 pub fn send<T: TypeMarker>(
82 &self,
83 body: impl Encode<T, D>,
84 tx_id: u32,
85 ordinal: u64,
86 dynamic_flags: DynamicFlags,
87 ) -> Result<(), Error> {
88 let msg = TransactionMessage {
89 header: TransactionHeader::new(tx_id, ordinal, dynamic_flags),
90 body,
91 };
92 crate::encoding::with_tls_encoded::<TransactionMessageType<T>, D, ()>(
93 msg,
94 |bytes, handles| self.send_raw_msg(bytes, handles),
95 )
96 }
97
98 #[inline]
103 pub fn send_framework_err(
104 &self,
105 framework_err: FrameworkErr,
106 tx_id: u32,
107 ordinal: u64,
108 dynamic_flags: DynamicFlags,
109 tls_decode_buf: (&mut Vec<u8>, &mut Vec<<D::Handle as HandleFor<D>>::HandleInfo>),
110 ) -> Result<(), Error> {
111 type Msg = TransactionMessageType<FlexibleType<EmptyStruct>>;
112 let msg = TransactionMessage {
113 header: TransactionHeader::new(tx_id, ordinal, dynamic_flags),
114 body: Flexible::<()>::FrameworkErr(framework_err),
115 };
116
117 let (bytes, handle_infos) = tls_decode_buf;
119 handle_infos.clear();
120 let mut handle_dispositions = Vec::new();
123 Encoder::<D>::encode::<Msg>(bytes, &mut handle_dispositions, msg)?;
124 debug_assert!(handle_dispositions.is_empty());
125 self.send_raw_msg(&*bytes, &mut [])
126 }
127
128 fn send_raw_msg(
130 &self,
131 bytes: &[u8],
132 handles: &mut [<D::ProxyChannel as ProxyChannelFor<D>>::HandleDisposition],
133 ) -> Result<(), Error> {
134 match self.channel.write_etc(bytes, handles) {
135 Ok(()) | Err(None) => Ok(()),
136 Err(Some(e)) => Err(Error::ServerResponseWrite(e.into())),
137 }
138 }
139}