mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-01-27 06:47:16 -05:00
break everything
This commit is contained in:
parent
79f55f1a0c
commit
25ace50d45
32
Cargo.lock
generated
32
Cargo.lock
generated
@ -3145,14 +3145,6 @@ dependencies = [
|
|||||||
"pin-utils",
|
"pin-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "no-std-net"
|
|
||||||
version = "0.6.0"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_test",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "5.1.2"
|
version = "5.1.2"
|
||||||
@ -4140,7 +4132,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rkyv"
|
name = "rkyv"
|
||||||
version = "0.7.39"
|
version = "0.7.39"
|
||||||
source = "git+https://github.com/crioux/rkyv.git?branch=issue_326#2f19cfac9f31a15e2fe74ad362eec7b011dc35b9"
|
source = "git+https://github.com/rkyv/rkyv.git?rev=57e2a8d#57e2a8daff3e6381e170e723ed1beea5c113b232"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytecheck",
|
"bytecheck",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@ -4153,7 +4145,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rkyv_derive"
|
name = "rkyv_derive"
|
||||||
version = "0.7.39"
|
version = "0.7.39"
|
||||||
source = "git+https://github.com/crioux/rkyv.git?branch=issue_326#2f19cfac9f31a15e2fe74ad362eec7b011dc35b9"
|
source = "git+https://github.com/rkyv/rkyv.git?rev=57e2a8d#57e2a8daff3e6381e170e723ed1beea5c113b232"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -4461,15 +4453,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_bytes"
|
|
||||||
version = "0.11.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_cbor"
|
name = "serde_cbor"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
@ -4513,15 +4496,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_test"
|
|
||||||
version = "1.0.147"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "641666500e4e6fba7b91b73651a375cb53579468ab3c38389289b802797cad94"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yaml"
|
name = "serde_yaml"
|
||||||
version = "0.9.14"
|
version = "0.9.14"
|
||||||
@ -5615,7 +5589,6 @@ dependencies = [
|
|||||||
"ndk 0.6.0",
|
"ndk 0.6.0",
|
||||||
"ndk-glue",
|
"ndk-glue",
|
||||||
"nix 0.25.0",
|
"nix 0.25.0",
|
||||||
"no-std-net",
|
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"owning_ref",
|
"owning_ref",
|
||||||
"owo-colors",
|
"owo-colors",
|
||||||
@ -5631,7 +5604,6 @@ dependencies = [
|
|||||||
"send_wrapper 0.6.0",
|
"send_wrapper 0.6.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-big-array",
|
"serde-big-array",
|
||||||
"serde_bytes",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serial_test",
|
"serial_test",
|
||||||
"simplelog 0.12.0",
|
"simplelog 0.12.0",
|
||||||
|
@ -34,6 +34,8 @@ secrecy = "^0"
|
|||||||
chacha20poly1305 = "^0"
|
chacha20poly1305 = "^0"
|
||||||
chacha20 = "^0"
|
chacha20 = "^0"
|
||||||
hashlink = { path = "../external/hashlink", features = ["serde_impl"] }
|
hashlink = { path = "../external/hashlink", features = ["serde_impl"] }
|
||||||
|
serde = { version = "^1", features = ["derive" ] }
|
||||||
|
serde_json = { version = "^1" }
|
||||||
serde-big-array = "^0"
|
serde-big-array = "^0"
|
||||||
futures-util = { version = "^0", default_features = false, features = ["alloc"] }
|
futures-util = { version = "^0", default_features = false, features = ["alloc"] }
|
||||||
parking_lot = "^0"
|
parking_lot = "^0"
|
||||||
@ -59,9 +61,8 @@ rtnetlink = { version = "^0", default-features = false, optional = true }
|
|||||||
async-std-resolver = { version = "^0", optional = true }
|
async-std-resolver = { version = "^0", optional = true }
|
||||||
trust-dns-resolver = { version = "^0", optional = true }
|
trust-dns-resolver = { version = "^0", optional = true }
|
||||||
keyvaluedb = { path = "../external/keyvaluedb/keyvaluedb" }
|
keyvaluedb = { path = "../external/keyvaluedb/keyvaluedb" }
|
||||||
serde_bytes = { version = "^0" }
|
#rkyv = { version = "^0", default_features = false, features = ["std", "alloc", "strict", "size_32", "validation"] }
|
||||||
#rkyv = { version = "^0", default_features = false, features = ["std", "alloc", "strict", "size_64", "validation"] }
|
rkyv = { git = "https://github.com/rkyv/rkyv.git", rev = "57e2a8d", default_features = false, features = ["std", "alloc", "strict", "size_32", "validation"] }
|
||||||
rkyv = { git = "https://github.com/crioux/rkyv.git", branch = "issue_326", default_features = false, features = ["std", "alloc", "strict", "size_64", "validation"] }
|
|
||||||
bytecheck = "^0"
|
bytecheck = "^0"
|
||||||
|
|
||||||
# Dependencies for native builds only
|
# Dependencies for native builds only
|
||||||
@ -85,8 +86,7 @@ rustls-pemfile = "^0.2"
|
|||||||
futures-util = { version = "^0", default-features = false, features = ["async-await", "sink", "std", "io"] }
|
futures-util = { version = "^0", default-features = false, features = ["async-await", "sink", "std", "io"] }
|
||||||
keyvaluedb-sqlite = { path = "../external/keyvaluedb/keyvaluedb-sqlite" }
|
keyvaluedb-sqlite = { path = "../external/keyvaluedb/keyvaluedb-sqlite" }
|
||||||
data-encoding = { version = "^2" }
|
data-encoding = { version = "^2" }
|
||||||
serde = { version = "^1", features = ["derive" ] }
|
|
||||||
serde_json = { version = "^1" }
|
|
||||||
socket2 = "^0"
|
socket2 = "^0"
|
||||||
bugsalot = "^0"
|
bugsalot = "^0"
|
||||||
chrono = "^0"
|
chrono = "^0"
|
||||||
@ -98,11 +98,8 @@ nix = "^0"
|
|||||||
wasm-bindgen = "^0"
|
wasm-bindgen = "^0"
|
||||||
js-sys = "^0"
|
js-sys = "^0"
|
||||||
wasm-bindgen-futures = "^0"
|
wasm-bindgen-futures = "^0"
|
||||||
no-std-net = { path = "../external/no-std-net", features = ["serde"] }
|
|
||||||
keyvaluedb-web = { path = "../external/keyvaluedb/keyvaluedb-web" }
|
keyvaluedb-web = { path = "../external/keyvaluedb/keyvaluedb-web" }
|
||||||
data-encoding = { version = "^2", default_features = false, features = ["alloc"] }
|
data-encoding = { version = "^2", default_features = false, features = ["alloc"] }
|
||||||
serde = { version = "^1", default-features = false, features = ["derive", "alloc"] }
|
|
||||||
serde_json = { version = "^1", default-features = false, features = ["alloc"] }
|
|
||||||
getrandom = { version = "^0", features = ["js"] }
|
getrandom = { version = "^0", features = ["js"] }
|
||||||
ws_stream_wasm = "^0"
|
ws_stream_wasm = "^0"
|
||||||
async_executors = { version = "^0", default-features = false, features = [ "bindgen", "timer" ]}
|
async_executors = { version = "^0", default-features = false, features = [ "bindgen", "timer" ]}
|
||||||
|
@ -76,7 +76,7 @@ impl Envelope {
|
|||||||
// Ensure we are at least the length of the envelope
|
// Ensure we are at least the length of the envelope
|
||||||
// Silent drop here, as we use zero length packets as part of the protocol for hole punching
|
// Silent drop here, as we use zero length packets as part of the protocol for hole punching
|
||||||
if data.len() < MIN_ENVELOPE_SIZE {
|
if data.len() < MIN_ENVELOPE_SIZE {
|
||||||
return Err(VeilidAPIError::generic("envelope data too small"));
|
apibail_generic!("envelope data too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify magic number
|
// Verify magic number
|
||||||
@ -84,31 +84,28 @@ impl Envelope {
|
|||||||
.try_into()
|
.try_into()
|
||||||
.map_err(VeilidAPIError::internal)?;
|
.map_err(VeilidAPIError::internal)?;
|
||||||
if magic != *ENVELOPE_MAGIC {
|
if magic != *ENVELOPE_MAGIC {
|
||||||
return Err(VeilidAPIError::generic("bad magic number"));
|
apibail_generic!("bad magic number");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check version
|
// Check version
|
||||||
let version = data[0x04];
|
let version = data[0x04];
|
||||||
if version > MAX_CRYPTO_VERSION || version < MIN_CRYPTO_VERSION {
|
if version > MAX_CRYPTO_VERSION || version < MIN_CRYPTO_VERSION {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("unsupported cryptography version", version);
|
||||||
"unsupported cryptography version",
|
|
||||||
version,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get min version
|
// Get min version
|
||||||
let min_version = data[0x05];
|
let min_version = data[0x05];
|
||||||
if min_version > version {
|
if min_version > version {
|
||||||
return Err(VeilidAPIError::parse_error("version too low", version));
|
apibail_parse_error!("version too low", version);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get max version
|
// Get max version
|
||||||
let max_version = data[0x06];
|
let max_version = data[0x06];
|
||||||
if version > max_version {
|
if version > max_version {
|
||||||
return Err(VeilidAPIError::parse_error("version too high", version));
|
apibail_parse_error!("version too high", version);
|
||||||
}
|
}
|
||||||
if min_version > max_version {
|
if min_version > max_version {
|
||||||
return Err(VeilidAPIError::generic("version information invalid"));
|
apibail_generic!("version information invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get size and ensure it matches the size of the envelope and is less than the maximum message size
|
// Get size and ensure it matches the size of the envelope and is less than the maximum message size
|
||||||
@ -118,17 +115,17 @@ impl Envelope {
|
|||||||
.map_err(VeilidAPIError::internal)?,
|
.map_err(VeilidAPIError::internal)?,
|
||||||
);
|
);
|
||||||
if (size as usize) > MAX_ENVELOPE_SIZE {
|
if (size as usize) > MAX_ENVELOPE_SIZE {
|
||||||
return Err(VeilidAPIError::parse_error("envelope too large", size));
|
apibail_parse_error!("envelope too large", size);
|
||||||
}
|
}
|
||||||
if (size as usize) != data.len() {
|
if (size as usize) != data.len() {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!(
|
||||||
"size doesn't match envelope size",
|
"size doesn't match envelope size",
|
||||||
format!(
|
format!(
|
||||||
"size doesn't match envelope size: size={} data.len()={}",
|
"size doesn't match envelope size: size={} data.len()={}",
|
||||||
size,
|
size,
|
||||||
data.len()
|
data.len()
|
||||||
),
|
)
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the timestamp
|
// Get the timestamp
|
||||||
@ -153,10 +150,10 @@ impl Envelope {
|
|||||||
|
|
||||||
// Ensure sender_id and recipient_id are not the same
|
// Ensure sender_id and recipient_id are not the same
|
||||||
if sender_id == recipient_id {
|
if sender_id == recipient_id {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!(
|
||||||
"sender_id should not be same as recipient_id",
|
"sender_id should not be same as recipient_id",
|
||||||
recipient_id.encode(),
|
recipient_id.encode()
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get signature
|
// Get signature
|
||||||
@ -206,10 +203,7 @@ impl Envelope {
|
|||||||
// Ensure body isn't too long
|
// Ensure body isn't too long
|
||||||
let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE;
|
let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE;
|
||||||
if envelope_size > MAX_ENVELOPE_SIZE {
|
if envelope_size > MAX_ENVELOPE_SIZE {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("envelope size is too large", envelope_size);
|
||||||
"envelope size is too large",
|
|
||||||
envelope_size,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let mut data = vec![0u8; envelope_size];
|
let mut data = vec![0u8; envelope_size];
|
||||||
|
|
||||||
|
@ -59,10 +59,10 @@ impl Receipt {
|
|||||||
extra_data: D,
|
extra_data: D,
|
||||||
) -> Result<Self, VeilidAPIError> {
|
) -> Result<Self, VeilidAPIError> {
|
||||||
if extra_data.as_ref().len() > MAX_EXTRA_DATA_SIZE {
|
if extra_data.as_ref().len() > MAX_EXTRA_DATA_SIZE {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!(
|
||||||
"extra data too large for receipt",
|
"extra data too large for receipt",
|
||||||
extra_data.as_ref().len(),
|
extra_data.as_ref().len()
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
version,
|
version,
|
||||||
@ -75,7 +75,7 @@ impl Receipt {
|
|||||||
pub fn from_signed_data(data: &[u8]) -> Result<Receipt, VeilidAPIError> {
|
pub fn from_signed_data(data: &[u8]) -> Result<Receipt, VeilidAPIError> {
|
||||||
// Ensure we are at least the length of the envelope
|
// Ensure we are at least the length of the envelope
|
||||||
if data.len() < MIN_RECEIPT_SIZE {
|
if data.len() < MIN_RECEIPT_SIZE {
|
||||||
return Err(VeilidAPIError::parse_error("receipt too small", data.len()));
|
apibail_parse_error!("receipt too small", data.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify magic number
|
// Verify magic number
|
||||||
@ -83,16 +83,13 @@ impl Receipt {
|
|||||||
.try_into()
|
.try_into()
|
||||||
.map_err(VeilidAPIError::internal)?;
|
.map_err(VeilidAPIError::internal)?;
|
||||||
if magic != *RECEIPT_MAGIC {
|
if magic != *RECEIPT_MAGIC {
|
||||||
return Err(VeilidAPIError::generic("bad magic number"));
|
apibail_generic!("bad magic number");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check version
|
// Check version
|
||||||
let version = data[0x04];
|
let version = data[0x04];
|
||||||
if version > MAX_CRYPTO_VERSION || version < MIN_CRYPTO_VERSION {
|
if version > MAX_CRYPTO_VERSION || version < MIN_CRYPTO_VERSION {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("unsupported cryptography version", version);
|
||||||
"unsupported cryptography version",
|
|
||||||
version,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get size and ensure it matches the size of the envelope and is less than the maximum message size
|
// Get size and ensure it matches the size of the envelope and is less than the maximum message size
|
||||||
@ -102,16 +99,13 @@ impl Receipt {
|
|||||||
.map_err(VeilidAPIError::internal)?,
|
.map_err(VeilidAPIError::internal)?,
|
||||||
);
|
);
|
||||||
if (size as usize) > MAX_RECEIPT_SIZE {
|
if (size as usize) > MAX_RECEIPT_SIZE {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("receipt size is too large", size);
|
||||||
"receipt size is too large",
|
|
||||||
size,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if (size as usize) != data.len() {
|
if (size as usize) != data.len() {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!(
|
||||||
"size doesn't match receipt size",
|
"size doesn't match receipt size",
|
||||||
format!("size={} data.len()={}", size, data.len()),
|
format!("size={} data.len()={}", size, data.len())
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get sender id
|
// Get sender id
|
||||||
@ -153,10 +147,7 @@ impl Receipt {
|
|||||||
// Ensure extra data isn't too long
|
// Ensure extra data isn't too long
|
||||||
let receipt_size: usize = self.extra_data.len() + MIN_RECEIPT_SIZE;
|
let receipt_size: usize = self.extra_data.len() + MIN_RECEIPT_SIZE;
|
||||||
if receipt_size > MAX_RECEIPT_SIZE {
|
if receipt_size > MAX_RECEIPT_SIZE {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("receipt too large", receipt_size);
|
||||||
"receipt too large",
|
|
||||||
receipt_size,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let mut data: Vec<u8> = vec![0u8; receipt_size];
|
let mut data: Vec<u8> = vec![0u8; receipt_size];
|
||||||
|
|
||||||
|
@ -2,10 +2,7 @@ use super::*;
|
|||||||
use crate::xx::*;
|
use crate::xx::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use data_encoding::BASE64URL_NOPAD;
|
use data_encoding::BASE64URL_NOPAD;
|
||||||
use js_sys::*;
|
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||||
use send_wrapper::*;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use wasm_bindgen_futures::*;
|
|
||||||
use web_sys::*;
|
use web_sys::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -44,15 +41,6 @@ impl ProtectedStore {
|
|||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub async fn terminate(&self) {}
|
pub async fn terminate(&self) {}
|
||||||
|
|
||||||
fn keyring_name(&self) -> String {
|
|
||||||
let c = self.config.get();
|
|
||||||
if c.namespace.is_empty() {
|
|
||||||
"veilid_protected_store".to_owned()
|
|
||||||
} else {
|
|
||||||
format!("veilid_protected_store_{}", c.namespace)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn browser_key_name(&self, key: &str) -> String {
|
fn browser_key_name(&self, key: &str) -> String {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
if c.namespace.is_empty() {
|
if c.namespace.is_empty() {
|
||||||
@ -136,22 +124,31 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, value))]
|
#[instrument(level = "trace", skip(self, value))]
|
||||||
pub async fn save_user_secret_frozen<T>(&self, key: &str, value: &T) -> EyreResult<bool>
|
pub async fn save_user_secret_rkyv<T>(&self, key: &str, value: &T) -> EyreResult<bool>
|
||||||
where
|
where
|
||||||
T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
|
T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
|
||||||
{
|
{
|
||||||
let v = to_frozen(value)?;
|
let v = to_rkyv(value)?;
|
||||||
|
self.save_user_secret(&key, &v).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace", skip(self, value))]
|
||||||
|
pub async fn save_user_secret_json<T>(&self, key: &str, value: &T) -> EyreResult<bool>
|
||||||
|
where
|
||||||
|
T: serde::Serialize,
|
||||||
|
{
|
||||||
|
let v = serde_json::to_vec(value)?;
|
||||||
self.save_user_secret(&key, &v).await
|
self.save_user_secret(&key, &v).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
pub async fn load_user_secret_frozen<T>(&self, key: &str) -> EyreResult<Option<T>>
|
pub async fn load_user_secret_rkyv<T>(&self, key: &str) -> EyreResult<Option<T>>
|
||||||
where
|
where
|
||||||
T: RkyvArchive,
|
T: RkyvArchive,
|
||||||
<T as RkyvArchive>::Archived:
|
<T as RkyvArchive>::Archived:
|
||||||
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
||||||
<T as RkyvArchive>::Archived:
|
<T as RkyvArchive>::Archived:
|
||||||
rkyv::Deserialize<T, rkyv::de::deserializers::SharedDeserializeMap>,
|
RkyvDeserialize<T, rkyv::de::deserializers::SharedDeserializeMap>,
|
||||||
{
|
{
|
||||||
let out = self.load_user_secret(key).await?;
|
let out = self.load_user_secret(key).await?;
|
||||||
let b = match out {
|
let b = match out {
|
||||||
@ -161,7 +158,24 @@ impl ProtectedStore {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let obj = from_frozen(&b)?;
|
let obj = from_rkyv(b)?;
|
||||||
|
Ok(Some(obj))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace", skip(self))]
|
||||||
|
pub async fn load_user_secret_json<T>(&self, key: &str) -> EyreResult<Option<T>>
|
||||||
|
where
|
||||||
|
T: for<'de> serde::de::Deserialize<'de>,
|
||||||
|
{
|
||||||
|
let out = self.load_user_secret(key).await?;
|
||||||
|
let b = match out {
|
||||||
|
Some(v) => v,
|
||||||
|
None => {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let obj = serde_json::from_slice(&b)?;
|
||||||
Ok(Some(obj))
|
Ok(Some(obj))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,8 +964,8 @@ impl RouteSpecStore {
|
|||||||
let safety_spec = SafetySpec {
|
let safety_spec = SafetySpec {
|
||||||
preferred_route: None,
|
preferred_route: None,
|
||||||
hop_count: self.unlocked_inner.default_route_hop_count,
|
hop_count: self.unlocked_inner.default_route_hop_count,
|
||||||
stability: Stability::LowLatency,
|
stability: Stability::default(),
|
||||||
sequencing: Sequencing::NoPreference,
|
sequencing: Sequencing::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let safety_selection = SafetySelection::Safe(safety_spec);
|
let safety_selection = SafetySelection::Safe(safety_spec);
|
||||||
|
@ -57,14 +57,14 @@ fn get_safety_selection(text: &str, rss: RouteSpecStore) -> Option<SafetySelecti
|
|||||||
if text.len() != 0 && &text[0..1] == "-" {
|
if text.len() != 0 && &text[0..1] == "-" {
|
||||||
// Unsafe
|
// Unsafe
|
||||||
let text = &text[1..];
|
let text = &text[1..];
|
||||||
let seq = get_sequencing(text).unwrap_or(Sequencing::NoPreference);
|
let seq = get_sequencing(text).unwrap_or_default();
|
||||||
Some(SafetySelection::Unsafe(seq))
|
Some(SafetySelection::Unsafe(seq))
|
||||||
} else {
|
} else {
|
||||||
// Safe
|
// Safe
|
||||||
let mut preferred_route = None;
|
let mut preferred_route = None;
|
||||||
let mut hop_count = 2;
|
let mut hop_count = 2;
|
||||||
let mut stability = Stability::LowLatency;
|
let mut stability = Stability::default();
|
||||||
let mut sequencing = Sequencing::NoPreference;
|
let mut sequencing = Sequencing::default();
|
||||||
for x in text.split(",") {
|
for x in text.split(",") {
|
||||||
let x = x.trim();
|
let x = x.trim();
|
||||||
if let Some(pr) = get_route_id(rss.clone())(x) {
|
if let Some(pr) = get_route_id(rss.clone())(x) {
|
||||||
@ -134,7 +134,7 @@ fn get_destination(routing_table: RoutingTable) -> impl FnOnce(&str) -> Option<D
|
|||||||
};
|
};
|
||||||
Some(Destination::private_route(
|
Some(Destination::private_route(
|
||||||
private_route,
|
private_route,
|
||||||
ss.unwrap_or(SafetySelection::Unsafe(Sequencing::NoPreference)),
|
ss.unwrap_or(SafetySelection::Unsafe(Sequencing::default())),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
let (text, mods) = text
|
let (text, mods) = text
|
||||||
@ -585,8 +585,8 @@ impl VeilidAPI {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut ai = 1;
|
let mut ai = 1;
|
||||||
let mut sequencing = Sequencing::NoPreference;
|
let mut sequencing = Sequencing::default();
|
||||||
let mut stability = Stability::LowLatency;
|
let mut stability = Stability::default();
|
||||||
let mut hop_count = default_route_hop_count;
|
let mut hop_count = default_route_hop_count;
|
||||||
let mut directions = DirectionSet::all();
|
let mut directions = DirectionSet::all();
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ macro_rules! apibail_internal {
|
|||||||
|
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! apibail_parse {
|
macro_rules! apibail_parse_error {
|
||||||
($x:expr, $y:expr) => {
|
($x:expr, $y:expr) => {
|
||||||
return Err(VeilidAPIError::parse_error($x, $y))
|
return Err(VeilidAPIError::parse_error($x, $y))
|
||||||
};
|
};
|
||||||
@ -563,6 +563,12 @@ pub enum Sequencing {
|
|||||||
EnsureOrdered,
|
EnsureOrdered,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Sequencing {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::NoPreference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ordering here matters, >= is used to check strength of stability requirement
|
// Ordering here matters, >= is used to check strength of stability requirement
|
||||||
#[derive(
|
#[derive(
|
||||||
Copy,
|
Copy,
|
||||||
@ -585,6 +591,12 @@ pub enum Stability {
|
|||||||
Reliable,
|
Reliable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Stability {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::LowLatency
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The choice of safety route to include in compiled routes
|
/// The choice of safety route to include in compiled routes
|
||||||
#[derive(
|
#[derive(
|
||||||
Copy,
|
Copy,
|
||||||
@ -1543,10 +1555,7 @@ impl FromStr for DialInfo {
|
|||||||
VeilidAPIError::parse_error(format!("unable to split WS url: {}", e), &url)
|
VeilidAPIError::parse_error(format!("unable to split WS url: {}", e), &url)
|
||||||
})?;
|
})?;
|
||||||
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("incorrect scheme for WS dialinfo", url);
|
||||||
"incorrect scheme for WS dialinfo",
|
|
||||||
url,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let url_port = split_url.port.unwrap_or(80u16);
|
let url_port = split_url.port.unwrap_or(80u16);
|
||||||
|
|
||||||
@ -1574,10 +1583,7 @@ impl FromStr for DialInfo {
|
|||||||
VeilidAPIError::parse_error(format!("unable to split WSS url: {}", e), &url)
|
VeilidAPIError::parse_error(format!("unable to split WSS url: {}", e), &url)
|
||||||
})?;
|
})?;
|
||||||
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("incorrect scheme for WSS dialinfo", url);
|
||||||
"incorrect scheme for WSS dialinfo",
|
|
||||||
url,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let url_port = split_url.port.unwrap_or(443u16);
|
let url_port = split_url.port.unwrap_or(443u16);
|
||||||
|
|
||||||
@ -1628,24 +1634,18 @@ impl DialInfo {
|
|||||||
VeilidAPIError::parse_error(format!("unable to split WS url: {}", e), &url)
|
VeilidAPIError::parse_error(format!("unable to split WS url: {}", e), &url)
|
||||||
})?;
|
})?;
|
||||||
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("incorrect scheme for WS dialinfo", url);
|
||||||
"incorrect scheme for WS dialinfo",
|
|
||||||
url,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let url_port = split_url.port.unwrap_or(80u16);
|
let url_port = split_url.port.unwrap_or(80u16);
|
||||||
if url_port != socket_address.port() {
|
if url_port != socket_address.port() {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("socket address port doesn't match url port", url);
|
||||||
"socket address port doesn't match url port",
|
|
||||||
url,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
||||||
if socket_address.to_ip_addr() != a {
|
if socket_address.to_ip_addr() != a {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!(
|
||||||
format!("request address does not match socket address: {}", a),
|
format!("request address does not match socket address: {}", a),
|
||||||
socket_address,
|
socket_address
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Self::WS(DialInfoWS {
|
Ok(Self::WS(DialInfoWS {
|
||||||
@ -1658,23 +1658,17 @@ impl DialInfo {
|
|||||||
VeilidAPIError::parse_error(format!("unable to split WSS url: {}", e), &url)
|
VeilidAPIError::parse_error(format!("unable to split WSS url: {}", e), &url)
|
||||||
})?;
|
})?;
|
||||||
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("incorrect scheme for WSS dialinfo", url);
|
||||||
"incorrect scheme for WSS dialinfo",
|
|
||||||
url,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let url_port = split_url.port.unwrap_or(443u16);
|
let url_port = split_url.port.unwrap_or(443u16);
|
||||||
if url_port != socket_address.port() {
|
if url_port != socket_address.port() {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("socket address port doesn't match url port", url);
|
||||||
"socket address port doesn't match url port",
|
|
||||||
url,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if !matches!(split_url.host, SplitUrlHost::Hostname(_)) {
|
if !matches!(split_url.host, SplitUrlHost::Hostname(_)) {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!(
|
||||||
"WSS url can not use address format, only hostname format",
|
"WSS url can not use address format, only hostname format",
|
||||||
url,
|
url
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
Ok(Self::WSS(DialInfoWSS {
|
Ok(Self::WSS(DialInfoWSS {
|
||||||
socket_address: socket_address.to_canonical(),
|
socket_address: socket_address.to_canonical(),
|
||||||
@ -1778,10 +1772,7 @@ impl DialInfo {
|
|||||||
let hostname = hostname.as_ref();
|
let hostname = hostname.as_ref();
|
||||||
|
|
||||||
if short.len() < 2 {
|
if short.len() < 2 {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("invalid short url length", short);
|
||||||
"invalid short url length",
|
|
||||||
short,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let url = match &short[0..1] {
|
let url = match &short[0..1] {
|
||||||
"U" => {
|
"U" => {
|
||||||
@ -1797,7 +1788,7 @@ impl DialInfo {
|
|||||||
format!("wss://{}:{}", hostname, &short[1..])
|
format!("wss://{}:{}", hostname, &short[1..])
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(VeilidAPIError::parse_error("invalid short url type", short));
|
apibail_parse_error!("invalid short url type", short);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Self::try_vec_from_url(url)
|
Self::try_vec_from_url(url)
|
||||||
@ -1815,10 +1806,7 @@ impl DialInfo {
|
|||||||
"ws" => split_url.port.unwrap_or(80u16),
|
"ws" => split_url.port.unwrap_or(80u16),
|
||||||
"wss" => split_url.port.unwrap_or(443u16),
|
"wss" => split_url.port.unwrap_or(443u16),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(VeilidAPIError::parse_error(
|
apibail_parse_error!("Invalid dial info url scheme", split_url.scheme);
|
||||||
"Invalid dial info url scheme",
|
|
||||||
split_url.scheme,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2753,36 +2741,35 @@ impl VeilidAPI {
|
|||||||
// Private route allocation
|
// Private route allocation
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub async fn new_default_private_route(&self) -> Result<(DHTKey, Vec<u8>), VeilidAPIError> {
|
pub async fn new_private_route(&self) -> Result<(DHTKey, Vec<u8>), VeilidAPIError> {
|
||||||
let config = self.config()?;
|
self.new_custom_private_route(Stability::default(), Sequencing::default())
|
||||||
let c = config.get();
|
|
||||||
self.new_private_route(
|
|
||||||
Stability::LowLatency,
|
|
||||||
Sequencing::NoPreference,
|
|
||||||
c.network.rpc.default_route_hop_count.into(),
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub async fn new_private_route(
|
pub async fn new_custom_private_route(
|
||||||
&self,
|
&self,
|
||||||
stability: Stability,
|
stability: Stability,
|
||||||
sequencing: Sequencing,
|
sequencing: Sequencing,
|
||||||
hop_count: usize,
|
|
||||||
) -> Result<(DHTKey, Vec<u8>), VeilidAPIError> {
|
) -> Result<(DHTKey, Vec<u8>), VeilidAPIError> {
|
||||||
|
let default_route_hop_count: usize = {
|
||||||
|
let config = self.config()?;
|
||||||
|
let c = config.get();
|
||||||
|
c.network.rpc.default_route_hop_count.into()
|
||||||
|
};
|
||||||
|
|
||||||
let rss = self.routing_table()?.route_spec_store();
|
let rss = self.routing_table()?.route_spec_store();
|
||||||
let r = rss
|
let r = rss
|
||||||
.allocate_route(
|
.allocate_route(
|
||||||
stability,
|
stability,
|
||||||
sequencing,
|
sequencing,
|
||||||
hop_count,
|
default_route_hop_count,
|
||||||
Direction::Inbound.into(),
|
Direction::Inbound.into(),
|
||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.map_err(VeilidAPIError::internal)?;
|
.map_err(VeilidAPIError::internal)?;
|
||||||
let Some(pr_pubkey) = r else {
|
let Some(pr_pubkey) = r else {
|
||||||
return Err(VeilidAPIError::generic("unable to allocate route"));
|
apibail_generic!("unable to allocate route");
|
||||||
};
|
};
|
||||||
if !rss
|
if !rss
|
||||||
.test_route(&pr_pubkey)
|
.test_route(&pr_pubkey)
|
||||||
@ -2790,7 +2777,7 @@ impl VeilidAPI {
|
|||||||
.map_err(VeilidAPIError::no_connection)?
|
.map_err(VeilidAPIError::no_connection)?
|
||||||
{
|
{
|
||||||
rss.release_route(&pr_pubkey);
|
rss.release_route(&pr_pubkey);
|
||||||
return Err(VeilidAPIError::generic("allocated route failed to test"));
|
apibail_generic!("allocated route failed to test");
|
||||||
}
|
}
|
||||||
let private_route = rss
|
let private_route = rss
|
||||||
.assemble_private_route(&pr_pubkey, Some(true))
|
.assemble_private_route(&pr_pubkey, Some(true))
|
||||||
@ -2799,12 +2786,37 @@ impl VeilidAPI {
|
|||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
rss.release_route(&pr_pubkey);
|
rss.release_route(&pr_pubkey);
|
||||||
return Err(VeilidAPIError::internal(e));
|
apibail_internal!(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rss.mark_route_published(&pr_pubkey, true)
|
||||||
|
.map_err(VeilidAPIError::internal)?;
|
||||||
|
|
||||||
Ok((pr_pubkey, blob))
|
Ok((pr_pubkey, blob))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> Result<DHTKey, VeilidAPIError> {
|
||||||
|
let rss = self.routing_table()?.route_spec_store();
|
||||||
|
rss.import_remote_private_route(blob)
|
||||||
|
.map_err(|e| VeilidAPIError::invalid_argument(e, "blob", "private route blob"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
pub fn release_private_route(&self, key: &DHTKey) -> Result<(), VeilidAPIError> {
|
||||||
|
let rss = self.routing_table()?.route_spec_store();
|
||||||
|
if rss.release_route(key) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(VeilidAPIError::invalid_argument(
|
||||||
|
"release_private_route",
|
||||||
|
"key",
|
||||||
|
key,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// App Calls
|
// App Calls
|
||||||
|
|
||||||
|
@ -39,14 +39,19 @@ impl RoutingContext {
|
|||||||
api,
|
api,
|
||||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||||
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
||||||
safety_selection: SafetySelection::Unsafe(Sequencing::NoPreference),
|
safety_selection: SafetySelection::Unsafe(Sequencing::default()),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_default_privacy(self) -> Result<Self, VeilidAPIError> {
|
pub fn with_privacy(self) -> Result<Self, VeilidAPIError> {
|
||||||
|
self.with_custom_privacy(Stability::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_custom_privacy(self, stability: Stability) -> Result<Self, VeilidAPIError> {
|
||||||
let config = self.api.config()?;
|
let config = self.api.config()?;
|
||||||
let c = config.get();
|
let c = config.get();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
api: self.api.clone(),
|
api: self.api.clone(),
|
||||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||||
@ -54,21 +59,12 @@ impl RoutingContext {
|
|||||||
safety_selection: SafetySelection::Safe(SafetySpec {
|
safety_selection: SafetySelection::Safe(SafetySpec {
|
||||||
preferred_route: None,
|
preferred_route: None,
|
||||||
hop_count: c.network.rpc.default_route_hop_count as usize,
|
hop_count: c.network.rpc.default_route_hop_count as usize,
|
||||||
stability: Stability::LowLatency,
|
stability,
|
||||||
sequencing: Sequencing::NoPreference,
|
sequencing: self.sequencing(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn with_privacy(self, safety_spec: SafetySpec) -> Result<Self, VeilidAPIError> {
|
|
||||||
Ok(Self {
|
|
||||||
api: self.api.clone(),
|
|
||||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
|
||||||
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
|
||||||
safety_selection: SafetySelection::Safe(safety_spec),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_sequencing(self, sequencing: Sequencing) -> Self {
|
pub fn with_sequencing(self, sequencing: Sequencing) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -87,18 +83,13 @@ impl RoutingContext {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn sequencing(&self) -> Sequencing {
|
|
||||||
|
fn sequencing(&self) -> Sequencing {
|
||||||
match self.unlocked_inner.safety_selection {
|
match self.unlocked_inner.safety_selection {
|
||||||
SafetySelection::Unsafe(sequencing) => sequencing,
|
SafetySelection::Unsafe(sequencing) => sequencing,
|
||||||
SafetySelection::Safe(safety_spec) => safety_spec.sequencing,
|
SafetySelection::Safe(safety_spec) => safety_spec.sequencing,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn safety_spec(&self) -> Option<SafetySpec> {
|
|
||||||
match self.unlocked_inner.safety_selection {
|
|
||||||
SafetySelection::Unsafe(_) => None,
|
|
||||||
SafetySelection::Safe(safety_spec) => Some(safety_spec.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn api(&self) -> VeilidAPI {
|
pub fn api(&self) -> VeilidAPI {
|
||||||
self.api.clone()
|
self.api.clone()
|
||||||
|
@ -756,7 +756,7 @@ impl VeilidConfig {
|
|||||||
let mut out = &jvc;
|
let mut out = &jvc;
|
||||||
for k in keypath {
|
for k in keypath {
|
||||||
if !out.has_key(k) {
|
if !out.has_key(k) {
|
||||||
apibail_parse!(format!("invalid subkey in key '{}'", key), k);
|
apibail_parse_error!(format!("invalid subkey in key '{}'", key), k);
|
||||||
}
|
}
|
||||||
out = &out[k];
|
out = &out[k];
|
||||||
}
|
}
|
||||||
@ -781,12 +781,12 @@ impl VeilidConfig {
|
|||||||
let mut out = &mut jvc;
|
let mut out = &mut jvc;
|
||||||
for k in objkeypath {
|
for k in objkeypath {
|
||||||
if !out.has_key(*k) {
|
if !out.has_key(*k) {
|
||||||
apibail_parse!(format!("invalid subkey in key '{}'", key), k);
|
apibail_parse_error!(format!("invalid subkey in key '{}'", key), k);
|
||||||
}
|
}
|
||||||
out = &mut out[*k];
|
out = &mut out[*k];
|
||||||
}
|
}
|
||||||
if !out.has_key(objkeyname) {
|
if !out.has_key(objkeyname) {
|
||||||
apibail_parse!(format!("invalid subkey in key '{}'", key), objkeyname);
|
apibail_parse_error!(format!("invalid subkey in key '{}'", key), objkeyname);
|
||||||
}
|
}
|
||||||
out[*objkeyname] = newval;
|
out[*objkeyname] = newval;
|
||||||
jvc.to_string()
|
jvc.to_string()
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
//
|
//
|
||||||
// This file really shouldn't be necessary, but 'ip' isn't a stable feature
|
// This file really shouldn't be necessary, but 'ip' isn't a stable feature
|
||||||
// and things may not agree between the no_std_net crate and the stuff in std.
|
|
||||||
//
|
//
|
||||||
|
|
||||||
use crate::xx::*;
|
use crate::xx::*;
|
||||||
|
@ -55,6 +55,9 @@ pub use std::convert::{TryFrom, TryInto};
|
|||||||
pub use std::fmt;
|
pub use std::fmt;
|
||||||
pub use std::future::Future;
|
pub use std::future::Future;
|
||||||
pub use std::mem;
|
pub use std::mem;
|
||||||
|
pub use std::net::{
|
||||||
|
IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
|
||||||
|
};
|
||||||
pub use std::ops::{Fn, FnMut, FnOnce};
|
pub use std::ops::{Fn, FnMut, FnOnce};
|
||||||
pub use std::pin::Pin;
|
pub use std::pin::Pin;
|
||||||
pub use std::rc::Rc;
|
pub use std::rc::Rc;
|
||||||
@ -73,10 +76,7 @@ cfg_if! {
|
|||||||
pub use async_lock::MutexGuard as AsyncMutexGuard;
|
pub use async_lock::MutexGuard as AsyncMutexGuard;
|
||||||
pub use async_lock::MutexGuardArc as AsyncMutexGuardArc;
|
pub use async_lock::MutexGuardArc as AsyncMutexGuardArc;
|
||||||
pub use async_executors::JoinHandle as LowLevelJoinHandle;
|
pub use async_executors::JoinHandle as LowLevelJoinHandle;
|
||||||
|
|
||||||
pub use no_std_net::{ SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, IpAddr, Ipv4Addr, Ipv6Addr };
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature="rt-async-std")] {
|
if #[cfg(feature="rt-async-std")] {
|
||||||
pub use async_std::sync::Mutex as AsyncMutex;
|
pub use async_std::sync::Mutex as AsyncMutex;
|
||||||
@ -92,7 +92,6 @@ cfg_if! {
|
|||||||
#[compile_error("must use an executor")]
|
#[compile_error("must use an executor")]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub use std::net::{ SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, IpAddr, Ipv4Addr, Ipv6Addr };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1696,6 +1696,70 @@ class VeilidVersion {
|
|||||||
VeilidVersion(this.major, this.minor, this.patch);
|
VeilidVersion(this.major, this.minor, this.patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
/// Stability
|
||||||
|
|
||||||
|
enum Stability {
|
||||||
|
lowLatency,
|
||||||
|
reliable,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension StabilityExt on Stability {
|
||||||
|
String get json {
|
||||||
|
return name.toPascalCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stability stabilityFromJson(String j) {
|
||||||
|
return Stability.values.byName(j.toCamelCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
/// Sequencing
|
||||||
|
|
||||||
|
enum Sequencing {
|
||||||
|
noPreference,
|
||||||
|
preferOrdered,
|
||||||
|
ensureOrdered,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SequencingExt on Sequencing {
|
||||||
|
String get json {
|
||||||
|
return name.toPascalCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequencing sequencingFromJson(String j) {
|
||||||
|
return Sequencing.values.byName(j.toCamelCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
/// KeyBlob
|
||||||
|
class KeyBlob {
|
||||||
|
final String key;
|
||||||
|
final Uint8List blob;
|
||||||
|
|
||||||
|
KeyBlob(this.key, this.blob);
|
||||||
|
|
||||||
|
KeyBlob.fromJson(Map<String, dynamic> json)
|
||||||
|
: key = json['key'],
|
||||||
|
blob = base64Decode(json['blob']);
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {'key': key, 'blob': base64UrlEncode(blob)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
/// VeilidRoutingContext
|
||||||
|
abstract class VeilidRoutingContext {
|
||||||
|
VeilidRoutingContext withPrivacy();
|
||||||
|
VeilidRoutingContext withCustomPrivacy(Stability stability);
|
||||||
|
VeilidRoutingContext withSequencing(Sequencing sequencing);
|
||||||
|
Future<Uint8List> appCall(String target, Uint8List request);
|
||||||
|
Future<void> appMessage(String target, Uint8List message);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
/// Veilid singleton factory
|
/// Veilid singleton factory
|
||||||
|
|
||||||
@ -1709,8 +1773,22 @@ abstract class Veilid {
|
|||||||
Future<void> attach();
|
Future<void> attach();
|
||||||
Future<void> detach();
|
Future<void> detach();
|
||||||
Future<void> shutdownVeilidCore();
|
Future<void> shutdownVeilidCore();
|
||||||
Future<String> debug(String command);
|
|
||||||
|
// Routing context
|
||||||
|
Future<VeilidRoutingContext> routingContext();
|
||||||
|
|
||||||
|
// Private route allocation
|
||||||
|
Future<KeyBlob> newPrivateRoute();
|
||||||
|
Future<KeyBlob> newCustomPrivateRoute(
|
||||||
|
Stability stability, Sequencing sequencing);
|
||||||
|
Future<String> importRemotePrivateRoute(Uint8List blob);
|
||||||
|
Future<void> releasePrivateRoute(String key);
|
||||||
|
|
||||||
|
// App calls
|
||||||
Future<void> appCallReply(String id, Uint8List message);
|
Future<void> appCallReply(String id, Uint8List message);
|
||||||
|
|
||||||
|
// Misc
|
||||||
String veilidVersionString();
|
String veilidVersionString();
|
||||||
VeilidVersion veilidVersion();
|
VeilidVersion veilidVersion();
|
||||||
|
Future<String> debug(String command);
|
||||||
}
|
}
|
||||||
|
@ -48,13 +48,56 @@ typedef _AttachDart = void Function(int);
|
|||||||
// fn detach(port: i64)
|
// fn detach(port: i64)
|
||||||
typedef _DetachC = Void Function(Int64);
|
typedef _DetachC = Void Function(Int64);
|
||||||
typedef _DetachDart = void Function(int);
|
typedef _DetachDart = void Function(int);
|
||||||
// fn debug(port: i64, log_level: FfiStr)
|
|
||||||
typedef _DebugC = Void Function(Int64, Pointer<Utf8>);
|
// fn routing_context(port: i64)
|
||||||
typedef _DebugDart = void Function(int, Pointer<Utf8>);
|
typedef _RoutingContextC = Void Function(Int64);
|
||||||
|
typedef _RoutingContextDart = void Function(int);
|
||||||
|
// fn release_routing_context(id: u32)
|
||||||
|
typedef _ReleaseRoutingContextC = Int32 Function(Uint32);
|
||||||
|
typedef _ReleaseRoutingContextDart = int Function(int);
|
||||||
|
// fn routing_context_with_privacy(id: u32) -> u32
|
||||||
|
typedef _RoutingContextWithPrivacyC = Uint32 Function(Uint32);
|
||||||
|
typedef _RoutingContextWithPrivacyDart = int Function(int);
|
||||||
|
// fn routing_context_with_custom_privacy(id: u32, stability: FfiStr)
|
||||||
|
typedef _RoutingContextWithCustomPrivacyC = Uint32 Function(
|
||||||
|
Uint32, Pointer<Utf8>);
|
||||||
|
typedef _RoutingContextWithCustomPrivacyDart = int Function(int, Pointer<Utf8>);
|
||||||
|
// fn routing_context_with_sequencing(id: u32, sequencing: FfiStr)
|
||||||
|
typedef _RoutingContextWithSequencingC = Uint32 Function(Uint32, Pointer<Utf8>);
|
||||||
|
typedef _RoutingContextWithSequencingDart = int Function(int, Pointer<Utf8>);
|
||||||
|
// fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr)
|
||||||
|
typedef _RoutingContextAppCallC = Void Function(
|
||||||
|
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
|
typedef _RoutingContextAppCallDart = void Function(
|
||||||
|
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
|
// fn routing_context_app_message(port: i64, id: u32, target: FfiStr, request: FfiStr)
|
||||||
|
typedef _RoutingContextAppMessageC = Void Function(
|
||||||
|
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
|
typedef _RoutingContextAppMessageDart = void Function(
|
||||||
|
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
|
|
||||||
|
// fn new_private_route(port: i64)
|
||||||
|
typedef _NewPrivateRouteC = Void Function(Int64);
|
||||||
|
typedef _NewPrivateRouteDart = void Function(int);
|
||||||
|
// fn new_custom_private_route(port: i64, stability: FfiStr, sequencing: FfiStr)
|
||||||
|
typedef _NewCustomPrivateRouteC = Void Function(
|
||||||
|
Int64, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
|
typedef _NewCustomPrivateRouteDart = void Function(
|
||||||
|
int, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
|
// fn import_remote_private_route(port: i64, blob: FfiStr)
|
||||||
|
typedef _ImportRemotePrivateRouteC = Void Function(Int64, Pointer<Utf8>);
|
||||||
|
typedef _ImportRemotePrivateRouteDart = void Function(int, Pointer<Utf8>);
|
||||||
|
// fn release_private_route(port:i64, key: FfiStr)
|
||||||
|
typedef _ReleasePrivateRouteC = Void Function(Int64, Pointer<Utf8>);
|
||||||
|
typedef _ReleasePrivateRouteDart = void Function(int, Pointer<Utf8>);
|
||||||
|
|
||||||
// fn app_call_reply(port: i64, id: FfiStr, message: FfiStr)
|
// fn app_call_reply(port: i64, id: FfiStr, message: FfiStr)
|
||||||
typedef _AppCallReplyC = Void Function(Int64, Pointer<Utf8>, Pointer<Utf8>);
|
typedef _AppCallReplyC = Void Function(Int64, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
typedef _AppCallReplyDart = void Function(int, Pointer<Utf8>, Pointer<Utf8>);
|
typedef _AppCallReplyDart = void Function(int, Pointer<Utf8>, Pointer<Utf8>);
|
||||||
|
|
||||||
|
// fn debug(port: i64, log_level: FfiStr)
|
||||||
|
typedef _DebugC = Void Function(Int64, Pointer<Utf8>);
|
||||||
|
typedef _DebugDart = void Function(int, Pointer<Utf8>);
|
||||||
// fn shutdown_veilid_core(port: i64)
|
// fn shutdown_veilid_core(port: i64)
|
||||||
typedef _ShutdownVeilidCoreC = Void Function(Int64);
|
typedef _ShutdownVeilidCoreC = Void Function(Int64);
|
||||||
typedef _ShutdownVeilidCoreDart = void Function(int);
|
typedef _ShutdownVeilidCoreDart = void Function(int);
|
||||||
@ -294,6 +337,58 @@ Stream<T> processStreamJson<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FFI implementation of VeilidRoutingContext
|
||||||
|
class VeilidRoutingContextFFI implements VeilidRoutingContext {
|
||||||
|
final int _id;
|
||||||
|
final VeilidFFI _ffi;
|
||||||
|
|
||||||
|
VeilidRoutingContextFFI._(this._id, this._ffi);
|
||||||
|
@override
|
||||||
|
VeilidRoutingContextFFI withPrivacy() {
|
||||||
|
final newId = _ffi._routingContextWithPrivacy(_id);
|
||||||
|
return VeilidRoutingContextFFI._(newId, _ffi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
VeilidRoutingContextFFI withCustomPrivacy(Stability stability) {
|
||||||
|
final newId = _ffi._routingContextWithCustomPrivacy(
|
||||||
|
_id, stability.json.toNativeUtf8());
|
||||||
|
return VeilidRoutingContextFFI._(newId, _ffi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
VeilidRoutingContextFFI withSequencing(Sequencing sequencing) {
|
||||||
|
final newId =
|
||||||
|
_ffi._routingContextWithSequencing(_id, sequencing.json.toNativeUtf8());
|
||||||
|
return VeilidRoutingContextFFI._(newId, _ffi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Uint8List> appCall(String target, Uint8List request) async {
|
||||||
|
var nativeEncodedTarget = target.toNativeUtf8();
|
||||||
|
var nativeEncodedRequest = base64UrlEncode(request).toNativeUtf8();
|
||||||
|
|
||||||
|
final recvPort = ReceivePort("routing_context_app_call");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_ffi._routingContextAppCall(
|
||||||
|
sendPort.nativePort, _id, nativeEncodedTarget, nativeEncodedRequest);
|
||||||
|
final out = await processFuturePlain(recvPort.first);
|
||||||
|
return base64Decode(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> appMessage(String target, Uint8List message) async {
|
||||||
|
var nativeEncodedTarget = target.toNativeUtf8();
|
||||||
|
var nativeEncodedMessage = base64UrlEncode(message).toNativeUtf8();
|
||||||
|
|
||||||
|
final recvPort = ReceivePort("routing_context_app_call");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_ffi._routingContextAppCall(
|
||||||
|
sendPort.nativePort, _id, nativeEncodedTarget, nativeEncodedMessage);
|
||||||
|
return processFutureVoid(recvPort.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FFI implementation of high level Veilid API
|
// FFI implementation of high level Veilid API
|
||||||
class VeilidFFI implements Veilid {
|
class VeilidFFI implements Veilid {
|
||||||
// veilid_core shared library
|
// veilid_core shared library
|
||||||
@ -308,8 +403,23 @@ class VeilidFFI implements Veilid {
|
|||||||
final _AttachDart _attach;
|
final _AttachDart _attach;
|
||||||
final _DetachDart _detach;
|
final _DetachDart _detach;
|
||||||
final _ShutdownVeilidCoreDart _shutdownVeilidCore;
|
final _ShutdownVeilidCoreDart _shutdownVeilidCore;
|
||||||
final _DebugDart _debug;
|
|
||||||
|
final _RoutingContextDart _routingContext;
|
||||||
|
final _ReleaseRoutingContextDart _releaseRoutingContext;
|
||||||
|
final _RoutingContextWithPrivacyDart _routingContextWithPrivacy;
|
||||||
|
final _RoutingContextWithCustomPrivacyDart _routingContextWithCustomPrivacy;
|
||||||
|
final _RoutingContextWithSequencingDart _routingContextWithSequencing;
|
||||||
|
final _RoutingContextAppCallDart _routingContextAppCall;
|
||||||
|
final _RoutingContextAppMessageDart _routingContextAppMessage;
|
||||||
|
|
||||||
|
final _NewPrivateRouteDart _newPrivateRoute;
|
||||||
|
final _NewCustomPrivateRouteDart _newCustomPrivateRoute;
|
||||||
|
final _ImportRemotePrivateRouteDart _importRemotePrivateRoute;
|
||||||
|
final _ReleasePrivateRouteDart _releasePrivateRoute;
|
||||||
|
|
||||||
final _AppCallReplyDart _appCallReply;
|
final _AppCallReplyDart _appCallReply;
|
||||||
|
|
||||||
|
final _DebugDart _debug;
|
||||||
final _VeilidVersionStringDart _veilidVersionString;
|
final _VeilidVersionStringDart _veilidVersionString;
|
||||||
final _VeilidVersionDart _veilidVersion;
|
final _VeilidVersionDart _veilidVersion;
|
||||||
|
|
||||||
@ -333,9 +443,40 @@ class VeilidFFI implements Veilid {
|
|||||||
_shutdownVeilidCore =
|
_shutdownVeilidCore =
|
||||||
dylib.lookupFunction<_ShutdownVeilidCoreC, _ShutdownVeilidCoreDart>(
|
dylib.lookupFunction<_ShutdownVeilidCoreC, _ShutdownVeilidCoreDart>(
|
||||||
'shutdown_veilid_core'),
|
'shutdown_veilid_core'),
|
||||||
_debug = dylib.lookupFunction<_DebugC, _DebugDart>('debug'),
|
_routingContext =
|
||||||
|
dylib.lookupFunction<_RoutingContextC, _RoutingContextDart>(
|
||||||
|
'routing_context'),
|
||||||
|
_releaseRoutingContext = dylib.lookupFunction<_ReleaseRoutingContextC,
|
||||||
|
_ReleaseRoutingContextDart>('release_routing_context'),
|
||||||
|
_routingContextWithPrivacy = dylib.lookupFunction<
|
||||||
|
_RoutingContextWithPrivacyC,
|
||||||
|
_RoutingContextWithPrivacyDart>('routing_context_with_privacy'),
|
||||||
|
_routingContextWithCustomPrivacy = dylib.lookupFunction<
|
||||||
|
_RoutingContextWithCustomPrivacyC,
|
||||||
|
_RoutingContextWithCustomPrivacyDart>(
|
||||||
|
'routing_context_with_custom_privacy'),
|
||||||
|
_routingContextWithSequencing = dylib.lookupFunction<
|
||||||
|
_RoutingContextWithSequencingC,
|
||||||
|
_RoutingContextWithSequencingDart>(
|
||||||
|
'routing_context_with_sequencing'),
|
||||||
|
_routingContextAppCall = dylib.lookupFunction<_RoutingContextAppCallC,
|
||||||
|
_RoutingContextAppCallDart>('routing_context_app_call'),
|
||||||
|
_routingContextAppMessage = dylib.lookupFunction<
|
||||||
|
_RoutingContextAppMessageC,
|
||||||
|
_RoutingContextAppMessageDart>('routing_context_app_message'),
|
||||||
|
_newPrivateRoute =
|
||||||
|
dylib.lookupFunction<_NewPrivateRouteC, _NewPrivateRouteDart>(
|
||||||
|
'new_private_route'),
|
||||||
|
_newCustomPrivateRoute = dylib.lookupFunction<_NewCustomPrivateRouteC,
|
||||||
|
_NewCustomPrivateRouteDart>('new_custom_private_route'),
|
||||||
|
_importRemotePrivateRoute = dylib.lookupFunction<
|
||||||
|
_ImportRemotePrivateRouteC,
|
||||||
|
_ImportRemotePrivateRouteDart>('import_remote_private_route'),
|
||||||
|
_releasePrivateRoute = dylib.lookupFunction<_ReleasePrivateRouteC,
|
||||||
|
_ReleasePrivateRouteDart>('release_private_route'),
|
||||||
_appCallReply = dylib.lookupFunction<_AppCallReplyC, _AppCallReplyDart>(
|
_appCallReply = dylib.lookupFunction<_AppCallReplyC, _AppCallReplyDart>(
|
||||||
'app_call_reply'),
|
'app_call_reply'),
|
||||||
|
_debug = dylib.lookupFunction<_DebugC, _DebugDart>('debug'),
|
||||||
_veilidVersionString = dylib.lookupFunction<_VeilidVersionStringC,
|
_veilidVersionString = dylib.lookupFunction<_VeilidVersionStringC,
|
||||||
_VeilidVersionStringDart>('veilid_version_string'),
|
_VeilidVersionStringDart>('veilid_version_string'),
|
||||||
_veilidVersion =
|
_veilidVersion =
|
||||||
@ -420,14 +561,53 @@ class VeilidFFI implements Veilid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> debug(String command) async {
|
Future<VeilidRoutingContext> routingContext() async {
|
||||||
var nativeCommand = command.toNativeUtf8();
|
final recvPort = ReceivePort("routing_context");
|
||||||
final recvPort = ReceivePort("debug");
|
|
||||||
final sendPort = recvPort.sendPort;
|
final sendPort = recvPort.sendPort;
|
||||||
_debug(sendPort.nativePort, nativeCommand);
|
_routingContext(sendPort.nativePort);
|
||||||
|
final id = await processFuturePlain(recvPort.first);
|
||||||
|
return VeilidRoutingContextFFI._(id, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<KeyBlob> newPrivateRoute() async {
|
||||||
|
final recvPort = ReceivePort("new_private_route");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_newPrivateRoute(sendPort.nativePort);
|
||||||
|
return processFutureJson(KeyBlob.fromJson, recvPort.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<KeyBlob> newCustomPrivateRoute(
|
||||||
|
Stability stability, Sequencing sequencing) async {
|
||||||
|
final recvPort = ReceivePort("new_custom_private_route");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_newCustomPrivateRoute(sendPort.nativePort, stability.json.toNativeUtf8(),
|
||||||
|
sequencing.json.toNativeUtf8());
|
||||||
|
final keyblob = await processFutureJson(KeyBlob.fromJson, recvPort.first);
|
||||||
|
return keyblob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> importRemotePrivateRoute(Uint8List blob) async {
|
||||||
|
var nativeEncodedBlob = base64UrlEncode(blob).toNativeUtf8();
|
||||||
|
|
||||||
|
final recvPort = ReceivePort("import_remote_private_route");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_importRemotePrivateRoute(sendPort.nativePort, nativeEncodedBlob);
|
||||||
return processFuturePlain(recvPort.first);
|
return processFuturePlain(recvPort.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> releasePrivateRoute(String key) async {
|
||||||
|
var nativeEncodedKey = key.toNativeUtf8();
|
||||||
|
|
||||||
|
final recvPort = ReceivePort("release_private_route");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_releasePrivateRoute(sendPort.nativePort, nativeEncodedKey);
|
||||||
|
return processFutureVoid(recvPort.first);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> appCallReply(String id, Uint8List message) async {
|
Future<void> appCallReply(String id, Uint8List message) async {
|
||||||
var nativeId = id.toNativeUtf8();
|
var nativeId = id.toNativeUtf8();
|
||||||
@ -438,6 +618,15 @@ class VeilidFFI implements Veilid {
|
|||||||
return processFutureVoid(recvPort.first);
|
return processFutureVoid(recvPort.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> debug(String command) async {
|
||||||
|
var nativeCommand = command.toNativeUtf8();
|
||||||
|
final recvPort = ReceivePort("debug");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_debug(sendPort.nativePort, nativeCommand);
|
||||||
|
return processFuturePlain(recvPort.first);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String veilidVersionString() {
|
String veilidVersionString() {
|
||||||
final versionString = _veilidVersionString();
|
final versionString = _veilidVersionString();
|
||||||
|
@ -19,6 +19,61 @@ Future<T> _wrapApiPromise<T>(Object p) {
|
|||||||
VeilidAPIException.fromJson(jsonDecode(error as String))));
|
VeilidAPIException.fromJson(jsonDecode(error as String))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JS implementation of VeilidRoutingContext
|
||||||
|
class VeilidRoutingContextJS implements VeilidRoutingContext {
|
||||||
|
final int _id;
|
||||||
|
final VeilidFFI _ffi;
|
||||||
|
|
||||||
|
VeilidRoutingContextFFI._(this._id, this._ffi);
|
||||||
|
@override
|
||||||
|
VeilidRoutingContextFFI withPrivacy() {
|
||||||
|
final newId = _ffi._routingContextWithPrivacy(_id);
|
||||||
|
return VeilidRoutingContextFFI._(newId, _ffi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
VeilidRoutingContextFFI withCustomPrivacy(Stability stability) {
|
||||||
|
final newId = _ffi._routingContextWithCustomPrivacy(
|
||||||
|
_id, stability.json.toNativeUtf8());
|
||||||
|
return VeilidRoutingContextFFI._(newId, _ffi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
VeilidRoutingContextFFI withSequencing(Sequencing sequencing) {
|
||||||
|
final newId =
|
||||||
|
_ffi._routingContextWithSequencing(_id, sequencing.json.toNativeUtf8());
|
||||||
|
return VeilidRoutingContextFFI._(newId, _ffi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Uint8List> appCall(String target, Uint8List request) async {
|
||||||
|
var nativeEncodedTarget = target.toNativeUtf8();
|
||||||
|
var nativeEncodedRequest = base64UrlEncode(request).toNativeUtf8();
|
||||||
|
|
||||||
|
final recvPort = ReceivePort("routing_context_app_call");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_ffi._routingContextAppCall(
|
||||||
|
sendPort.nativePort, _id, nativeEncodedTarget, nativeEncodedRequest);
|
||||||
|
final out = await processFuturePlain(recvPort.first);
|
||||||
|
return base64Decode(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> appMessage(String target, Uint8List message) async {
|
||||||
|
var nativeEncodedTarget = target.toNativeUtf8();
|
||||||
|
var nativeEncodedMessage = base64UrlEncode(message).toNativeUtf8();
|
||||||
|
|
||||||
|
final recvPort = ReceivePort("routing_context_app_call");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_ffi._routingContextAppCall(
|
||||||
|
sendPort.nativePort, _id, nativeEncodedTarget, nativeEncodedMessage);
|
||||||
|
return processFutureVoid(recvPort.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// JS implementation of high level Veilid API
|
||||||
|
|
||||||
class VeilidJS implements Veilid {
|
class VeilidJS implements Veilid {
|
||||||
@override
|
@override
|
||||||
void initializeVeilidCore(Map<String, dynamic> platformConfigJson) {
|
void initializeVeilidCore(Map<String, dynamic> platformConfigJson) {
|
||||||
@ -78,9 +133,43 @@ class VeilidJS implements Veilid {
|
|||||||
js_util.callMethod(wasm, "shutdown_veilid_core", []));
|
js_util.callMethod(wasm, "shutdown_veilid_core", []));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> debug(String command) {
|
Future<VeilidRoutingContext> routingContext() async {
|
||||||
return _wrapApiPromise(js_util.callMethod(wasm, "debug", [command]));
|
final recvPort = ReceivePort("routing_context");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_routingContext(sendPort.nativePort);
|
||||||
|
final id = await processFuturePlain(recvPort.first);
|
||||||
|
return VeilidRoutingContextFFI._(id, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<KeyBlob> newPrivateRoute() async {
|
||||||
|
final recvPort = ReceivePort("new_private_route");
|
||||||
|
final sendPort = recvPort.sendPort;
|
||||||
|
_newPrivateRoute(sendPort.nativePort);
|
||||||
|
return processFutureJson(KeyBlob.fromJson, recvPort.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<KeyBlob> newCustomPrivateRoute(
|
||||||
|
Stability stability, Sequencing sequencing) async {
|
||||||
|
return _wrapApiPromise(
|
||||||
|
js_util.callMethod(wasm, "new_custom_private_route", [stability, sequencing]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> importRemotePrivateRoute(Uint8List blob) async {
|
||||||
|
var encodedBlob = base64UrlEncode(blob);
|
||||||
|
return _wrapApiPromise(
|
||||||
|
js_util.callMethod(wasm, "import_remote_private_route", [encodedBlob]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> releasePrivateRoute(String key) async {
|
||||||
|
return _wrapApiPromise(
|
||||||
|
js_util.callMethod(wasm, "release_private_route", [key]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -90,6 +179,11 @@ class VeilidJS implements Veilid {
|
|||||||
js_util.callMethod(wasm, "app_call_reply", [id, encodedMessage]));
|
js_util.callMethod(wasm, "app_call_reply", [id, encodedMessage]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> debug(String command) {
|
||||||
|
return _wrapApiPromise(js_util.callMethod(wasm, "debug", [command]));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String veilidVersionString() {
|
String veilidVersionString() {
|
||||||
return js_util.callMethod(wasm, "veilid_version_string", []);
|
return js_util.callMethod(wasm, "veilid_version_string", []);
|
||||||
|
@ -21,6 +21,8 @@ lazy_static! {
|
|||||||
static ref VEILID_API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
|
static ref VEILID_API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
|
||||||
static ref FILTERS: Mutex<BTreeMap<&'static str, veilid_core::VeilidLayerFilter>> =
|
static ref FILTERS: Mutex<BTreeMap<&'static str, veilid_core::VeilidLayerFilter>> =
|
||||||
Mutex::new(BTreeMap::new());
|
Mutex::new(BTreeMap::new());
|
||||||
|
static ref ROUTING_CONTEXTS: Mutex<BTreeMap<u32, veilid_core::RoutingContext>> =
|
||||||
|
Mutex::new(BTreeMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||||
@ -49,7 +51,7 @@ type APIResult<T> = Result<T, veilid_core::VeilidAPIError>;
|
|||||||
const APIRESULT_VOID: APIResult<()> = APIResult::Ok(());
|
const APIRESULT_VOID: APIResult<()> = APIResult::Ok(());
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
// FFI-specific cofnig
|
// FFI-specific
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct VeilidFFIConfigLoggingTerminal {
|
pub struct VeilidFFIConfigLoggingTerminal {
|
||||||
@ -83,6 +85,13 @@ pub struct VeilidFFIConfig {
|
|||||||
pub logging: VeilidFFIConfigLogging,
|
pub logging: VeilidFFIConfigLogging,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct VeilidFFIKeyBlob {
|
||||||
|
pub key: veilid_core::DHTKey,
|
||||||
|
#[serde(with = "veilid_core::json_as_base64")]
|
||||||
|
pub blob: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
// Initializer
|
// Initializer
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -317,13 +326,208 @@ pub extern "C" fn shutdown_veilid_core(port: i64) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_routing_context(routing_context: veilid_core::RoutingContext) -> u32 {
|
||||||
|
let mut next_id: u32 = 1;
|
||||||
|
let mut rc = ROUTING_CONTEXTS.lock();
|
||||||
|
while rc.contains_key(&next_id) {
|
||||||
|
next_id += 1;
|
||||||
|
}
|
||||||
|
rc.insert(next_id, routing_context);
|
||||||
|
next_id
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn debug(port: i64, command: FfiStr) {
|
pub extern "C" fn routing_context(port: i64) {
|
||||||
let command = command.into_opt_string().unwrap_or_default();
|
|
||||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||||
let veilid_api = get_veilid_api().await?;
|
let veilid_api = get_veilid_api().await?;
|
||||||
let out = veilid_api.debug(command).await?;
|
let routing_context = veilid_api.routing_context();
|
||||||
APIResult::Ok(out)
|
let new_id = add_routing_context(routing_context);
|
||||||
|
APIResult::Ok(new_id)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn release_routing_context(id: u32) -> i32 {
|
||||||
|
let mut rc = ROUTING_CONTEXTS.lock();
|
||||||
|
if rc.remove(&id).is_none() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn routing_context_with_privacy(id: u32) -> u32 {
|
||||||
|
let rc = ROUTING_CONTEXTS.lock();
|
||||||
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
let Ok(routing_context) = routing_context.clone().with_privacy() else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
let new_id = add_routing_context(routing_context);
|
||||||
|
new_id
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn routing_context_with_custom_privacy(id: u32, stability: FfiStr) -> u32 {
|
||||||
|
let stability: veilid_core::Stability =
|
||||||
|
veilid_core::deserialize_opt_json(stability.into_opt_string()).unwrap();
|
||||||
|
|
||||||
|
let rc = ROUTING_CONTEXTS.lock();
|
||||||
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
let Ok(routing_context) = routing_context.clone().with_custom_privacy(stability) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
let new_id = add_routing_context(routing_context);
|
||||||
|
new_id
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn routing_context_with_sequencing(id: u32, sequencing: FfiStr) -> u32 {
|
||||||
|
let sequencing: veilid_core::Sequencing =
|
||||||
|
veilid_core::deserialize_opt_json(sequencing.into_opt_string()).unwrap();
|
||||||
|
|
||||||
|
let rc = ROUTING_CONTEXTS.lock();
|
||||||
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
let routing_context = routing_context.clone().with_sequencing(sequencing);
|
||||||
|
let new_id = add_routing_context(routing_context);
|
||||||
|
new_id
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) {
|
||||||
|
let target: veilid_core::DHTKey =
|
||||||
|
veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap();
|
||||||
|
let request: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(
|
||||||
|
veilid_core::deserialize_opt_json::<String>(request.into_opt_string())
|
||||||
|
.unwrap()
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
let routing_table = veilid_api.routing_table()?;
|
||||||
|
let rss = routing_table.route_spec_store();
|
||||||
|
|
||||||
|
let routing_context = {
|
||||||
|
let rc = ROUTING_CONTEXTS.lock();
|
||||||
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
|
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_app_call", "id", id));
|
||||||
|
};
|
||||||
|
routing_context.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let target = if rss.get_remote_private_route(&target).is_some() {
|
||||||
|
veilid_core::Target::PrivateRoute(target)
|
||||||
|
} else {
|
||||||
|
veilid_core::Target::NodeId(veilid_core::NodeId::new(target))
|
||||||
|
};
|
||||||
|
|
||||||
|
let answer = routing_context.app_call(target, request).await?;
|
||||||
|
let answer = data_encoding::BASE64URL_NOPAD.encode(&answer);
|
||||||
|
APIResult::Ok(answer)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr, message: FfiStr) {
|
||||||
|
let target: veilid_core::DHTKey =
|
||||||
|
veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap();
|
||||||
|
let message: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(
|
||||||
|
veilid_core::deserialize_opt_json::<String>(message.into_opt_string())
|
||||||
|
.unwrap()
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
let routing_table = veilid_api.routing_table()?;
|
||||||
|
let rss = routing_table.route_spec_store();
|
||||||
|
|
||||||
|
let routing_context = {
|
||||||
|
let rc = ROUTING_CONTEXTS.lock();
|
||||||
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
|
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_app_call", "id", id));
|
||||||
|
};
|
||||||
|
routing_context.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let target = if rss.get_remote_private_route(&target).is_some() {
|
||||||
|
veilid_core::Target::PrivateRoute(target)
|
||||||
|
} else {
|
||||||
|
veilid_core::Target::NodeId(veilid_core::NodeId::new(target))
|
||||||
|
};
|
||||||
|
|
||||||
|
routing_context.app_message(target, message).await?;
|
||||||
|
APIRESULT_VOID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn new_private_route(port: i64) {
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
|
||||||
|
let (key, blob) = veilid_api.new_private_route().await?;
|
||||||
|
|
||||||
|
let keyblob = VeilidFFIKeyBlob { key, blob };
|
||||||
|
|
||||||
|
APIResult::Ok(keyblob)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn new_custom_private_route(port: i64, stability: FfiStr, sequencing: FfiStr) {
|
||||||
|
let stability: veilid_core::Stability =
|
||||||
|
veilid_core::deserialize_opt_json(stability.into_opt_string()).unwrap();
|
||||||
|
let sequencing: veilid_core::Sequencing =
|
||||||
|
veilid_core::deserialize_opt_json(sequencing.into_opt_string()).unwrap();
|
||||||
|
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
|
||||||
|
let (key, blob) = veilid_api
|
||||||
|
.new_custom_private_route(stability, sequencing)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let keyblob = VeilidFFIKeyBlob { key, blob };
|
||||||
|
|
||||||
|
APIResult::Ok(keyblob)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn import_remote_private_route(port: i64, blob: FfiStr) {
|
||||||
|
let blob: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
|
.decode(
|
||||||
|
veilid_core::deserialize_opt_json::<String>(blob.into_opt_string())
|
||||||
|
.unwrap()
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
|
||||||
|
let key = veilid_api.import_remote_private_route(blob)?;
|
||||||
|
|
||||||
|
APIResult::Ok(key.encode())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn release_private_route(port: i64, key: FfiStr) {
|
||||||
|
let key: veilid_core::DHTKey =
|
||||||
|
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||||
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
veilid_api.release_private_route(&key)?;
|
||||||
|
APIRESULT_VOID
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +551,16 @@ pub extern "C" fn app_call_reply(port: i64, id: FfiStr, message: FfiStr) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn debug(port: i64, command: FfiStr) {
|
||||||
|
let command = command.into_opt_string().unwrap_or_default();
|
||||||
|
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
let out = veilid_api.debug(command).await?;
|
||||||
|
APIResult::Ok(out)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn veilid_version_string() -> *mut c_char {
|
pub extern "C" fn veilid_version_string() -> *mut c_char {
|
||||||
veilid_core::veilid_version_string().into_ffi_value()
|
veilid_core::veilid_version_string().into_ffi_value()
|
||||||
|
@ -39,6 +39,8 @@ lazy_static! {
|
|||||||
SendWrapper::new(RefCell::new(None));
|
SendWrapper::new(RefCell::new(None));
|
||||||
static ref FILTERS: SendWrapper<RefCell<BTreeMap<&'static str, veilid_core::VeilidLayerFilter>>> =
|
static ref FILTERS: SendWrapper<RefCell<BTreeMap<&'static str, veilid_core::VeilidLayerFilter>>> =
|
||||||
SendWrapper::new(RefCell::new(BTreeMap::new()));
|
SendWrapper::new(RefCell::new(BTreeMap::new()));
|
||||||
|
static ref ROUTING_CONTEXTS: SendWrapper<RefCell<BTreeMap<u32, veilid_core::RoutingContext>>> =
|
||||||
|
SendWrapper::new(RefCell::new(BTreeMap::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||||
@ -54,20 +56,7 @@ fn take_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIErr
|
|||||||
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON Marshalling
|
// JSON Helpers for WASM
|
||||||
pub fn serialize_json<T: Serialize>(val: T) -> String {
|
|
||||||
serde_json::to_string(&val).expect("failed to serialize json value")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_json<T: de::DeserializeOwned>(
|
|
||||||
arg: &str,
|
|
||||||
) -> Result<T, veilid_core::VeilidAPIError> {
|
|
||||||
serde_json::from_str(arg).map_err(|e| veilid_core::VeilidAPIError::ParseError {
|
|
||||||
message: e.to_string(),
|
|
||||||
value: String::new(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_json<T: Serialize>(val: T) -> JsValue {
|
pub fn to_json<T: Serialize>(val: T) -> JsValue {
|
||||||
JsValue::from_str(&serialize_json(val))
|
JsValue::from_str(&serialize_json(val))
|
||||||
}
|
}
|
||||||
@ -104,7 +93,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
// WASM-specific cofnig
|
// WASM-specific
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct VeilidWASMConfigLoggingPerformance {
|
pub struct VeilidWASMConfigLoggingPerformance {
|
||||||
@ -131,6 +120,13 @@ pub struct VeilidWASMConfig {
|
|||||||
pub logging: VeilidWASMConfigLogging,
|
pub logging: VeilidWASMConfigLogging,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct VeilidFFIKeyBlob {
|
||||||
|
pub key: veilid_core::DHTKey,
|
||||||
|
#[serde(with = "veilid_core::json_as_base64")]
|
||||||
|
pub blob: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
// WASM Bindings
|
// WASM Bindings
|
||||||
|
|
||||||
#[wasm_bindgen()]
|
#[wasm_bindgen()]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user