overnet_core/proxy/handle/
signals.rs1use super::ReadValue;
6use fidl::{HandleRef, Signals};
7use fidl_fuchsia_overnet_protocol::{SignalUpdate, Signals as WireSignals};
8use fuchsia_async::OnSignalsRef;
9use futures::FutureExt;
10use std::task::{Context, Poll};
11use zx_status;
12
13const POLLED_SIGNALS: Signals = Signals::from_bits_truncate(
14 Signals::USER_0.bits()
15 | Signals::USER_1.bits()
16 | Signals::USER_2.bits()
17 | Signals::USER_3.bits()
18 | Signals::USER_4.bits()
19 | Signals::USER_5.bits()
20 | Signals::USER_6.bits()
21 | Signals::USER_7.bits(),
22);
23
24#[derive(Default)]
25pub(crate) struct Collector<'a> {
26 on_signals: Option<OnSignalsRef<'a>>,
27 shutdown: bool,
28}
29
30impl<'h> Collector<'h> {
31 pub(crate) fn after_read<'ctx>(
32 &mut self,
33 ctx: &mut Context<'ctx>,
34 hdl: HandleRef<'h>,
35 read_result: Poll<Result<(), zx_status::Status>>,
36 do_peer_closed: bool,
37 ) -> Poll<Result<ReadValue, zx_status::Status>> {
38 match read_result {
39 Poll::Ready(Ok(())) => Poll::Ready(Ok(ReadValue::Message)),
40 Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
41 Poll::Pending => {
42 if self.shutdown {
43 return Poll::Ready(Err(zx_status::Status::PEER_CLOSED));
44 }
45
46 let signals = if do_peer_closed {
47 POLLED_SIGNALS | Signals::OBJECT_PEER_CLOSED
48 } else {
49 POLLED_SIGNALS
50 };
51
52 let mut on_signals = self
53 .on_signals
54 .take()
55 .unwrap_or_else(|| OnSignalsRef::new(hdl.clone(), signals));
56 match on_signals.poll_unpin(ctx) {
57 Poll::Ready(Ok(mut signals)) => {
58 self.shutdown =
59 self.shutdown || signals.contains(Signals::OBJECT_PEER_CLOSED);
60 signals.remove(Signals::OBJECT_PEER_CLOSED);
61 if signals.is_empty() {
62 Poll::Ready(Err(zx_status::Status::PEER_CLOSED))
63 } else {
64 hdl.signal(signals & POLLED_SIGNALS, Signals::empty()).inspect_err(
65 |e| log::warn!("failed to clear signals in handle {e:?}"),
66 )?;
67 Poll::Ready(Ok(ReadValue::SignalUpdate(SignalUpdate {
68 assert_signals: Some(to_wire_signals(signals)),
69 ..Default::default()
70 })))
71 }
72 }
73 Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
74 Poll::Pending => {
75 self.on_signals = Some(on_signals);
76 Poll::Pending
77 }
78 }
79 }
80 }
81 }
82}
83
84fn to_wire_signals(signals: Signals) -> WireSignals {
85 let mut out = WireSignals::empty();
86 if signals.contains(Signals::USER_0) {
87 out.insert(WireSignals::USER_0);
88 }
89 if signals.contains(Signals::USER_1) {
90 out.insert(WireSignals::USER_1);
91 }
92 if signals.contains(Signals::USER_2) {
93 out.insert(WireSignals::USER_2);
94 }
95 if signals.contains(Signals::USER_3) {
96 out.insert(WireSignals::USER_3);
97 }
98 if signals.contains(Signals::USER_4) {
99 out.insert(WireSignals::USER_4);
100 }
101 if signals.contains(Signals::USER_5) {
102 out.insert(WireSignals::USER_5);
103 }
104 if signals.contains(Signals::USER_6) {
105 out.insert(WireSignals::USER_6);
106 }
107 if signals.contains(Signals::USER_7) {
108 out.insert(WireSignals::USER_7);
109 }
110 out
111}
112
113pub(crate) fn from_wire_signals(signals: WireSignals) -> Signals {
114 let mut out = Signals::empty();
115 if signals.contains(WireSignals::USER_0) {
116 out.insert(Signals::USER_0);
117 }
118 if signals.contains(WireSignals::USER_1) {
119 out.insert(Signals::USER_1);
120 }
121 if signals.contains(WireSignals::USER_2) {
122 out.insert(Signals::USER_2);
123 }
124 if signals.contains(WireSignals::USER_3) {
125 out.insert(Signals::USER_3);
126 }
127 if signals.contains(WireSignals::USER_4) {
128 out.insert(Signals::USER_4);
129 }
130 if signals.contains(WireSignals::USER_5) {
131 out.insert(Signals::USER_5);
132 }
133 if signals.contains(WireSignals::USER_6) {
134 out.insert(Signals::USER_6);
135 }
136 if signals.contains(WireSignals::USER_7) {
137 out.insert(Signals::USER_7);
138 }
139 out
140}