xref: /aosp_15_r20/external/crosvm/base/src/sys/unix/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::os::unix::prelude::AsRawFd;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::prelude::RawFd;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
8*bb4ee6a4SAndroid Build Coastguard Worker 
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 
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor_reflection::deserialize_with_descriptors;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor_reflection::SerializeDescriptors;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::handle_eintr;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::Error;
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::RecvTube;
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::Result;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::tube::SendTube;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::BlockingMode;
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::FramingMode;
23*bb4ee6a4SAndroid Build Coastguard Worker use crate::RawDescriptor;
24*bb4ee6a4SAndroid Build Coastguard Worker use crate::ReadNotifier;
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::ScmSocket;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::StreamChannel;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::UnixSeqpacket;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::SCM_SOCKET_MAX_FD_COUNT;
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker // This size matches the inline buffer size of CmsgBuffer.
31*bb4ee6a4SAndroid Build Coastguard Worker const TUBE_MAX_FDS: usize = 32;
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker /// Bidirectional tube that support both send and recv.
34*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
35*bb4ee6a4SAndroid Build Coastguard Worker pub struct Tube {
36*bb4ee6a4SAndroid Build Coastguard Worker     socket: ScmSocket<StreamChannel>,
37*bb4ee6a4SAndroid Build Coastguard Worker }
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker impl Tube {
40*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a pair of connected tubes. Request is sent in one direction while response is in the
41*bb4ee6a4SAndroid Build Coastguard Worker     /// other direction.
pair() -> Result<(Tube, Tube)>42*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pair() -> Result<(Tube, Tube)> {
43*bb4ee6a4SAndroid Build Coastguard Worker         let (socket1, socket2) = StreamChannel::pair(BlockingMode::Blocking, FramingMode::Message)
44*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|errno| Error::Pair(std::io::Error::from(errno)))?;
45*bb4ee6a4SAndroid Build Coastguard Worker         let tube1 = Tube::new(socket1)?;
46*bb4ee6a4SAndroid Build Coastguard Worker         let tube2 = Tube::new(socket2)?;
47*bb4ee6a4SAndroid Build Coastguard Worker         Ok((tube1, tube2))
48*bb4ee6a4SAndroid Build Coastguard Worker     }
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a new `Tube` from a `StreamChannel`.
51*bb4ee6a4SAndroid Build Coastguard Worker     /// The StreamChannel must use FramingMode::Message (meaning, must use a SOCK_SEQPACKET as the
52*bb4ee6a4SAndroid Build Coastguard Worker     /// underlying socket type), otherwise, this method returns an error.
new(socket: StreamChannel) -> Result<Tube>53*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(socket: StreamChannel) -> Result<Tube> {
54*bb4ee6a4SAndroid Build Coastguard Worker         match socket.get_framing_mode() {
55*bb4ee6a4SAndroid Build Coastguard Worker             FramingMode::Message => Ok(Tube {
56*bb4ee6a4SAndroid Build Coastguard Worker                 socket: socket.try_into().map_err(Error::DupDescriptor)?,
57*bb4ee6a4SAndroid Build Coastguard Worker             }),
58*bb4ee6a4SAndroid Build Coastguard Worker             FramingMode::Byte => Err(Error::InvalidFramingMode),
59*bb4ee6a4SAndroid Build Coastguard Worker         }
60*bb4ee6a4SAndroid Build Coastguard Worker     }
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a new `Tube` from a UnixSeqpacket. The StreamChannel is implicitly constructed to
63*bb4ee6a4SAndroid Build Coastguard Worker     /// have the right FramingMode by being constructed from a UnixSeqpacket.
new_from_unix_seqpacket(sock: UnixSeqpacket) -> Result<Tube>64*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_from_unix_seqpacket(sock: UnixSeqpacket) -> Result<Tube> {
65*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Tube {
66*bb4ee6a4SAndroid Build Coastguard Worker             socket: StreamChannel::from_unix_seqpacket(sock)
67*bb4ee6a4SAndroid Build Coastguard Worker                 .try_into()
68*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::DupDescriptor)?,
69*bb4ee6a4SAndroid Build Coastguard Worker         })
70*bb4ee6a4SAndroid Build Coastguard Worker     }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker     /// DO NOT USE this method directly as it will become private soon (b/221484449). Use a
73*bb4ee6a4SAndroid Build Coastguard Worker     /// directional Tube pair instead.
74*bb4ee6a4SAndroid Build Coastguard Worker     #[deprecated]
try_clone(&self) -> Result<Self>75*bb4ee6a4SAndroid Build Coastguard Worker     pub fn try_clone(&self) -> Result<Self> {
76*bb4ee6a4SAndroid Build Coastguard Worker         self.socket
77*bb4ee6a4SAndroid Build Coastguard Worker             .inner()
78*bb4ee6a4SAndroid Build Coastguard Worker             .try_clone()
79*bb4ee6a4SAndroid Build Coastguard Worker             .map(Tube::new)
80*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::Clone)?
81*bb4ee6a4SAndroid Build Coastguard Worker     }
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker     /// Sends a message via a Tube.
84*bb4ee6a4SAndroid Build Coastguard Worker     /// The number of file descriptors that this method can send is limited to `TUBE_MAX_FDS`.
85*bb4ee6a4SAndroid Build Coastguard Worker     /// If you want to send more descriptors, use `send_with_max_fds` instead.
send<T: Serialize>(&self, msg: &T) -> Result<()>86*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send<T: Serialize>(&self, msg: &T) -> Result<()> {
87*bb4ee6a4SAndroid Build Coastguard Worker         self.send_with_max_fds(msg, TUBE_MAX_FDS)
88*bb4ee6a4SAndroid Build Coastguard Worker     }
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker     /// Sends a message with at most `max_fds` file descriptors via a Tube.
91*bb4ee6a4SAndroid Build Coastguard Worker     /// Note that `max_fds` must not exceed `SCM_SOCKET_MAX_FD_COUNT` (= 253).
send_with_max_fds<T: Serialize>(&self, msg: &T, max_fds: usize) -> Result<()>92*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send_with_max_fds<T: Serialize>(&self, msg: &T, max_fds: usize) -> Result<()> {
93*bb4ee6a4SAndroid Build Coastguard Worker         if max_fds > SCM_SOCKET_MAX_FD_COUNT {
94*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::SendTooManyFds);
95*bb4ee6a4SAndroid Build Coastguard Worker         }
96*bb4ee6a4SAndroid Build Coastguard Worker         let msg_serialize = SerializeDescriptors::new(&msg);
97*bb4ee6a4SAndroid Build Coastguard Worker         let msg_json = serde_json::to_vec(&msg_serialize).map_err(Error::Json)?;
98*bb4ee6a4SAndroid Build Coastguard Worker         let msg_descriptors = msg_serialize.into_descriptors();
99*bb4ee6a4SAndroid Build Coastguard Worker 
100*bb4ee6a4SAndroid Build Coastguard Worker         if msg_descriptors.len() > max_fds {
101*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::SendTooManyFds);
102*bb4ee6a4SAndroid Build Coastguard Worker         }
103*bb4ee6a4SAndroid Build Coastguard Worker 
104*bb4ee6a4SAndroid Build Coastguard Worker         handle_eintr!(self.socket.send_with_fds(&msg_json, &msg_descriptors))
105*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::Send)?;
106*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
107*bb4ee6a4SAndroid Build Coastguard Worker     }
108*bb4ee6a4SAndroid Build Coastguard Worker 
109*bb4ee6a4SAndroid Build Coastguard Worker     /// Recieves a message from a Tube.
110*bb4ee6a4SAndroid Build Coastguard Worker     /// If the sender sent file descriptors more than TUBE_MAX_FDS with `send_with_max_fds`, use
111*bb4ee6a4SAndroid Build Coastguard Worker     /// `recv_with_max_fds` instead.
recv<T: DeserializeOwned>(&self) -> Result<T>112*bb4ee6a4SAndroid Build Coastguard Worker     pub fn recv<T: DeserializeOwned>(&self) -> Result<T> {
113*bb4ee6a4SAndroid Build Coastguard Worker         self.recv_with_max_fds(TUBE_MAX_FDS)
114*bb4ee6a4SAndroid Build Coastguard Worker     }
115*bb4ee6a4SAndroid Build Coastguard Worker 
116*bb4ee6a4SAndroid Build Coastguard Worker     /// Recieves a message with at most `max_fds` file descriptors from a Tube.
recv_with_max_fds<T: DeserializeOwned>(&self, max_fds: usize) -> Result<T>117*bb4ee6a4SAndroid Build Coastguard Worker     pub fn recv_with_max_fds<T: DeserializeOwned>(&self, max_fds: usize) -> Result<T> {
118*bb4ee6a4SAndroid Build Coastguard Worker         if max_fds > SCM_SOCKET_MAX_FD_COUNT {
119*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::RecvTooManyFds);
120*bb4ee6a4SAndroid Build Coastguard Worker         }
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker         // WARNING: The `cros_async` and `base_tokio` tube wrappers both assume that, if the tube
123*bb4ee6a4SAndroid Build Coastguard Worker         // is readable, then a call to `Tube::recv` will not block (which ought to be true since we
124*bb4ee6a4SAndroid Build Coastguard Worker         // use SOCK_SEQPACKET and a single recvmsg call currently).
125*bb4ee6a4SAndroid Build Coastguard Worker 
126*bb4ee6a4SAndroid Build Coastguard Worker         let msg_size = handle_eintr!(self.socket.inner().peek_size()).map_err(Error::Recv)?;
127*bb4ee6a4SAndroid Build Coastguard Worker         // This buffer is the right size, as the size received in peek_size() represents the size
128*bb4ee6a4SAndroid Build Coastguard Worker         // of only the message itself and not the file descriptors. The descriptors are stored
129*bb4ee6a4SAndroid Build Coastguard Worker         // separately in msghdr::msg_control.
130*bb4ee6a4SAndroid Build Coastguard Worker         let mut msg_json = vec![0u8; msg_size];
131*bb4ee6a4SAndroid Build Coastguard Worker 
132*bb4ee6a4SAndroid Build Coastguard Worker         let (msg_json_size, msg_descriptors) =
133*bb4ee6a4SAndroid Build Coastguard Worker             handle_eintr!(self.socket.recv_with_fds(&mut msg_json, max_fds))
134*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::Recv)?;
135*bb4ee6a4SAndroid Build Coastguard Worker 
136*bb4ee6a4SAndroid Build Coastguard Worker         if msg_json_size == 0 {
137*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::Disconnected);
138*bb4ee6a4SAndroid Build Coastguard Worker         }
139*bb4ee6a4SAndroid Build Coastguard Worker 
140*bb4ee6a4SAndroid Build Coastguard Worker         deserialize_with_descriptors(
141*bb4ee6a4SAndroid Build Coastguard Worker             || serde_json::from_slice(&msg_json[0..msg_json_size]),
142*bb4ee6a4SAndroid Build Coastguard Worker             msg_descriptors,
143*bb4ee6a4SAndroid Build Coastguard Worker         )
144*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::Json)
145*bb4ee6a4SAndroid Build Coastguard Worker     }
146*bb4ee6a4SAndroid Build Coastguard Worker 
set_send_timeout(&self, timeout: Option<Duration>) -> Result<()>147*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_send_timeout(&self, timeout: Option<Duration>) -> Result<()> {
148*bb4ee6a4SAndroid Build Coastguard Worker         self.socket
149*bb4ee6a4SAndroid Build Coastguard Worker             .inner()
150*bb4ee6a4SAndroid Build Coastguard Worker             .set_write_timeout(timeout)
151*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetSendTimeout)
152*bb4ee6a4SAndroid Build Coastguard Worker     }
153*bb4ee6a4SAndroid Build Coastguard Worker 
set_recv_timeout(&self, timeout: Option<Duration>) -> Result<()>154*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_recv_timeout(&self, timeout: Option<Duration>) -> Result<()> {
155*bb4ee6a4SAndroid Build Coastguard Worker         self.socket
156*bb4ee6a4SAndroid Build Coastguard Worker             .inner()
157*bb4ee6a4SAndroid Build Coastguard Worker             .set_read_timeout(timeout)
158*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::SetRecvTimeout)
159*bb4ee6a4SAndroid Build Coastguard Worker     }
160*bb4ee6a4SAndroid Build Coastguard Worker 
161*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "proto_tube")]
send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()>162*bb4ee6a4SAndroid Build Coastguard Worker     fn send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()> {
163*bb4ee6a4SAndroid Build Coastguard Worker         let bytes = msg.write_to_bytes().map_err(Error::Proto)?;
164*bb4ee6a4SAndroid Build Coastguard Worker         let no_fds: [RawFd; 0] = [];
165*bb4ee6a4SAndroid Build Coastguard Worker 
166*bb4ee6a4SAndroid Build Coastguard Worker         handle_eintr!(self.socket.send_with_fds(&bytes, &no_fds)).map_err(Error::Send)?;
167*bb4ee6a4SAndroid Build Coastguard Worker 
168*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
169*bb4ee6a4SAndroid Build Coastguard Worker     }
170*bb4ee6a4SAndroid Build Coastguard Worker 
171*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "proto_tube")]
recv_proto<M: protobuf::Message>(&self) -> Result<M>172*bb4ee6a4SAndroid Build Coastguard Worker     fn recv_proto<M: protobuf::Message>(&self) -> Result<M> {
173*bb4ee6a4SAndroid Build Coastguard Worker         let msg_size = handle_eintr!(self.socket.inner().peek_size()).map_err(Error::Recv)?;
174*bb4ee6a4SAndroid Build Coastguard Worker         let mut msg_bytes = vec![0u8; msg_size];
175*bb4ee6a4SAndroid Build Coastguard Worker 
176*bb4ee6a4SAndroid Build Coastguard Worker         let (msg_bytes_size, _) =
177*bb4ee6a4SAndroid Build Coastguard Worker             handle_eintr!(self.socket.recv_with_fds(&mut msg_bytes, TUBE_MAX_FDS))
178*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(Error::Recv)?;
179*bb4ee6a4SAndroid Build Coastguard Worker 
180*bb4ee6a4SAndroid Build Coastguard Worker         if msg_bytes_size == 0 {
181*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::Disconnected);
182*bb4ee6a4SAndroid Build Coastguard Worker         }
183*bb4ee6a4SAndroid Build Coastguard Worker 
184*bb4ee6a4SAndroid Build Coastguard Worker         protobuf::Message::parse_from_bytes(&msg_bytes).map_err(Error::Proto)
185*bb4ee6a4SAndroid Build Coastguard Worker     }
186*bb4ee6a4SAndroid Build Coastguard Worker }
187*bb4ee6a4SAndroid Build Coastguard Worker 
188*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for Tube {
as_raw_descriptor(&self) -> RawDescriptor189*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
190*bb4ee6a4SAndroid Build Coastguard Worker         self.socket.as_raw_descriptor()
191*bb4ee6a4SAndroid Build Coastguard Worker     }
192*bb4ee6a4SAndroid Build Coastguard Worker }
193*bb4ee6a4SAndroid Build Coastguard Worker 
194*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawFd for Tube {
as_raw_fd(&self) -> RawFd195*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_fd(&self) -> RawFd {
196*bb4ee6a4SAndroid Build Coastguard Worker         self.socket.inner().as_raw_fd()
197*bb4ee6a4SAndroid Build Coastguard Worker     }
198*bb4ee6a4SAndroid Build Coastguard Worker }
199*bb4ee6a4SAndroid Build Coastguard Worker 
200*bb4ee6a4SAndroid Build Coastguard Worker impl ReadNotifier for Tube {
get_read_notifier(&self) -> &dyn AsRawDescriptor201*bb4ee6a4SAndroid Build Coastguard Worker     fn get_read_notifier(&self) -> &dyn AsRawDescriptor {
202*bb4ee6a4SAndroid Build Coastguard Worker         &self.socket
203*bb4ee6a4SAndroid Build Coastguard Worker     }
204*bb4ee6a4SAndroid Build Coastguard Worker }
205*bb4ee6a4SAndroid Build Coastguard Worker 
206*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for SendTube {
as_raw_descriptor(&self) -> RawDescriptor207*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
208*bb4ee6a4SAndroid Build Coastguard Worker         self.0.as_raw_descriptor()
209*bb4ee6a4SAndroid Build Coastguard Worker     }
210*bb4ee6a4SAndroid Build Coastguard Worker }
211*bb4ee6a4SAndroid Build Coastguard Worker 
212*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for RecvTube {
as_raw_descriptor(&self) -> RawDescriptor213*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
214*bb4ee6a4SAndroid Build Coastguard Worker         self.0.as_raw_descriptor()
215*bb4ee6a4SAndroid Build Coastguard Worker     }
216*bb4ee6a4SAndroid Build Coastguard Worker }
217*bb4ee6a4SAndroid Build Coastguard Worker 
218*bb4ee6a4SAndroid Build Coastguard Worker /// Wrapper for Tube used for sending and receiving protos - avoids extra overhead of serialization
219*bb4ee6a4SAndroid Build Coastguard Worker /// via serde_json. Since protos should be standalone objects we do not support sending of file
220*bb4ee6a4SAndroid Build Coastguard Worker /// descriptors as a normal Tube would.
221*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "proto_tube")]
222*bb4ee6a4SAndroid Build Coastguard Worker pub struct ProtoTube(Tube);
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "proto_tube")]
225*bb4ee6a4SAndroid Build Coastguard Worker impl ProtoTube {
pair() -> Result<(ProtoTube, ProtoTube)>226*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pair() -> Result<(ProtoTube, ProtoTube)> {
227*bb4ee6a4SAndroid Build Coastguard Worker         Tube::pair().map(|(t1, t2)| (ProtoTube(t1), ProtoTube(t2)))
228*bb4ee6a4SAndroid Build Coastguard Worker     }
229*bb4ee6a4SAndroid Build Coastguard Worker 
send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()>230*bb4ee6a4SAndroid Build Coastguard Worker     pub fn send_proto<M: protobuf::Message>(&self, msg: &M) -> Result<()> {
231*bb4ee6a4SAndroid Build Coastguard Worker         self.0.send_proto(msg)
232*bb4ee6a4SAndroid Build Coastguard Worker     }
233*bb4ee6a4SAndroid Build Coastguard Worker 
recv_proto<M: protobuf::Message>(&self) -> Result<M>234*bb4ee6a4SAndroid Build Coastguard Worker     pub fn recv_proto<M: protobuf::Message>(&self) -> Result<M> {
235*bb4ee6a4SAndroid Build Coastguard Worker         self.0.recv_proto()
236*bb4ee6a4SAndroid Build Coastguard Worker     }
237*bb4ee6a4SAndroid Build Coastguard Worker 
new_from_unix_seqpacket(sock: UnixSeqpacket) -> Result<ProtoTube>238*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_from_unix_seqpacket(sock: UnixSeqpacket) -> Result<ProtoTube> {
239*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ProtoTube(Tube::new_from_unix_seqpacket(sock)?))
240*bb4ee6a4SAndroid Build Coastguard Worker     }
241*bb4ee6a4SAndroid Build Coastguard Worker }
242*bb4ee6a4SAndroid Build Coastguard Worker 
243*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(feature = "proto_tube", test))]
244*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unused_variables)]
245*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
246*bb4ee6a4SAndroid Build Coastguard Worker     // not testing this proto specifically, just need an existing one to test the ProtoTube.
247*bb4ee6a4SAndroid Build Coastguard Worker     use protos::cdisk_spec::ComponentDisk;
248*bb4ee6a4SAndroid Build Coastguard Worker 
249*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
250*bb4ee6a4SAndroid Build Coastguard Worker 
251*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
tube_serializes_and_deserializes()252*bb4ee6a4SAndroid Build Coastguard Worker     fn tube_serializes_and_deserializes() {
253*bb4ee6a4SAndroid Build Coastguard Worker         let (pt1, pt2) = ProtoTube::pair().unwrap();
254*bb4ee6a4SAndroid Build Coastguard Worker         let proto = ComponentDisk {
255*bb4ee6a4SAndroid Build Coastguard Worker             file_path: "/some/cool/path".to_string(),
256*bb4ee6a4SAndroid Build Coastguard Worker             offset: 99,
257*bb4ee6a4SAndroid Build Coastguard Worker             ..ComponentDisk::new()
258*bb4ee6a4SAndroid Build Coastguard Worker         };
259*bb4ee6a4SAndroid Build Coastguard Worker 
260*bb4ee6a4SAndroid Build Coastguard Worker         pt1.send_proto(&proto).unwrap();
261*bb4ee6a4SAndroid Build Coastguard Worker 
262*bb4ee6a4SAndroid Build Coastguard Worker         let recv_proto = pt2.recv_proto().unwrap();
263*bb4ee6a4SAndroid Build Coastguard Worker 
264*bb4ee6a4SAndroid Build Coastguard Worker         assert!(proto.eq(&recv_proto));
265*bb4ee6a4SAndroid Build Coastguard Worker     }
266*bb4ee6a4SAndroid Build Coastguard Worker }
267