Update rmp-ipc and implement wrapper protocol
Signed-off-by: trivernis <trivernis@protonmail.com>pull/4/head
parent
5fee8a2e4a
commit
f48a9aad64
@ -0,0 +1,177 @@
|
||||
use async_trait::async_trait;
|
||||
use rmp_ipc::error::Result;
|
||||
use rmp_ipc::prelude::IPCResult;
|
||||
use rmp_ipc::protocol::*;
|
||||
use std::io::Error;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ApiProtocolListener {
|
||||
#[cfg(unix)]
|
||||
UnixSocket(tokio::net::UnixListener),
|
||||
|
||||
Tcp(TcpListener),
|
||||
}
|
||||
|
||||
unsafe impl Send for ApiProtocolListener {}
|
||||
unsafe impl Sync for ApiProtocolListener {}
|
||||
|
||||
#[async_trait]
|
||||
impl AsyncStreamProtocolListener for ApiProtocolListener {
|
||||
type AddressType = String;
|
||||
type RemoteAddressType = String;
|
||||
type Stream = ApiProtocolStream;
|
||||
|
||||
async fn protocol_bind(address: Self::AddressType) -> Result<Self> {
|
||||
if let Some(addr) = address.to_socket_addrs().ok().and_then(|mut a| a.next()) {
|
||||
let listener = TcpListener::bind(addr).await?;
|
||||
Ok(Self::Tcp(listener))
|
||||
} else {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::path::PathBuf;
|
||||
use tokio::net::UnixListener;
|
||||
let path = PathBuf::from(address);
|
||||
let listener = UnixListener::bind(path)?;
|
||||
|
||||
Ok(Self::UnixSocket(listener))
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
Err(IPCError::BuildError(
|
||||
"The address can not be made into a socket address".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn protocol_accept(&self) -> Result<(Self::Stream, Self::RemoteAddressType)> {
|
||||
match self {
|
||||
ApiProtocolListener::UnixSocket(listener) => {
|
||||
let (stream, addr) = listener.accept().await?;
|
||||
Ok((
|
||||
ApiProtocolStream::UnixSocket(stream),
|
||||
addr.as_pathname()
|
||||
.map(|p| p.to_str().unwrap().to_string())
|
||||
.unwrap_or(String::from("unknown")),
|
||||
))
|
||||
}
|
||||
ApiProtocolListener::Tcp(listener) => {
|
||||
let (stream, addr) = listener.accept().await?;
|
||||
Ok((ApiProtocolStream::Tcp(stream), addr.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ApiProtocolStream {
|
||||
#[cfg(unix)]
|
||||
UnixSocket(tokio::net::UnixStream),
|
||||
|
||||
Tcp(TcpStream),
|
||||
}
|
||||
|
||||
unsafe impl Send for ApiProtocolStream {}
|
||||
unsafe impl Sync for ApiProtocolStream {}
|
||||
|
||||
impl AsyncProtocolStreamSplit for ApiProtocolStream {
|
||||
type OwnedSplitReadHalf = Box<dyn AsyncRead + Unpin + Send + Sync>;
|
||||
type OwnedSplitWriteHalf = Box<dyn AsyncWrite + Unpin + Send + Sync>;
|
||||
|
||||
fn protocol_into_split(self) -> (Self::OwnedSplitReadHalf, Self::OwnedSplitWriteHalf) {
|
||||
match self {
|
||||
#[cfg(unix)]
|
||||
ApiProtocolStream::UnixSocket(stream) => {
|
||||
let (read, write) = stream.into_split();
|
||||
(Box::new(read), Box::new(write))
|
||||
}
|
||||
ApiProtocolStream::Tcp(stream) => {
|
||||
let (read, write) = stream.into_split();
|
||||
(Box::new(read), Box::new(write))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AsyncProtocolStream for ApiProtocolStream {
|
||||
type AddressType = String;
|
||||
|
||||
async fn protocol_connect(address: Self::AddressType) -> IPCResult<Self> {
|
||||
if let Some(addr) = address.to_socket_addrs().ok().and_then(|mut a| a.next()) {
|
||||
let stream = TcpStream::connect(addr).await?;
|
||||
Ok(Self::Tcp(stream))
|
||||
} else {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::path::PathBuf;
|
||||
use tokio::net::UnixStream;
|
||||
let path = PathBuf::from(address);
|
||||
let stream = UnixStream::connect(path).await?;
|
||||
|
||||
Ok(Self::UnixSocket(stream))
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
Err(IPCError::BuildError(
|
||||
"The address can not be made into a socket address".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for ApiProtocolStream {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut ReadBuf<'_>,
|
||||
) -> Poll<std::io::Result<()>> {
|
||||
match self.get_mut() {
|
||||
#[cfg(unix)]
|
||||
ApiProtocolStream::UnixSocket(stream) => Pin::new(stream).poll_read(cx, buf),
|
||||
ApiProtocolStream::Tcp(stream) => Pin::new(stream).poll_read(cx, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for ApiProtocolStream {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<std::prelude::rust_2015::Result<usize, Error>> {
|
||||
match self.get_mut() {
|
||||
#[cfg(unix)]
|
||||
ApiProtocolStream::UnixSocket(stream) => Pin::new(stream).poll_write(cx, buf),
|
||||
ApiProtocolStream::Tcp(stream) => Pin::new(stream).poll_write(cx, buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_flush(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<std::prelude::rust_2015::Result<(), Error>> {
|
||||
match self.get_mut() {
|
||||
#[cfg(unix)]
|
||||
ApiProtocolStream::UnixSocket(stream) => Pin::new(stream).poll_flush(cx),
|
||||
ApiProtocolStream::Tcp(stream) => Pin::new(stream).poll_flush(cx),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_shutdown(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<std::prelude::rust_2015::Result<(), Error>> {
|
||||
match self.get_mut() {
|
||||
#[cfg(unix)]
|
||||
ApiProtocolStream::UnixSocket(stream) => Pin::new(stream).poll_shutdown(cx),
|
||||
ApiProtocolStream::Tcp(stream) => Pin::new(stream).poll_flush(cx),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue