use std::fmt;
use std::sync::Arc;
use net_backend_protocol::auth::{AuthSession, LoginRequest, RegisterRequest, SteamLoginRequest, TokenPair};
use net_backend_protocol::{HttpCall, ServerInfo};
use crate::runtime::{refuse_on_client_thread, RuntimeThread};
use crate::{ClientBuilder, Error, Reply, TokenUpdates};
#[derive(Clone)]
pub struct Client {
pub(crate) inner: crate::Client,
pub(crate) runtime: Arc<RuntimeThread>,
}
impl fmt::Debug for Client {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("blocking::Client").field("client", &self.inner).finish()
}
}
impl Client {
pub fn new(url: &str) -> Result<Self, Error> {
Self::from_builder(crate::Client::builder(url))
}
pub fn from_builder(builder: ClientBuilder) -> Result<Self, Error> {
refuse_on_client_thread()?;
let inner = builder.build()?;
let runtime = RuntimeThread::start()?;
Ok(Self { inner, runtime })
}
pub fn async_client(&self) -> &crate::Client {
&self.inner
}
pub fn call<C: HttpCall + Clone + Send + Sync + 'static>(&self, call: &C) -> Result<C::Response, Error>
where
C::Response: Send + 'static,
{
let client = self.inner.clone();
let call = call.clone();
self.runtime.block(async move { client.call(&call).await })
}
pub fn send<C: HttpCall + Send + Sync + 'static>(&self, call: C) -> Reply<C::Response>
where
C::Response: Send + 'static,
{
let client = self.inner.clone();
self.runtime.spawn(async move { client.call(&call).await })
}
pub fn info(&self) -> Result<ServerInfo, Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.info().await })
}
pub fn register(&self, request: RegisterRequest) -> Result<AuthSession, Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.register(request).await })
}
pub fn login(&self, request: LoginRequest) -> Result<AuthSession, Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.login(request).await })
}
pub fn login_steam(&self, request: SteamLoginRequest) -> Result<AuthSession, Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.login_steam(request).await })
}
pub fn link_steam(&self, request: SteamLoginRequest) -> Result<AuthSession, Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.link_steam(request).await })
}
pub fn refresh(&self) -> Result<TokenPair, Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.refresh().await })
}
pub fn logout(&self) -> Result<(), Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.logout().await })
}
pub fn logout_everywhere(&self) -> Result<(), Error> {
let client = self.inner.clone();
self.runtime.block(async move { client.logout_everywhere().await })
}
pub fn resume(&self, tokens: TokenPair) {
self.inner.resume(tokens);
}
pub fn forget_session(&self) {
self.inner.forget_session();
}
pub fn tokens(&self) -> Option<TokenPair> {
self.inner.tokens()
}
pub fn is_logged_in(&self) -> bool {
self.inner.is_logged_in()
}
pub fn token_updates(&self) -> TokenUpdates {
self.inner.token_updates()
}
}
#[cfg(feature = "ssh")]
#[cfg_attr(docsrs, doc(cfg(feature = "ssh")))]
#[derive(Clone, Debug)]
pub struct SshSession {
inner: crate::ssh::SshSession,
runtime: Arc<RuntimeThread>,
}
#[cfg(feature = "ssh")]
impl SshSession {
pub fn connect(target: crate::ssh::SshTarget) -> Result<Self, Error> {
refuse_on_client_thread()?;
let runtime = RuntimeThread::start()?;
let inner = runtime.block(crate::ssh::SshSession::connect(target))?;
Ok(Self { inner, runtime })
}
pub fn async_session(&self) -> &crate::ssh::SshSession {
&self.inner
}
pub fn fingerprint(&self) -> &str {
self.inner.fingerprint()
}
pub fn is_closed(&self) -> bool {
self.inner.is_closed()
}
pub fn run(&self, command: impl Into<crate::ssh::SshCommand>) -> Result<crate::ssh::SshOutput, Error> {
let session = self.inner.clone();
let command = command.into();
self.runtime.block(async move { session.run(command).await })
}
pub fn run_streaming(&self, command: impl Into<crate::ssh::SshCommand>) -> crate::ssh::SshRun {
self.runtime.enter(|| self.inner.run_streaming(command))
}
pub fn close(&self) {
let session = self.inner.clone();
let _ = self.runtime.block(async move {
session.close().await;
Ok(())
});
}
}
#[cfg(feature = "sftp")]
#[cfg_attr(docsrs, doc(cfg(feature = "sftp")))]
impl SshSession {
pub fn upload(&self, remote: &str, data: impl Into<Vec<u8>>) -> Result<u64, Error> {
let (session, remote, data) = (self.inner.clone(), remote.to_string(), data.into());
self.runtime.block(async move { session.upload(&remote, data).await })
}
pub fn upload_file(&self, local: impl AsRef<std::path::Path>, remote: &str) -> Result<u64, Error> {
let (session, local, remote) = (self.inner.clone(), local.as_ref().to_path_buf(), remote.to_string());
self.runtime.block(async move { session.upload_file(&local, &remote).await })
}
pub fn download(&self, remote: &str) -> Result<Vec<u8>, Error> {
let (session, remote) = (self.inner.clone(), remote.to_string());
self.runtime.block(async move { session.download(&remote).await })
}
pub fn download_file(&self, remote: &str, local: impl AsRef<std::path::Path>) -> Result<u64, Error> {
let (session, remote, local) = (self.inner.clone(), remote.to_string(), local.as_ref().to_path_buf());
self.runtime.block(async move { session.download_file(&remote, &local).await })
}
pub fn list_dir(&self, path: &str) -> Result<Vec<crate::ssh::SftpEntry>, Error> {
let (session, path) = (self.inner.clone(), path.to_string());
self.runtime.block(async move { session.list_dir(&path).await })
}
pub fn create_dir(&self, path: &str) -> Result<(), Error> {
let (session, path) = (self.inner.clone(), path.to_string());
self.runtime.block(async move { session.create_dir(&path).await })
}
pub fn remove_file(&self, path: &str) -> Result<(), Error> {
let (session, path) = (self.inner.clone(), path.to_string());
self.runtime.block(async move { session.remove_file(&path).await })
}
pub fn remove_dir(&self, path: &str) -> Result<(), Error> {
let (session, path) = (self.inner.clone(), path.to_string());
self.runtime.block(async move { session.remove_dir(&path).await })
}
pub fn rename(&self, from: &str, to: &str) -> Result<(), Error> {
let (session, from, to) = (self.inner.clone(), from.to_string(), to.to_string());
self.runtime.block(async move { session.rename(&from, &to).await })
}
}