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