1use crate::handle::handle_type;
6use crate::responder::Responder;
7use crate::{Error, Event, EventPair, Handle, OnFDomainSignals, Socket, Vmo, ordinals};
8use fidl_fuchsia_fdomain as proto;
9use futures::future::Either;
10use futures::stream::Stream;
11use std::future::Future;
12use std::pin::Pin;
13use std::sync::{Arc, Weak};
14use std::task::{Context, Poll, ready};
15
16#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct Channel(pub(crate) Handle);
19
20handle_type!(Channel CHANNEL peered);
21
22#[derive(Debug)]
24pub struct MessageBuf {
25 pub bytes: Vec<u8>,
26 pub handles: Vec<HandleInfo>,
27}
28
29impl MessageBuf {
30 pub fn new() -> Self {
32 MessageBuf { bytes: Vec::new(), handles: Vec::new() }
33 }
34
35 pub fn split(self) -> (Vec<u8>, Vec<HandleInfo>) {
37 (self.bytes, self.handles)
38 }
39
40 pub fn ensure_capacity_bytes(&mut self, bytes: usize) {
42 self.bytes.reserve(bytes);
43 }
44
45 pub fn clear(&mut self) {
47 self.bytes.clear();
48 self.handles.clear();
49 }
50
51 pub fn bytes(&self) -> &[u8] {
53 self.bytes.as_slice()
54 }
55
56 fn from_proto(client: &Arc<crate::Client>, message: proto::ChannelMessage) -> MessageBuf {
58 let proto::ChannelMessage { data, handles } = message;
59 MessageBuf {
60 bytes: data,
61 handles: handles
62 .into_iter()
63 .map(|info| {
64 let handle = Handle { id: info.handle.id, client: Arc::downgrade(client) };
65 HandleInfo {
66 rights: info.rights,
67 handle: AnyHandle::from_handle(handle, info.type_),
68 }
69 })
70 .collect(),
71 }
72 }
73}
74
75#[derive(Debug)]
77pub struct HandleInfo {
78 pub handle: AnyHandle,
79 pub rights: fidl::Rights,
80}
81
82#[derive(Debug, PartialEq)]
85pub enum AnyHandle {
86 Channel(Channel),
87 Socket(Socket),
88 Event(Event),
89 EventPair(EventPair),
90 Vmo(Vmo),
91 Unknown(Handle, fidl::ObjectType),
92}
93
94impl AnyHandle {
95 pub fn from_handle(handle: Handle, ty: fidl::ObjectType) -> AnyHandle {
97 match ty {
98 fidl::ObjectType::CHANNEL => AnyHandle::Channel(Channel(handle)),
99 fidl::ObjectType::SOCKET => AnyHandle::Socket(Socket(handle)),
100 fidl::ObjectType::EVENT => AnyHandle::Event(Event(handle)),
101 fidl::ObjectType::EVENTPAIR => AnyHandle::EventPair(EventPair(handle)),
102 fidl::ObjectType::VMO => AnyHandle::Vmo(Vmo(handle)),
103 _ => AnyHandle::Unknown(handle, ty),
104 }
105 }
106
107 pub fn invalid() -> AnyHandle {
109 AnyHandle::Unknown(Handle::invalid(), fidl::ObjectType::NONE)
110 }
111
112 pub fn is_invalid(&self) -> bool {
114 match self {
115 AnyHandle::Channel(h) => h.is_invalid(),
116 AnyHandle::Socket(h) => h.is_invalid(),
117 AnyHandle::Event(h) => h.is_invalid(),
118 AnyHandle::EventPair(h) => h.is_invalid(),
119 AnyHandle::Vmo(h) => h.is_invalid(),
120 AnyHandle::Unknown(h, _) => h.is_invalid(),
121 }
122 }
123
124 pub fn object_type(&self) -> fidl::ObjectType {
126 match self {
127 AnyHandle::Channel(_) => fidl::ObjectType::CHANNEL,
128 AnyHandle::Socket(_) => fidl::ObjectType::SOCKET,
129 AnyHandle::Event(_) => fidl::ObjectType::EVENT,
130 AnyHandle::EventPair(_) => fidl::ObjectType::EVENTPAIR,
131 AnyHandle::Vmo(_) => fidl::ObjectType::VMO,
132 AnyHandle::Unknown(_, t) => *t,
133 }
134 }
135}
136
137impl From<AnyHandle> for Handle {
138 fn from(item: AnyHandle) -> Handle {
139 match item {
140 AnyHandle::Channel(h) => h.into(),
141 AnyHandle::Socket(h) => h.into(),
142 AnyHandle::Event(h) => h.into(),
143 AnyHandle::EventPair(h) => h.into(),
144 AnyHandle::Vmo(h) => h.into(),
145 AnyHandle::Unknown(h, _) => h,
146 }
147 }
148}
149
150pub enum HandleOp<'h> {
152 Move(Handle, fidl::Rights),
153 Duplicate(&'h Handle, fidl::Rights),
154}
155
156impl Channel {
157 pub fn recv_msg(&self) -> impl Future<Output = Result<MessageBuf, Error>> + use<> {
159 let client = Arc::downgrade(&self.0.client());
160 let handle = self.0.proto();
161
162 futures::future::poll_fn(move |ctx| {
163 let client = client.upgrade().unwrap_or_else(|| Arc::clone(&crate::DEAD_CLIENT));
164 client.poll_channel(handle, ctx, false).map(|x| {
165 x.expect("Got stream termination indication from non-streaming read!")
166 .map(|x| MessageBuf::from_proto(&client, x))
167 })
168 })
169 }
170
171 pub fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Result<MessageBuf, Error>> {
173 let client = self.0.client();
174 let handle = self.0.proto();
175
176 client.poll_channel(handle, cx, false).map(|x| {
177 x.expect("Got stream termination indication from non-streaming read!")
178 .map(|x| MessageBuf::from_proto(&client, x))
179 })
180 }
181
182 pub fn recv_from(&self, cx: &mut Context<'_>, buf: &mut MessageBuf) -> Poll<Result<(), Error>> {
184 let client = self.0.client();
185 match ready!(client.poll_channel(self.0.proto(), cx, false))
186 .expect("Got stream termination indication from non-streaming read!")
187 {
188 Ok(msg) => {
189 *buf = MessageBuf::from_proto(&client, msg);
190 Poll::Ready(Ok(()))
191 }
192 Err(e) => Poll::Ready(Err(e)),
193 }
194 }
195
196 pub fn write(&self, bytes: &[u8], handles: Vec<Handle>) -> Result<(), Error> {
198 if bytes.len() > zx_types::ZX_CHANNEL_MAX_MSG_BYTES as usize
199 || handles.len() > zx_types::ZX_CHANNEL_MAX_MSG_HANDLES as usize
200 {
201 return Err(Error::FDomain(proto::Error::TargetError(
202 fidl::Status::OUT_OF_RANGE.into_raw(),
203 )));
204 }
205
206 let _ = self.write_inner(
207 bytes,
208 proto::Handles::Handles(handles.into_iter().map(|x| x.take_proto()).collect()),
209 );
210 Ok(())
211 }
212
213 pub fn fdomain_write(
217 &self,
218 bytes: &[u8],
219 handles: Vec<Handle>,
220 ) -> impl Future<Output = Result<(), Error>> + use<> {
221 if bytes.len() > zx_types::ZX_CHANNEL_MAX_MSG_BYTES as usize
222 || handles.len() > zx_types::ZX_CHANNEL_MAX_MSG_HANDLES as usize
223 {
224 Either::Left(async {
225 Err(Error::FDomain(proto::Error::TargetError(
226 fidl::Status::OUT_OF_RANGE.into_raw(),
227 )))
228 })
229 } else {
230 Either::Right(self.write_inner(
231 bytes,
232 proto::Handles::Handles(handles.into_iter().map(|x| x.take_proto()).collect()),
233 ))
234 }
235 }
236
237 pub fn on_closed(&self) -> OnFDomainSignals {
239 OnFDomainSignals::new(&self.0, fidl::Signals::OBJECT_PEER_CLOSED)
240 }
241
242 pub fn is_closed(&self) -> bool {
244 self.0.client.upgrade().is_none()
245 }
246
247 pub fn fdomain_write_etc<'b>(
251 &self,
252 bytes: &[u8],
253 handles: Vec<HandleOp<'b>>,
254 ) -> impl Future<Output = Result<(), Error>> + use<'b> {
255 let handles = handles
256 .into_iter()
257 .map(|handle| match handle {
258 HandleOp::Move(x, rights) => {
259 if Weak::ptr_eq(&x.client, &self.0.client) {
260 Ok(proto::HandleDisposition {
261 handle: proto::HandleOp::Move_(x.take_proto()),
262 rights,
263 })
264 } else {
265 Err(Error::ConnectionMismatch)
266 }
267 }
268 HandleOp::Duplicate(x, rights) => {
269 if Weak::ptr_eq(&x.client, &self.0.client) {
270 Ok(proto::HandleDisposition {
271 handle: proto::HandleOp::Duplicate(x.proto()),
272 rights,
273 })
274 } else {
275 Err(Error::ConnectionMismatch)
276 }
277 }
278 })
279 .collect::<Result<Vec<_>, Error>>();
280
281 let handles = if handles
282 .as_ref()
283 .map(|x| x.len() > zx_types::ZX_CHANNEL_MAX_MSG_HANDLES as usize)
284 .unwrap_or(false)
285 || bytes.len() > zx_types::ZX_CHANNEL_MAX_MSG_BYTES as usize
286 {
287 Err(Error::FDomain(proto::Error::TargetError(fidl::Status::OUT_OF_RANGE.into_raw())))
288 } else {
289 handles
290 };
291
292 match handles {
293 Ok(handles) => {
294 Either::Left(self.write_inner(bytes, proto::Handles::Dispositions(handles)))
295 }
296 Err(e) => Either::Right(async move { Err(e) }),
297 }
298 }
299
300 fn write_inner(
302 &self,
303 bytes: &[u8],
304 handles: proto::Handles,
305 ) -> impl Future<Output = Result<(), Error>> + use<> {
306 let data = bytes.to_vec();
307 let client = self.0.client();
308 let handle = self.0.proto();
309
310 client.clear_handles_for_transfer(&handles);
311 client.transaction(
312 ordinals::WRITE_CHANNEL,
313 proto::ChannelWriteChannelRequest { handle, data, handles },
314 move |x| Responder::WriteChannel(x),
315 )
316 }
317
318 pub fn stream(self) -> Result<(ChannelMessageStream, ChannelWriter), Error> {
325 let (a, b, err) = self.force_stream();
326 if let Some(err) = err { Err(err) } else { Ok((a, b)) }
327 }
328
329 pub(crate) fn force_stream(self) -> (ChannelMessageStream, ChannelWriter, Option<Error>) {
333 let err = self.0.client().start_channel_streaming(self.0.proto()).err();
334
335 let a = Arc::new(self);
336 let b = Arc::clone(&a);
337
338 (ChannelMessageStream(a), ChannelWriter(b), err)
339 }
340}
341
342#[derive(Debug, Clone)]
344pub struct ChannelWriter(Arc<Channel>);
345
346impl ChannelWriter {
347 pub fn write(&self, bytes: &[u8], handles: Vec<Handle>) -> Result<(), Error> {
349 self.0.write(bytes, handles)
350 }
351
352 pub fn fdomain_write(
356 &self,
357 bytes: &[u8],
358 handles: Vec<Handle>,
359 ) -> impl Future<Output = Result<(), Error>> {
360 self.0.fdomain_write(bytes, handles)
361 }
362
363 pub fn fdomain_write_etc<'b>(
365 &self,
366 bytes: &[u8],
367 handles: Vec<HandleOp<'b>>,
368 ) -> impl Future<Output = Result<(), Error>> + 'b {
369 self.0.fdomain_write_etc(bytes, handles)
370 }
371
372 pub fn as_channel(&self) -> &Channel {
374 &*self.0
375 }
376}
377
378#[derive(Debug)]
380pub struct ChannelMessageStream(Arc<Channel>);
381
382impl ChannelMessageStream {
383 pub fn rejoin(mut self, writer: ChannelWriter) -> Channel {
390 assert!(Arc::ptr_eq(&self.0, &writer.0), "Tried to join stream with wrong writer!");
391 if let Some(client) = self.0.0.client.upgrade() {
392 client.stop_channel_streaming(self.0.0.proto())
393 }
394 std::mem::drop(writer);
395 let channel = std::mem::replace(&mut self.0, Arc::new(Channel(Handle::invalid())));
396 Arc::try_unwrap(channel).expect("Stream pointer no longer unique!")
397 }
398
399 pub fn is_closed(&self) -> bool {
401 let client = self.0.0.client();
402
403 !client.channel_is_streaming(self.0.0.proto())
404 }
405
406 pub fn as_channel(&self) -> &Channel {
408 &*self.0
409 }
410}
411
412impl Stream for ChannelMessageStream {
413 type Item = Result<MessageBuf, Error>;
414 fn poll_next(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
415 let client = self.0.0.client();
416 client
417 .poll_channel(self.0.0.proto(), ctx, true)
418 .map(|x| x.map(|x| x.map(|x| MessageBuf::from_proto(&client, x))))
419 }
420}
421
422impl Drop for ChannelMessageStream {
423 fn drop(&mut self) {
424 if let Some(client) = self.0.0.client.upgrade() {
425 client.stop_channel_streaming(self.0.0.proto());
426 }
427 }
428}