1use crate::codec::remote::{
6 from_wire_list_remotes_response, from_wire_registration_check_response, from_wire_remote,
7 to_wire_create_remote_request, to_wire_delete_remote_request, to_wire_list_remotes_request,
8 to_wire_registration_check_request,
9};
10use crate::generated::v1;
11use crate::rpc_support::GestaltError;
12
13#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct CreateRemoteRequest {
17 pub tunnel: Option<TunnelEndpoint>,
19 pub providers: Vec<RemoteProviderDefinition>,
21 pub expected_generation: u64,
23}
24
25#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct DeleteRemoteRequest {
29 pub id: String,
31 pub expected_generation: u64,
33}
34
35#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
37#[serde(rename_all = "camelCase")]
38pub struct ListRemotesRequest {}
39
40#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
42#[serde(rename_all = "camelCase")]
43pub struct ListRemotesResponse {
44 pub remotes: Vec<Remote>,
46 pub server_identity: Option<ServerIdentity>,
48 pub tunnel: Option<TunnelBootstrap>,
50 #[serde(with = "crate::serde_duration")]
51 pub lease_duration: Option<std::time::Duration>,
53}
54
55#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
57#[serde(rename_all = "camelCase")]
58pub struct ProviderRef {
59 pub kind: String,
61 pub name: String,
63}
64
65#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct RegistrationCheckRequest {
69 pub registration_id: String,
71 pub generation: u64,
73 pub providers: Vec<ProviderRef>,
75}
76
77#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
79#[serde(rename_all = "camelCase")]
80pub struct RegistrationCheckResponse {
81 pub ready: bool,
83 pub message: String,
85}
86
87#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
89#[serde(rename_all = "camelCase")]
90pub struct Remote {
91 pub id: String,
93 pub owner_subject_id: String,
95 pub generation: u64,
97 pub providers: Vec<RemoteProviderSummary>,
99 pub reachability: Option<RemoteReachability>,
101 pub server_spki_sha256: String,
103 #[serde(with = "crate::serde_time")]
104 pub created_at: Option<std::time::SystemTime>,
106 #[serde(with = "crate::serde_time")]
107 pub updated_at: Option<std::time::SystemTime>,
109 #[serde(with = "crate::serde_time")]
110 pub last_checked_at: Option<std::time::SystemTime>,
112 #[serde(with = "crate::serde_time")]
113 pub last_successful_heartbeat_at: Option<std::time::SystemTime>,
115 pub last_error: String,
117 #[serde(with = "crate::serde_time")]
118 pub lease_expires_at: Option<std::time::SystemTime>,
120}
121
122#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub struct RemoteProviderDefinition {
126 pub kind: String,
128 pub name: String,
130 pub definition: Option<serde_json::Map<String, serde_json::Value>>,
132}
133
134#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
136#[serde(rename_all = "camelCase")]
137pub struct RemoteProviderSummary {
138 pub kind: String,
140 pub name: String,
142}
143
144#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct RemoteReachability {
148 pub reachable: bool,
150 pub message: String,
152}
153
154#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
156#[serde(rename_all = "camelCase")]
157pub struct ServerIdentity {
158 pub client_spki_sha256: String,
160}
161
162#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
164#[serde(rename_all = "camelCase")]
165pub struct TunnelBootstrap {
166 pub frps_address: String,
168 #[serde(with = "crate::serde_duration")]
169 pub lease_duration: Option<std::time::Duration>,
171}
172
173#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
175#[serde(rename_all = "camelCase")]
176pub struct TunnelEndpoint {
177 pub host: String,
179 pub certificate: Vec<u8>,
181 pub server_spki_sha256: String,
183}
184
185pub struct RegistrationLifecycle {
191 inner:
192 v1::registration_lifecycle_client::RegistrationLifecycleClient<tonic::transport::Channel>,
193 timeout: Option<std::time::Duration>,
194}
195
196impl RegistrationLifecycle {
197 pub fn new(channel: tonic::transport::Channel) -> Self {
199 Self {
200 inner: v1::registration_lifecycle_client::RegistrationLifecycleClient::new(channel),
201 timeout: None,
202 }
203 }
204
205 pub fn with_timeout(mut self, timeout: std::time::Duration) -> Self {
208 self.timeout = Some(timeout);
209 self
210 }
211
212 pub async fn check(
217 &mut self,
218 request: RegistrationCheckRequest,
219 ) -> Result<RegistrationCheckResponse, GestaltError> {
220 let mut tonic_request = tonic::Request::new(to_wire_registration_check_request(request));
221 if let Some(timeout) = self.timeout {
222 tonic_request.set_timeout(timeout);
223 }
224 let response = self.inner.check(tonic_request).await?;
225 Ok(from_wire_registration_check_response(response.into_inner()))
226 }
227}
228
229pub struct RemoteManagement {
236 inner: v1::remote_management_client::RemoteManagementClient<tonic::transport::Channel>,
237 timeout: Option<std::time::Duration>,
238}
239
240impl RemoteManagement {
241 pub fn new(channel: tonic::transport::Channel) -> Self {
243 Self {
244 inner: v1::remote_management_client::RemoteManagementClient::new(channel),
245 timeout: None,
246 }
247 }
248
249 pub fn with_timeout(mut self, timeout: std::time::Duration) -> Self {
252 self.timeout = Some(timeout);
253 self
254 }
255
256 pub async fn create_remote(
258 &mut self,
259 request: CreateRemoteRequest,
260 ) -> Result<Remote, GestaltError> {
261 let mut tonic_request = tonic::Request::new(to_wire_create_remote_request(request));
262 if let Some(timeout) = self.timeout {
263 tonic_request.set_timeout(timeout);
264 }
265 let response = self.inner.create_remote(tonic_request).await?;
266 Ok(from_wire_remote(response.into_inner()))
267 }
268
269 pub async fn list_remotes(
271 &mut self,
272 request: ListRemotesRequest,
273 ) -> Result<ListRemotesResponse, GestaltError> {
274 let mut tonic_request = tonic::Request::new(to_wire_list_remotes_request(request));
275 if let Some(timeout) = self.timeout {
276 tonic_request.set_timeout(timeout);
277 }
278 let response = self.inner.list_remotes(tonic_request).await?;
279 Ok(from_wire_list_remotes_response(response.into_inner()))
280 }
281
282 pub async fn delete_remote(
284 &mut self,
285 request: DeleteRemoteRequest,
286 ) -> Result<(), GestaltError> {
287 let mut tonic_request = tonic::Request::new(to_wire_delete_remote_request(request));
288 if let Some(timeout) = self.timeout {
289 tonic_request.set_timeout(timeout);
290 }
291 self.inner.delete_remote(tonic_request).await?;
292 Ok(())
293 }
294}