xref: /aosp_15_r20/external/crosvm/base/src/tube.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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::time::Duration;
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
9*bb4ee6a4SAndroid Build Coastguard Worker use serde::de::DeserializeOwned;
10*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
11*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
12*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::sys::tube::*;
15*bb4ee6a4SAndroid Build Coastguard Worker 
16*bb4ee6a4SAndroid Build Coastguard Worker impl Tube {
17*bb4ee6a4SAndroid Build Coastguard Worker     /// Given a Tube end, creates two new ends, one each for sending and receiving.
split_to_send_recv(self) -> Result<(SendTube, RecvTube)>18*bb4ee6a4SAndroid Build Coastguard Worker     pub fn split_to_send_recv(self) -> Result<(SendTube, RecvTube)> {
19*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because receiving isn't allowd on this end.
20*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(deprecated)]
21*bb4ee6a4SAndroid Build Coastguard Worker         let send_end = self.try_clone()?;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker         Ok((SendTube(send_end), RecvTube(self)))
24*bb4ee6a4SAndroid Build Coastguard Worker     }
25*bb4ee6a4SAndroid Build Coastguard Worker 
26*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a Send/Recv pair of Tubes.
directional_pair() -> Result<(SendTube, RecvTube)>27*bb4ee6a4SAndroid Build Coastguard Worker     pub fn directional_pair() -> Result<(SendTube, RecvTube)> {
28*bb4ee6a4SAndroid Build Coastguard Worker         let (t1, t2) = Self::pair()?;
29*bb4ee6a4SAndroid Build Coastguard Worker         Ok((SendTube(t1), RecvTube(t2)))
30*bb4ee6a4SAndroid Build Coastguard Worker     }
31*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone_send_tube(&self) -> Result<SendTube>32*bb4ee6a4SAndroid Build Coastguard Worker     pub fn try_clone_send_tube(&self) -> Result<SendTube> {
33*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because receiving is only allowed on original Tube.
34*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(deprecated)]
35*bb4ee6a4SAndroid Build Coastguard Worker         let send_end = self.try_clone()?;
36*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SendTube(send_end))
37*bb4ee6a4SAndroid Build Coastguard Worker     }
38*bb4ee6a4SAndroid Build Coastguard Worker }
39*bb4ee6a4SAndroid Build Coastguard Worker 
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::AsRawDescriptor;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::ReadNotifier;
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
44*bb4ee6a4SAndroid Build Coastguard Worker #[serde(transparent)]
45*bb4ee6a4SAndroid Build Coastguard Worker /// A Tube end which can only send messages. Cloneable.
46*bb4ee6a4SAndroid Build Coastguard Worker pub struct SendTube(pub(crate) Tube);
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
49*bb4ee6a4SAndroid Build Coastguard Worker impl SendTube {
50*bb4ee6a4SAndroid Build Coastguard Worker     /// TODO(b/145998747, b/184398671): this method should be removed.
set_send_timeout(&self, _timeout: Option<Duration>) -> Result<()>51*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_send_timeout(&self, _timeout: Option<Duration>) -> Result<()> {
52*bb4ee6a4SAndroid Build Coastguard Worker         unimplemented!("To be removed/refactored upstream.");
53*bb4ee6a4SAndroid Build Coastguard Worker     }
54*bb4ee6a4SAndroid Build Coastguard Worker 
send<T: Serialize>(&self, msg: &T) -> Result<()>55*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send<T: Serialize>(&self, msg: &T) -> Result<()> {
56*bb4ee6a4SAndroid Build Coastguard Worker         self.0.send(msg)
57*bb4ee6a4SAndroid Build Coastguard Worker     }
58*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone(&self) -> Result<Self>59*bb4ee6a4SAndroid Build Coastguard Worker     pub fn try_clone(&self) -> Result<Self> {
60*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SendTube(
61*bb4ee6a4SAndroid Build Coastguard Worker             #[allow(deprecated)]
62*bb4ee6a4SAndroid Build Coastguard Worker             self.0.try_clone()?,
63*bb4ee6a4SAndroid Build Coastguard Worker         ))
64*bb4ee6a4SAndroid Build Coastguard Worker     }
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker     /// Never call this function, it is for use by cros_async to provide
67*bb4ee6a4SAndroid Build Coastguard Worker     /// directional wrapper types only. Using it in any other context may
68*bb4ee6a4SAndroid Build Coastguard Worker     /// violate concurrency assumptions. (Type splitting across crates has put
69*bb4ee6a4SAndroid Build Coastguard Worker     /// us in a situation where we can't use Rust privacy to enforce this.)
70*bb4ee6a4SAndroid Build Coastguard Worker     #[deprecated]
into_tube(self) -> Tube71*bb4ee6a4SAndroid Build Coastguard Worker     pub fn into_tube(self) -> Tube {
72*bb4ee6a4SAndroid Build Coastguard Worker         self.0
73*bb4ee6a4SAndroid Build Coastguard Worker     }
74*bb4ee6a4SAndroid Build Coastguard Worker }
75*bb4ee6a4SAndroid Build Coastguard Worker 
76*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
77*bb4ee6a4SAndroid Build Coastguard Worker #[serde(transparent)]
78*bb4ee6a4SAndroid Build Coastguard Worker /// A Tube end which can only recv messages.
79*bb4ee6a4SAndroid Build Coastguard Worker pub struct RecvTube(pub(crate) Tube);
80*bb4ee6a4SAndroid Build Coastguard Worker 
81*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
82*bb4ee6a4SAndroid Build Coastguard Worker impl RecvTube {
recv<T: DeserializeOwned>(&self) -> Result<T>83*bb4ee6a4SAndroid Build Coastguard Worker     pub fn recv<T: DeserializeOwned>(&self) -> Result<T> {
84*bb4ee6a4SAndroid Build Coastguard Worker         self.0.recv()
85*bb4ee6a4SAndroid Build Coastguard Worker     }
86*bb4ee6a4SAndroid Build Coastguard Worker 
87*bb4ee6a4SAndroid Build Coastguard Worker     /// TODO(b/145998747, b/184398671): this method should be removed.
set_recv_timeout(&self, _timeout: Option<Duration>) -> Result<()>88*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_recv_timeout(&self, _timeout: Option<Duration>) -> Result<()> {
89*bb4ee6a4SAndroid Build Coastguard Worker         unimplemented!("To be removed/refactored upstream.");
90*bb4ee6a4SAndroid Build Coastguard Worker     }
91*bb4ee6a4SAndroid Build Coastguard Worker 
92*bb4ee6a4SAndroid Build Coastguard Worker     /// Never call this function, it is for use by cros_async to provide
93*bb4ee6a4SAndroid Build Coastguard Worker     /// directional wrapper types only. Using it in any other context may
94*bb4ee6a4SAndroid Build Coastguard Worker     /// violate concurrency assumptions. (Type splitting across crates has put
95*bb4ee6a4SAndroid Build Coastguard Worker     /// us in a situation where we can't use Rust privacy to enforce this.)
96*bb4ee6a4SAndroid Build Coastguard Worker     #[deprecated]
into_tube(self) -> Tube97*bb4ee6a4SAndroid Build Coastguard Worker     pub fn into_tube(self) -> Tube {
98*bb4ee6a4SAndroid Build Coastguard Worker         self.0
99*bb4ee6a4SAndroid Build Coastguard Worker     }
100*bb4ee6a4SAndroid Build Coastguard Worker }
101*bb4ee6a4SAndroid Build Coastguard Worker 
102*bb4ee6a4SAndroid Build Coastguard Worker impl ReadNotifier for RecvTube {
get_read_notifier(&self) -> &dyn AsRawDescriptor103*bb4ee6a4SAndroid Build Coastguard Worker     fn get_read_notifier(&self) -> &dyn AsRawDescriptor {
104*bb4ee6a4SAndroid Build Coastguard Worker         self.0.get_read_notifier()
105*bb4ee6a4SAndroid Build Coastguard Worker     }
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker 
108*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
109*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug)]
110*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
111*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
112*bb4ee6a4SAndroid Build Coastguard Worker     #[error("attempt to duplicate descriptor via broker failed")]
113*bb4ee6a4SAndroid Build Coastguard Worker     BrokerDupDescriptor,
114*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to clone transport: {0}")]
115*bb4ee6a4SAndroid Build Coastguard Worker     Clone(io::Error),
116*bb4ee6a4SAndroid Build Coastguard Worker     #[error("tube was disconnected")]
117*bb4ee6a4SAndroid Build Coastguard Worker     Disconnected,
118*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to duplicate descriptor: {0}")]
119*bb4ee6a4SAndroid Build Coastguard Worker     DupDescriptor(io::Error),
120*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
121*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to flush named pipe: {0}")]
122*bb4ee6a4SAndroid Build Coastguard Worker     Flush(io::Error),
123*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(unix)]
124*bb4ee6a4SAndroid Build Coastguard Worker     #[error("byte framing mode is not supported")]
125*bb4ee6a4SAndroid Build Coastguard Worker     InvalidFramingMode,
126*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to serialize/deserialize json from packet: {0}")]
127*bb4ee6a4SAndroid Build Coastguard Worker     Json(serde_json::Error),
128*bb4ee6a4SAndroid Build Coastguard Worker     #[error("cancelled a queued async operation")]
129*bb4ee6a4SAndroid Build Coastguard Worker     OperationCancelled,
130*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to crate tube pair: {0}")]
131*bb4ee6a4SAndroid Build Coastguard Worker     Pair(io::Error),
132*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(windows, feature = "proto_tube"))]
133*bb4ee6a4SAndroid Build Coastguard Worker     #[error("encountered protobuf error: {0}")]
134*bb4ee6a4SAndroid Build Coastguard Worker     Proto(protobuf::Error),
135*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to receive packet: {0}")]
136*bb4ee6a4SAndroid Build Coastguard Worker     Recv(io::Error),
137*bb4ee6a4SAndroid Build Coastguard Worker     #[error("attempted to receive too many file descriptors")]
138*bb4ee6a4SAndroid Build Coastguard Worker     RecvTooManyFds,
139*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Received a message with a zero sized body. This should not happen.")]
140*bb4ee6a4SAndroid Build Coastguard Worker     RecvUnexpectedEmptyBody,
141*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to send packet: {0}")]
142*bb4ee6a4SAndroid Build Coastguard Worker     Send(io::Error),
143*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to write packet to intermediate buffer: {0}")]
144*bb4ee6a4SAndroid Build Coastguard Worker     SendIoBuf(io::Error),
145*bb4ee6a4SAndroid Build Coastguard Worker     #[error("attempted to send too many file descriptors")]
146*bb4ee6a4SAndroid Build Coastguard Worker     SendTooManyFds,
147*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set recv timeout: {0}")]
148*bb4ee6a4SAndroid Build Coastguard Worker     SetRecvTimeout(io::Error),
149*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set send timeout: {0}")]
150*bb4ee6a4SAndroid Build Coastguard Worker     SetSendTimeout(io::Error),
151*bb4ee6a4SAndroid Build Coastguard Worker }
152*bb4ee6a4SAndroid Build Coastguard Worker 
153*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
154