1use crate::error::{ErrorKind, RpcError};
2use crate::protocol::PROVIDER_PROTOCOL;
3use crate::protocol::callback::{self, CredentialParams, CredentialResult};
4use crate::protocol::provider::{
5 Address, AddressParams, CAPABILITIES, ClearParams, ClearResult, DescribeWriteTargetResult,
6 ExistsResult, GetManyParams, GetManyResult, GetResult, InitializeApplication,
7 InitializedApplication, Metadata, ReflectParams, ReflectResult, ResolveAddressResult,
8 SetExpiringParams, SetParams, method,
9};
10use crate::server::{ApplicationHandler, RequestContext, RpcResult, ServerConfig};
11use async_trait::async_trait;
12use serde::de::DeserializeOwned;
13use serde_json::{Value, json};
14use std::sync::Arc;
15use std::sync::OnceLock;
16use zeroize::Zeroizing;
17
18#[derive(Clone)]
21pub struct SecretValue(Zeroizing<String>);
22
23impl std::fmt::Debug for SecretValue {
24 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 formatter
26 .debug_tuple("SecretValue")
27 .field(&crate::protocol::Redacted)
28 .finish()
29 }
30}
31
32impl SecretValue {
33 pub fn new(value: String) -> Self {
34 Self(Zeroizing::new(value))
35 }
36
37 pub fn expose(&self) -> &str {
38 self.0.as_str()
39 }
40
41 fn into_string(self) -> String {
48 self.0.as_str().to_owned()
49 }
50}
51
52#[derive(Debug, Clone)]
58pub struct ProvidedSecret {
59 value: SecretValue,
60 expires_at_unix_ms: Option<u64>,
61 revision: Option<crate::Revision>,
62}
63
64impl ProvidedSecret {
65 pub fn new(value: String, expires_at_unix_ms: Option<u64>) -> Self {
66 Self {
67 value: SecretValue::new(value),
68 expires_at_unix_ms,
69 revision: None,
70 }
71 }
72
73 pub fn value(&self) -> &str {
74 self.value.expose()
75 }
76
77 pub const fn expires_at_unix_ms(&self) -> Option<u64> {
78 self.expires_at_unix_ms
79 }
80
81 pub fn with_revision(mut self, revision: Option<crate::Revision>) -> Self {
83 self.revision = revision;
84 self
85 }
86
87 pub fn revision(&self) -> Option<&crate::Revision> {
88 self.revision.as_ref()
89 }
90
91 fn into_parts(self) -> (String, Option<u64>, Option<crate::Revision>) {
92 (
93 self.value.into_string(),
94 self.expires_at_unix_ms,
95 self.revision,
96 )
97 }
98}
99
100#[async_trait]
101pub trait ProviderHandler: Send + Sync + 'static {
102 fn capabilities(&self) -> Vec<String>;
104
105 async fn initialize(
106 &self,
107 context: &RequestContext,
108 application: InitializeApplication,
109 ) -> RpcResult<Metadata>;
110
111 async fn resolve_address(
112 &self,
113 context: RequestContext,
114 address: Address,
115 ) -> RpcResult<ResolveAddressResult>;
116
117 async fn get(
118 &self,
119 _context: RequestContext,
120 _address: Address,
121 ) -> RpcResult<Option<ProvidedSecret>> {
122 Err(RpcError::new(ErrorKind::CapabilityRequired))
123 }
124
125 async fn get_many(
126 &self,
127 _context: RequestContext,
128 _params: GetManyParams,
129 ) -> RpcResult<GetManyResult> {
130 Err(RpcError::new(ErrorKind::CapabilityRequired))
131 }
132
133 async fn exists(&self, _context: RequestContext, _address: Address) -> RpcResult<bool> {
134 Err(RpcError::new(ErrorKind::CapabilityRequired))
135 }
136
137 async fn set(
138 &self,
139 _context: RequestContext,
140 _address: Address,
141 _value: SecretValue,
142 ) -> RpcResult<()> {
143 Err(RpcError::new(ErrorKind::CapabilityRequired))
144 }
145
146 async fn set_expiring(
147 &self,
148 _context: RequestContext,
149 _address: Address,
150 _value: SecretValue,
151 _ttl_ms: u64,
152 ) -> RpcResult<()> {
153 Err(RpcError::new(ErrorKind::CapabilityRequired))
154 }
155
156 async fn delete(&self, _context: RequestContext, _address: Address) -> RpcResult<bool> {
157 Err(RpcError::new(ErrorKind::CapabilityRequired))
158 }
159
160 async fn clear(&self, _context: RequestContext, _params: ClearParams) -> RpcResult<usize> {
161 Err(RpcError::new(ErrorKind::CapabilityRequired))
162 }
163
164 async fn check_writable(&self, _context: RequestContext, _address: Address) -> RpcResult<()> {
165 Err(RpcError::new(ErrorKind::CapabilityRequired))
166 }
167
168 async fn check_deletable(&self, _context: RequestContext, _address: Address) -> RpcResult<()> {
169 Err(RpcError::new(ErrorKind::CapabilityRequired))
170 }
171
172 async fn describe_write_target(
173 &self,
174 _context: RequestContext,
175 _address: Address,
176 ) -> RpcResult<String> {
177 Err(RpcError::new(ErrorKind::CapabilityRequired))
178 }
179
180 async fn reflect(
181 &self,
182 _context: RequestContext,
183 _params: ReflectParams,
184 ) -> RpcResult<ReflectResult> {
185 Err(RpcError::new(ErrorKind::CapabilityRequired))
186 }
187
188 async fn shutdown(&self) {}
189}
190
191pub async fn request_credential(
198 context: &RequestContext,
199 params: CredentialParams,
200) -> RpcResult<Option<SecretValue>> {
201 params
202 .validate()
203 .map_err(|_| RpcError::new(ErrorKind::InvalidParams))?;
204 if !context.peer.supports(callback::method::CREDENTIAL) {
205 return Ok(None);
206 }
207 let result: CredentialResult = context
208 .peer
209 .call(callback::method::CREDENTIAL, ¶ms, context)
210 .await?;
211 result
212 .validate()
213 .map_err(|_| RpcError::new(ErrorKind::OperationFailed))?;
214 Ok(match result {
215 CredentialResult::Found { value } => Some(SecretValue::new(value)),
216 CredentialResult::Missing => None,
217 })
218}
219
220struct ProviderApplication<H> {
221 handler: Arc<H>,
222 metadata: OnceLock<Metadata>,
223}
224
225impl<H> ProviderApplication<H> {
226 fn new(handler: Arc<H>) -> Self {
227 Self {
228 handler,
229 metadata: OnceLock::new(),
230 }
231 }
232
233 fn validate_address(&self, address: &Address) -> RpcResult<()> {
234 address.validate().map_err(invalid_params)?;
235 let metadata = self
236 .metadata
237 .get()
238 .ok_or_else(|| RpcError::new(ErrorKind::Internal))?;
239 if let Address::Native { coordinates } = address
240 && coordinates
241 .unsupported(&metadata.supported_coordinates)
242 .is_some()
243 {
244 return Err(RpcError::new(ErrorKind::InvalidParams));
245 }
246 Ok(())
247 }
248
249 fn address_params(&self, value: Value) -> RpcResult<AddressParams> {
250 let params: AddressParams = parse(value)?;
251 self.validate_address(¶ms.address)?;
252 Ok(params)
253 }
254}
255
256#[async_trait]
257impl<H: ProviderHandler> ApplicationHandler for ProviderApplication<H> {
258 fn protocol(&self) -> &'static str {
259 PROVIDER_PROTOCOL
260 }
261
262 fn capabilities(&self) -> Vec<String> {
263 let mut capabilities = self.handler.capabilities();
264 capabilities.retain(|capability| CAPABILITIES.contains(&capability.as_str()));
265 capabilities.sort();
266 capabilities.dedup();
267 capabilities
268 }
269
270 fn validate_capabilities(&self, capabilities: &[String]) -> RpcResult<()> {
271 crate::protocol::provider::validate_capabilities(capabilities)
272 .map_err(|_| RpcError::new(ErrorKind::CapabilityRequired))
273 }
274
275 async fn initialize(&self, context: &RequestContext, application: Value) -> RpcResult<Value> {
276 let application: InitializeApplication = parse(application)?;
277 application.validate().map_err(invalid_params)?;
278 let scheme = application.scheme.clone();
279 let metadata = self.handler.initialize(context, application).await?;
280 metadata
281 .validate()
282 .map_err(|_| RpcError::new(ErrorKind::OperationFailed))?;
283 if metadata.name != scheme {
284 return Err(RpcError::new(ErrorKind::Conflict));
285 }
286 self.metadata
287 .set(metadata.clone())
288 .map_err(|_| RpcError::new(ErrorKind::Conflict))?;
289 serde_json::to_value(InitializedApplication { provider: metadata })
290 .map_err(|_| RpcError::new(ErrorKind::Internal))
291 }
292
293 async fn call(&self, context: RequestContext, method: &str, params: Value) -> RpcResult<Value> {
294 match method {
295 method::RESOLVE_ADDRESS => {
296 let params = self.address_params(params)?;
297 let result = self
298 .handler
299 .resolve_address(context, params.address)
300 .await?;
301 result
302 .coordinates
303 .validate()
304 .map_err(|_| RpcError::new(ErrorKind::OperationFailed))?;
305 if result
306 .coordinates
307 .unsupported(
308 &self
309 .metadata
310 .get()
311 .expect("provider initialized before calls")
312 .supported_coordinates,
313 )
314 .is_some()
315 {
316 return Err(RpcError::new(ErrorKind::OperationFailed));
317 }
318 encode(result)
319 }
320 method::GET => {
321 let params = self.address_params(params)?;
322 let result = match self.handler.get(context, params.address).await? {
323 Some(value) => {
324 let (value, expires_at_unix_ms, revision) = value.into_parts();
325 GetResult::Found {
326 value,
327 expires_at_unix_ms,
328 revision,
329 }
330 }
331 None => GetResult::Missing,
332 };
333 encode(result)
334 }
335 method::GET_MANY => {
336 let params: GetManyParams = parse(params)?;
337 params.validate().map_err(invalid_params)?;
338 for request in ¶ms.requests {
339 self.validate_address(&request.address)?;
340 }
341 let expected = params
342 .requests
343 .iter()
344 .map(|request| request.name.clone())
345 .collect::<Vec<_>>();
346 let result = self.handler.get_many(context, params).await?;
347 if result.results.len() != expected.len()
348 || result
349 .results
350 .iter()
351 .zip(expected)
352 .any(|(result, expected)| result.name != expected)
353 {
354 return Err(RpcError::new(ErrorKind::OperationFailed));
355 }
356 encode(result)
357 }
358 method::EXISTS => {
359 let params = self.address_params(params)?;
360 encode(ExistsResult {
361 exists: self.handler.exists(context, params.address).await?,
362 })
363 }
364 method::SET => {
365 let params: SetParams = parse(params)?;
366 params.validate().map_err(invalid_params)?;
367 self.validate_address(¶ms.address)?;
368 self.handler
369 .set(context, params.address, SecretValue::new(params.value))
370 .await?;
371 Ok(json!({"stored": true}))
372 }
373 method::SET_EXPIRING => {
374 let params: SetExpiringParams = parse(params)?;
375 params.validate().map_err(invalid_params)?;
376 self.validate_address(¶ms.address)?;
377 self.handler
378 .set_expiring(
379 context,
380 params.address,
381 SecretValue::new(params.value),
382 params.ttl_ms,
383 )
384 .await?;
385 Ok(json!({"stored": true}))
386 }
387 method::DELETE => {
388 let params = self.address_params(params)?;
389 Ok(json!({"deleted": self.handler.delete(context, params.address).await?}))
390 }
391 method::CLEAR => {
392 let params: ClearParams = parse(params)?;
393 params.validate().map_err(invalid_params)?;
394 let cleared = self.handler.clear(context, params).await?;
395 encode(ClearResult { cleared })
396 }
397 method::CHECK_WRITABLE => {
398 let params = self.address_params(params)?;
399 self.handler.check_writable(context, params.address).await?;
400 Ok(json!({}))
401 }
402 method::CHECK_DELETABLE => {
403 let params = self.address_params(params)?;
404 self.handler
405 .check_deletable(context, params.address)
406 .await?;
407 Ok(json!({}))
408 }
409 method::DESCRIBE_WRITE_TARGET => {
410 let params = self.address_params(params)?;
411 encode(DescribeWriteTargetResult {
412 description: self
413 .handler
414 .describe_write_target(context, params.address)
415 .await?,
416 })
417 }
418 method::REFLECT => {
419 let params: ReflectParams = parse(params)?;
420 params.validate().map_err(invalid_params)?;
421 let result = self.handler.reflect(context, params).await?;
422 result
423 .validate()
424 .map_err(|_| RpcError::new(ErrorKind::OperationFailed))?;
425 encode(result)
426 }
427 _ => Err(RpcError::new(ErrorKind::MethodNotFound)),
428 }
429 }
430
431 async fn shutdown(&self) {
432 self.handler.shutdown().await;
433 }
434}
435
436fn parse<T: DeserializeOwned>(value: Value) -> RpcResult<T> {
437 serde_json::from_value(value).map_err(|_| RpcError::new(ErrorKind::InvalidParams))
438}
439
440fn encode<T: serde::Serialize>(value: T) -> RpcResult<Value> {
441 serde_json::to_value(value).map_err(|_| RpcError::new(ErrorKind::Internal))
442}
443
444fn invalid_params(_: crate::Error) -> RpcError {
445 RpcError::new(ErrorKind::InvalidParams)
446}
447
448pub async fn serve_provider<R, W, H>(
450 reader: R,
451 writer: W,
452 handler: H,
453 config: ServerConfig,
454) -> crate::Result<()>
455where
456 R: tokio::io::AsyncRead + Unpin + Send + 'static,
457 W: tokio::io::AsyncWrite + Unpin + Send + 'static,
458 H: ProviderHandler,
459{
460 crate::server::serve(
461 reader,
462 writer,
463 Arc::new(ProviderApplication::new(Arc::new(handler))),
464 config,
465 )
466 .await
467}