Skip to content

Commit

Permalink
Add service_binding::Stream support
Browse files Browse the repository at this point in the history
Signed-off-by: Wiktor Kwapisiewicz <[email protected]>
  • Loading branch information
wiktor-k committed Apr 18, 2024
1 parent 23e611c commit 3122c1b
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 33 deletions.
16 changes: 14 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ byteorder = "1.4.3"
async-trait = { version = "0.1.77", optional = true }
futures = { version = "0.3.30", optional = true }
log = { version = "0.4.6", optional = true }
tokio = { version = "1", optional = true, features = ["rt", "net"] }
tokio = { version = "1", optional = true, features = ["rt", "net", "time"] }
tokio-util = { version = "0.7.1", optional = true, features = ["codec"] }
service-binding = { version = "^2" }
service-binding = { version = "^2.1" }
ssh-encoding = { version = "0.2.0" }
ssh-key = { version = "0.6.6", features = ["rsa", "alloc"] }
thiserror = "1.0.58"
Expand All @@ -43,7 +43,7 @@ required-features = ["agent"]
env_logger = "0.11.0"
rand = "0.8.5"
rsa = { version = "0.9.6", features = ["sha2", "sha1"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "time"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
sha1 = { version = "0.10.5", default-features = false, features = ["oid"] }
testresult = "0.4.0"
hex-literal = "0.4.1"
Expand Down
34 changes: 7 additions & 27 deletions examples/ssh-agent-client.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,15 @@
use ssh_agent_lib::agent::Session;
use ssh_agent_lib::client::Client;
#[cfg(windows)]
use tokio::net::windows::named_pipe::ClientOptions;
#[cfg(unix)]
use tokio::net::UnixStream;
use service_binding::Binding;
use ssh_agent_lib::client::connect;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(unix)]
let mut client = {
let stream = UnixStream::connect(std::env::var("SSH_AUTH_SOCK")?).await?;
Client::new(stream)
};
#[cfg(windows)]
let mut client = {
let stream = loop {
// https://docs.rs/windows-sys/latest/windows_sys/Win32/Foundation/constant.ERROR_PIPE_BUSY.html
const ERROR_PIPE_BUSY: u32 = 231u32;

// correct way to do it taken from
// https://docs.rs/tokio/latest/tokio/net/windows/named_pipe/struct.NamedPipeClient.html
match ClientOptions::new().open(std::env::var("SSH_AUTH_SOCK")?) {
Ok(client) => break client,
Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY as i32) => (),
Err(e) => Err(e)?,
}
let mut client =
connect(Binding::FilePath(std::env::var("SSH_AUTH_SOCK")?.into()).try_into()?).await?;

tokio::time::sleep(std::time::Duration::from_millis(50)).await;
};
Client::new(stream)
};
#[cfg(windows)]
let mut client =
connect(Binding::NamedPipe(std::env::var("SSH_AUTH_SOCK")?.into()).try_into()?).await?;

eprintln!(
"Identities that this agent knows of: {:#?}",
Expand Down
2 changes: 1 addition & 1 deletion src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl ListeningSocket for NamedPipeListener {
}

#[async_trait]
pub trait Session: 'static + Sync + Send + Sized {
pub trait Session: 'static + Sync + Send + Unpin {
async fn request_identities(&mut self) -> Result<Vec<Identity>, Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 11 }))
}
Expand Down
40 changes: 40 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,46 @@ where
}
}

pub async fn connect(
stream: service_binding::Stream,
) -> Result<std::pin::Pin<Box<dyn crate::agent::Session>>, Box<dyn std::error::Error>> {
match stream {
#[cfg(unix)]
service_binding::Stream::Unix(stream) => {
let stream = tokio::net::UnixStream::from_std(stream)?;
Ok(Box::pin(Client::new(stream)))
}
service_binding::Stream::Tcp(stream) => {
let stream = tokio::net::TcpStream::from_std(stream)?;
Ok(Box::pin(Client::new(stream)))
}
#[cfg(windows)]
service_binding::Stream::NamedPipe(pipe) => {
use tokio::net::windows::named_pipe::ClientOptions;
let stream = loop {
// https://docs.rs/windows-sys/latest/windows_sys/Win32/Foundation/constant.ERROR_PIPE_BUSY.html
const ERROR_PIPE_BUSY: u32 = 231u32;

// correct way to do it taken from
// https://docs.rs/tokio/latest/tokio/net/windows/named_pipe/struct.NamedPipeClient.html
match ClientOptions::new().open(pipe) {
Ok(client) => break client,
Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY as i32) => (),
Err(e) => Err(e)?,
}

tokio::time::sleep(std::time::Duration::from_millis(50)).await;
};
Ok(Box::pin(Client::new(stream)))
}
#[cfg(not(windows))]
service_binding::Stream::NamedPipe(_) => Err(ProtoError::IO(std::io::Error::other(
"Named pipes supported on Windows only",
))
.into()),
}
}

#[async_trait::async_trait]
impl<Stream> crate::agent::Session for Client<Stream>
where
Expand Down

0 comments on commit 3122c1b

Please sign in to comment.