add initial tokio socket/server types

This commit is contained in:
Josh Junon 2024-01-24 18:43:09 +01:00 committed by GitButler
parent 9c022f7c22
commit ac6800d9ed
3 changed files with 61 additions and 3 deletions

View File

@ -35,4 +35,4 @@ rand = { version = "0.8.5", optional = true }
tokio = { workspace = true, features = ["rt", "rt-multi-thread", "process"]}
[target."cfg(unix)".dependencies]
nix = { version = "0.27.1", optional = true, features = ["process", "socket", "user"] }
nix = { version = "0.27.1", optional = true, features = ["process", "socket", "user", "rt"] }

View File

@ -191,16 +191,19 @@ pub trait Socket {
type Error: core::error::Error + core::fmt::Debug + Send + Sync + 'static;
/// The process ID of the connecting client.
fn pid(&self) -> Pid;
fn pid(&self) -> Result<Pid, Self::Error>;
/// The user ID of the connecting client.
#[cfg(unix)]
fn uid(&self) -> Uid;
fn uid(&self) -> Result<Uid, Self::Error>;
/// Reads a line from the socket. Must not include the newline.
///
/// The returned line must not include a newline, and any
/// trailing carriage return (`\r`) must be stripped.
///
/// Implementations are allowed to simply call `.trim()` on the
/// line, as whitespace is not significant in the protocol.
async fn read_line(&mut self) -> Result<String, Self::Error>;
/// Writes a line to the socket. The write must
@ -209,5 +212,8 @@ pub trait Socket {
///
/// The input line will not include a newline; one must be
/// added. Newlines should never include a carriage return (`\r`).
///
/// Unlike `read_line`, implementations are not allowed to
/// modify the line prior to sending aside from appending a newline.
async fn write_line(&mut self, line: &str) -> Result<(), Self::Error>;
}

View File

@ -9,6 +9,8 @@ pub struct TokioExecutor;
impl super::GitExecutor for TokioExecutor {
type Error = std::io::Error;
#[cfg(unix)]
type SocketHandle = tokio::io::BufStream<tokio::net::UnixStream>;
async fn execute_raw(
&self,
@ -30,3 +32,53 @@ impl super::GitExecutor for TokioExecutor {
))
}
}
#[cfg(unix)]
impl super::Socket for tokio::io::BufStream<tokio::net::UnixStream> {
type Error = std::io::Error;
fn pid(&self) -> Result<super::Pid, Self::Error> {
self.peer_cred().unwrap().pid()
}
fn uid(&self) -> Result<super::Uid, Self::Error> {
self.peer_cred().unwrap().uid()
}
async fn read_line(&mut self) -> Result<String, Self::Error> {
let mut buf = String::new();
<Self as tokio::io::AsyncBufReadExt>::read_line(self, &mut buf).await?;
Ok(buf)
}
async fn write_line(&mut self, line: &str) -> Result<(), Self::Error> {
<Self as tokio::io::AsyncWriteExt>::write_all(self, line.as_bytes()).await?;
<Self as tokio::io::AsyncWriteExt>::write_all(self, b"\n").await?;
Ok(())
}
}
#[cfg(unix)]
pub struct TokioAskpassServer {
abort_handle: tokio::sync::AbortHandle,
pathname: String,
}
#[cfg(unix)]
impl super::AskpassServer for TokioAskpassServer {}
#[cfg(unix)]
impl core::fmt::Display for TokioAskpassServer {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.pathname.fmt(f)
}
}
#[cfg(unix)]
impl Drop for TokioAskpassServer {
fn drop(&mut self) {
self.abort_handle.abort();
// best-effort
std::fs::remove_file(&self.pathname).ok();
}
}