sirenia: Switch over to libchromeos-rs's vsock implementation.
This required adding #[derive(Debug)] in some parts of
libchromeos::vsock.
BUG=b:144915425
TEST=cargo test
Change-Id: I2f25bb93cc748ac5f82399231d60ac976e987cec
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2337149
Tested-by: Allen Webb <allenwebb@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Reviewed-by: Stephen Barber <smbarber@chromium.org>
diff --git a/libchromeos-rs/src/vsock.rs b/libchromeos-rs/src/vsock.rs
index f96a0f8..b4fa589 100644
--- a/libchromeos-rs/src/vsock.rs
+++ b/libchromeos-rs/src/vsock.rs
@@ -48,7 +48,7 @@
}
/// An address associated with a virtual socket.
-#[derive(Copy, Clone)]
+#[derive(Debug, Copy, Clone)]
pub struct SocketAddr {
pub cid: c_uint,
pub port: c_uint,
@@ -123,6 +123,7 @@
}
/// A virtual stream socket.
+#[derive(Debug)]
pub struct VsockStream {
fd: RawFd,
}
@@ -244,6 +245,7 @@
}
/// Represents a virtual socket server.
+#[derive(Debug)]
pub struct VsockListener {
fd: RawFd,
}
diff --git a/sirenia/Cargo.toml b/sirenia/Cargo.toml
index 7cda6b5..5716188 100644
--- a/sirenia/Cargo.toml
+++ b/sirenia/Cargo.toml
@@ -20,5 +20,6 @@
[dependencies]
getopts = "0.2"
libc = "0.2.44"
+libchromeos = { path = "../libchromeos-rs" } # provided by ebuild
minijail = { path = "../../aosp/external/minijail/rust/minijail" } # provided by ebuild
sys_util = { path = "../../platform/crosvm/sys_util" } # provided by ebuild
diff --git a/sirenia/src/to_sys_util/mod.rs b/sirenia/src/to_sys_util/mod.rs
index aad573c..d52d3d2 100644
--- a/sirenia/src/to_sys_util/mod.rs
+++ b/sirenia/src/to_sys_util/mod.rs
@@ -8,32 +8,17 @@
//!
//! TODO(b/162502718) Move this over to crosvm/sys_util
-use std::fs::File;
use std::io;
-use std::mem::{size_of, MaybeUninit};
-use std::net::TcpStream;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use std::mem::MaybeUninit;
use std::ptr::null_mut;
use libc::{
- self, accept4, bind, c_int, connect, listen, sigfillset, sigprocmask, sigset_t, sockaddr_vm,
- socket, socklen_t, wait, AF_VSOCK, ECHILD, SIG_BLOCK, SIG_UNBLOCK, SOCK_CLOEXEC, SOCK_STREAM,
- SOMAXCONN, VMADDR_CID_ANY, VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR,
+ self, c_int, sigfillset, sigprocmask, sigset_t, wait, ECHILD, SIG_BLOCK, SIG_UNBLOCK,
+ VMADDR_CID_ANY, VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR,
};
-use sys_util::handle_eintr_errno;
const VMADDR_CID_LOCAL: u32 = 1;
-pub const VMADDR_PORT_ANY: u32 = libc::VMADDR_PORT_ANY;
-
-const DEFAULT_SOCKADDR_VM: sockaddr_vm = sockaddr_vm {
- svm_family: 0,
- svm_reserved1: 0,
- svm_port: 0,
- svm_cid: 0,
- svm_zero: [0; 4],
-};
-
pub fn errno() -> c_int {
io::Error::last_os_error().raw_os_error().unwrap()
}
@@ -88,26 +73,6 @@
}
}
-fn get_vsock_stream() -> Result<RawFd, io::Error> {
- // This is safe because it doesn't take any references.
- let fd: RawFd = handle_eintr_errno!(unsafe { socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC, 0) });
- if fd < 0 {
- Err(io::Error::last_os_error())
- } else {
- Ok(fd)
- }
-}
-
-fn new_vsock_addr(cid: VsockCid, port: u32) -> sockaddr_vm {
- let mut addr: sockaddr_vm = DEFAULT_SOCKADDR_VM.clone();
-
- addr.svm_family = AF_VSOCK as u16;
- addr.svm_port = port;
- addr.svm_cid = cid.into();
-
- addr
-}
-
#[derive(Debug, Copy, Clone)]
pub enum VsockCid {
Any,
@@ -140,91 +105,3 @@
}
}
}
-
-pub struct VsockStreamListener(File);
-
-impl VsockStreamListener {
- pub fn new(cid: VsockCid, port: u32) -> Result<Self, io::Error> {
- // This is safe because the fd is valid and not associated with a rust
- // struct yet.
- let fd = unsafe { File::from_raw_fd(get_vsock_stream()?) };
- let addr = new_vsock_addr(cid, port);
-
- // This is safe because the passed structs will outlive the bind
- // call.
- if handle_eintr_errno!(unsafe {
- bind(
- fd.as_raw_fd(),
- &addr as *const _ as *const _,
- size_of::<sockaddr_vm>() as socklen_t,
- )
- }) != 0
- {
- return Err(io::Error::last_os_error());
- }
-
- // This is safe because the file descriptor is owned.
- if handle_eintr_errno!(unsafe { listen(fd.as_raw_fd(), SOMAXCONN) }) != 0 {
- return Err(io::Error::last_os_error());
- }
-
- Ok(VsockStreamListener(fd))
- }
-
- pub fn accept(&self) -> Result<(TcpStream, (VsockCid, u32)), io::Error> {
- let mut addr: sockaddr_vm = DEFAULT_SOCKADDR_VM.clone();
- let mut len: socklen_t = size_of::<sockaddr_vm>() as socklen_t;
- let stream: TcpStream;
-
- // This is safe because the passed structs will outlive the accept4
- // call and if the resulting file descriptor is valid it is wrapped
- // with a type that will close it when dropped.
- let fd: c_int = handle_eintr_errno!(unsafe {
- accept4(
- self.0.as_raw_fd(),
- &mut addr as *mut _ as *mut _,
- &mut len as *mut _,
- SOCK_CLOEXEC,
- )
- });
- if fd < 0 {
- return Err(io::Error::last_os_error());
- }
-
- // This is safe because the file descriptor is valid and isn't
- // associated with a rust struct yet.
- stream = unsafe { TcpStream::from_raw_fd(fd) };
- if size_of::<sockaddr_vm>() as socklen_t != len {
- return Err(io::Error::last_os_error());
- }
- Ok((stream, (VsockCid::from(addr.svm_cid), addr.svm_port)))
- }
-}
-
-pub fn vsock_connect(cid: VsockCid, port: u32) -> Result<TcpStream, io::Error> {
- let fd: RawFd = get_vsock_stream()?;
- let addr: sockaddr_vm = new_vsock_addr(cid, port);
-
- if handle_eintr_errno!(unsafe {
- // This is safe because the passed structs will outlive the connect
- // call.
- connect(
- fd,
- &addr as *const _ as *const _,
- size_of::<sockaddr_vm>() as socklen_t,
- )
- }) != 0
- {
- // This is safe because the file descriptor is valid and isn't
- // associated with a rust struct yet. It is used to close the
- // file descriptor.
- unsafe {
- File::from_raw_fd(fd);
- }
- return Err(io::Error::last_os_error());
- }
-
- // This is safe because the file descriptor is valid and isn't associated
- // with a rust struct yet.
- Ok(unsafe { TcpStream::from_raw_fd(fd) })
-}
diff --git a/sirenia/src/transport/mod.rs b/sirenia/src/transport/mod.rs
index c944901..a9321b2 100644
--- a/sirenia/src/transport/mod.rs
+++ b/sirenia/src/transport/mod.rs
@@ -16,9 +16,10 @@
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
use core::mem::replace;
-use sys_util::pipe;
+use libchromeos::vsock::{self, VsockListener, VsockStream};
+use sys_util::{handle_eintr, pipe};
-use super::to_sys_util::{self, VsockCid, VsockStreamListener};
+use super::to_sys_util::VsockCid;
const DEFAULT_PORT: u32 = 5552;
@@ -98,6 +99,11 @@
Ok(Transport(Box::new(stream), Box::new(write)))
}
+fn vsockstream_to_transport(stream: VsockStream) -> Result<Transport> {
+ let write = stream.try_clone().map_err(Error::Clone)?;
+ Ok(Transport(Box::new(stream), Box::new(write)))
+}
+
/// Abstracts transport methods that accept incoming connections.
pub trait ServerTransport {
fn accept(&mut self) -> Result<Transport>;
@@ -127,7 +133,7 @@
impl ServerTransport for IPServerTransport {
fn accept(&mut self) -> Result<Transport> {
- let (stream, _) = self.0.accept().map_err(Error::Accept)?;
+ let (stream, _) = handle_eintr!(self.0.accept()).map_err(Error::Accept)?;
tcpstream_to_transport(stream)
}
}
@@ -149,26 +155,25 @@
impl ClientTransport for IPClientTransport {
fn connect(&mut self) -> Result<Transport> {
- let stream = TcpStream::connect(&self.0).map_err(Error::Connect)?;
+ let stream = handle_eintr!(TcpStream::connect(&self.0)).map_err(Error::Connect)?;
tcpstream_to_transport(stream)
}
}
/// A transport method that listens for incoming vsock connections.
-pub struct VsockServerTransport(VsockStreamListener);
+pub struct VsockServerTransport(VsockListener);
impl VsockServerTransport {
pub fn new() -> Result<Self> {
- let listener =
- VsockStreamListener::new(VsockCid::Any, DEFAULT_PORT).map_err(Error::Bind)?;
+ let listener = VsockListener::bind(DEFAULT_PORT).map_err(Error::Bind)?;
Ok(VsockServerTransport(listener))
}
}
impl ServerTransport for VsockServerTransport {
fn accept(&mut self) -> Result<Transport> {
- let (stream, _) = self.0.accept().map_err(Error::Accept)?;
- tcpstream_to_transport(stream)
+ let (stream, _) = handle_eintr!(self.0.accept()).map_err(Error::Accept)?;
+ vsockstream_to_transport(stream)
}
}
@@ -183,8 +188,12 @@
impl ClientTransport for VsockClientTransport {
fn connect(&mut self) -> Result<Transport> {
- let stream = to_sys_util::vsock_connect(self.0, DEFAULT_PORT).map_err(Error::Connect)?;
- tcpstream_to_transport(stream)
+ let addr = vsock::SocketAddr {
+ cid: self.0.into(),
+ port: DEFAULT_PORT,
+ };
+ let stream = handle_eintr!(VsockStream::connect(&addr)).map_err(Error::Connect)?;
+ vsockstream_to_transport(stream)
}
}