1use super::*;
2
3pub fn to_json_api_result<T: Clone + fmt::Debug + JsonSchema>(
4 r: VeilidAPIResult<T>,
5) -> super::ApiResult<T> {
6 match r {
7 Err(e) => super::ApiResult::Err { error: e },
8 Ok(v) => super::ApiResult::Ok { value: v },
9 }
10}
11
12pub fn to_json_api_result_with_string<T: Clone + fmt::Debug>(
13 r: VeilidAPIResult<T>,
14) -> super::ApiResultWithString<T> {
15 match r {
16 Err(e) => super::ApiResultWithString::Err { error: e },
17 Ok(v) => super::ApiResultWithString::Ok { value: v },
18 }
19}
20
21pub fn to_json_api_result_with_vec_string<T: Clone + fmt::Debug>(
22 r: VeilidAPIResult<T>,
23) -> super::ApiResultWithVecString<T> {
24 match r {
25 Err(e) => super::ApiResultWithVecString::Err { error: e },
26 Ok(v) => super::ApiResultWithVecString::Ok { value: v },
27 }
28}
29
30pub fn to_json_api_result_with_opt_vec_string<T: Clone + fmt::Debug>(
31 r: VeilidAPIResult<T>,
32) -> super::ApiResultWithOptVecString<T> {
33 match r {
34 Err(e) => super::ApiResultWithOptVecString::Err { error: e },
35 Ok(v) => super::ApiResultWithOptVecString::Ok { value: v },
36 }
37}
38
39#[must_use]
40pub fn to_json_api_result_with_vec_u8(r: VeilidAPIResult<Vec<u8>>) -> super::ApiResultWithVecU8 {
41 match r {
42 Err(e) => super::ApiResultWithVecU8::Err { error: e },
43 Ok(v) => super::ApiResultWithVecU8::Ok { value: v },
44 }
45}
46
47#[must_use]
48pub fn to_json_api_result_with_vec_vec_u8(
49 r: VeilidAPIResult<Vec<Vec<u8>>>,
50) -> super::ApiResultWithVecVecU8 {
51 match r {
52 Err(e) => super::ApiResultWithVecVecU8::Err { error: e },
53 Ok(v) => super::ApiResultWithVecVecU8::Ok {
54 value: v.into_iter().map(|v| VecU8 { value: v }).collect(),
55 },
56 }
57}
58
59struct JsonRequestProcessorInner {
60 routing_contexts: BTreeMap<u32, RoutingContext>,
61 table_dbs: BTreeMap<u32, TableDB>,
62 table_db_transactions: BTreeMap<u32, TableDBTransaction>,
63 dht_transactions: BTreeMap<u32, DHTTransaction>,
64 crypto_kinds: BTreeMap<u32, CryptoKind>,
65}
66
67#[derive(Clone)]
68pub struct JsonRequestProcessor {
69 api: VeilidAPI,
70 inner: Arc<Mutex<JsonRequestProcessorInner>>,
71}
72
73impl JsonRequestProcessor {
74 #[must_use]
75 pub fn new(api: VeilidAPI) -> Self {
76 Self {
77 api,
78 inner: Arc::new(Mutex::new(JsonRequestProcessorInner {
79 routing_contexts: Default::default(),
80 table_dbs: Default::default(),
81 table_db_transactions: Default::default(),
82 dht_transactions: Default::default(),
83 crypto_kinds: Default::default(),
84 })),
85 }
86 }
87
88 fn add_routing_context(&self, routing_context: RoutingContext) -> u32 {
90 let mut inner = self.inner.lock();
91 let mut next_id: u32 = 1;
92 while inner.routing_contexts.contains_key(&next_id) {
93 next_id += 1;
94 }
95 inner.routing_contexts.insert(next_id, routing_context);
96 next_id
97 }
98 fn lookup_routing_context(&self, id: u32, rc_id: u32) -> Result<RoutingContext, Response> {
99 let inner = self.inner.lock();
100 let Some(routing_context) = inner.routing_contexts.get(&rc_id).cloned() else {
101 return Err(Response {
102 id,
103 op: ResponseOp::RoutingContext(Box::new(RoutingContextResponse {
104 rc_id,
105 rc_op: RoutingContextResponseOp::InvalidId,
106 })),
107 });
108 };
109 Ok(routing_context)
110 }
111 fn release_routing_context(&self, id: u32) -> i32 {
112 let mut inner = self.inner.lock();
113 if inner.routing_contexts.remove(&id).is_none() {
114 return 0;
115 }
116 1
117 }
118
119 fn add_table_db(&self, table_db: TableDB) -> u32 {
121 let mut inner = self.inner.lock();
122 let mut next_id: u32 = 1;
123 while inner.table_dbs.contains_key(&next_id) {
124 next_id += 1;
125 }
126 inner.table_dbs.insert(next_id, table_db);
127 next_id
128 }
129 fn lookup_table_db(&self, id: u32, db_id: u32) -> Result<TableDB, Response> {
130 let inner = self.inner.lock();
131 let Some(table_db) = inner.table_dbs.get(&db_id).cloned() else {
132 return Err(Response {
133 id,
134 op: ResponseOp::TableDb(TableDbResponse {
135 db_id,
136 db_op: TableDbResponseOp::InvalidId,
137 }),
138 });
139 };
140 Ok(table_db)
141 }
142 fn release_table_db(&self, id: u32) -> i32 {
143 let mut inner = self.inner.lock();
144 if inner.table_dbs.remove(&id).is_none() {
145 return 0;
146 }
147 1
148 }
149
150 fn add_table_db_transaction(&self, tdbt: TableDBTransaction) -> u32 {
152 let mut inner = self.inner.lock();
153 let mut next_id: u32 = 1;
154 while inner.table_db_transactions.contains_key(&next_id) {
155 next_id += 1;
156 }
157 inner.table_db_transactions.insert(next_id, tdbt);
158 next_id
159 }
160 fn lookup_table_db_transaction(
161 &self,
162 id: u32,
163 tx_id: u32,
164 ) -> Result<TableDBTransaction, Response> {
165 let inner = self.inner.lock();
166 let Some(table_db_transaction) = inner.table_db_transactions.get(&tx_id).cloned() else {
167 return Err(Response {
168 id,
169 op: ResponseOp::TableDbTransaction(TableDbTransactionResponse {
170 tx_id,
171 tx_op: TableDbTransactionResponseOp::InvalidId,
172 }),
173 });
174 };
175 Ok(table_db_transaction)
176 }
177 fn release_table_db_transaction(&self, id: u32) -> i32 {
178 let mut inner = self.inner.lock();
179 if inner.table_db_transactions.remove(&id).is_none() {
180 return 0;
181 }
182 1
183 }
184
185 fn add_crypto_system(&self, csv: CryptoKind) -> u32 {
187 let mut inner = self.inner.lock();
188 let mut next_id: u32 = 1;
189 while inner.crypto_kinds.contains_key(&next_id) {
190 next_id += 1;
191 }
192 inner.crypto_kinds.insert(next_id, csv);
193 next_id
194 }
195 fn lookup_crypto_system(&self, id: u32, cs_id: u32) -> Result<CryptoKind, Response> {
196 let inner = self.inner.lock();
197 let Some(crypto_kind) = inner.crypto_kinds.get(&cs_id).cloned() else {
198 return Err(Response {
199 id,
200 op: ResponseOp::CryptoSystem(CryptoSystemResponse {
201 cs_id,
202 cs_op: CryptoSystemResponseOp::InvalidId,
203 }),
204 });
205 };
206 Ok(crypto_kind)
207 }
208 fn release_crypto_system(&self, id: u32) -> i32 {
209 let mut inner = self.inner.lock();
210 if inner.crypto_kinds.remove(&id).is_none() {
211 return 0;
212 }
213 1
214 }
215
216 fn add_dht_transaction(&self, dht_transaction: DHTTransaction) -> u32 {
218 let mut inner = self.inner.lock();
219 let mut next_id: u32 = 1;
220 while inner.dht_transactions.contains_key(&next_id) {
221 next_id += 1;
222 }
223 inner.dht_transactions.insert(next_id, dht_transaction);
224 next_id
225 }
226 fn lookup_dht_transaction(&self, id: u32, dhttx_id: u32) -> Result<DHTTransaction, Response> {
227 let inner = self.inner.lock();
228 let Some(dht_transaction) = inner.dht_transactions.get(&dhttx_id).cloned() else {
229 return Err(Response {
230 id,
231 op: ResponseOp::DhtTransaction(Box::new(DhtTransactionResponse {
232 dhttx_id,
233 dhttx_op: DhtTransactionResponseOp::InvalidId,
234 })),
235 });
236 };
237 Ok(dht_transaction)
238 }
239 fn release_dht_transaction(&self, id: u32) -> i32 {
240 let mut inner = self.inner.lock();
241 if inner.dht_transactions.remove(&id).is_none() {
242 return 0;
243 }
244 1
245 }
246
247 #[instrument(level = "trace", target = "json_api", skip_all)]
250 pub async fn process_routing_context_request(
251 &self,
252 routing_context: RoutingContext,
253 rcr: RoutingContextRequest,
254 ) -> RoutingContextResponse {
255 let rc_op = match rcr.rc_op {
256 RoutingContextRequestOp::Release => {
257 self.release_routing_context(rcr.rc_id);
258 RoutingContextResponseOp::Release {}
259 }
260 RoutingContextRequestOp::WithDefaultSafety => {
261 RoutingContextResponseOp::WithDefaultSafety {
262 result: to_json_api_result(
263 routing_context
264 .clone()
265 .with_default_safety()
266 .map(|new_rc| self.add_routing_context(new_rc)),
267 ),
268 }
269 }
270 RoutingContextRequestOp::WithSafety { safety_selection } => {
271 RoutingContextResponseOp::WithSafety {
272 result: to_json_api_result(
273 routing_context
274 .clone()
275 .with_safety(safety_selection)
276 .map(|new_rc| self.add_routing_context(new_rc)),
277 ),
278 }
279 }
280 RoutingContextRequestOp::WithSequencing { sequencing } => {
281 RoutingContextResponseOp::WithSequencing {
282 value: self
283 .add_routing_context(routing_context.clone().with_sequencing(sequencing)),
284 }
285 }
286 RoutingContextRequestOp::Safety => RoutingContextResponseOp::Safety {
287 value: routing_context.safety(),
288 },
289 RoutingContextRequestOp::AppCall { target, message } => {
290 RoutingContextResponseOp::AppCall {
291 result: to_json_api_result_with_vec_u8(
292 async { routing_context.app_call(target, message).await }.await,
293 ),
294 }
295 }
296 RoutingContextRequestOp::AppMessage { target, message } => {
297 RoutingContextResponseOp::AppMessage {
298 result: to_json_api_result(
299 async { routing_context.app_message(target, message).await }.await,
300 ),
301 }
302 }
303 RoutingContextRequestOp::CreateDhtRecord {
304 kind,
305 schema,
306 owner,
307 } => RoutingContextResponseOp::CreateDhtRecord {
308 result: to_json_api_result(
309 routing_context
310 .create_dht_record(kind, schema, owner)
311 .await
312 .map(Box::new),
313 ),
314 },
315 RoutingContextRequestOp::OpenDhtRecord { key, writer } => {
316 RoutingContextResponseOp::OpenDhtRecord {
317 result: to_json_api_result(
318 routing_context
319 .open_dht_record(key, writer)
320 .await
321 .map(Box::new),
322 ),
323 }
324 }
325 RoutingContextRequestOp::CloseDhtRecord { key } => {
326 RoutingContextResponseOp::CloseDhtRecord {
327 result: to_json_api_result(routing_context.close_dht_record(key).await),
328 }
329 }
330 RoutingContextRequestOp::DeleteDhtRecord { key } => {
331 RoutingContextResponseOp::DeleteDhtRecord {
332 result: to_json_api_result(routing_context.delete_dht_record(key).await),
333 }
334 }
335 RoutingContextRequestOp::GetDhtValue {
336 key,
337 subkey,
338 force_refresh,
339 } => RoutingContextResponseOp::GetDhtValue {
340 result: to_json_api_result(
341 routing_context
342 .get_dht_value(key, subkey, force_refresh)
343 .await,
344 ),
345 },
346 RoutingContextRequestOp::SetDhtValue {
347 key,
348 subkey,
349 data,
350 options,
351 } => RoutingContextResponseOp::SetDhtValue {
352 result: to_json_api_result(
353 routing_context
354 .set_dht_value(key, subkey, data, options)
355 .await,
356 ),
357 },
358 RoutingContextRequestOp::WatchDhtValues {
359 key,
360 subkeys,
361 expiration,
362 count,
363 } => RoutingContextResponseOp::WatchDhtValues {
364 result: to_json_api_result(
365 routing_context
366 .watch_dht_values(key, subkeys, expiration, count)
367 .await,
368 ),
369 },
370 RoutingContextRequestOp::CancelDhtWatch { key, subkeys } => {
371 RoutingContextResponseOp::CancelDhtWatch {
372 result: to_json_api_result(
373 routing_context.cancel_dht_watch(key, subkeys).await,
374 ),
375 }
376 }
377 RoutingContextRequestOp::InspectDhtRecord {
378 key,
379 subkeys,
380 scope,
381 } => RoutingContextResponseOp::InspectDhtRecord {
382 result: to_json_api_result(
383 routing_context
384 .inspect_dht_record(key, subkeys, scope)
385 .await
386 .map(Box::new),
387 ),
388 },
389 };
390 RoutingContextResponse {
391 rc_id: rcr.rc_id,
392 rc_op,
393 }
394 }
395
396 #[instrument(level = "trace", target = "json_api", skip_all)]
397 pub async fn process_table_db_request(
398 &self,
399 table_db: TableDB,
400 tdr: TableDbRequest,
401 ) -> TableDbResponse {
402 let db_op = match tdr.db_op {
403 TableDbRequestOp::Release => {
404 self.release_table_db(tdr.db_id);
405 TableDbResponseOp::Release {}
406 }
407 TableDbRequestOp::GetColumnCount => TableDbResponseOp::GetColumnCount {
408 result: to_json_api_result(table_db.get_column_count()),
409 },
410 TableDbRequestOp::GetKeys { col } => TableDbResponseOp::GetKeys {
411 result: to_json_api_result_with_vec_vec_u8(table_db.get_keys(col).await),
412 },
413 TableDbRequestOp::Transact => TableDbResponseOp::Transact {
414 value: self.add_table_db_transaction(table_db.transact()),
415 },
416 TableDbRequestOp::Store { col, key, value } => TableDbResponseOp::Store {
417 result: to_json_api_result(table_db.store(col, &key, &value).await),
418 },
419 TableDbRequestOp::Load { col, key } => TableDbResponseOp::Load {
420 result: to_json_api_result(
421 table_db
422 .load(col, &key)
423 .await
424 .map(|vopt| vopt.map(|v| VecU8 { value: v })),
425 ),
426 },
427 TableDbRequestOp::Delete { col, key } => TableDbResponseOp::Delete {
428 result: to_json_api_result(
429 table_db
430 .delete(col, &key)
431 .await
432 .map(|vopt| vopt.map(|v| VecU8 { value: v })),
433 ),
434 },
435 };
436 TableDbResponse {
437 db_id: tdr.db_id,
438 db_op,
439 }
440 }
441
442 #[instrument(level = "trace", target = "json_api", skip_all)]
443 pub async fn process_table_db_transaction_request(
444 &self,
445 table_db_transaction: TableDBTransaction,
446 tdtr: TableDbTransactionRequest,
447 ) -> TableDbTransactionResponse {
448 let tx_op = match tdtr.tx_op {
449 TableDbTransactionRequestOp::Commit => TableDbTransactionResponseOp::Commit {
450 result: to_json_api_result(table_db_transaction.commit().await.map(|_| {
451 self.release_table_db_transaction(tdtr.tx_id);
452 })),
453 },
454 TableDbTransactionRequestOp::Rollback => {
455 table_db_transaction.rollback();
456 self.release_table_db_transaction(tdtr.tx_id);
457 TableDbTransactionResponseOp::Rollback {}
458 }
459 TableDbTransactionRequestOp::Store { col, key, value } => {
460 TableDbTransactionResponseOp::Store {
461 result: to_json_api_result(table_db_transaction.store(col, &key, &value).await),
462 }
463 }
464
465 TableDbTransactionRequestOp::Delete { col, key } => {
466 TableDbTransactionResponseOp::Delete {
467 result: to_json_api_result(table_db_transaction.delete(col, &key).await),
468 }
469 }
470 };
471 TableDbTransactionResponse {
472 tx_id: tdtr.tx_id,
473 tx_op,
474 }
475 }
476
477 #[instrument(level = "trace", target = "json_api", skip_all)]
478 pub async fn process_crypto_system_request(
479 &self,
480 csv: &CryptoSystemGuard<'_>,
481 csr: CryptoSystemRequest,
482 ) -> CryptoSystemResponse {
483 let cs_op = match csr.cs_op {
484 CryptoSystemRequestOp::Release => {
485 self.release_crypto_system(csr.cs_id);
486 CryptoSystemResponseOp::Release {}
487 }
488 CryptoSystemRequestOp::Kind => CryptoSystemResponseOp::Kind { value: csv.kind() },
489 CryptoSystemRequestOp::CachedDh { key, secret } => CryptoSystemResponseOp::CachedDh {
490 result: to_json_api_result_with_string(csv.cached_dh(&key, &secret)),
491 },
492 CryptoSystemRequestOp::ComputeDh { key, secret } => CryptoSystemResponseOp::ComputeDh {
493 result: to_json_api_result_with_string(csv.compute_dh(&key, &secret)),
494 },
495 CryptoSystemRequestOp::GenerateSharedSecret {
496 key,
497 secret,
498 domain,
499 } => CryptoSystemResponseOp::GenerateSharedSecret {
500 result: to_json_api_result_with_string(
501 csv.generate_shared_secret(&key, &secret, &domain),
502 ),
503 },
504
505 CryptoSystemRequestOp::RandomBytes { len } => CryptoSystemResponseOp::RandomBytes {
506 value: csv.random_bytes(len as usize),
507 },
508 CryptoSystemRequestOp::SharedSecretLength => {
509 CryptoSystemResponseOp::SharedSecretLength {
510 value: csv.shared_secret_length() as u32,
511 }
512 }
513 CryptoSystemRequestOp::NonceLength => CryptoSystemResponseOp::NonceLength {
514 value: csv.nonce_length() as u32,
515 },
516 CryptoSystemRequestOp::HashDigestLength => CryptoSystemResponseOp::HashDigestLength {
517 value: csv.hash_digest_length() as u32,
518 },
519 CryptoSystemRequestOp::PublicKeyLength => CryptoSystemResponseOp::PublicKeyLength {
520 value: csv.public_key_length() as u32,
521 },
522 CryptoSystemRequestOp::SecretKeyLength => CryptoSystemResponseOp::SecretKeyLength {
523 value: csv.secret_key_length() as u32,
524 },
525 CryptoSystemRequestOp::SignatureLength => CryptoSystemResponseOp::SignatureLength {
526 value: csv.signature_length() as u32,
527 },
528 CryptoSystemRequestOp::DefaultSaltLength => CryptoSystemResponseOp::DefaultSaltLength {
529 value: csv.default_salt_length() as u32,
530 },
531 CryptoSystemRequestOp::AeadOverhead => CryptoSystemResponseOp::AeadOverhead {
532 value: csv.aead_overhead() as u32,
533 },
534 CryptoSystemRequestOp::CheckSharedSecret { secret } => {
535 CryptoSystemResponseOp::CheckSharedSecret {
536 result: to_json_api_result(csv.check_shared_secret(&secret)),
537 }
538 }
539 CryptoSystemRequestOp::CheckNonce { nonce } => CryptoSystemResponseOp::CheckNonce {
540 result: to_json_api_result(csv.check_nonce(&nonce)),
541 },
542 CryptoSystemRequestOp::CheckHashDigest { digest } => {
543 CryptoSystemResponseOp::CheckHashDigest {
544 result: to_json_api_result(csv.check_hash_digest(&digest)),
545 }
546 }
547 CryptoSystemRequestOp::CheckPublicKey { key } => {
548 CryptoSystemResponseOp::CheckPublicKey {
549 result: to_json_api_result(csv.check_public_key(&key)),
550 }
551 }
552 CryptoSystemRequestOp::CheckSecretKey { key } => {
553 CryptoSystemResponseOp::CheckSecretKey {
554 result: to_json_api_result(csv.check_secret_key(&key)),
555 }
556 }
557 CryptoSystemRequestOp::CheckSignature { signature } => {
558 CryptoSystemResponseOp::CheckSignature {
559 result: to_json_api_result(csv.check_signature(&signature)),
560 }
561 }
562 CryptoSystemRequestOp::HashPassword { password, salt } => {
563 CryptoSystemResponseOp::HashPassword {
564 result: to_json_api_result(csv.hash_password(&password, &salt)),
565 }
566 }
567 CryptoSystemRequestOp::VerifyPassword {
568 password,
569 password_hash,
570 } => CryptoSystemResponseOp::VerifyPassword {
571 result: to_json_api_result(csv.verify_password(&password, &password_hash)),
572 },
573 CryptoSystemRequestOp::DeriveSharedSecret { password, salt } => {
574 CryptoSystemResponseOp::DeriveSharedSecret {
575 result: to_json_api_result_with_string(
576 csv.derive_shared_secret(&password, &salt),
577 ),
578 }
579 }
580 CryptoSystemRequestOp::RandomNonce => CryptoSystemResponseOp::RandomNonce {
581 value: csv.random_nonce(),
582 },
583 CryptoSystemRequestOp::RandomSharedSecret => {
584 CryptoSystemResponseOp::RandomSharedSecret {
585 value: csv.random_shared_secret(),
586 }
587 }
588 CryptoSystemRequestOp::GenerateKeyPair => CryptoSystemResponseOp::GenerateKeyPair {
589 value: csv.generate_keypair(),
590 },
591 CryptoSystemRequestOp::GenerateHash { data } => CryptoSystemResponseOp::GenerateHash {
592 value: csv.generate_hash(&data),
593 },
594 CryptoSystemRequestOp::ValidateKeyPair { key, secret } => {
595 CryptoSystemResponseOp::ValidateKeyPair {
596 result: to_json_api_result(csv.validate_keypair(&key, &secret)),
597 }
598 }
599 CryptoSystemRequestOp::ValidateHash { data, hash_digest } => {
600 CryptoSystemResponseOp::ValidateHash {
601 result: to_json_api_result(csv.validate_hash(&data, &hash_digest)),
602 }
603 }
604 CryptoSystemRequestOp::Sign { key, secret, data } => CryptoSystemResponseOp::Sign {
605 result: to_json_api_result_with_string(csv.sign(&key, &secret, &data)),
606 },
607 CryptoSystemRequestOp::Verify {
608 key,
609 data,
610 signature,
611 } => CryptoSystemResponseOp::Verify {
612 result: to_json_api_result(csv.verify(&key, &data, &signature)),
613 },
614 CryptoSystemRequestOp::DecryptAead {
615 body,
616 nonce,
617 shared_secret,
618 associated_data,
619 } => CryptoSystemResponseOp::DecryptAead {
620 result: to_json_api_result_with_vec_u8(csv.decrypt_aead(
621 &body,
622 &nonce,
623 &shared_secret,
624 associated_data.as_deref(),
625 )),
626 },
627 CryptoSystemRequestOp::EncryptAead {
628 body,
629 nonce,
630 shared_secret,
631 associated_data,
632 } => CryptoSystemResponseOp::EncryptAead {
633 result: to_json_api_result_with_vec_u8(csv.encrypt_aead(
634 &body,
635 &nonce,
636 &shared_secret,
637 associated_data.as_deref(),
638 )),
639 },
640 CryptoSystemRequestOp::CryptNoAuth {
641 body,
642 nonce,
643 shared_secret,
644 } => CryptoSystemResponseOp::CryptNoAuth {
645 result: to_json_api_result_with_vec_u8(csv.crypt_no_auth_unaligned(
646 &body,
647 &nonce,
648 &shared_secret,
649 )),
650 },
651 };
652 CryptoSystemResponse {
653 cs_id: csr.cs_id,
654 cs_op,
655 }
656 }
657
658 #[instrument(level = "trace", target = "json_api", skip_all)]
659 pub async fn process_dht_transaction_request(
660 &self,
661 dht_transaction: DHTTransaction,
662 dhttr: DhtTransactionRequest,
663 ) -> DhtTransactionResponse {
664 let dhttx_op = match dhttr.dhttx_op {
665 DhtTransactionRequestOp::Release => {
666 self.release_dht_transaction(dhttr.dhttx_id);
667 DhtTransactionResponseOp::Release {}
668 }
669 DhtTransactionRequestOp::Commit => DhtTransactionResponseOp::Commit {
670 result: to_json_api_result(dht_transaction.commit().await.map(|_| {
671 self.release_dht_transaction(dhttr.dhttx_id);
672 })),
673 },
674 DhtTransactionRequestOp::Rollback => DhtTransactionResponseOp::Rollback {
675 result: to_json_api_result(dht_transaction.rollback().await.map(|_| {
676 self.release_dht_transaction(dhttr.dhttx_id);
677 })),
678 },
679 DhtTransactionRequestOp::Get { key, subkey } => DhtTransactionResponseOp::Get {
680 result: to_json_api_result(dht_transaction.get(key, subkey).await),
681 },
682 DhtTransactionRequestOp::Set {
683 key,
684 subkey,
685 data,
686 options,
687 } => DhtTransactionResponseOp::Set {
688 result: to_json_api_result(dht_transaction.set(key, subkey, data, options).await),
689 },
690 DhtTransactionRequestOp::Inspect {
691 key,
692 subkeys,
693 scope,
694 } => DhtTransactionResponseOp::Inspect {
695 result: to_json_api_result(
696 dht_transaction
697 .inspect(key, subkeys, scope)
698 .await
699 .map(Box::new),
700 ),
701 },
702 };
703 DhtTransactionResponse {
704 dhttx_id: dhttr.dhttx_id,
705 dhttx_op,
706 }
707 }
708
709 #[instrument(level = "trace", target = "json_api", skip_all)]
710 pub async fn process_request(self, request: Request) -> Response {
711 let id = request.id;
712
713 let op = match request.op {
714 RequestOp::Control { args: _args } => ResponseOp::Control {
715 result: to_json_api_result(VeilidAPIResult::Err(VeilidAPIError::unimplemented(
716 "control should be handled by veilid-core host application",
717 ))),
718 },
719 RequestOp::GetState => ResponseOp::GetState {
720 result: to_json_api_result(self.api.get_state().await.map(Box::new)),
721 },
722 RequestOp::IsShutdown => ResponseOp::IsShutdown {
723 value: self.api.is_shutdown(),
724 },
725 RequestOp::Attach => ResponseOp::Attach {
726 result: to_json_api_result(self.api.attach().await),
727 },
728 RequestOp::Detach => ResponseOp::Detach {
729 result: to_json_api_result(self.api.detach().await),
730 },
731 RequestOp::GenerateMemberId { writer_key } => ResponseOp::GenerateMemberId {
732 result: to_json_api_result_with_string(self.api.generate_member_id(&writer_key)),
733 },
734 RequestOp::GetDhtRecordKey {
735 schema,
736 owner,
737 encryption_key,
738 } => ResponseOp::GetDhtRecordKey {
739 result: to_json_api_result_with_string(
740 self.api
741 .get_dht_record_key(schema, owner, encryption_key)
742 .await,
743 ),
744 },
745 RequestOp::NewPrivateRoute => ResponseOp::NewPrivateRoute {
746 result: to_json_api_result(self.api.new_private_route().await),
747 },
748 RequestOp::NewCustomPrivateRoute { private_spec } => {
749 ResponseOp::NewCustomPrivateRoute {
750 result: to_json_api_result(
751 self.api.new_custom_private_route(private_spec).await,
752 ),
753 }
754 }
755 RequestOp::ImportRemotePrivateRoute { blob } => ResponseOp::ImportRemotePrivateRoute {
756 result: to_json_api_result_with_string(self.api.import_remote_private_route(blob)),
757 },
758 RequestOp::ReleasePrivateRoute { route_id } => ResponseOp::ReleasePrivateRoute {
759 result: to_json_api_result(self.api.release_private_route(route_id)),
760 },
761 RequestOp::AppCallReply { call_id, message } => ResponseOp::AppCallReply {
762 result: to_json_api_result(self.api.app_call_reply(call_id, message).await),
763 },
764 RequestOp::NewRoutingContext => ResponseOp::NewRoutingContext {
765 result: to_json_api_result(
766 self.api
767 .routing_context()
768 .map(|rc| self.add_routing_context(rc)),
769 ),
770 },
771 RequestOp::RoutingContext(rcr) => {
772 let routing_context = match self.lookup_routing_context(id, rcr.rc_id) {
773 Ok(v) => v,
774 Err(e) => return e,
775 };
776 ResponseOp::RoutingContext(Box::new(
777 self.process_routing_context_request(routing_context, rcr)
778 .await,
779 ))
780 }
781 RequestOp::OpenTableDb { name, column_count } => {
782 let table_store = match self.api.table_store() {
783 Ok(v) => v,
784 Err(e) => {
785 return Response {
786 id,
787 op: ResponseOp::OpenTableDb {
788 result: to_json_api_result(Err(e)),
789 },
790 }
791 }
792 };
793 ResponseOp::OpenTableDb {
794 result: to_json_api_result(
795 table_store
796 .open(&name, column_count)
797 .await
798 .map(|table_db| self.add_table_db(table_db)),
799 ),
800 }
801 }
802 RequestOp::DeleteTableDb { name } => {
803 let table_store = match self.api.table_store() {
804 Ok(v) => v,
805 Err(e) => {
806 return Response {
807 id,
808 op: ResponseOp::DeleteTableDb {
809 result: to_json_api_result(Err(e)),
810 },
811 }
812 }
813 };
814 ResponseOp::DeleteTableDb {
815 result: to_json_api_result(table_store.delete(&name).await),
816 }
817 }
818 RequestOp::TableDb(tdr) => {
819 let table_db = match self.lookup_table_db(id, tdr.db_id) {
820 Ok(v) => v,
821 Err(e) => return e,
822 };
823 ResponseOp::TableDb(self.process_table_db_request(table_db, tdr).await)
824 }
825 RequestOp::TableDbTransaction(tdtr) => {
826 let table_db_transaction = match self.lookup_table_db_transaction(id, tdtr.tx_id) {
827 Ok(v) => v,
828 Err(e) => return e,
829 };
830 ResponseOp::TableDbTransaction(
831 self.process_table_db_transaction_request(table_db_transaction, tdtr)
832 .await,
833 )
834 }
835 RequestOp::GetCryptoSystem { kind } => {
836 let crypto = match self.api.crypto() {
837 Ok(v) => v,
838 Err(e) => {
839 return Response {
840 id,
841 op: ResponseOp::GetCryptoSystem {
842 result: to_json_api_result(Err(e)),
843 },
844 }
845 }
846 };
847 ResponseOp::GetCryptoSystem {
848 result: to_json_api_result(
849 crypto
850 .get(kind)
851 .ok_or_else(|| {
852 VeilidAPIError::invalid_argument(
853 "unsupported cryptosystem",
854 "kind",
855 kind,
856 )
857 })
858 .map(|csv| self.add_crypto_system(csv.kind())),
859 ),
860 }
861 }
862 RequestOp::CryptoSystem(csr) => {
863 let crypto_kind = match self.lookup_crypto_system(id, csr.cs_id) {
864 Ok(v) => v,
865 Err(e) => return e,
866 };
867 let crypto = match self.api.crypto() {
868 Ok(v) => v,
869 Err(e) => {
870 return Response {
871 id,
872 op: ResponseOp::GetCryptoSystem {
873 result: to_json_api_result(Err(e)),
874 },
875 }
876 }
877 };
878 let csv = crypto.get(crypto_kind).unwrap_or_log();
879
880 ResponseOp::CryptoSystem(self.process_crypto_system_request(&csv, csr).await)
881 }
882 RequestOp::VerifySignatures {
883 node_ids,
884 data,
885 signatures,
886 } => {
887 let crypto = match self.api.crypto() {
888 Ok(v) => v,
889 Err(e) => {
890 return Response {
891 id,
892 op: ResponseOp::GetCryptoSystem {
893 result: to_json_api_result(Err(e)),
894 },
895 }
896 }
897 };
898 ResponseOp::VerifySignatures {
899 result: to_json_api_result_with_opt_vec_string(crypto.verify_signatures(
900 &node_ids,
901 &data,
902 &signatures,
903 )),
904 }
905 }
906 RequestOp::GenerateSignatures { data, key_pairs } => {
907 let crypto = match self.api.crypto() {
908 Ok(v) => v,
909 Err(e) => {
910 return Response {
911 id,
912 op: ResponseOp::GetCryptoSystem {
913 result: to_json_api_result(Err(e)),
914 },
915 }
916 }
917 };
918 ResponseOp::GenerateSignatures {
919 result: to_json_api_result_with_vec_string(crypto.generate_signatures(
920 &data,
921 &key_pairs,
922 |_k, s| s,
923 )),
924 }
925 }
926 RequestOp::GenerateKeyPair { kind } => ResponseOp::GenerateKeyPair {
927 result: to_json_api_result_with_string(Crypto::generate_keypair(kind)),
928 },
929 RequestOp::Now => ResponseOp::Now {
930 value: Timestamp::now(),
931 },
932 RequestOp::Debug { command } => ResponseOp::Debug {
933 result: to_json_api_result(self.api.debug(command).await),
934 },
935 RequestOp::VeilidVersionString => ResponseOp::VeilidVersionString {
936 value: veilid_version_string(),
937 },
938 RequestOp::VeilidVersion => {
939 let (major, minor, patch) = veilid_version();
940
941 ResponseOp::VeilidVersion {
942 major,
943 minor,
944 patch,
945 }
946 }
947 RequestOp::VeilidFeatures => ResponseOp::VeilidFeatures {
948 value: veilid_features(),
949 },
950 RequestOp::DefaultVeilidConfig => ResponseOp::DefaultVeilidConfig {
951 value: default_veilid_config(),
952 },
953 RequestOp::ValidCryptoKinds => ResponseOp::ValidCryptoKinds {
954 value: VALID_CRYPTO_KINDS.to_vec(),
955 },
956 RequestOp::DhtTransaction(dhttx) => {
957 let dht_transaction = match self.lookup_dht_transaction(id, dhttx.dhttx_id) {
958 Ok(v) => v,
959 Err(e) => return e,
960 };
961 ResponseOp::DhtTransaction(Box::new(
962 self.process_dht_transaction_request(dht_transaction, dhttx)
963 .await,
964 ))
965 }
966 RequestOp::TransactDhtRecords {
967 record_keys,
968 options,
969 } => ResponseOp::TransactDhtRecords {
970 result: to_json_api_result(
971 self.api
972 .transact_dht_records(record_keys, options)
973 .await
974 .map(|dht_tx| self.add_dht_transaction(dht_tx)),
975 ),
976 },
977 };
978
979 Response { id, op }
980 }
981}