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),
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(self.api.get_dht_record_key(
740 schema,
741 owner,
742 encryption_key,
743 )),
744 },
745 RequestOp::NewPrivateRoute => ResponseOp::NewPrivateRoute {
746 result: to_json_api_result(self.api.new_private_route().await),
747 },
748 RequestOp::NewCustomPrivateRoute {
749 kinds,
750 stability,
751 sequencing,
752 } => ResponseOp::NewCustomPrivateRoute {
753 result: to_json_api_result(
754 self.api
755 .new_custom_private_route(&kinds, stability, sequencing)
756 .await,
757 ),
758 },
759 RequestOp::ImportRemotePrivateRoute { blob } => ResponseOp::ImportRemotePrivateRoute {
760 result: to_json_api_result_with_string(self.api.import_remote_private_route(blob)),
761 },
762 RequestOp::ReleasePrivateRoute { route_id } => ResponseOp::ReleasePrivateRoute {
763 result: to_json_api_result(self.api.release_private_route(route_id)),
764 },
765 RequestOp::AppCallReply { call_id, message } => ResponseOp::AppCallReply {
766 result: to_json_api_result(self.api.app_call_reply(call_id, message).await),
767 },
768 RequestOp::NewRoutingContext => ResponseOp::NewRoutingContext {
769 result: to_json_api_result(
770 self.api
771 .routing_context()
772 .map(|rc| self.add_routing_context(rc)),
773 ),
774 },
775 RequestOp::RoutingContext(rcr) => {
776 let routing_context = match self.lookup_routing_context(id, rcr.rc_id) {
777 Ok(v) => v,
778 Err(e) => return e,
779 };
780 ResponseOp::RoutingContext(Box::new(
781 self.process_routing_context_request(routing_context, rcr)
782 .await,
783 ))
784 }
785 RequestOp::OpenTableDb { name, column_count } => {
786 let table_store = match self.api.table_store() {
787 Ok(v) => v,
788 Err(e) => {
789 return Response {
790 id,
791 op: ResponseOp::OpenTableDb {
792 result: to_json_api_result(Err(e)),
793 },
794 }
795 }
796 };
797 ResponseOp::OpenTableDb {
798 result: to_json_api_result(
799 table_store
800 .open(&name, column_count)
801 .await
802 .map(|table_db| self.add_table_db(table_db)),
803 ),
804 }
805 }
806 RequestOp::DeleteTableDb { name } => {
807 let table_store = match self.api.table_store() {
808 Ok(v) => v,
809 Err(e) => {
810 return Response {
811 id,
812 op: ResponseOp::DeleteTableDb {
813 result: to_json_api_result(Err(e)),
814 },
815 }
816 }
817 };
818 ResponseOp::DeleteTableDb {
819 result: to_json_api_result(table_store.delete(&name).await),
820 }
821 }
822 RequestOp::TableDb(tdr) => {
823 let table_db = match self.lookup_table_db(id, tdr.db_id) {
824 Ok(v) => v,
825 Err(e) => return e,
826 };
827 ResponseOp::TableDb(self.process_table_db_request(table_db, tdr).await)
828 }
829 RequestOp::TableDbTransaction(tdtr) => {
830 let table_db_transaction = match self.lookup_table_db_transaction(id, tdtr.tx_id) {
831 Ok(v) => v,
832 Err(e) => return e,
833 };
834 ResponseOp::TableDbTransaction(
835 self.process_table_db_transaction_request(table_db_transaction, tdtr)
836 .await,
837 )
838 }
839 RequestOp::GetCryptoSystem { kind } => {
840 let crypto = match self.api.crypto() {
841 Ok(v) => v,
842 Err(e) => {
843 return Response {
844 id,
845 op: ResponseOp::GetCryptoSystem {
846 result: to_json_api_result(Err(e)),
847 },
848 }
849 }
850 };
851 ResponseOp::GetCryptoSystem {
852 result: to_json_api_result(
853 crypto
854 .get(kind)
855 .ok_or_else(|| {
856 VeilidAPIError::invalid_argument(
857 "unsupported cryptosystem",
858 "kind",
859 kind,
860 )
861 })
862 .map(|csv| self.add_crypto_system(csv.kind())),
863 ),
864 }
865 }
866 RequestOp::CryptoSystem(csr) => {
867 let crypto_kind = match self.lookup_crypto_system(id, csr.cs_id) {
868 Ok(v) => v,
869 Err(e) => return e,
870 };
871 let crypto = match self.api.crypto() {
872 Ok(v) => v,
873 Err(e) => {
874 return Response {
875 id,
876 op: ResponseOp::GetCryptoSystem {
877 result: to_json_api_result(Err(e)),
878 },
879 }
880 }
881 };
882 let csv = crypto.get(crypto_kind).unwrap();
883
884 ResponseOp::CryptoSystem(self.process_crypto_system_request(&csv, csr).await)
885 }
886 RequestOp::VerifySignatures {
887 node_ids,
888 data,
889 signatures,
890 } => {
891 let crypto = match self.api.crypto() {
892 Ok(v) => v,
893 Err(e) => {
894 return Response {
895 id,
896 op: ResponseOp::GetCryptoSystem {
897 result: to_json_api_result(Err(e)),
898 },
899 }
900 }
901 };
902 ResponseOp::VerifySignatures {
903 result: to_json_api_result_with_opt_vec_string(crypto.verify_signatures(
904 &node_ids,
905 &data,
906 &signatures,
907 )),
908 }
909 }
910 RequestOp::GenerateSignatures { data, key_pairs } => {
911 let crypto = match self.api.crypto() {
912 Ok(v) => v,
913 Err(e) => {
914 return Response {
915 id,
916 op: ResponseOp::GetCryptoSystem {
917 result: to_json_api_result(Err(e)),
918 },
919 }
920 }
921 };
922 ResponseOp::GenerateSignatures {
923 result: to_json_api_result_with_vec_string(crypto.generate_signatures(
924 &data,
925 &key_pairs,
926 |_k, s| s,
927 )),
928 }
929 }
930 RequestOp::GenerateKeyPair { kind } => ResponseOp::GenerateKeyPair {
931 result: to_json_api_result_with_string(Crypto::generate_keypair(kind)),
932 },
933 RequestOp::Now => ResponseOp::Now {
934 value: Timestamp::now(),
935 },
936 RequestOp::Debug { command } => ResponseOp::Debug {
937 result: to_json_api_result(self.api.debug(command).await),
938 },
939 RequestOp::VeilidVersionString => ResponseOp::VeilidVersionString {
940 value: veilid_version_string(),
941 },
942 RequestOp::VeilidVersion => {
943 let (major, minor, patch) = veilid_version();
944
945 ResponseOp::VeilidVersion {
946 major,
947 minor,
948 patch,
949 }
950 }
951 RequestOp::VeilidFeatures => ResponseOp::VeilidFeatures {
952 value: veilid_features(),
953 },
954 RequestOp::DefaultVeilidConfig => ResponseOp::DefaultVeilidConfig {
955 value: default_veilid_config(),
956 },
957 RequestOp::ValidCryptoKinds => ResponseOp::ValidCryptoKinds {
958 value: VALID_CRYPTO_KINDS.to_vec(),
959 },
960 RequestOp::DhtTransaction(dhttx) => {
961 let dht_transaction = match self.lookup_dht_transaction(id, dhttx.dhttx_id) {
962 Ok(v) => v,
963 Err(e) => return e,
964 };
965 ResponseOp::DhtTransaction(Box::new(
966 self.process_dht_transaction_request(dht_transaction, dhttx)
967 .await,
968 ))
969 }
970 RequestOp::TransactDhtRecords {
971 record_keys,
972 options,
973 } => ResponseOp::TransactDhtRecords {
974 result: to_json_api_result(
975 self.api
976 .transact_dht_records(record_keys, options)
977 .await
978 .map(|dht_tx| self.add_dht_transaction(dht_tx)),
979 ),
980 },
981 };
982
983 Response { id, op }
984 }
985}