mirror of
https://gitlab.com/veilid/veilid.git
synced 2026-01-15 14:31:12 -05:00
985 lines
38 KiB
Rust
985 lines
38 KiB
Rust
use super::*;
|
|
|
|
pub fn to_json_api_result<T: Clone + fmt::Debug + JsonSchema>(
|
|
r: VeilidAPIResult<T>,
|
|
) -> super::ApiResult<T> {
|
|
match r {
|
|
Err(e) => super::ApiResult::Err { error: e },
|
|
Ok(v) => super::ApiResult::Ok { value: v },
|
|
}
|
|
}
|
|
|
|
pub fn to_json_api_result_with_string<T: Clone + fmt::Debug>(
|
|
r: VeilidAPIResult<T>,
|
|
) -> super::ApiResultWithString<T> {
|
|
match r {
|
|
Err(e) => super::ApiResultWithString::Err { error: e },
|
|
Ok(v) => super::ApiResultWithString::Ok { value: v },
|
|
}
|
|
}
|
|
|
|
pub fn to_json_api_result_with_vec_string<T: Clone + fmt::Debug>(
|
|
r: VeilidAPIResult<T>,
|
|
) -> super::ApiResultWithVecString<T> {
|
|
match r {
|
|
Err(e) => super::ApiResultWithVecString::Err { error: e },
|
|
Ok(v) => super::ApiResultWithVecString::Ok { value: v },
|
|
}
|
|
}
|
|
|
|
pub fn to_json_api_result_with_opt_vec_string<T: Clone + fmt::Debug>(
|
|
r: VeilidAPIResult<T>,
|
|
) -> super::ApiResultWithOptVecString<T> {
|
|
match r {
|
|
Err(e) => super::ApiResultWithOptVecString::Err { error: e },
|
|
Ok(v) => super::ApiResultWithOptVecString::Ok { value: v },
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn to_json_api_result_with_vec_u8(r: VeilidAPIResult<Vec<u8>>) -> super::ApiResultWithVecU8 {
|
|
match r {
|
|
Err(e) => super::ApiResultWithVecU8::Err { error: e },
|
|
Ok(v) => super::ApiResultWithVecU8::Ok { value: v },
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn to_json_api_result_with_vec_vec_u8(
|
|
r: VeilidAPIResult<Vec<Vec<u8>>>,
|
|
) -> super::ApiResultWithVecVecU8 {
|
|
match r {
|
|
Err(e) => super::ApiResultWithVecVecU8::Err { error: e },
|
|
Ok(v) => super::ApiResultWithVecVecU8::Ok {
|
|
value: v.into_iter().map(|v| VecU8 { value: v }).collect(),
|
|
},
|
|
}
|
|
}
|
|
|
|
struct JsonRequestProcessorInner {
|
|
routing_contexts: BTreeMap<u32, RoutingContext>,
|
|
table_dbs: BTreeMap<u32, TableDB>,
|
|
table_db_transactions: BTreeMap<u32, TableDBTransaction>,
|
|
dht_transactions: BTreeMap<u32, DHTTransaction>,
|
|
crypto_kinds: BTreeMap<u32, CryptoKind>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct JsonRequestProcessor {
|
|
api: VeilidAPI,
|
|
inner: Arc<Mutex<JsonRequestProcessorInner>>,
|
|
}
|
|
|
|
impl JsonRequestProcessor {
|
|
#[must_use]
|
|
pub fn new(api: VeilidAPI) -> Self {
|
|
Self {
|
|
api,
|
|
inner: Arc::new(Mutex::new(JsonRequestProcessorInner {
|
|
routing_contexts: Default::default(),
|
|
table_dbs: Default::default(),
|
|
table_db_transactions: Default::default(),
|
|
dht_transactions: Default::default(),
|
|
crypto_kinds: Default::default(),
|
|
})),
|
|
}
|
|
}
|
|
|
|
// Routing Context
|
|
fn add_routing_context(&self, routing_context: RoutingContext) -> u32 {
|
|
let mut inner = self.inner.lock();
|
|
let mut next_id: u32 = 1;
|
|
while inner.routing_contexts.contains_key(&next_id) {
|
|
next_id += 1;
|
|
}
|
|
inner.routing_contexts.insert(next_id, routing_context);
|
|
next_id
|
|
}
|
|
fn lookup_routing_context(&self, id: u32, rc_id: u32) -> Result<RoutingContext, Response> {
|
|
let inner = self.inner.lock();
|
|
let Some(routing_context) = inner.routing_contexts.get(&rc_id).cloned() else {
|
|
return Err(Response {
|
|
id,
|
|
op: ResponseOp::RoutingContext(Box::new(RoutingContextResponse {
|
|
rc_id,
|
|
rc_op: RoutingContextResponseOp::InvalidId,
|
|
})),
|
|
});
|
|
};
|
|
Ok(routing_context)
|
|
}
|
|
fn release_routing_context(&self, id: u32) -> i32 {
|
|
let mut inner = self.inner.lock();
|
|
if inner.routing_contexts.remove(&id).is_none() {
|
|
return 0;
|
|
}
|
|
1
|
|
}
|
|
|
|
// TableDB
|
|
fn add_table_db(&self, table_db: TableDB) -> u32 {
|
|
let mut inner = self.inner.lock();
|
|
let mut next_id: u32 = 1;
|
|
while inner.table_dbs.contains_key(&next_id) {
|
|
next_id += 1;
|
|
}
|
|
inner.table_dbs.insert(next_id, table_db);
|
|
next_id
|
|
}
|
|
fn lookup_table_db(&self, id: u32, db_id: u32) -> Result<TableDB, Response> {
|
|
let inner = self.inner.lock();
|
|
let Some(table_db) = inner.table_dbs.get(&db_id).cloned() else {
|
|
return Err(Response {
|
|
id,
|
|
op: ResponseOp::TableDb(TableDbResponse {
|
|
db_id,
|
|
db_op: TableDbResponseOp::InvalidId,
|
|
}),
|
|
});
|
|
};
|
|
Ok(table_db)
|
|
}
|
|
fn release_table_db(&self, id: u32) -> i32 {
|
|
let mut inner = self.inner.lock();
|
|
if inner.table_dbs.remove(&id).is_none() {
|
|
return 0;
|
|
}
|
|
1
|
|
}
|
|
|
|
// TableDBTransaction
|
|
fn add_table_db_transaction(&self, tdbt: TableDBTransaction) -> u32 {
|
|
let mut inner = self.inner.lock();
|
|
let mut next_id: u32 = 1;
|
|
while inner.table_db_transactions.contains_key(&next_id) {
|
|
next_id += 1;
|
|
}
|
|
inner.table_db_transactions.insert(next_id, tdbt);
|
|
next_id
|
|
}
|
|
fn lookup_table_db_transaction(
|
|
&self,
|
|
id: u32,
|
|
tx_id: u32,
|
|
) -> Result<TableDBTransaction, Response> {
|
|
let inner = self.inner.lock();
|
|
let Some(table_db_transaction) = inner.table_db_transactions.get(&tx_id).cloned() else {
|
|
return Err(Response {
|
|
id,
|
|
op: ResponseOp::TableDbTransaction(TableDbTransactionResponse {
|
|
tx_id,
|
|
tx_op: TableDbTransactionResponseOp::InvalidId,
|
|
}),
|
|
});
|
|
};
|
|
Ok(table_db_transaction)
|
|
}
|
|
fn release_table_db_transaction(&self, id: u32) -> i32 {
|
|
let mut inner = self.inner.lock();
|
|
if inner.table_db_transactions.remove(&id).is_none() {
|
|
return 0;
|
|
}
|
|
1
|
|
}
|
|
|
|
// CryptoSystem
|
|
fn add_crypto_system(&self, csv: CryptoKind) -> u32 {
|
|
let mut inner = self.inner.lock();
|
|
let mut next_id: u32 = 1;
|
|
while inner.crypto_kinds.contains_key(&next_id) {
|
|
next_id += 1;
|
|
}
|
|
inner.crypto_kinds.insert(next_id, csv);
|
|
next_id
|
|
}
|
|
fn lookup_crypto_system(&self, id: u32, cs_id: u32) -> Result<CryptoKind, Response> {
|
|
let inner = self.inner.lock();
|
|
let Some(crypto_kind) = inner.crypto_kinds.get(&cs_id).cloned() else {
|
|
return Err(Response {
|
|
id,
|
|
op: ResponseOp::CryptoSystem(CryptoSystemResponse {
|
|
cs_id,
|
|
cs_op: CryptoSystemResponseOp::InvalidId,
|
|
}),
|
|
});
|
|
};
|
|
Ok(crypto_kind)
|
|
}
|
|
fn release_crypto_system(&self, id: u32) -> i32 {
|
|
let mut inner = self.inner.lock();
|
|
if inner.crypto_kinds.remove(&id).is_none() {
|
|
return 0;
|
|
}
|
|
1
|
|
}
|
|
|
|
// Routing Context
|
|
fn add_dht_transaction(&self, dht_transaction: DHTTransaction) -> u32 {
|
|
let mut inner = self.inner.lock();
|
|
let mut next_id: u32 = 1;
|
|
while inner.dht_transactions.contains_key(&next_id) {
|
|
next_id += 1;
|
|
}
|
|
inner.dht_transactions.insert(next_id, dht_transaction);
|
|
next_id
|
|
}
|
|
fn lookup_dht_transaction(&self, id: u32, dhttx_id: u32) -> Result<DHTTransaction, Response> {
|
|
let inner = self.inner.lock();
|
|
let Some(dht_transaction) = inner.dht_transactions.get(&dhttx_id).cloned() else {
|
|
return Err(Response {
|
|
id,
|
|
op: ResponseOp::DhtTransaction(Box::new(DhtTransactionResponse {
|
|
dhttx_id,
|
|
dhttx_op: DhtTransactionResponseOp::InvalidId,
|
|
})),
|
|
});
|
|
};
|
|
Ok(dht_transaction)
|
|
}
|
|
fn release_dht_transaction(&self, id: u32) -> i32 {
|
|
let mut inner = self.inner.lock();
|
|
if inner.dht_transactions.remove(&id).is_none() {
|
|
return 0;
|
|
}
|
|
1
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#[instrument(level = "trace", target = "json_api", skip_all)]
|
|
pub async fn process_routing_context_request(
|
|
&self,
|
|
routing_context: RoutingContext,
|
|
rcr: RoutingContextRequest,
|
|
) -> RoutingContextResponse {
|
|
let rc_op = match rcr.rc_op {
|
|
RoutingContextRequestOp::Release => {
|
|
self.release_routing_context(rcr.rc_id);
|
|
RoutingContextResponseOp::Release {}
|
|
}
|
|
RoutingContextRequestOp::WithDefaultSafety => {
|
|
RoutingContextResponseOp::WithDefaultSafety {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.clone()
|
|
.with_default_safety()
|
|
.map(|new_rc| self.add_routing_context(new_rc)),
|
|
),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::WithSafety { safety_selection } => {
|
|
RoutingContextResponseOp::WithSafety {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.clone()
|
|
.with_safety(safety_selection)
|
|
.map(|new_rc| self.add_routing_context(new_rc)),
|
|
),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::WithSequencing { sequencing } => {
|
|
RoutingContextResponseOp::WithSequencing {
|
|
value: self
|
|
.add_routing_context(routing_context.clone().with_sequencing(sequencing)),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::Safety => RoutingContextResponseOp::Safety {
|
|
value: routing_context.safety(),
|
|
},
|
|
RoutingContextRequestOp::AppCall { target, message } => {
|
|
RoutingContextResponseOp::AppCall {
|
|
result: to_json_api_result_with_vec_u8(
|
|
async { routing_context.app_call(target, message).await }.await,
|
|
),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::AppMessage { target, message } => {
|
|
RoutingContextResponseOp::AppMessage {
|
|
result: to_json_api_result(
|
|
async { routing_context.app_message(target, message).await }.await,
|
|
),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::CreateDhtRecord {
|
|
kind,
|
|
schema,
|
|
owner,
|
|
} => RoutingContextResponseOp::CreateDhtRecord {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.create_dht_record(kind, schema, owner)
|
|
.await
|
|
.map(Box::new),
|
|
),
|
|
},
|
|
RoutingContextRequestOp::OpenDhtRecord { key, writer } => {
|
|
RoutingContextResponseOp::OpenDhtRecord {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.open_dht_record(key, writer)
|
|
.await
|
|
.map(Box::new),
|
|
),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::CloseDhtRecord { key } => {
|
|
RoutingContextResponseOp::CloseDhtRecord {
|
|
result: to_json_api_result(routing_context.close_dht_record(key).await),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::DeleteDhtRecord { key } => {
|
|
RoutingContextResponseOp::DeleteDhtRecord {
|
|
result: to_json_api_result(routing_context.delete_dht_record(key).await),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::GetDhtValue {
|
|
key,
|
|
subkey,
|
|
force_refresh,
|
|
} => RoutingContextResponseOp::GetDhtValue {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.get_dht_value(key, subkey, force_refresh)
|
|
.await,
|
|
),
|
|
},
|
|
RoutingContextRequestOp::SetDhtValue {
|
|
key,
|
|
subkey,
|
|
data,
|
|
options,
|
|
} => RoutingContextResponseOp::SetDhtValue {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.set_dht_value(key, subkey, data, options)
|
|
.await,
|
|
),
|
|
},
|
|
RoutingContextRequestOp::WatchDhtValues {
|
|
key,
|
|
subkeys,
|
|
expiration,
|
|
count,
|
|
} => RoutingContextResponseOp::WatchDhtValues {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.watch_dht_values(key, subkeys, expiration, count)
|
|
.await,
|
|
),
|
|
},
|
|
RoutingContextRequestOp::CancelDhtWatch { key, subkeys } => {
|
|
RoutingContextResponseOp::CancelDhtWatch {
|
|
result: to_json_api_result(
|
|
routing_context.cancel_dht_watch(key, subkeys).await,
|
|
),
|
|
}
|
|
}
|
|
RoutingContextRequestOp::InspectDhtRecord {
|
|
key,
|
|
subkeys,
|
|
scope,
|
|
} => RoutingContextResponseOp::InspectDhtRecord {
|
|
result: to_json_api_result(
|
|
routing_context
|
|
.inspect_dht_record(key, subkeys, scope)
|
|
.await
|
|
.map(Box::new),
|
|
),
|
|
},
|
|
};
|
|
RoutingContextResponse {
|
|
rc_id: rcr.rc_id,
|
|
rc_op,
|
|
}
|
|
}
|
|
|
|
#[instrument(level = "trace", target = "json_api", skip_all)]
|
|
pub async fn process_table_db_request(
|
|
&self,
|
|
table_db: TableDB,
|
|
tdr: TableDbRequest,
|
|
) -> TableDbResponse {
|
|
let db_op = match tdr.db_op {
|
|
TableDbRequestOp::Release => {
|
|
self.release_table_db(tdr.db_id);
|
|
TableDbResponseOp::Release {}
|
|
}
|
|
TableDbRequestOp::GetColumnCount => TableDbResponseOp::GetColumnCount {
|
|
result: to_json_api_result(table_db.get_column_count()),
|
|
},
|
|
TableDbRequestOp::GetKeys { col } => TableDbResponseOp::GetKeys {
|
|
result: to_json_api_result_with_vec_vec_u8(table_db.get_keys(col).await),
|
|
},
|
|
TableDbRequestOp::Transact => TableDbResponseOp::Transact {
|
|
value: self.add_table_db_transaction(table_db.transact()),
|
|
},
|
|
TableDbRequestOp::Store { col, key, value } => TableDbResponseOp::Store {
|
|
result: to_json_api_result(table_db.store(col, &key, &value).await),
|
|
},
|
|
TableDbRequestOp::Load { col, key } => TableDbResponseOp::Load {
|
|
result: to_json_api_result(
|
|
table_db
|
|
.load(col, &key)
|
|
.await
|
|
.map(|vopt| vopt.map(|v| VecU8 { value: v })),
|
|
),
|
|
},
|
|
TableDbRequestOp::Delete { col, key } => TableDbResponseOp::Delete {
|
|
result: to_json_api_result(
|
|
table_db
|
|
.delete(col, &key)
|
|
.await
|
|
.map(|vopt| vopt.map(|v| VecU8 { value: v })),
|
|
),
|
|
},
|
|
};
|
|
TableDbResponse {
|
|
db_id: tdr.db_id,
|
|
db_op,
|
|
}
|
|
}
|
|
|
|
#[instrument(level = "trace", target = "json_api", skip_all)]
|
|
pub async fn process_table_db_transaction_request(
|
|
&self,
|
|
table_db_transaction: TableDBTransaction,
|
|
tdtr: TableDbTransactionRequest,
|
|
) -> TableDbTransactionResponse {
|
|
let tx_op = match tdtr.tx_op {
|
|
TableDbTransactionRequestOp::Commit => TableDbTransactionResponseOp::Commit {
|
|
result: to_json_api_result(table_db_transaction.commit().await.map(|_| {
|
|
self.release_table_db_transaction(tdtr.tx_id);
|
|
})),
|
|
},
|
|
TableDbTransactionRequestOp::Rollback => {
|
|
table_db_transaction.rollback();
|
|
self.release_table_db_transaction(tdtr.tx_id);
|
|
TableDbTransactionResponseOp::Rollback {}
|
|
}
|
|
TableDbTransactionRequestOp::Store { col, key, value } => {
|
|
TableDbTransactionResponseOp::Store {
|
|
result: to_json_api_result(table_db_transaction.store(col, &key, &value).await),
|
|
}
|
|
}
|
|
|
|
TableDbTransactionRequestOp::Delete { col, key } => {
|
|
TableDbTransactionResponseOp::Delete {
|
|
result: to_json_api_result(table_db_transaction.delete(col, &key).await),
|
|
}
|
|
}
|
|
};
|
|
TableDbTransactionResponse {
|
|
tx_id: tdtr.tx_id,
|
|
tx_op,
|
|
}
|
|
}
|
|
|
|
#[instrument(level = "trace", target = "json_api", skip_all)]
|
|
pub async fn process_crypto_system_request(
|
|
&self,
|
|
csv: &CryptoSystemGuard<'_>,
|
|
csr: CryptoSystemRequest,
|
|
) -> CryptoSystemResponse {
|
|
let cs_op = match csr.cs_op {
|
|
CryptoSystemRequestOp::Release => {
|
|
self.release_crypto_system(csr.cs_id);
|
|
CryptoSystemResponseOp::Release {}
|
|
}
|
|
CryptoSystemRequestOp::Kind => CryptoSystemResponseOp::Kind { value: csv.kind() },
|
|
CryptoSystemRequestOp::CachedDh { key, secret } => CryptoSystemResponseOp::CachedDh {
|
|
result: to_json_api_result_with_string(csv.cached_dh(&key, &secret)),
|
|
},
|
|
CryptoSystemRequestOp::ComputeDh { key, secret } => CryptoSystemResponseOp::ComputeDh {
|
|
result: to_json_api_result_with_string(csv.compute_dh(&key, &secret)),
|
|
},
|
|
CryptoSystemRequestOp::GenerateSharedSecret {
|
|
key,
|
|
secret,
|
|
domain,
|
|
} => CryptoSystemResponseOp::GenerateSharedSecret {
|
|
result: to_json_api_result_with_string(
|
|
csv.generate_shared_secret(&key, &secret, &domain),
|
|
),
|
|
},
|
|
|
|
CryptoSystemRequestOp::RandomBytes { len } => CryptoSystemResponseOp::RandomBytes {
|
|
value: csv.random_bytes(len),
|
|
},
|
|
CryptoSystemRequestOp::SharedSecretLength => {
|
|
CryptoSystemResponseOp::SharedSecretLength {
|
|
value: csv.shared_secret_length() as u32,
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::NonceLength => CryptoSystemResponseOp::NonceLength {
|
|
value: csv.nonce_length() as u32,
|
|
},
|
|
CryptoSystemRequestOp::HashDigestLength => CryptoSystemResponseOp::HashDigestLength {
|
|
value: csv.hash_digest_length() as u32,
|
|
},
|
|
CryptoSystemRequestOp::PublicKeyLength => CryptoSystemResponseOp::PublicKeyLength {
|
|
value: csv.public_key_length() as u32,
|
|
},
|
|
CryptoSystemRequestOp::SecretKeyLength => CryptoSystemResponseOp::SecretKeyLength {
|
|
value: csv.secret_key_length() as u32,
|
|
},
|
|
CryptoSystemRequestOp::SignatureLength => CryptoSystemResponseOp::SignatureLength {
|
|
value: csv.signature_length() as u32,
|
|
},
|
|
CryptoSystemRequestOp::DefaultSaltLength => CryptoSystemResponseOp::DefaultSaltLength {
|
|
value: csv.default_salt_length() as u32,
|
|
},
|
|
CryptoSystemRequestOp::AeadOverhead => CryptoSystemResponseOp::AeadOverhead {
|
|
value: csv.aead_overhead() as u32,
|
|
},
|
|
CryptoSystemRequestOp::CheckSharedSecret { secret } => {
|
|
CryptoSystemResponseOp::CheckSharedSecret {
|
|
result: to_json_api_result(csv.check_shared_secret(&secret)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::CheckNonce { nonce } => CryptoSystemResponseOp::CheckNonce {
|
|
result: to_json_api_result(csv.check_nonce(&nonce)),
|
|
},
|
|
CryptoSystemRequestOp::CheckHashDigest { digest } => {
|
|
CryptoSystemResponseOp::CheckHashDigest {
|
|
result: to_json_api_result(csv.check_hash_digest(&digest)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::CheckPublicKey { key } => {
|
|
CryptoSystemResponseOp::CheckPublicKey {
|
|
result: to_json_api_result(csv.check_public_key(&key)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::CheckSecretKey { key } => {
|
|
CryptoSystemResponseOp::CheckSecretKey {
|
|
result: to_json_api_result(csv.check_secret_key(&key)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::CheckSignature { signature } => {
|
|
CryptoSystemResponseOp::CheckSignature {
|
|
result: to_json_api_result(csv.check_signature(&signature)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::HashPassword { password, salt } => {
|
|
CryptoSystemResponseOp::HashPassword {
|
|
result: to_json_api_result(csv.hash_password(&password, &salt)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::VerifyPassword {
|
|
password,
|
|
password_hash,
|
|
} => CryptoSystemResponseOp::VerifyPassword {
|
|
result: to_json_api_result(csv.verify_password(&password, &password_hash)),
|
|
},
|
|
CryptoSystemRequestOp::DeriveSharedSecret { password, salt } => {
|
|
CryptoSystemResponseOp::DeriveSharedSecret {
|
|
result: to_json_api_result_with_string(
|
|
csv.derive_shared_secret(&password, &salt),
|
|
),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::RandomNonce => CryptoSystemResponseOp::RandomNonce {
|
|
value: csv.random_nonce(),
|
|
},
|
|
CryptoSystemRequestOp::RandomSharedSecret => {
|
|
CryptoSystemResponseOp::RandomSharedSecret {
|
|
value: csv.random_shared_secret(),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::GenerateKeyPair => CryptoSystemResponseOp::GenerateKeyPair {
|
|
value: csv.generate_keypair(),
|
|
},
|
|
CryptoSystemRequestOp::GenerateHash { data } => CryptoSystemResponseOp::GenerateHash {
|
|
value: csv.generate_hash(&data),
|
|
},
|
|
CryptoSystemRequestOp::ValidateKeyPair { key, secret } => {
|
|
CryptoSystemResponseOp::ValidateKeyPair {
|
|
result: to_json_api_result(csv.validate_keypair(&key, &secret)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::ValidateHash { data, hash_digest } => {
|
|
CryptoSystemResponseOp::ValidateHash {
|
|
result: to_json_api_result(csv.validate_hash(&data, &hash_digest)),
|
|
}
|
|
}
|
|
CryptoSystemRequestOp::Sign { key, secret, data } => CryptoSystemResponseOp::Sign {
|
|
result: to_json_api_result_with_string(csv.sign(&key, &secret, &data)),
|
|
},
|
|
CryptoSystemRequestOp::Verify {
|
|
key,
|
|
data,
|
|
signature,
|
|
} => CryptoSystemResponseOp::Verify {
|
|
result: to_json_api_result(csv.verify(&key, &data, &signature)),
|
|
},
|
|
CryptoSystemRequestOp::DecryptAead {
|
|
body,
|
|
nonce,
|
|
shared_secret,
|
|
associated_data,
|
|
} => CryptoSystemResponseOp::DecryptAead {
|
|
result: to_json_api_result_with_vec_u8(csv.decrypt_aead(
|
|
&body,
|
|
&nonce,
|
|
&shared_secret,
|
|
associated_data.as_deref(),
|
|
)),
|
|
},
|
|
CryptoSystemRequestOp::EncryptAead {
|
|
body,
|
|
nonce,
|
|
shared_secret,
|
|
associated_data,
|
|
} => CryptoSystemResponseOp::EncryptAead {
|
|
result: to_json_api_result_with_vec_u8(csv.encrypt_aead(
|
|
&body,
|
|
&nonce,
|
|
&shared_secret,
|
|
associated_data.as_deref(),
|
|
)),
|
|
},
|
|
CryptoSystemRequestOp::CryptNoAuth {
|
|
body,
|
|
nonce,
|
|
shared_secret,
|
|
} => CryptoSystemResponseOp::CryptNoAuth {
|
|
result: to_json_api_result_with_vec_u8(csv.crypt_no_auth_unaligned(
|
|
&body,
|
|
&nonce,
|
|
&shared_secret,
|
|
)),
|
|
},
|
|
};
|
|
CryptoSystemResponse {
|
|
cs_id: csr.cs_id,
|
|
cs_op,
|
|
}
|
|
}
|
|
|
|
#[instrument(level = "trace", target = "json_api", skip_all)]
|
|
pub async fn process_dht_transaction_request(
|
|
&self,
|
|
dht_transaction: DHTTransaction,
|
|
dhttr: DhtTransactionRequest,
|
|
) -> DhtTransactionResponse {
|
|
let dhttx_op = match dhttr.dhttx_op {
|
|
DhtTransactionRequestOp::Release => {
|
|
self.release_dht_transaction(dhttr.dhttx_id);
|
|
DhtTransactionResponseOp::Release {}
|
|
}
|
|
DhtTransactionRequestOp::Commit => DhtTransactionResponseOp::Commit {
|
|
result: to_json_api_result(dht_transaction.commit().await.map(|_| {
|
|
self.release_dht_transaction(dhttr.dhttx_id);
|
|
})),
|
|
},
|
|
DhtTransactionRequestOp::Rollback => DhtTransactionResponseOp::Rollback {
|
|
result: to_json_api_result(dht_transaction.rollback().await.map(|_| {
|
|
self.release_dht_transaction(dhttr.dhttx_id);
|
|
})),
|
|
},
|
|
DhtTransactionRequestOp::Get { key, subkey } => DhtTransactionResponseOp::Get {
|
|
result: to_json_api_result(dht_transaction.get(key, subkey).await),
|
|
},
|
|
DhtTransactionRequestOp::Set {
|
|
key,
|
|
subkey,
|
|
data,
|
|
options,
|
|
} => DhtTransactionResponseOp::Set {
|
|
result: to_json_api_result(dht_transaction.set(key, subkey, data, options).await),
|
|
},
|
|
DhtTransactionRequestOp::Inspect {
|
|
key,
|
|
subkeys,
|
|
scope,
|
|
} => DhtTransactionResponseOp::Inspect {
|
|
result: to_json_api_result(
|
|
dht_transaction
|
|
.inspect(key, subkeys, scope)
|
|
.await
|
|
.map(Box::new),
|
|
),
|
|
},
|
|
};
|
|
DhtTransactionResponse {
|
|
dhttx_id: dhttr.dhttx_id,
|
|
dhttx_op,
|
|
}
|
|
}
|
|
|
|
#[instrument(level = "trace", target = "json_api", skip_all)]
|
|
pub async fn process_request(self, request: Request) -> Response {
|
|
let id = request.id;
|
|
|
|
let op = match request.op {
|
|
RequestOp::Control { args: _args } => ResponseOp::Control {
|
|
result: to_json_api_result(VeilidAPIResult::Err(VeilidAPIError::unimplemented(
|
|
"control should be handled by veilid-core host application",
|
|
))),
|
|
},
|
|
RequestOp::GetState => ResponseOp::GetState {
|
|
result: to_json_api_result(self.api.get_state().await.map(Box::new)),
|
|
},
|
|
RequestOp::IsShutdown => ResponseOp::IsShutdown {
|
|
value: self.api.is_shutdown(),
|
|
},
|
|
RequestOp::Attach => ResponseOp::Attach {
|
|
result: to_json_api_result(self.api.attach().await),
|
|
},
|
|
RequestOp::Detach => ResponseOp::Detach {
|
|
result: to_json_api_result(self.api.detach().await),
|
|
},
|
|
RequestOp::GenerateMemberId { writer_key } => ResponseOp::GenerateMemberId {
|
|
result: to_json_api_result_with_string(self.api.generate_member_id(&writer_key)),
|
|
},
|
|
RequestOp::GetDhtRecordKey {
|
|
schema,
|
|
owner,
|
|
encryption_key,
|
|
} => ResponseOp::GetDhtRecordKey {
|
|
result: to_json_api_result_with_string(self.api.get_dht_record_key(
|
|
schema,
|
|
owner,
|
|
encryption_key,
|
|
)),
|
|
},
|
|
RequestOp::NewPrivateRoute => ResponseOp::NewPrivateRoute {
|
|
result: to_json_api_result(self.api.new_private_route().await),
|
|
},
|
|
RequestOp::NewCustomPrivateRoute {
|
|
kinds,
|
|
stability,
|
|
sequencing,
|
|
} => ResponseOp::NewCustomPrivateRoute {
|
|
result: to_json_api_result(
|
|
self.api
|
|
.new_custom_private_route(&kinds, stability, sequencing)
|
|
.await,
|
|
),
|
|
},
|
|
RequestOp::ImportRemotePrivateRoute { blob } => ResponseOp::ImportRemotePrivateRoute {
|
|
result: to_json_api_result_with_string(self.api.import_remote_private_route(blob)),
|
|
},
|
|
RequestOp::ReleasePrivateRoute { route_id } => ResponseOp::ReleasePrivateRoute {
|
|
result: to_json_api_result(self.api.release_private_route(route_id)),
|
|
},
|
|
RequestOp::AppCallReply { call_id, message } => ResponseOp::AppCallReply {
|
|
result: to_json_api_result(self.api.app_call_reply(call_id, message).await),
|
|
},
|
|
RequestOp::NewRoutingContext => ResponseOp::NewRoutingContext {
|
|
result: to_json_api_result(
|
|
self.api
|
|
.routing_context()
|
|
.map(|rc| self.add_routing_context(rc)),
|
|
),
|
|
},
|
|
RequestOp::RoutingContext(rcr) => {
|
|
let routing_context = match self.lookup_routing_context(id, rcr.rc_id) {
|
|
Ok(v) => v,
|
|
Err(e) => return e,
|
|
};
|
|
ResponseOp::RoutingContext(Box::new(
|
|
self.process_routing_context_request(routing_context, rcr)
|
|
.await,
|
|
))
|
|
}
|
|
RequestOp::OpenTableDb { name, column_count } => {
|
|
let table_store = match self.api.table_store() {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return Response {
|
|
id,
|
|
op: ResponseOp::OpenTableDb {
|
|
result: to_json_api_result(Err(e)),
|
|
},
|
|
}
|
|
}
|
|
};
|
|
ResponseOp::OpenTableDb {
|
|
result: to_json_api_result(
|
|
table_store
|
|
.open(&name, column_count)
|
|
.await
|
|
.map(|table_db| self.add_table_db(table_db)),
|
|
),
|
|
}
|
|
}
|
|
RequestOp::DeleteTableDb { name } => {
|
|
let table_store = match self.api.table_store() {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return Response {
|
|
id,
|
|
op: ResponseOp::DeleteTableDb {
|
|
result: to_json_api_result(Err(e)),
|
|
},
|
|
}
|
|
}
|
|
};
|
|
ResponseOp::DeleteTableDb {
|
|
result: to_json_api_result(table_store.delete(&name).await),
|
|
}
|
|
}
|
|
RequestOp::TableDb(tdr) => {
|
|
let table_db = match self.lookup_table_db(id, tdr.db_id) {
|
|
Ok(v) => v,
|
|
Err(e) => return e,
|
|
};
|
|
ResponseOp::TableDb(self.process_table_db_request(table_db, tdr).await)
|
|
}
|
|
RequestOp::TableDbTransaction(tdtr) => {
|
|
let table_db_transaction = match self.lookup_table_db_transaction(id, tdtr.tx_id) {
|
|
Ok(v) => v,
|
|
Err(e) => return e,
|
|
};
|
|
ResponseOp::TableDbTransaction(
|
|
self.process_table_db_transaction_request(table_db_transaction, tdtr)
|
|
.await,
|
|
)
|
|
}
|
|
RequestOp::GetCryptoSystem { kind } => {
|
|
let crypto = match self.api.crypto() {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return Response {
|
|
id,
|
|
op: ResponseOp::GetCryptoSystem {
|
|
result: to_json_api_result(Err(e)),
|
|
},
|
|
}
|
|
}
|
|
};
|
|
ResponseOp::GetCryptoSystem {
|
|
result: to_json_api_result(
|
|
crypto
|
|
.get(kind)
|
|
.ok_or_else(|| {
|
|
VeilidAPIError::invalid_argument(
|
|
"unsupported cryptosystem",
|
|
"kind",
|
|
kind,
|
|
)
|
|
})
|
|
.map(|csv| self.add_crypto_system(csv.kind())),
|
|
),
|
|
}
|
|
}
|
|
RequestOp::CryptoSystem(csr) => {
|
|
let crypto_kind = match self.lookup_crypto_system(id, csr.cs_id) {
|
|
Ok(v) => v,
|
|
Err(e) => return e,
|
|
};
|
|
let crypto = match self.api.crypto() {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return Response {
|
|
id,
|
|
op: ResponseOp::GetCryptoSystem {
|
|
result: to_json_api_result(Err(e)),
|
|
},
|
|
}
|
|
}
|
|
};
|
|
let csv = crypto.get(crypto_kind).unwrap();
|
|
|
|
ResponseOp::CryptoSystem(self.process_crypto_system_request(&csv, csr).await)
|
|
}
|
|
RequestOp::VerifySignatures {
|
|
node_ids,
|
|
data,
|
|
signatures,
|
|
} => {
|
|
let crypto = match self.api.crypto() {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return Response {
|
|
id,
|
|
op: ResponseOp::GetCryptoSystem {
|
|
result: to_json_api_result(Err(e)),
|
|
},
|
|
}
|
|
}
|
|
};
|
|
ResponseOp::VerifySignatures {
|
|
result: to_json_api_result_with_opt_vec_string(crypto.verify_signatures(
|
|
&node_ids,
|
|
&data,
|
|
&signatures,
|
|
)),
|
|
}
|
|
}
|
|
RequestOp::GenerateSignatures { data, key_pairs } => {
|
|
let crypto = match self.api.crypto() {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return Response {
|
|
id,
|
|
op: ResponseOp::GetCryptoSystem {
|
|
result: to_json_api_result(Err(e)),
|
|
},
|
|
}
|
|
}
|
|
};
|
|
ResponseOp::GenerateSignatures {
|
|
result: to_json_api_result_with_vec_string(crypto.generate_signatures(
|
|
&data,
|
|
&key_pairs,
|
|
|_k, s| s,
|
|
)),
|
|
}
|
|
}
|
|
RequestOp::GenerateKeyPair { kind } => ResponseOp::GenerateKeyPair {
|
|
result: to_json_api_result_with_string(Crypto::generate_keypair(kind)),
|
|
},
|
|
RequestOp::Now => ResponseOp::Now {
|
|
value: Timestamp::now(),
|
|
},
|
|
RequestOp::Debug { command } => ResponseOp::Debug {
|
|
result: to_json_api_result(self.api.debug(command).await),
|
|
},
|
|
RequestOp::VeilidVersionString => ResponseOp::VeilidVersionString {
|
|
value: veilid_version_string(),
|
|
},
|
|
RequestOp::VeilidVersion => {
|
|
let (major, minor, patch) = veilid_version();
|
|
|
|
ResponseOp::VeilidVersion {
|
|
major,
|
|
minor,
|
|
patch,
|
|
}
|
|
}
|
|
RequestOp::VeilidFeatures => ResponseOp::VeilidFeatures {
|
|
value: veilid_features(),
|
|
},
|
|
RequestOp::DefaultVeilidConfig => ResponseOp::DefaultVeilidConfig {
|
|
value: default_veilid_config(),
|
|
},
|
|
RequestOp::ValidCryptoKinds => ResponseOp::ValidCryptoKinds {
|
|
value: VALID_CRYPTO_KINDS.to_vec(),
|
|
},
|
|
RequestOp::DhtTransaction(dhttx) => {
|
|
let dht_transaction = match self.lookup_dht_transaction(id, dhttx.dhttx_id) {
|
|
Ok(v) => v,
|
|
Err(e) => return e,
|
|
};
|
|
ResponseOp::DhtTransaction(Box::new(
|
|
self.process_dht_transaction_request(dht_transaction, dhttx)
|
|
.await,
|
|
))
|
|
}
|
|
RequestOp::TransactDhtRecords {
|
|
record_keys,
|
|
options,
|
|
} => ResponseOp::TransactDhtRecords {
|
|
result: to_json_api_result(
|
|
self.api
|
|
.transact_dht_records(record_keys, options)
|
|
.await
|
|
.map(|dht_tx| self.add_dht_transaction(dht_tx)),
|
|
),
|
|
},
|
|
};
|
|
|
|
Response { id, op }
|
|
}
|
|
}
|