1use std::{net::SocketAddr, ops::Deref, sync::Arc};
17
18use async_trait::async_trait;
19use endhost_api_client::client::CrpcEndhostApiClient;
20use scion_sdk_reqwest_connect_rpc::{client::CrpcClientError, token_source::TokenSource};
21use url::Url;
22
23use crate::{
24 crpc_api::api_service::{
25 GET_SNAP_DATA_PLANE_SESSION_GRANT, RENEW_SNAP_DATA_PLANE_SESSION_GRANT, SERVICE_PATH,
26 convert::SessionGrantError, model::SessionGrant,
27 },
28 protobuf::anapaya::snap::v1::api_service::{
29 GetSnapDataPlaneSessionGrantRequest, GetSnapDataPlaneSessionGrantResponse,
30 RenewSnapDataPlaneSessionGrantRequest, RenewSnapDataPlaneSessionGrantResponse,
31 },
32};
33
34pub mod re_export {
36 pub use endhost_api_client::client::{CrpcEndhostApiClient, EndhostApiClient};
37 pub use scion_sdk_reqwest_connect_rpc::{client::CrpcClientError, token_source::*};
38}
39
40#[async_trait]
42pub trait ControlPlaneApi: Send + Sync {
43 async fn create_data_plane_sessions(&self) -> Result<Vec<SessionGrant>, CrpcClientError>;
45 async fn renew_data_plane_session(
47 &self,
48 addr: SocketAddr,
49 ) -> Result<SessionGrant, CrpcClientError>;
50}
51
52pub struct CrpcSnapControlClient {
54 client: CrpcEndhostApiClient,
55}
56
57impl Deref for CrpcSnapControlClient {
58 type Target = CrpcEndhostApiClient;
59
60 fn deref(&self) -> &Self::Target {
61 &self.client
62 }
63}
64
65impl CrpcSnapControlClient {
66 pub fn new(base_url: &Url) -> anyhow::Result<Self> {
68 let client = CrpcEndhostApiClient::new(base_url)?;
69 Ok(Self { client })
70 }
71
72 pub fn new_with_client(base_url: &Url, client: reqwest::Client) -> anyhow::Result<Self> {
74 Ok(Self {
75 client: CrpcEndhostApiClient::new_with_client(base_url, client)?,
76 })
77 }
78
79 pub fn use_token_source(&mut self, token_source: Arc<dyn TokenSource>) -> &mut Self {
81 self.client.use_token_source(token_source);
82 self
83 }
84}
85
86#[async_trait]
87impl ControlPlaneApi for CrpcSnapControlClient {
88 async fn create_data_plane_sessions(&self) -> Result<Vec<SessionGrant>, CrpcClientError> {
89 self.client
90 .unary_request::<GetSnapDataPlaneSessionGrantRequest, GetSnapDataPlaneSessionGrantResponse>(
91 &format!("{SERVICE_PATH}{GET_SNAP_DATA_PLANE_SESSION_GRANT}"),
92 GetSnapDataPlaneSessionGrantRequest::default(),
93 )
94 .await?
95 .try_into()
96 .map_err(
97 |e: SessionGrantError| {
98 CrpcClientError::DecodeError {
99 context: "decoding session grants".into(),
100 source: e.into(),
101 body: None,
102 }
103 },
104 )
105 }
106 async fn renew_data_plane_session(
107 &self,
108 address: SocketAddr,
109 ) -> Result<SessionGrant, CrpcClientError> {
110 self.client
111 .unary_request::<RenewSnapDataPlaneSessionGrantRequest, RenewSnapDataPlaneSessionGrantResponse>(
112 &format!("{SERVICE_PATH}{RENEW_SNAP_DATA_PLANE_SESSION_GRANT}"),
113 RenewSnapDataPlaneSessionGrantRequest{
114 address: address.to_string(),
115 },
116 )
117 .await?
118 .try_into()
119 .map_err(
120 |e: SessionGrantError| {
121 CrpcClientError::DecodeError {
122 context: "decoding renewed session grant".into(),
123 source: e.into(),
124 body: None,
125 }
126 },
127 )
128 }
129}