1use crate::encoding::{
8 self, DynamicFlags, EpitaphBody, NoHandleResourceDialect, TransactionHeader,
9 TransactionMessage, TransactionMessageType,
10};
11use crate::error::Error;
12use crate::{AsyncChannel, Channel, TransportError};
13use zx_status;
14
15pub trait ChannelEpitaphExt {
17 fn close_with_epitaph(self, status: zx_status::Status) -> Result<(), Error>;
19}
20
21impl<T: ChannelLike> ChannelEpitaphExt for T {
22 fn close_with_epitaph(self, status: zx_status::Status) -> Result<(), Error> {
23 write_epitaph_impl(&self, status)
24 }
25}
26
27pub trait ChannelLike {
29 fn write_epitaph(&self, bytes: &[u8]) -> Result<(), TransportError>;
31}
32
33impl ChannelLike for Channel {
34 fn write_epitaph(&self, bytes: &[u8]) -> Result<(), TransportError> {
35 self.write_etc(bytes, &mut []).map_err(Into::into)
36 }
37}
38
39impl ChannelLike for AsyncChannel {
40 fn write_epitaph(&self, bytes: &[u8]) -> Result<(), TransportError> {
41 self.write_etc(bytes, &mut []).map_err(Into::into)
42 }
43}
44
45pub(crate) fn write_epitaph_impl<T: ChannelLike>(
46 channel: &T,
47 status: zx_status::Status,
48) -> Result<(), Error> {
49 let msg = TransactionMessage {
50 header: TransactionHeader::new(0, encoding::EPITAPH_ORDINAL, DynamicFlags::empty()),
51 body: &EpitaphBody { error: status },
52 };
53 encoding::with_tls_encoded::<TransactionMessageType<EpitaphBody>, NoHandleResourceDialect, ()>(
54 msg,
55 |bytes, handles| {
56 assert!(handles.is_empty(), "Epitaph should not have handles!");
57 match channel.write_epitaph(bytes) {
58 Ok(()) | Err(TransportError::Status(zx_status::Status::PEER_CLOSED)) => Ok(()),
59 Err(e) => Err(Error::ServerEpitaphWrite(e)),
60 }
61 },
62 )
63}