use std::os::fd::OwnedFd;
use vsock::{VsockAddr, VsockStream};
use super::{read_frame, write_frame, PeerIdentity, RpcTransport};
use crate::rpc::RpcResult;
pub struct VsockTransport {
stream: VsockStream,
peer: PeerIdentity,
desc: String,
}
impl VsockTransport {
pub fn connect(cid: u32, port: u32) -> RpcResult<Self> {
let stream = VsockStream::connect(&VsockAddr::new(cid, port))?;
Self::from_stream(stream)
}
pub fn from_owned_fd(fd: OwnedFd) -> RpcResult<Self> {
Self::from_stream(VsockStream::from(fd))
}
pub fn from_stream(stream: VsockStream) -> RpcResult<Self> {
let peer = match stream.peer_addr() {
Ok(a) => PeerIdentity::Vsock { cid: a.cid() },
Err(_) => PeerIdentity::Anonymous,
};
let desc = match stream.peer_addr() {
Ok(a) => format!("vsock:cid={},port={}", a.cid(), a.port()),
Err(_) => "vsock".to_string(),
};
Ok(VsockTransport { stream, peer, desc })
}
}
impl RpcTransport for VsockTransport {
fn send_frame(&self, buf: &[u8]) -> RpcResult<()> {
let mut w = &self.stream;
write_frame(&mut w, buf)
}
fn recv_frame(&self) -> RpcResult<Vec<u8>> {
let mut r = &self.stream;
read_frame(&mut r)
}
fn peer_identity(&self) -> PeerIdentity {
self.peer.clone()
}
fn describe(&self) -> &str {
&self.desc
}
fn set_read_timeout(&self, timeout: Option<std::time::Duration>) -> RpcResult<()> {
self.stream.set_read_timeout(timeout)?;
Ok(())
}
fn set_write_timeout(&self, timeout: Option<std::time::Duration>) -> RpcResult<()> {
self.stream.set_write_timeout(timeout)?;
Ok(())
}
}