1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2021 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Cursor;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::os::windows::io::AsRawHandle;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::os::windows::io::RawHandle;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
13*bb4ee6a4SAndroid Build Coastguard Worker
14*bb4ee6a4SAndroid Build Coastguard Worker use log::warn;
15*bb4ee6a4SAndroid Build Coastguard Worker use serde::de::DeserializeOwned;
16*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
17*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
18*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serializer;
19*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::winerror::ERROR_MORE_DATA;
20*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
21*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
22*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
23*bb4ee6a4SAndroid Build Coastguard Worker
24*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::SafeDescriptor;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor_reflection::deserialize_with_descriptors;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor_reflection::SerializeDescriptors;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::Error;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::RecvTube;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::Result;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::SendTube;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::BlockingMode;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::CloseNotifier;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::Event;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::EventToken;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::FramingMode;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::PipeConnection;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::RawDescriptor;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::ReadNotifier;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::StreamChannel;
42*bb4ee6a4SAndroid Build Coastguard Worker
43*bb4ee6a4SAndroid Build Coastguard Worker /// Bidirectional tube that support both send and recv.
44*bb4ee6a4SAndroid Build Coastguard Worker ///
45*bb4ee6a4SAndroid Build Coastguard Worker /// NOTE: serializing this type across processes is slightly involved. Suppose there is a Tube pair
46*bb4ee6a4SAndroid Build Coastguard Worker /// (A, B). We wish to send B to another process, and communicate with it using A from the current
47*bb4ee6a4SAndroid Build Coastguard Worker /// process:
48*bb4ee6a4SAndroid Build Coastguard Worker /// 1. B's target_pid must be set to the current PID *before* serialization. There is a
49*bb4ee6a4SAndroid Build Coastguard Worker /// serialization hook that sets it to the current PID automatically if target_pid is unset.
50*bb4ee6a4SAndroid Build Coastguard Worker /// 2. A's target_pid must be set to the PID of the process where B was sent.
51*bb4ee6a4SAndroid Build Coastguard Worker ///
52*bb4ee6a4SAndroid Build Coastguard Worker /// If instead you are sending both A and B to separate processes, then:
53*bb4ee6a4SAndroid Build Coastguard Worker /// 1. A's target_pid must be set to B's pid, manually.
54*bb4ee6a4SAndroid Build Coastguard Worker /// 2. B's target_pid must be set to A's pid, manually.
55*bb4ee6a4SAndroid Build Coastguard Worker ///
56*bb4ee6a4SAndroid Build Coastguard Worker /// Automating all of this and getting a completely clean interface is tricky. We would need
57*bb4ee6a4SAndroid Build Coastguard Worker /// intercept the serialization of Tubes in any part of Serde messages, and use Weak refs to sync
58*bb4ee6a4SAndroid Build Coastguard Worker /// state about PIDs between the ends. There are alternatives like reusing the underlying
59*bb4ee6a4SAndroid Build Coastguard Worker /// StreamChannel to share PIDs, or having a separate pipe just for this purpose; however, we've yet
60*bb4ee6a4SAndroid Build Coastguard Worker /// to find a compelling solution that isn't a mess to implement. Suggestions are welcome.
61*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug)]
62*bb4ee6a4SAndroid Build Coastguard Worker pub struct Tube {
63*bb4ee6a4SAndroid Build Coastguard Worker socket: StreamChannel,
64*bb4ee6a4SAndroid Build Coastguard Worker
65*bb4ee6a4SAndroid Build Coastguard Worker // Default target_pid to current PID on serialization (see `Tube` comment header for details).
66*bb4ee6a4SAndroid Build Coastguard Worker #[serde(serialize_with = "set_tube_pid_on_serialize")]
67*bb4ee6a4SAndroid Build Coastguard Worker target_pid: Option<u32>,
68*bb4ee6a4SAndroid Build Coastguard Worker }
69*bb4ee6a4SAndroid Build Coastguard Worker
70*bb4ee6a4SAndroid Build Coastguard Worker /// For a Tube which has not had its target_pid set, when it is serialized, we should automatically
71*bb4ee6a4SAndroid Build Coastguard Worker /// default it to the current process, because the other end will be in the current process.
set_tube_pid_on_serialize<S>( existing_pid_value: &Option<u32>, serializer: S, ) -> std::result::Result<S::Ok, S::Error> where S: Serializer,72*bb4ee6a4SAndroid Build Coastguard Worker fn set_tube_pid_on_serialize<S>(
73*bb4ee6a4SAndroid Build Coastguard Worker existing_pid_value: &Option<u32>,
74*bb4ee6a4SAndroid Build Coastguard Worker serializer: S,
75*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::result::Result<S::Ok, S::Error>
76*bb4ee6a4SAndroid Build Coastguard Worker where
77*bb4ee6a4SAndroid Build Coastguard Worker S: Serializer,
78*bb4ee6a4SAndroid Build Coastguard Worker {
79*bb4ee6a4SAndroid Build Coastguard Worker match existing_pid_value {
80*bb4ee6a4SAndroid Build Coastguard Worker Some(pid) => serializer.serialize_u32(*pid),
81*bb4ee6a4SAndroid Build Coastguard Worker None => serializer.serialize_u32(ALIAS_PID.lock().unwrap_or(std::process::id())),
82*bb4ee6a4SAndroid Build Coastguard Worker }
83*bb4ee6a4SAndroid Build Coastguard Worker }
84*bb4ee6a4SAndroid Build Coastguard Worker
85*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, Default, AsBytes, FromZeroes, FromBytes)]
86*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
87*bb4ee6a4SAndroid Build Coastguard Worker struct MsgHeader {
88*bb4ee6a4SAndroid Build Coastguard Worker msg_json_size: usize,
89*bb4ee6a4SAndroid Build Coastguard Worker descriptor_json_size: usize,
90*bb4ee6a4SAndroid Build Coastguard Worker }
91*bb4ee6a4SAndroid Build Coastguard Worker
92*bb4ee6a4SAndroid Build Coastguard Worker static DH_TUBE: sync::Mutex<Option<DuplicateHandleTube>> = sync::Mutex::new(None);
93*bb4ee6a4SAndroid Build Coastguard Worker static ALIAS_PID: sync::Mutex<Option<u32>> = sync::Mutex::new(None);
94*bb4ee6a4SAndroid Build Coastguard Worker
95*bb4ee6a4SAndroid Build Coastguard Worker /// Set a tube to delegate duplicate handle calls.
set_duplicate_handle_tube(dh_tube: DuplicateHandleTube)96*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_duplicate_handle_tube(dh_tube: DuplicateHandleTube) {
97*bb4ee6a4SAndroid Build Coastguard Worker DH_TUBE.lock().replace(dh_tube);
98*bb4ee6a4SAndroid Build Coastguard Worker }
99*bb4ee6a4SAndroid Build Coastguard Worker
100*bb4ee6a4SAndroid Build Coastguard Worker /// Set alias pid for use with a DuplicateHandleTube.
set_alias_pid(alias_pid: u32)101*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_alias_pid(alias_pid: u32) {
102*bb4ee6a4SAndroid Build Coastguard Worker ALIAS_PID.lock().replace(alias_pid);
103*bb4ee6a4SAndroid Build Coastguard Worker }
104*bb4ee6a4SAndroid Build Coastguard Worker
105*bb4ee6a4SAndroid Build Coastguard Worker impl Tube {
106*bb4ee6a4SAndroid Build Coastguard Worker /// Create a pair of connected tubes. Request is sent in one direction while response is
107*bb4ee6a4SAndroid Build Coastguard Worker /// received in the other direction.
108*bb4ee6a4SAndroid Build Coastguard Worker /// The result is in the form (server, client).
pair() -> Result<(Tube, Tube)>109*bb4ee6a4SAndroid Build Coastguard Worker pub fn pair() -> Result<(Tube, Tube)> {
110*bb4ee6a4SAndroid Build Coastguard Worker let (socket1, socket2) = StreamChannel::pair(BlockingMode::Blocking, FramingMode::Message)
111*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| Error::Pair(io::Error::from_raw_os_error(e.errno())))?;
112*bb4ee6a4SAndroid Build Coastguard Worker
113*bb4ee6a4SAndroid Build Coastguard Worker Ok((Tube::new(socket1), Tube::new(socket2)))
114*bb4ee6a4SAndroid Build Coastguard Worker }
115*bb4ee6a4SAndroid Build Coastguard Worker
116*bb4ee6a4SAndroid Build Coastguard Worker /// Create a pair of connected tubes with the specified buffer size.
117*bb4ee6a4SAndroid Build Coastguard Worker /// Request is sent in one direction while response is received in the other direction.
118*bb4ee6a4SAndroid Build Coastguard Worker /// The result is in the form (server, client).
pair_with_buffer_size(buffer_size: usize) -> Result<(Tube, Tube)>119*bb4ee6a4SAndroid Build Coastguard Worker pub fn pair_with_buffer_size(buffer_size: usize) -> Result<(Tube, Tube)> {
120*bb4ee6a4SAndroid Build Coastguard Worker let (socket1, socket2) = StreamChannel::pair_with_buffer_size(
121*bb4ee6a4SAndroid Build Coastguard Worker BlockingMode::Blocking,
122*bb4ee6a4SAndroid Build Coastguard Worker FramingMode::Message,
123*bb4ee6a4SAndroid Build Coastguard Worker buffer_size,
124*bb4ee6a4SAndroid Build Coastguard Worker )
125*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| Error::Pair(io::Error::from_raw_os_error(e.errno())))?;
126*bb4ee6a4SAndroid Build Coastguard Worker let tube1 = Tube::new(socket1);
127*bb4ee6a4SAndroid Build Coastguard Worker let tube2 = Tube::new(socket2);
128*bb4ee6a4SAndroid Build Coastguard Worker Ok((tube1, tube2))
129*bb4ee6a4SAndroid Build Coastguard Worker }
130*bb4ee6a4SAndroid Build Coastguard Worker
131*bb4ee6a4SAndroid Build Coastguard Worker // Create a new `Tube`.
new(socket: StreamChannel) -> Tube132*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(socket: StreamChannel) -> Tube {
133*bb4ee6a4SAndroid Build Coastguard Worker Tube {
134*bb4ee6a4SAndroid Build Coastguard Worker socket,
135*bb4ee6a4SAndroid Build Coastguard Worker target_pid: None,
136*bb4ee6a4SAndroid Build Coastguard Worker }
137*bb4ee6a4SAndroid Build Coastguard Worker }
138*bb4ee6a4SAndroid Build Coastguard Worker
try_clone(&self) -> Result<Self>139*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn try_clone(&self) -> Result<Self> {
140*bb4ee6a4SAndroid Build Coastguard Worker Ok(Tube {
141*bb4ee6a4SAndroid Build Coastguard Worker socket: self.socket.try_clone().map_err(Error::Clone)?,
142*bb4ee6a4SAndroid Build Coastguard Worker target_pid: self.target_pid,
143*bb4ee6a4SAndroid Build Coastguard Worker })
144*bb4ee6a4SAndroid Build Coastguard Worker }
145*bb4ee6a4SAndroid Build Coastguard Worker
send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()>146*bb4ee6a4SAndroid Build Coastguard Worker fn send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()> {
147*bb4ee6a4SAndroid Build Coastguard Worker let bytes = msg.write_to_bytes().map_err(Error::Proto)?;
148*bb4ee6a4SAndroid Build Coastguard Worker let size_header = bytes.len();
149*bb4ee6a4SAndroid Build Coastguard Worker
150*bb4ee6a4SAndroid Build Coastguard Worker let mut data_packet =
151*bb4ee6a4SAndroid Build Coastguard Worker Cursor::new(Vec::with_capacity(mem::size_of::<usize>() + size_header));
152*bb4ee6a4SAndroid Build Coastguard Worker data_packet
153*bb4ee6a4SAndroid Build Coastguard Worker .write(&size_header.to_le_bytes())
154*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::from_send_io_buf_error)?;
155*bb4ee6a4SAndroid Build Coastguard Worker data_packet.write(&bytes).map_err(Error::SendIoBuf)?;
156*bb4ee6a4SAndroid Build Coastguard Worker self.socket
157*bb4ee6a4SAndroid Build Coastguard Worker .write_immutable(&data_packet.into_inner())
158*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::from_send_error)?;
159*bb4ee6a4SAndroid Build Coastguard Worker
160*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
161*bb4ee6a4SAndroid Build Coastguard Worker }
162*bb4ee6a4SAndroid Build Coastguard Worker
recv_proto<M: protobuf::Message>(&self) -> Result<M>163*bb4ee6a4SAndroid Build Coastguard Worker fn recv_proto<M: protobuf::Message>(&self) -> Result<M> {
164*bb4ee6a4SAndroid Build Coastguard Worker let mut header_bytes = [0u8; mem::size_of::<usize>()];
165*bb4ee6a4SAndroid Build Coastguard Worker perform_read(&mut |buf| (&self.socket).read(buf), &mut header_bytes)
166*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::from_recv_io_error)?;
167*bb4ee6a4SAndroid Build Coastguard Worker let size_header = usize::from_le_bytes(header_bytes);
168*bb4ee6a4SAndroid Build Coastguard Worker
169*bb4ee6a4SAndroid Build Coastguard Worker let mut proto_bytes = vec![0u8; size_header];
170*bb4ee6a4SAndroid Build Coastguard Worker perform_read(&mut |buf| (&self.socket).read(buf), &mut proto_bytes)
171*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::from_recv_io_error)?;
172*bb4ee6a4SAndroid Build Coastguard Worker protobuf::Message::parse_from_bytes(&proto_bytes).map_err(Error::Proto)
173*bb4ee6a4SAndroid Build Coastguard Worker }
174*bb4ee6a4SAndroid Build Coastguard Worker
send<T: Serialize>(&self, msg: &T) -> Result<()>175*bb4ee6a4SAndroid Build Coastguard Worker pub fn send<T: Serialize>(&self, msg: &T) -> Result<()> {
176*bb4ee6a4SAndroid Build Coastguard Worker serialize_and_send(|buf| self.socket.write_immutable(buf), msg, self.target_pid)
177*bb4ee6a4SAndroid Build Coastguard Worker }
178*bb4ee6a4SAndroid Build Coastguard Worker
recv<T: DeserializeOwned>(&self) -> Result<T>179*bb4ee6a4SAndroid Build Coastguard Worker pub fn recv<T: DeserializeOwned>(&self) -> Result<T> {
180*bb4ee6a4SAndroid Build Coastguard Worker deserialize_and_recv(|buf| (&self.socket).read(buf))
181*bb4ee6a4SAndroid Build Coastguard Worker }
182*bb4ee6a4SAndroid Build Coastguard Worker
183*bb4ee6a4SAndroid Build Coastguard Worker /// NOTE: On Windows this will only succeed if called on a server pipe. See #pair
184*bb4ee6a4SAndroid Build Coastguard Worker /// documentation to ensure you have a server pipe before calling.
185*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
flush_blocking(&mut self) -> Result<()>186*bb4ee6a4SAndroid Build Coastguard Worker pub fn flush_blocking(&mut self) -> Result<()> {
187*bb4ee6a4SAndroid Build Coastguard Worker self.socket.flush_blocking().map_err(Error::Flush)
188*bb4ee6a4SAndroid Build Coastguard Worker }
189*bb4ee6a4SAndroid Build Coastguard Worker
190*bb4ee6a4SAndroid Build Coastguard Worker /// For Tubes that span processes, this method must be used to set the PID of the other end
191*bb4ee6a4SAndroid Build Coastguard Worker /// of the Tube, otherwise sending handles to the other end won't work.
set_target_pid(&mut self, target_pid: u32)192*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_target_pid(&mut self, target_pid: u32) {
193*bb4ee6a4SAndroid Build Coastguard Worker self.target_pid = Some(target_pid);
194*bb4ee6a4SAndroid Build Coastguard Worker }
195*bb4ee6a4SAndroid Build Coastguard Worker
196*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the PID of the process at the other end of the Tube, if any is set.
target_pid(&self) -> Option<u32>197*bb4ee6a4SAndroid Build Coastguard Worker pub fn target_pid(&self) -> Option<u32> {
198*bb4ee6a4SAndroid Build Coastguard Worker self.target_pid
199*bb4ee6a4SAndroid Build Coastguard Worker }
200*bb4ee6a4SAndroid Build Coastguard Worker
201*bb4ee6a4SAndroid Build Coastguard Worker /// TODO(b/145998747, b/184398671): this method should be removed.
set_send_timeout(&self, _timeout: Option<Duration>) -> Result<()>202*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_send_timeout(&self, _timeout: Option<Duration>) -> Result<()> {
203*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("To be removed/refactored upstream.");
204*bb4ee6a4SAndroid Build Coastguard Worker }
205*bb4ee6a4SAndroid Build Coastguard Worker
206*bb4ee6a4SAndroid Build Coastguard Worker /// TODO(b/145998747, b/184398671): this method should be removed.
set_recv_timeout(&self, _timeout: Option<Duration>) -> Result<()>207*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_recv_timeout(&self, _timeout: Option<Duration>) -> Result<()> {
208*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("To be removed/refactored upstream.");
209*bb4ee6a4SAndroid Build Coastguard Worker }
210*bb4ee6a4SAndroid Build Coastguard Worker
get_read_notifier_event(&self) -> &Event211*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_read_notifier_event(&self) -> &Event {
212*bb4ee6a4SAndroid Build Coastguard Worker self.socket.get_read_notifier_event()
213*bb4ee6a4SAndroid Build Coastguard Worker }
214*bb4ee6a4SAndroid Build Coastguard Worker
get_close_notifier_event(&self) -> &Event215*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_close_notifier_event(&self) -> &Event {
216*bb4ee6a4SAndroid Build Coastguard Worker self.socket.get_close_notifier_event()
217*bb4ee6a4SAndroid Build Coastguard Worker }
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker
serialize_and_send<T: Serialize, F: Fn(&[u8]) -> io::Result<usize>>( write_fn: F, msg: &T, target_pid: Option<u32>, ) -> Result<()>220*bb4ee6a4SAndroid Build Coastguard Worker pub fn serialize_and_send<T: Serialize, F: Fn(&[u8]) -> io::Result<usize>>(
221*bb4ee6a4SAndroid Build Coastguard Worker write_fn: F,
222*bb4ee6a4SAndroid Build Coastguard Worker msg: &T,
223*bb4ee6a4SAndroid Build Coastguard Worker target_pid: Option<u32>,
224*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
225*bb4ee6a4SAndroid Build Coastguard Worker let msg_serialize = SerializeDescriptors::new(&msg);
226*bb4ee6a4SAndroid Build Coastguard Worker let msg_json = serde_json::to_vec(&msg_serialize).map_err(Error::Json)?;
227*bb4ee6a4SAndroid Build Coastguard Worker let msg_descriptors = msg_serialize.into_descriptors();
228*bb4ee6a4SAndroid Build Coastguard Worker
229*bb4ee6a4SAndroid Build Coastguard Worker let mut duped_descriptors = Vec::with_capacity(msg_descriptors.len());
230*bb4ee6a4SAndroid Build Coastguard Worker for desc in msg_descriptors {
231*bb4ee6a4SAndroid Build Coastguard Worker // Safe because these handles are guaranteed to be valid. Details:
232*bb4ee6a4SAndroid Build Coastguard Worker // 1. They come from base::descriptor_reflection::with_as_descriptor.
233*bb4ee6a4SAndroid Build Coastguard Worker // 2. with_as_descriptor is intended to be applied to owned descriptor types (e.g. File,
234*bb4ee6a4SAndroid Build Coastguard Worker // SafeDescriptor).
235*bb4ee6a4SAndroid Build Coastguard Worker // 3. The owning object is borrowed by msg until sending is complete.
236*bb4ee6a4SAndroid Build Coastguard Worker duped_descriptors.push(duplicate_handle(desc, target_pid)? as usize)
237*bb4ee6a4SAndroid Build Coastguard Worker }
238*bb4ee6a4SAndroid Build Coastguard Worker
239*bb4ee6a4SAndroid Build Coastguard Worker let descriptor_json = if duped_descriptors.is_empty() {
240*bb4ee6a4SAndroid Build Coastguard Worker None
241*bb4ee6a4SAndroid Build Coastguard Worker } else {
242*bb4ee6a4SAndroid Build Coastguard Worker Some(serde_json::to_vec(&duped_descriptors).map_err(Error::Json)?)
243*bb4ee6a4SAndroid Build Coastguard Worker };
244*bb4ee6a4SAndroid Build Coastguard Worker
245*bb4ee6a4SAndroid Build Coastguard Worker let header = MsgHeader {
246*bb4ee6a4SAndroid Build Coastguard Worker msg_json_size: msg_json.len(),
247*bb4ee6a4SAndroid Build Coastguard Worker descriptor_json_size: descriptor_json.as_ref().map_or(0, |json| json.len()),
248*bb4ee6a4SAndroid Build Coastguard Worker };
249*bb4ee6a4SAndroid Build Coastguard Worker
250*bb4ee6a4SAndroid Build Coastguard Worker let mut data_packet = Cursor::new(Vec::with_capacity(
251*bb4ee6a4SAndroid Build Coastguard Worker header.as_bytes().len() + header.msg_json_size + header.descriptor_json_size,
252*bb4ee6a4SAndroid Build Coastguard Worker ));
253*bb4ee6a4SAndroid Build Coastguard Worker data_packet
254*bb4ee6a4SAndroid Build Coastguard Worker .write(header.as_bytes())
255*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::SendIoBuf)?;
256*bb4ee6a4SAndroid Build Coastguard Worker data_packet
257*bb4ee6a4SAndroid Build Coastguard Worker .write(msg_json.as_slice())
258*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::SendIoBuf)?;
259*bb4ee6a4SAndroid Build Coastguard Worker if let Some(descriptor_json) = descriptor_json {
260*bb4ee6a4SAndroid Build Coastguard Worker data_packet
261*bb4ee6a4SAndroid Build Coastguard Worker .write(descriptor_json.as_slice())
262*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::SendIoBuf)?;
263*bb4ee6a4SAndroid Build Coastguard Worker }
264*bb4ee6a4SAndroid Build Coastguard Worker
265*bb4ee6a4SAndroid Build Coastguard Worker // Multiple writers (producers) are safe because each write is atomic.
266*bb4ee6a4SAndroid Build Coastguard Worker let data_bytes = data_packet.into_inner();
267*bb4ee6a4SAndroid Build Coastguard Worker
268*bb4ee6a4SAndroid Build Coastguard Worker write_fn(&data_bytes).map_err(Error::from_send_error)?;
269*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
270*bb4ee6a4SAndroid Build Coastguard Worker }
271*bb4ee6a4SAndroid Build Coastguard Worker
duplicate_handle(desc: RawHandle, target_pid: Option<u32>) -> Result<RawHandle>272*bb4ee6a4SAndroid Build Coastguard Worker fn duplicate_handle(desc: RawHandle, target_pid: Option<u32>) -> Result<RawHandle> {
273*bb4ee6a4SAndroid Build Coastguard Worker match target_pid {
274*bb4ee6a4SAndroid Build Coastguard Worker Some(pid) => match &*DH_TUBE.lock() {
275*bb4ee6a4SAndroid Build Coastguard Worker Some(tube) => tube.request_duplicate_handle(pid, desc),
276*bb4ee6a4SAndroid Build Coastguard Worker None => {
277*bb4ee6a4SAndroid Build Coastguard Worker win_util::duplicate_handle_with_target_pid(desc, pid).map_err(Error::DupDescriptor)
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker },
280*bb4ee6a4SAndroid Build Coastguard Worker None => win_util::duplicate_handle(desc).map_err(Error::DupDescriptor),
281*bb4ee6a4SAndroid Build Coastguard Worker }
282*bb4ee6a4SAndroid Build Coastguard Worker }
283*bb4ee6a4SAndroid Build Coastguard Worker
284*bb4ee6a4SAndroid Build Coastguard Worker /// Reads a part of a Tube packet asserting that it was correctly read. This means:
285*bb4ee6a4SAndroid Build Coastguard Worker /// * Treats partial "message" (transport framing) reads are Ok, as long as we filled our buffer. We
286*bb4ee6a4SAndroid Build Coastguard Worker /// use this to ignore errors when reading the message header, which has the lengths we need to
287*bb4ee6a4SAndroid Build Coastguard Worker /// allocate our buffers for the remainder of the message.
288*bb4ee6a4SAndroid Build Coastguard Worker /// * We filled the supplied buffer.
perform_read<F: FnMut(&mut [u8]) -> io::Result<usize>>( read_fn: &mut F, buf: &mut [u8], ) -> io::Result<usize>289*bb4ee6a4SAndroid Build Coastguard Worker fn perform_read<F: FnMut(&mut [u8]) -> io::Result<usize>>(
290*bb4ee6a4SAndroid Build Coastguard Worker read_fn: &mut F,
291*bb4ee6a4SAndroid Build Coastguard Worker buf: &mut [u8],
292*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<usize> {
293*bb4ee6a4SAndroid Build Coastguard Worker let bytes_read = match read_fn(buf) {
294*bb4ee6a4SAndroid Build Coastguard Worker Ok(s) => Ok(s),
295*bb4ee6a4SAndroid Build Coastguard Worker Err(e)
296*bb4ee6a4SAndroid Build Coastguard Worker if e.raw_os_error()
297*bb4ee6a4SAndroid Build Coastguard Worker .map_or(false, |errno| errno == ERROR_MORE_DATA as i32) =>
298*bb4ee6a4SAndroid Build Coastguard Worker {
299*bb4ee6a4SAndroid Build Coastguard Worker Ok(buf.len())
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => Err(e),
302*bb4ee6a4SAndroid Build Coastguard Worker }?;
303*bb4ee6a4SAndroid Build Coastguard Worker
304*bb4ee6a4SAndroid Build Coastguard Worker if bytes_read != buf.len() {
305*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::new(
306*bb4ee6a4SAndroid Build Coastguard Worker io::ErrorKind::UnexpectedEof,
307*bb4ee6a4SAndroid Build Coastguard Worker format!(
308*bb4ee6a4SAndroid Build Coastguard Worker "failed to fill whole buffer, expected {} got {}",
309*bb4ee6a4SAndroid Build Coastguard Worker buf.len(),
310*bb4ee6a4SAndroid Build Coastguard Worker bytes_read
311*bb4ee6a4SAndroid Build Coastguard Worker ),
312*bb4ee6a4SAndroid Build Coastguard Worker ))
313*bb4ee6a4SAndroid Build Coastguard Worker } else {
314*bb4ee6a4SAndroid Build Coastguard Worker Ok(bytes_read)
315*bb4ee6a4SAndroid Build Coastguard Worker }
316*bb4ee6a4SAndroid Build Coastguard Worker }
317*bb4ee6a4SAndroid Build Coastguard Worker
318*bb4ee6a4SAndroid Build Coastguard Worker /// Deserializes a Tube packet by calling the supplied read function. This function MUST
319*bb4ee6a4SAndroid Build Coastguard Worker /// assert that the buffer was filled.
deserialize_and_recv<T: DeserializeOwned, F: FnMut(&mut [u8]) -> io::Result<usize>>( mut read_fn: F, ) -> Result<T>320*bb4ee6a4SAndroid Build Coastguard Worker pub fn deserialize_and_recv<T: DeserializeOwned, F: FnMut(&mut [u8]) -> io::Result<usize>>(
321*bb4ee6a4SAndroid Build Coastguard Worker mut read_fn: F,
322*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<T> {
323*bb4ee6a4SAndroid Build Coastguard Worker let mut header = MsgHeader::default();
324*bb4ee6a4SAndroid Build Coastguard Worker perform_read(&mut read_fn, header.as_bytes_mut()).map_err(Error::from_recv_io_error)?;
325*bb4ee6a4SAndroid Build Coastguard Worker
326*bb4ee6a4SAndroid Build Coastguard Worker let mut msg_json = vec![0u8; header.msg_json_size];
327*bb4ee6a4SAndroid Build Coastguard Worker perform_read(&mut read_fn, msg_json.as_mut_slice()).map_err(Error::from_recv_io_error)?;
328*bb4ee6a4SAndroid Build Coastguard Worker
329*bb4ee6a4SAndroid Build Coastguard Worker if msg_json.is_empty() {
330*bb4ee6a4SAndroid Build Coastguard Worker // This means we got a message header, but there is no json body (due to a zero size in
331*bb4ee6a4SAndroid Build Coastguard Worker // the header). This should never happen because it means the receiver is getting no
332*bb4ee6a4SAndroid Build Coastguard Worker // data whatsoever from the sender.
333*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::RecvUnexpectedEmptyBody);
334*bb4ee6a4SAndroid Build Coastguard Worker }
335*bb4ee6a4SAndroid Build Coastguard Worker
336*bb4ee6a4SAndroid Build Coastguard Worker let descriptor_usizes: Vec<usize> = if header.descriptor_json_size > 0 {
337*bb4ee6a4SAndroid Build Coastguard Worker let mut msg_descriptors_json = vec![0u8; header.descriptor_json_size];
338*bb4ee6a4SAndroid Build Coastguard Worker perform_read(&mut read_fn, msg_descriptors_json.as_mut_slice())
339*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::from_recv_io_error)?;
340*bb4ee6a4SAndroid Build Coastguard Worker serde_json::from_slice(msg_descriptors_json.as_slice()).map_err(Error::Json)?
341*bb4ee6a4SAndroid Build Coastguard Worker } else {
342*bb4ee6a4SAndroid Build Coastguard Worker Vec::new()
343*bb4ee6a4SAndroid Build Coastguard Worker };
344*bb4ee6a4SAndroid Build Coastguard Worker
345*bb4ee6a4SAndroid Build Coastguard Worker let msg_descriptors = descriptor_usizes.into_iter().map(|item| {
346*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: the usizes are RawDescriptors that were duplicated and converted to usize in the
347*bb4ee6a4SAndroid Build Coastguard Worker // send method.
348*bb4ee6a4SAndroid Build Coastguard Worker unsafe { SafeDescriptor::from_raw_descriptor(item as RawDescriptor) }
349*bb4ee6a4SAndroid Build Coastguard Worker });
350*bb4ee6a4SAndroid Build Coastguard Worker
351*bb4ee6a4SAndroid Build Coastguard Worker deserialize_with_descriptors(|| serde_json::from_slice(&msg_json), msg_descriptors)
352*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::Json)
353*bb4ee6a4SAndroid Build Coastguard Worker }
354*bb4ee6a4SAndroid Build Coastguard Worker
355*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken, Eq, PartialEq, Copy, Clone)]
356*bb4ee6a4SAndroid Build Coastguard Worker enum Token {
357*bb4ee6a4SAndroid Build Coastguard Worker SocketReady,
358*bb4ee6a4SAndroid Build Coastguard Worker }
359*bb4ee6a4SAndroid Build Coastguard Worker
360*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for Tube {
as_raw_descriptor(&self) -> RawDescriptor361*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
362*bb4ee6a4SAndroid Build Coastguard Worker self.socket.as_raw_descriptor()
363*bb4ee6a4SAndroid Build Coastguard Worker }
364*bb4ee6a4SAndroid Build Coastguard Worker }
365*bb4ee6a4SAndroid Build Coastguard Worker
366*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawHandle for Tube {
as_raw_handle(&self) -> RawHandle367*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_handle(&self) -> RawHandle {
368*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor()
369*bb4ee6a4SAndroid Build Coastguard Worker }
370*bb4ee6a4SAndroid Build Coastguard Worker }
371*bb4ee6a4SAndroid Build Coastguard Worker
372*bb4ee6a4SAndroid Build Coastguard Worker impl ReadNotifier for Tube {
get_read_notifier(&self) -> &dyn AsRawDescriptor373*bb4ee6a4SAndroid Build Coastguard Worker fn get_read_notifier(&self) -> &dyn AsRawDescriptor {
374*bb4ee6a4SAndroid Build Coastguard Worker self.socket.get_read_notifier()
375*bb4ee6a4SAndroid Build Coastguard Worker }
376*bb4ee6a4SAndroid Build Coastguard Worker }
377*bb4ee6a4SAndroid Build Coastguard Worker
378*bb4ee6a4SAndroid Build Coastguard Worker impl CloseNotifier for Tube {
get_close_notifier(&self) -> &dyn AsRawDescriptor379*bb4ee6a4SAndroid Build Coastguard Worker fn get_close_notifier(&self) -> &dyn AsRawDescriptor {
380*bb4ee6a4SAndroid Build Coastguard Worker self.socket.get_close_notifier()
381*bb4ee6a4SAndroid Build Coastguard Worker }
382*bb4ee6a4SAndroid Build Coastguard Worker }
383*bb4ee6a4SAndroid Build Coastguard Worker
384*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for SendTube {
as_raw_descriptor(&self) -> RawDescriptor385*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
386*bb4ee6a4SAndroid Build Coastguard Worker self.0.as_raw_descriptor()
387*bb4ee6a4SAndroid Build Coastguard Worker }
388*bb4ee6a4SAndroid Build Coastguard Worker }
389*bb4ee6a4SAndroid Build Coastguard Worker
390*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for RecvTube {
as_raw_descriptor(&self) -> RawDescriptor391*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
392*bb4ee6a4SAndroid Build Coastguard Worker self.0.as_raw_descriptor()
393*bb4ee6a4SAndroid Build Coastguard Worker }
394*bb4ee6a4SAndroid Build Coastguard Worker }
395*bb4ee6a4SAndroid Build Coastguard Worker
396*bb4ee6a4SAndroid Build Coastguard Worker impl CloseNotifier for SendTube {
get_close_notifier(&self) -> &dyn AsRawDescriptor397*bb4ee6a4SAndroid Build Coastguard Worker fn get_close_notifier(&self) -> &dyn AsRawDescriptor {
398*bb4ee6a4SAndroid Build Coastguard Worker self.0.get_close_notifier()
399*bb4ee6a4SAndroid Build Coastguard Worker }
400*bb4ee6a4SAndroid Build Coastguard Worker }
401*bb4ee6a4SAndroid Build Coastguard Worker
402*bb4ee6a4SAndroid Build Coastguard Worker impl CloseNotifier for RecvTube {
get_close_notifier(&self) -> &dyn AsRawDescriptor403*bb4ee6a4SAndroid Build Coastguard Worker fn get_close_notifier(&self) -> &dyn AsRawDescriptor {
404*bb4ee6a4SAndroid Build Coastguard Worker self.0.get_close_notifier()
405*bb4ee6a4SAndroid Build Coastguard Worker }
406*bb4ee6a4SAndroid Build Coastguard Worker }
407*bb4ee6a4SAndroid Build Coastguard Worker
408*bb4ee6a4SAndroid Build Coastguard Worker /// A request to duplicate a handle to a target process.
409*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug)]
410*bb4ee6a4SAndroid Build Coastguard Worker pub struct DuplicateHandleRequest {
411*bb4ee6a4SAndroid Build Coastguard Worker pub target_alias_pid: u32,
412*bb4ee6a4SAndroid Build Coastguard Worker pub handle: usize,
413*bb4ee6a4SAndroid Build Coastguard Worker }
414*bb4ee6a4SAndroid Build Coastguard Worker
415*bb4ee6a4SAndroid Build Coastguard Worker /// Contains a duplicated handle or None if an error occurred.
416*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug)]
417*bb4ee6a4SAndroid Build Coastguard Worker pub struct DuplicateHandleResponse {
418*bb4ee6a4SAndroid Build Coastguard Worker pub handle: Option<usize>,
419*bb4ee6a4SAndroid Build Coastguard Worker }
420*bb4ee6a4SAndroid Build Coastguard Worker
421*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper for tube which is used to delegate DuplicateHandle function calls to
422*bb4ee6a4SAndroid Build Coastguard Worker /// the broker process.
423*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug)]
424*bb4ee6a4SAndroid Build Coastguard Worker pub struct DuplicateHandleTube(Tube);
425*bb4ee6a4SAndroid Build Coastguard Worker
426*bb4ee6a4SAndroid Build Coastguard Worker impl DuplicateHandleTube {
new(tube: Tube) -> Self427*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(tube: Tube) -> Self {
428*bb4ee6a4SAndroid Build Coastguard Worker Self(tube)
429*bb4ee6a4SAndroid Build Coastguard Worker }
430*bb4ee6a4SAndroid Build Coastguard Worker
request_duplicate_handle( &self, target_alias_pid: u32, handle: RawHandle, ) -> Result<RawHandle>431*bb4ee6a4SAndroid Build Coastguard Worker pub fn request_duplicate_handle(
432*bb4ee6a4SAndroid Build Coastguard Worker &self,
433*bb4ee6a4SAndroid Build Coastguard Worker target_alias_pid: u32,
434*bb4ee6a4SAndroid Build Coastguard Worker handle: RawHandle,
435*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<RawHandle> {
436*bb4ee6a4SAndroid Build Coastguard Worker let req = DuplicateHandleRequest {
437*bb4ee6a4SAndroid Build Coastguard Worker target_alias_pid,
438*bb4ee6a4SAndroid Build Coastguard Worker handle: handle as usize,
439*bb4ee6a4SAndroid Build Coastguard Worker };
440*bb4ee6a4SAndroid Build Coastguard Worker self.0.send(&req)?;
441*bb4ee6a4SAndroid Build Coastguard Worker let res: DuplicateHandleResponse = self.0.recv()?;
442*bb4ee6a4SAndroid Build Coastguard Worker res.handle
443*bb4ee6a4SAndroid Build Coastguard Worker .map(|h| h as RawHandle)
444*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::BrokerDupDescriptor)
445*bb4ee6a4SAndroid Build Coastguard Worker }
446*bb4ee6a4SAndroid Build Coastguard Worker }
447*bb4ee6a4SAndroid Build Coastguard Worker
448*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper for Tube used for sending and recving protos. The main usecase is to send a message
449*bb4ee6a4SAndroid Build Coastguard Worker /// without serialization bloat caused from `serde-json`.
450*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
451*bb4ee6a4SAndroid Build Coastguard Worker pub struct ProtoTube(Tube);
452*bb4ee6a4SAndroid Build Coastguard Worker
453*bb4ee6a4SAndroid Build Coastguard Worker impl ProtoTube {
pair() -> Result<(ProtoTube, ProtoTube)>454*bb4ee6a4SAndroid Build Coastguard Worker pub fn pair() -> Result<(ProtoTube, ProtoTube)> {
455*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair().map(|(t1, t2)| (ProtoTube(t1), ProtoTube(t2)))
456*bb4ee6a4SAndroid Build Coastguard Worker }
457*bb4ee6a4SAndroid Build Coastguard Worker
pair_with_buffer_size(size: usize) -> Result<(ProtoTube, ProtoTube)>458*bb4ee6a4SAndroid Build Coastguard Worker pub fn pair_with_buffer_size(size: usize) -> Result<(ProtoTube, ProtoTube)> {
459*bb4ee6a4SAndroid Build Coastguard Worker Tube::pair_with_buffer_size(size).map(|(t1, t2)| (ProtoTube(t1), ProtoTube(t2)))
460*bb4ee6a4SAndroid Build Coastguard Worker }
461*bb4ee6a4SAndroid Build Coastguard Worker
send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()>462*bb4ee6a4SAndroid Build Coastguard Worker pub fn send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()> {
463*bb4ee6a4SAndroid Build Coastguard Worker self.0.send_proto(msg)
464*bb4ee6a4SAndroid Build Coastguard Worker }
465*bb4ee6a4SAndroid Build Coastguard Worker
recv_proto<M: protobuf::Message>(&self) -> Result<M>466*bb4ee6a4SAndroid Build Coastguard Worker pub fn recv_proto<M: protobuf::Message>(&self) -> Result<M> {
467*bb4ee6a4SAndroid Build Coastguard Worker self.0.recv_proto()
468*bb4ee6a4SAndroid Build Coastguard Worker }
469*bb4ee6a4SAndroid Build Coastguard Worker }
470*bb4ee6a4SAndroid Build Coastguard Worker
471*bb4ee6a4SAndroid Build Coastguard Worker impl ReadNotifier for ProtoTube {
get_read_notifier(&self) -> &dyn AsRawDescriptor472*bb4ee6a4SAndroid Build Coastguard Worker fn get_read_notifier(&self) -> &dyn AsRawDescriptor {
473*bb4ee6a4SAndroid Build Coastguard Worker self.0.get_read_notifier()
474*bb4ee6a4SAndroid Build Coastguard Worker }
475*bb4ee6a4SAndroid Build Coastguard Worker }
476*bb4ee6a4SAndroid Build Coastguard Worker
477*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for ProtoTube {
as_raw_descriptor(&self) -> RawDescriptor478*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor {
479*bb4ee6a4SAndroid Build Coastguard Worker self.0.as_raw_descriptor()
480*bb4ee6a4SAndroid Build Coastguard Worker }
481*bb4ee6a4SAndroid Build Coastguard Worker }
482*bb4ee6a4SAndroid Build Coastguard Worker
483*bb4ee6a4SAndroid Build Coastguard Worker /// A wrapper around a named pipe that uses Tube serialization.
484*bb4ee6a4SAndroid Build Coastguard Worker ///
485*bb4ee6a4SAndroid Build Coastguard Worker /// This limited form of `Tube` offers absolutely no notifier support, and can only send/recv
486*bb4ee6a4SAndroid Build Coastguard Worker /// blocking messages.
487*bb4ee6a4SAndroid Build Coastguard Worker pub struct PipeTube {
488*bb4ee6a4SAndroid Build Coastguard Worker pipe: PipeConnection,
489*bb4ee6a4SAndroid Build Coastguard Worker
490*bb4ee6a4SAndroid Build Coastguard Worker // Default target_pid to current PID on serialization (see `Tube` comment header for details).
491*bb4ee6a4SAndroid Build Coastguard Worker target_pid: Option<u32>,
492*bb4ee6a4SAndroid Build Coastguard Worker }
493*bb4ee6a4SAndroid Build Coastguard Worker
494*bb4ee6a4SAndroid Build Coastguard Worker impl PipeTube {
from(pipe: PipeConnection, target_pid: Option<u32>) -> Self495*bb4ee6a4SAndroid Build Coastguard Worker pub fn from(pipe: PipeConnection, target_pid: Option<u32>) -> Self {
496*bb4ee6a4SAndroid Build Coastguard Worker Self { pipe, target_pid }
497*bb4ee6a4SAndroid Build Coastguard Worker }
498*bb4ee6a4SAndroid Build Coastguard Worker
send<T: Serialize>(&self, msg: &T) -> Result<()>499*bb4ee6a4SAndroid Build Coastguard Worker pub fn send<T: Serialize>(&self, msg: &T) -> Result<()> {
500*bb4ee6a4SAndroid Build Coastguard Worker serialize_and_send(|buf| self.pipe.write(buf), msg, self.target_pid)
501*bb4ee6a4SAndroid Build Coastguard Worker }
502*bb4ee6a4SAndroid Build Coastguard Worker
recv<T: DeserializeOwned>(&self) -> Result<T>503*bb4ee6a4SAndroid Build Coastguard Worker pub fn recv<T: DeserializeOwned>(&self) -> Result<T> {
504*bb4ee6a4SAndroid Build Coastguard Worker deserialize_and_recv(|buf| {
505*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
506*bb4ee6a4SAndroid Build Coastguard Worker // 1. We are reading bytes, so no matter what data is on the pipe, it is representable
507*bb4ee6a4SAndroid Build Coastguard Worker // as bytes.
508*bb4ee6a4SAndroid Build Coastguard Worker // 2. A read is quantized in bytes, so no partial reads are possible.
509*bb4ee6a4SAndroid Build Coastguard Worker unsafe { self.pipe.read(buf) }
510*bb4ee6a4SAndroid Build Coastguard Worker })
511*bb4ee6a4SAndroid Build Coastguard Worker }
512*bb4ee6a4SAndroid Build Coastguard Worker }
513*bb4ee6a4SAndroid Build Coastguard Worker
514*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper around a Tube which is known to be the server end of a named pipe. This wrapper ensures
515*bb4ee6a4SAndroid Build Coastguard Worker /// that the Tube is flushed before it is dropped.
516*bb4ee6a4SAndroid Build Coastguard Worker pub struct FlushOnDropTube(pub Tube);
517*bb4ee6a4SAndroid Build Coastguard Worker
518*bb4ee6a4SAndroid Build Coastguard Worker impl FlushOnDropTube {
from(tube: Tube) -> Self519*bb4ee6a4SAndroid Build Coastguard Worker pub fn from(tube: Tube) -> Self {
520*bb4ee6a4SAndroid Build Coastguard Worker Self(tube)
521*bb4ee6a4SAndroid Build Coastguard Worker }
522*bb4ee6a4SAndroid Build Coastguard Worker }
523*bb4ee6a4SAndroid Build Coastguard Worker
524*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for FlushOnDropTube {
drop(&mut self)525*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) {
526*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.0.flush_blocking() {
527*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to flush Tube: {}", e)
528*bb4ee6a4SAndroid Build Coastguard Worker }
529*bb4ee6a4SAndroid Build Coastguard Worker }
530*bb4ee6a4SAndroid Build Coastguard Worker }
531*bb4ee6a4SAndroid Build Coastguard Worker
532*bb4ee6a4SAndroid Build Coastguard Worker impl Error {
map_io_error(e: io::Error, err_ctor: fn(io::Error) -> Error) -> Error533*bb4ee6a4SAndroid Build Coastguard Worker fn map_io_error(e: io::Error, err_ctor: fn(io::Error) -> Error) -> Error {
534*bb4ee6a4SAndroid Build Coastguard Worker if e.kind() == io::ErrorKind::UnexpectedEof || e.kind() == io::ErrorKind::BrokenPipe {
535*bb4ee6a4SAndroid Build Coastguard Worker Error::Disconnected
536*bb4ee6a4SAndroid Build Coastguard Worker } else {
537*bb4ee6a4SAndroid Build Coastguard Worker err_ctor(e)
538*bb4ee6a4SAndroid Build Coastguard Worker }
539*bb4ee6a4SAndroid Build Coastguard Worker }
540*bb4ee6a4SAndroid Build Coastguard Worker
from_recv_io_error(e: io::Error) -> Error541*bb4ee6a4SAndroid Build Coastguard Worker fn from_recv_io_error(e: io::Error) -> Error {
542*bb4ee6a4SAndroid Build Coastguard Worker Self::map_io_error(e, Error::Recv)
543*bb4ee6a4SAndroid Build Coastguard Worker }
544*bb4ee6a4SAndroid Build Coastguard Worker
from_send_error(e: io::Error) -> Error545*bb4ee6a4SAndroid Build Coastguard Worker fn from_send_error(e: io::Error) -> Error {
546*bb4ee6a4SAndroid Build Coastguard Worker Self::map_io_error(e, Error::Send)
547*bb4ee6a4SAndroid Build Coastguard Worker }
548*bb4ee6a4SAndroid Build Coastguard Worker
from_send_io_buf_error(e: io::Error) -> Error549*bb4ee6a4SAndroid Build Coastguard Worker fn from_send_io_buf_error(e: io::Error) -> Error {
550*bb4ee6a4SAndroid Build Coastguard Worker Self::map_io_error(e, Error::SendIoBuf)
551*bb4ee6a4SAndroid Build Coastguard Worker }
552*bb4ee6a4SAndroid Build Coastguard Worker }
553