use std::{net::SocketAddr, ops::Deref, sync::Arc};
use async_trait::async_trait;
use endhost_api_client::client::CrpcEndhostApiClient;
use scion_sdk_reqwest_connect_rpc::{client::CrpcClientError, token_source::TokenSource};
use url::Url;
use crate::{
crpc_api::api_service::{
GET_SNAP_DATA_PLANE_SESSION_GRANT, RENEW_SNAP_DATA_PLANE_SESSION_GRANT, SERVICE_PATH,
convert::SessionGrantError, model::SessionGrant,
},
protobuf::anapaya::snap::v1::api_service::{
GetSnapDataPlaneSessionGrantRequest, GetSnapDataPlaneSessionGrantResponse,
RenewSnapDataPlaneSessionGrantRequest, RenewSnapDataPlaneSessionGrantResponse,
},
};
pub mod re_export {
pub use endhost_api_client::client::{CrpcEndhostApiClient, EndhostApiClient};
pub use scion_sdk_reqwest_connect_rpc::{client::CrpcClientError, token_source::*};
}
#[async_trait]
pub trait ControlPlaneApi: Send + Sync {
async fn create_data_plane_sessions(&self) -> Result<Vec<SessionGrant>, CrpcClientError>;
async fn renew_data_plane_session(
&self,
addr: SocketAddr,
) -> Result<SessionGrant, CrpcClientError>;
}
pub struct CrpcSnapControlClient {
client: CrpcEndhostApiClient,
}
impl Deref for CrpcSnapControlClient {
type Target = CrpcEndhostApiClient;
fn deref(&self) -> &Self::Target {
&self.client
}
}
impl CrpcSnapControlClient {
pub fn new(base_url: &Url) -> anyhow::Result<Self> {
let client = CrpcEndhostApiClient::new(base_url)?;
Ok(Self { client })
}
pub fn new_with_client(base_url: &Url, client: reqwest::Client) -> anyhow::Result<Self> {
Ok(Self {
client: CrpcEndhostApiClient::new_with_client(base_url, client)?,
})
}
pub fn use_token_source(&mut self, token_source: Arc<dyn TokenSource>) -> &mut Self {
self.client.use_token_source(token_source);
self
}
}
#[async_trait]
impl ControlPlaneApi for CrpcSnapControlClient {
async fn create_data_plane_sessions(&self) -> Result<Vec<SessionGrant>, CrpcClientError> {
self.client
.unary_request::<GetSnapDataPlaneSessionGrantRequest, GetSnapDataPlaneSessionGrantResponse>(
&format!("{SERVICE_PATH}{GET_SNAP_DATA_PLANE_SESSION_GRANT}"),
GetSnapDataPlaneSessionGrantRequest::default(),
)
.await?
.try_into()
.map_err(
|e: SessionGrantError| {
CrpcClientError::DecodeError {
context: "decoding session grants".into(),
source: e.into(),
body: None,
}
},
)
}
async fn renew_data_plane_session(
&self,
address: SocketAddr,
) -> Result<SessionGrant, CrpcClientError> {
self.client
.unary_request::<RenewSnapDataPlaneSessionGrantRequest, RenewSnapDataPlaneSessionGrantResponse>(
&format!("{SERVICE_PATH}{RENEW_SNAP_DATA_PLANE_SESSION_GRANT}"),
RenewSnapDataPlaneSessionGrantRequest{
address: address.to_string(),
},
)
.await?
.try_into()
.map_err(
|e: SessionGrantError| {
CrpcClientError::DecodeError {
context: "decoding renewed session grant".into(),
source: e.into(),
body: None,
}
},
)
}
}