use super::addr::VsockAddr;
use super::stream::VsockStream;
use crate::error::{Result, TransportError};
use std::os::fd::RawFd;
use tokio::sync::mpsc;
#[derive(Debug, Clone)]
pub struct IncomingVsockConnection {
pub fd: RawFd,
pub source_port: u32,
pub destination_port: u32,
}
pub fn connect_vsock(_addr: VsockAddr) -> Result<VsockStream> {
Err(TransportError::Protocol(
"macOS vsock requires connection through hypervisor".to_string(),
))
}
#[allow(dead_code)]
pub struct VsockListenerHandle {
port: u32,
receiver: mpsc::UnboundedReceiver<IncomingVsockConnection>,
}
#[allow(dead_code)]
impl VsockListenerHandle {
pub const fn new(
port: u32,
receiver: mpsc::UnboundedReceiver<IncomingVsockConnection>,
) -> Self {
Self { port, receiver }
}
pub const fn port(&self) -> u32 {
self.port
}
pub async fn accept(&mut self) -> Result<(VsockStream, VsockAddr)> {
match self.receiver.recv().await {
Some(conn) => {
let stream =
unsafe { VsockStream::from_raw_fd(conn.fd) }.map_err(TransportError::io)?;
let addr = VsockAddr::new(VsockAddr::CID_ANY, conn.source_port);
Ok((stream, addr))
}
None => Err(TransportError::ConnectionReset),
}
}
pub fn try_accept(&mut self) -> Option<Result<(VsockStream, VsockAddr)>> {
match self.receiver.try_recv() {
Ok(conn) => {
let stream =
unsafe { VsockStream::from_raw_fd(conn.fd) }.map_err(TransportError::io);
match stream {
Ok(s) => {
let addr = VsockAddr::new(VsockAddr::CID_ANY, conn.source_port);
Some(Ok((s, addr)))
}
Err(e) => Some(Err(e)),
}
}
Err(mpsc::error::TryRecvError::Empty) => None,
Err(mpsc::error::TryRecvError::Disconnected) => {
Some(Err(TransportError::ConnectionReset))
}
}
}
}