use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use super::Result;
#[derive(Debug)]
pub(crate) enum SocketStream {
#[cfg(unix)]
Unix(tokio::net::UnixStream),
#[cfg(windows)]
NamedPipe(tokio::net::windows::named_pipe::NamedPipeClient),
}
impl SocketStream {
#[cfg(unix)]
pub(crate) async fn connect(socket_path: &str) -> Result<Self> {
let stream = tokio::net::UnixStream::connect(socket_path)
.await
.map_err(|e| super::socket_error(socket_path, e))?;
Ok(Self::Unix(stream))
}
#[cfg(windows)]
pub(crate) async fn connect(socket_path: &str) -> Result<Self> {
use super::PodmanError;
let mut last_err = None;
for _ in 0..20 {
match tokio::net::windows::named_pipe::ClientOptions::new().open(socket_path) {
Ok(p) => return Ok(Self::NamedPipe(p)),
Err(e) if e.raw_os_error() == Some(231) => {
last_err = Some(e);
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
}
Err(e) => return Err(PodmanError::Connect(e)),
}
}
Err(PodmanError::Connect(last_err.unwrap_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::TimedOut,
"named pipe busy after 20 retries",
)
})))
}
}
impl AsyncRead for SocketStream {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
match self.get_mut() {
#[cfg(unix)]
Self::Unix(s) => Pin::new(s).poll_read(cx, buf),
#[cfg(windows)]
Self::NamedPipe(s) => Pin::new(s).poll_read(cx, buf),
}
}
}
impl AsyncWrite for SocketStream {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
match self.get_mut() {
#[cfg(unix)]
Self::Unix(s) => Pin::new(s).poll_write(cx, buf),
#[cfg(windows)]
Self::NamedPipe(s) => Pin::new(s).poll_write(cx, buf),
}
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
match self.get_mut() {
#[cfg(unix)]
Self::Unix(s) => Pin::new(s).poll_flush(cx),
#[cfg(windows)]
Self::NamedPipe(s) => Pin::new(s).poll_flush(cx),
}
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
match self.get_mut() {
#[cfg(unix)]
Self::Unix(s) => Pin::new(s).poll_shutdown(cx),
#[cfg(windows)]
Self::NamedPipe(s) => Pin::new(s).poll_shutdown(cx),
}
}
}