mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
safety by default
This commit is contained in:
parent
88389a1b78
commit
ee375ad430
@ -372,18 +372,18 @@ impl ConnectionManager {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Callbacks
|
||||
/// Asynchronous Event Processor
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
async fn async_processor(
|
||||
self,
|
||||
stop_token: StopToken,
|
||||
receiver: flume::Receiver<ConnectionManagerEvent>,
|
||||
async fn process_connection_manager_event(
|
||||
&self,
|
||||
event: ConnectionManagerEvent,
|
||||
allow_accept: bool,
|
||||
) {
|
||||
// Process async commands
|
||||
while let Ok(Ok(event)) = receiver.recv_async().timeout_at(stop_token.clone()).await {
|
||||
match event {
|
||||
ConnectionManagerEvent::Accepted(prot_conn) => {
|
||||
if !allow_accept {
|
||||
return;
|
||||
}
|
||||
// Async lock on the remote address for atomicity per remote
|
||||
let _lock_guard = self
|
||||
.arc
|
||||
@ -417,6 +417,21 @@ impl ConnectionManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
async fn async_processor(
|
||||
self,
|
||||
stop_token: StopToken,
|
||||
receiver: flume::Receiver<ConnectionManagerEvent>,
|
||||
) {
|
||||
// Process async commands
|
||||
while let Ok(Ok(event)) = receiver.recv_async().timeout_at(stop_token.clone()).await {
|
||||
self.process_connection_manager_event(event, true).await;
|
||||
}
|
||||
// Ensure receiver is drained completely
|
||||
for event in receiver.drain() {
|
||||
self.process_connection_manager_event(event, false).await;
|
||||
}
|
||||
}
|
||||
|
||||
// Called by low-level network when any connection-oriented protocol connection appears
|
||||
|
@ -11,35 +11,55 @@ lazy_static! {
|
||||
}
|
||||
|
||||
pub async fn test_get_dht_value_unopened(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let result = rc.get_dht_value(*BOGUS_KEY, 0, false).await;
|
||||
assert_err!(result);
|
||||
}
|
||||
|
||||
pub async fn test_open_dht_record_nonexistent_no_writer(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let result = rc.get_dht_value(*BOGUS_KEY, 0, false).await;
|
||||
assert_err!(result);
|
||||
}
|
||||
|
||||
pub async fn test_close_dht_record_nonexistent(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let result = rc.close_dht_record(*BOGUS_KEY).await;
|
||||
assert_err!(result);
|
||||
}
|
||||
|
||||
pub async fn test_delete_dht_record_nonexistent(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let result = rc.delete_dht_record(*BOGUS_KEY).await;
|
||||
assert_err!(result);
|
||||
}
|
||||
|
||||
pub async fn test_create_delete_dht_record_simple(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let rec = rc
|
||||
.create_dht_record(
|
||||
@ -55,7 +75,11 @@ pub async fn test_create_delete_dht_record_simple(api: VeilidAPI) {
|
||||
}
|
||||
|
||||
pub async fn test_get_dht_value_nonexistent(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let rec = rc
|
||||
.create_dht_record(
|
||||
@ -73,7 +97,11 @@ pub async fn test_get_dht_value_nonexistent(api: VeilidAPI) {
|
||||
}
|
||||
|
||||
pub async fn test_set_get_dht_value(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let rec = rc
|
||||
.create_dht_record(
|
||||
@ -124,7 +152,11 @@ pub async fn test_set_get_dht_value(api: VeilidAPI) {
|
||||
}
|
||||
|
||||
pub async fn test_open_writer_dht_value(api: VeilidAPI) {
|
||||
let rc = api.routing_context();
|
||||
let rc = api
|
||||
.routing_context()
|
||||
.unwrap()
|
||||
.with_safety(SafetySelection::Unsafe(Sequencing::EnsureOrdered))
|
||||
.unwrap();
|
||||
|
||||
let rec = rc
|
||||
.create_dht_record(
|
||||
|
@ -189,8 +189,8 @@ impl VeilidAPI {
|
||||
// Routing Context
|
||||
|
||||
/// Get a new `RoutingContext` object to use to send messages over the Veilid network.
|
||||
pub fn routing_context(&self) -> RoutingContext {
|
||||
RoutingContext::new(self.clone())
|
||||
pub fn routing_context(&self) -> VeilidAPIResult<RoutingContext> {
|
||||
RoutingContext::try_new(self.clone())
|
||||
}
|
||||
|
||||
/// Parse a string into a target object that can be used in a [RoutingContext]
|
||||
|
@ -1394,10 +1394,10 @@ impl VeilidAPI {
|
||||
)
|
||||
.ok();
|
||||
|
||||
// Get routing context with optional privacy
|
||||
let rc = self.routing_context();
|
||||
// Get routing context with optional safety
|
||||
let rc = self.routing_context()?;
|
||||
let rc = if let Some(ss) = ss {
|
||||
match rc.with_custom_privacy(ss) {
|
||||
match rc.with_safety(ss) {
|
||||
Err(e) => return Ok(format!("Can't use safety selection: {}", e)),
|
||||
Ok(v) => v,
|
||||
}
|
||||
@ -1453,9 +1453,9 @@ impl VeilidAPI {
|
||||
};
|
||||
|
||||
// Get routing context with optional privacy
|
||||
let rc = self.routing_context();
|
||||
let rc = self.routing_context()?;
|
||||
let rc = if let Some(ss) = ss {
|
||||
match rc.with_custom_privacy(ss) {
|
||||
match rc.with_safety(ss) {
|
||||
Err(e) => return Ok(format!("Can't use safety selection: {}", e)),
|
||||
Ok(v) => v,
|
||||
}
|
||||
@ -1514,9 +1514,9 @@ impl VeilidAPI {
|
||||
let data = get_debug_argument_at(&args, 4, "debug_record_set", "data", get_data)?;
|
||||
|
||||
// Get routing context with optional privacy
|
||||
let rc = self.routing_context();
|
||||
let rc = self.routing_context()?;
|
||||
let rc = if let Some(ss) = ss {
|
||||
match rc.with_custom_privacy(ss) {
|
||||
match rc.with_safety(ss) {
|
||||
Err(e) => return Ok(format!("Can't use safety selection: {}", e)),
|
||||
Ok(v) => v,
|
||||
}
|
||||
@ -1560,7 +1560,7 @@ impl VeilidAPI {
|
||||
let key = get_debug_argument_at(&args, 1, "debug_record_delete", "key", get_typed_key)?;
|
||||
|
||||
// Do a record delete
|
||||
let rc = self.routing_context();
|
||||
let rc = self.routing_context()?;
|
||||
match rc.delete_dht_record(key).await {
|
||||
Err(e) => return Ok(format!("Can't delete DHT record: {}", e)),
|
||||
Ok(v) => v,
|
||||
|
@ -173,7 +173,8 @@ pub enum ResponseOp {
|
||||
},
|
||||
// Routing Context
|
||||
NewRoutingContext {
|
||||
value: u32,
|
||||
#[serde(flatten)]
|
||||
result: ApiResult<u32>,
|
||||
},
|
||||
RoutingContext(Box<RoutingContextResponse>),
|
||||
// TableDb
|
||||
|
@ -235,20 +235,22 @@ impl JsonRequestProcessor {
|
||||
self.release_routing_context(rcr.rc_id);
|
||||
RoutingContextResponseOp::Release {}
|
||||
}
|
||||
RoutingContextRequestOp::WithPrivacy => RoutingContextResponseOp::WithPrivacy {
|
||||
RoutingContextRequestOp::WithDefaultSafety => {
|
||||
RoutingContextResponseOp::WithDefaultSafety {
|
||||
result: to_json_api_result(
|
||||
routing_context
|
||||
.clone()
|
||||
.with_privacy()
|
||||
.with_default_safety()
|
||||
.map(|new_rc| self.add_routing_context(new_rc)),
|
||||
),
|
||||
},
|
||||
RoutingContextRequestOp::WithCustomPrivacy { safety_selection } => {
|
||||
RoutingContextResponseOp::WithCustomPrivacy {
|
||||
}
|
||||
}
|
||||
RoutingContextRequestOp::WithSafety { safety_selection } => {
|
||||
RoutingContextResponseOp::WithSafety {
|
||||
result: to_json_api_result(
|
||||
routing_context
|
||||
.clone()
|
||||
.with_custom_privacy(safety_selection)
|
||||
.with_safety(safety_selection)
|
||||
.map(|new_rc| self.add_routing_context(new_rc)),
|
||||
),
|
||||
}
|
||||
@ -259,6 +261,9 @@ impl JsonRequestProcessor {
|
||||
.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(
|
||||
@ -597,7 +602,11 @@ impl JsonRequestProcessor {
|
||||
result: to_json_api_result(self.api.app_call_reply(call_id, message).await),
|
||||
},
|
||||
RequestOp::NewRoutingContext => ResponseOp::NewRoutingContext {
|
||||
value: self.add_routing_context(self.api.routing_context()),
|
||||
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) {
|
||||
|
@ -18,13 +18,14 @@ pub struct RoutingContextResponse {
|
||||
#[serde(tag = "rc_op")]
|
||||
pub enum RoutingContextRequestOp {
|
||||
Release,
|
||||
WithPrivacy,
|
||||
WithCustomPrivacy {
|
||||
WithDefaultSafety,
|
||||
WithSafety {
|
||||
safety_selection: SafetySelection,
|
||||
},
|
||||
WithSequencing {
|
||||
sequencing: Sequencing,
|
||||
},
|
||||
Safety,
|
||||
AppCall {
|
||||
target: String,
|
||||
#[serde(with = "as_human_base64")]
|
||||
@ -88,17 +89,20 @@ pub enum RoutingContextRequestOp {
|
||||
pub enum RoutingContextResponseOp {
|
||||
InvalidId,
|
||||
Release,
|
||||
WithPrivacy {
|
||||
WithDefaultSafety {
|
||||
#[serde(flatten)]
|
||||
result: ApiResult<u32>,
|
||||
},
|
||||
WithCustomPrivacy {
|
||||
WithSafety {
|
||||
#[serde(flatten)]
|
||||
result: ApiResult<u32>,
|
||||
},
|
||||
WithSequencing {
|
||||
value: u32,
|
||||
},
|
||||
Safety {
|
||||
value: SafetySelection,
|
||||
},
|
||||
AppCall {
|
||||
#[serde(flatten)]
|
||||
#[schemars(with = "ApiResult<String>")]
|
||||
|
@ -21,9 +21,9 @@ pub struct RoutingContextUnlockedInner {
|
||||
|
||||
/// Routing contexts are the way you specify the communication preferences for Veilid.
|
||||
///
|
||||
/// By default routing contexts are 'direct' from node to node, offering no privacy. To enable sender
|
||||
/// privacy, use [RoutingContext::with_privacy()]. To enable receiver privacy, you should send to a private route RouteId that you have
|
||||
/// imported, rather than directly to a NodeId.
|
||||
/// By default routing contexts have 'safety routing' enabled which offers sender privacy.
|
||||
/// privacy. To disable this and send RPC operations straight from the node use [RoutingContext::with_safety()] with a [SafetySelection::Unsafe] parameter.
|
||||
/// To enable receiver privacy, you should send to a private route RouteId that you have imported, rather than directly to a NodeId.
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub struct RoutingContext {
|
||||
@ -36,17 +36,26 @@ pub struct RoutingContext {
|
||||
impl RoutingContext {
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
pub(super) fn new(api: VeilidAPI) -> Self {
|
||||
Self {
|
||||
pub(super) fn try_new(api: VeilidAPI) -> VeilidAPIResult<Self> {
|
||||
let config = api.config()?;
|
||||
let c = config.get();
|
||||
|
||||
Ok(Self {
|
||||
api,
|
||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
||||
safety_selection: SafetySelection::Unsafe(Sequencing::default()),
|
||||
safety_selection: SafetySelection::Safe(SafetySpec {
|
||||
preferred_route: None,
|
||||
hop_count: c.network.rpc.default_route_hop_count as usize,
|
||||
stability: Stability::default(),
|
||||
sequencing: Sequencing::default(),
|
||||
}),
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
/// Turn on sender privacy, enabling the use of safety routes.
|
||||
/// Turn on sender privacy, enabling the use of safety routes. This is the default and
|
||||
/// calling this function is only necessary if you have previously disable safety or used other parameters.
|
||||
///
|
||||
/// Default values for hop count, stability and sequencing preferences are used.
|
||||
///
|
||||
@ -54,12 +63,12 @@ impl RoutingContext {
|
||||
/// * Stability default is to choose 'low latency' routes, preferring them over long-term reliability.
|
||||
/// * Sequencing default is to have no preference for ordered vs unordered message delivery
|
||||
///
|
||||
/// To modify these defaults, use [RoutingContext::with_custom_privacy()].
|
||||
pub fn with_privacy(self) -> VeilidAPIResult<Self> {
|
||||
/// To customize the safety selection in use, use [RoutingContext::with_safety()].
|
||||
pub fn with_default_safety(self) -> VeilidAPIResult<Self> {
|
||||
let config = self.api.config()?;
|
||||
let c = config.get();
|
||||
|
||||
self.with_custom_privacy(SafetySelection::Safe(SafetySpec {
|
||||
self.with_safety(SafetySelection::Safe(SafetySpec {
|
||||
preferred_route: None,
|
||||
hop_count: c.network.rpc.default_route_hop_count as usize,
|
||||
stability: Stability::default(),
|
||||
@ -67,8 +76,8 @@ impl RoutingContext {
|
||||
}))
|
||||
}
|
||||
|
||||
/// Turn on privacy using a custom [SafetySelection]
|
||||
pub fn with_custom_privacy(self, safety_selection: SafetySelection) -> VeilidAPIResult<Self> {
|
||||
/// Use a custom [SafetySelection]. Can be used to disable safety via [SafetySelection::Unsafe]
|
||||
pub fn with_safety(self, safety_selection: SafetySelection) -> VeilidAPIResult<Self> {
|
||||
Ok(Self {
|
||||
api: self.api.clone(),
|
||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||
@ -95,6 +104,11 @@ impl RoutingContext {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the safety selection in use on this routing context
|
||||
pub fn safety(&self) -> SafetySelection {
|
||||
self.unlocked_inner.safety_selection
|
||||
}
|
||||
|
||||
fn sequencing(&self) -> Sequencing {
|
||||
match self.unlocked_inner.safety_selection {
|
||||
SafetySelection::Unsafe(sequencing) => sequencing,
|
||||
|
@ -37,7 +37,12 @@ impl Default for Stability {
|
||||
#[derive(
|
||||
Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
|
||||
)]
|
||||
#[cfg_attr(target_arch = "wasm32", derive(Tsify), tsify(from_wasm_abi, namespace))]
|
||||
#[cfg_attr(
|
||||
target_arch = "wasm32",
|
||||
derive(Tsify),
|
||||
tsify(from_wasm_abi, into_wasm_abi, namespace)
|
||||
)]
|
||||
|
||||
pub enum SafetySelection {
|
||||
/// Don't use a safety route, only specify the sequencing preference
|
||||
Unsafe(Sequencing),
|
||||
|
@ -239,9 +239,10 @@ abstract class VeilidRoutingContext {
|
||||
void close();
|
||||
|
||||
// Modifiers
|
||||
VeilidRoutingContext withPrivacy();
|
||||
VeilidRoutingContext withCustomPrivacy(SafetySelection safetySelection);
|
||||
VeilidRoutingContext withDefaultSafety();
|
||||
VeilidRoutingContext withSafety(SafetySelection safetySelection);
|
||||
VeilidRoutingContext withSequencing(Sequencing sequencing);
|
||||
Future<SafetySelection> safety();
|
||||
|
||||
// App call/message
|
||||
Future<Uint8List> appCall(String target, Uint8List request);
|
||||
|
@ -45,12 +45,15 @@ typedef _DetachDart = void Function(int);
|
||||
typedef _RoutingContextDart = void Function(int);
|
||||
// fn release_routing_context(id: u32)
|
||||
typedef _ReleaseRoutingContextDart = int Function(int);
|
||||
// fn routing_context_with_privacy(id: u32) -> u32
|
||||
typedef _RoutingContextWithPrivacyDart = int Function(int);
|
||||
// fn routing_context_with_custom_privacy(id: u32, stability: FfiStr)
|
||||
typedef _RoutingContextWithCustomPrivacyDart = int Function(int, Pointer<Utf8>);
|
||||
// fn routing_context_with_default_safety(id: u32) -> u32
|
||||
typedef _RoutingContextWithDefaultSafetyDart = int Function(int);
|
||||
// fn routing_context_with_safety(id: u32, stability: FfiStr)
|
||||
typedef _RoutingContextWithSafetyDart = int Function(int, Pointer<Utf8>);
|
||||
// fn routing_context_with_sequencing(id: u32, sequencing: FfiStr)
|
||||
typedef _RoutingContextWithSequencingDart = int Function(int, Pointer<Utf8>);
|
||||
// fn routing_context_safety(port: i64,
|
||||
// id: u32)
|
||||
typedef _RoutingContextSafetyDart = void Function(int, int);
|
||||
// fn routing_context_app_call(port: i64,
|
||||
// id: u32, target: FfiStr, request: FfiStr)
|
||||
typedef _RoutingContextAppCallDart = void Function(
|
||||
@ -525,16 +528,16 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext {
|
||||
}
|
||||
|
||||
@override
|
||||
VeilidRoutingContextFFI withPrivacy() {
|
||||
VeilidRoutingContextFFI withDefaultSafety() {
|
||||
_ctx.ensureValid();
|
||||
final newId = _ctx.ffi._routingContextWithPrivacy(_ctx.id!);
|
||||
final newId = _ctx.ffi._routingContextWithDefaultSafety(_ctx.id!);
|
||||
return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi));
|
||||
}
|
||||
|
||||
@override
|
||||
VeilidRoutingContextFFI withCustomPrivacy(SafetySelection safetySelection) {
|
||||
VeilidRoutingContextFFI withSafety(SafetySelection safetySelection) {
|
||||
_ctx.ensureValid();
|
||||
final newId = _ctx.ffi._routingContextWithCustomPrivacy(
|
||||
final newId = _ctx.ffi._routingContextWithSafety(
|
||||
_ctx.id!, jsonEncode(safetySelection).toNativeUtf8());
|
||||
return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi));
|
||||
}
|
||||
@ -547,6 +550,17 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext {
|
||||
return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SafetySelection> safety() async {
|
||||
_ctx.ensureValid();
|
||||
final recvPort = ReceivePort('routing_context_safety');
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextSafety(sendPort.nativePort, _ctx.id!);
|
||||
final out = await processFutureJson<SafetySelection>(
|
||||
SafetySelection.fromJson, recvPort.first);
|
||||
return out;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> appCall(String target, Uint8List request) async {
|
||||
_ctx.ensureValid();
|
||||
@ -1175,17 +1189,20 @@ class VeilidFFI extends Veilid {
|
||||
'routing_context'),
|
||||
_releaseRoutingContext = dylib.lookupFunction<Int32 Function(Uint32),
|
||||
_ReleaseRoutingContextDart>('release_routing_context'),
|
||||
_routingContextWithPrivacy = dylib.lookupFunction<
|
||||
Uint32 Function(Uint32),
|
||||
_RoutingContextWithPrivacyDart>('routing_context_with_privacy'),
|
||||
_routingContextWithCustomPrivacy = dylib.lookupFunction<
|
||||
_routingContextWithDefaultSafety = dylib.lookupFunction<
|
||||
Uint32 Function(Uint32), _RoutingContextWithDefaultSafetyDart>(
|
||||
'routing_context_with_default_safety'),
|
||||
_routingContextWithSafety = dylib.lookupFunction<
|
||||
Uint32 Function(Uint32, Pointer<Utf8>),
|
||||
_RoutingContextWithCustomPrivacyDart>(
|
||||
_RoutingContextWithSafetyDart>(
|
||||
'routing_context_with_custom_privacy'),
|
||||
_routingContextWithSequencing = dylib.lookupFunction<
|
||||
Uint32 Function(Uint32, Pointer<Utf8>),
|
||||
_RoutingContextWithSequencingDart>(
|
||||
'routing_context_with_sequencing'),
|
||||
_routingContextSafety = dylib.lookupFunction<
|
||||
Void Function(Int64, Uint32),
|
||||
_RoutingContextSafetyDart>('routing_context_safety'),
|
||||
_routingContextAppCall = dylib.lookupFunction<
|
||||
Void Function(Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>),
|
||||
_RoutingContextAppCallDart>('routing_context_app_call'),
|
||||
@ -1383,9 +1400,10 @@ class VeilidFFI extends Veilid {
|
||||
|
||||
final _RoutingContextDart _routingContext;
|
||||
final _ReleaseRoutingContextDart _releaseRoutingContext;
|
||||
final _RoutingContextWithPrivacyDart _routingContextWithPrivacy;
|
||||
final _RoutingContextWithCustomPrivacyDart _routingContextWithCustomPrivacy;
|
||||
final _RoutingContextWithDefaultSafetyDart _routingContextWithDefaultSafety;
|
||||
final _RoutingContextWithSafetyDart _routingContextWithSafety;
|
||||
final _RoutingContextWithSequencingDart _routingContextWithSequencing;
|
||||
final _RoutingContextSafetyDart _routingContextSafety;
|
||||
final _RoutingContextAppCallDart _routingContextAppCall;
|
||||
final _RoutingContextAppMessageDart _routingContextAppMessage;
|
||||
final _RoutingContextCreateDHTRecordDart _routingContextCreateDHTRecord;
|
||||
|
@ -68,20 +68,18 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
|
||||
}
|
||||
|
||||
@override
|
||||
VeilidRoutingContextJS withPrivacy() {
|
||||
VeilidRoutingContextJS withDefaultSafety() {
|
||||
final id = _ctx.requireId();
|
||||
final int newId =
|
||||
js_util.callMethod(wasm, 'routing_context_with_privacy', [id]);
|
||||
js_util.callMethod(wasm, 'routing_context_with_default_safety', [id]);
|
||||
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
|
||||
}
|
||||
|
||||
@override
|
||||
VeilidRoutingContextJS withCustomPrivacy(SafetySelection safetySelection) {
|
||||
VeilidRoutingContextJS withSafety(SafetySelection safetySelection) {
|
||||
final id = _ctx.requireId();
|
||||
final newId = js_util.callMethod<int>(
|
||||
wasm,
|
||||
'routing_context_with_custom_privacy',
|
||||
[id, jsonEncode(safetySelection)]);
|
||||
wasm, 'routing_context_with_safety', [id, jsonEncode(safetySelection)]);
|
||||
|
||||
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
|
||||
}
|
||||
@ -94,6 +92,15 @@ class VeilidRoutingContextJS extends VeilidRoutingContext {
|
||||
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SafetySelection> safety() async {
|
||||
final id = _ctx.requireId();
|
||||
return SafetySelection.fromJson(jsonDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, 'routing_context_safety', [
|
||||
id,
|
||||
]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> appCall(String target, Uint8List request) async {
|
||||
final id = _ctx.requireId();
|
||||
|
@ -407,7 +407,7 @@ fn add_routing_context(
|
||||
pub extern "C" fn routing_context(port: i64) {
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let routing_context = veilid_api.routing_context();
|
||||
let routing_context = veilid_api.routing_context()?;
|
||||
let mut rc = ROUTING_CONTEXTS.lock();
|
||||
let new_id = add_routing_context(&mut rc, routing_context);
|
||||
APIResult::Ok(new_id)
|
||||
@ -424,12 +424,12 @@ pub extern "C" fn release_routing_context(id: u32) -> i32 {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_with_privacy(id: u32) -> u32 {
|
||||
pub extern "C" fn routing_context_with_default_safety(id: u32) -> u32 {
|
||||
let mut rc = ROUTING_CONTEXTS.lock();
|
||||
let Some(routing_context) = rc.get(&id) else {
|
||||
return 0;
|
||||
};
|
||||
let Ok(routing_context) = routing_context.clone().with_privacy() else {
|
||||
let Ok(routing_context) = routing_context.clone().with_default_safety() else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
@ -437,7 +437,7 @@ pub extern "C" fn routing_context_with_privacy(id: u32) -> u32 {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_with_custom_privacy(id: u32, safety_selection: FfiStr) -> u32 {
|
||||
pub extern "C" fn routing_context_with_safety(id: u32, safety_selection: FfiStr) -> u32 {
|
||||
let safety_selection: veilid_core::SafetySelection =
|
||||
veilid_core::deserialize_opt_json(safety_selection.into_opt_string()).unwrap();
|
||||
|
||||
@ -445,10 +445,7 @@ pub extern "C" fn routing_context_with_custom_privacy(id: u32, safety_selection:
|
||||
let Some(routing_context) = rc.get(&id) else {
|
||||
return 0;
|
||||
};
|
||||
let Ok(routing_context) = routing_context
|
||||
.clone()
|
||||
.with_custom_privacy(safety_selection)
|
||||
else {
|
||||
let Ok(routing_context) = routing_context.clone().with_safety(safety_selection) else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
@ -469,6 +466,23 @@ pub extern "C" fn routing_context_with_sequencing(id: u32, sequencing: FfiStr) -
|
||||
add_routing_context(&mut rc, routing_context)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_safety(port: i64, id: u32) {
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
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()
|
||||
};
|
||||
APIResult::Ok(routing_context.safety())
|
||||
});
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) {
|
||||
let target_string: String = target.into_opt_string().unwrap();
|
||||
|
@ -22,7 +22,7 @@ async def test_routing_contexts(api_connection: veilid.VeilidAPI):
|
||||
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
rcp = await rc.with_privacy(release=False)
|
||||
rcp = await rc.with_default_safety(release=False)
|
||||
async with rcp:
|
||||
pass
|
||||
|
||||
@ -32,15 +32,15 @@ async def test_routing_contexts(api_connection: veilid.VeilidAPI):
|
||||
async with rc:
|
||||
pass
|
||||
|
||||
rc = await (await api_connection.new_routing_context()).with_custom_privacy(
|
||||
rc = await (await api_connection.new_routing_context()).with_safety(
|
||||
veilid.SafetySelection.safe(
|
||||
veilid.SafetySpec(None, 2, veilid.Stability.RELIABLE, veilid.Sequencing.ENSURE_ORDERED)
|
||||
veilid.SafetySpec(None, 2, veilid.Stability.LOW_LATENCY, veilid.Sequencing.NO_PREFERENCE)
|
||||
)
|
||||
)
|
||||
await rc.release()
|
||||
|
||||
rc = await (await api_connection.new_routing_context()).with_custom_privacy(
|
||||
veilid.SafetySelection.unsafe(veilid.Sequencing.ENSURE_ORDERED)
|
||||
rc = await (await api_connection.new_routing_context()).with_safety(
|
||||
veilid.SafetySelection.unsafe(veilid.Sequencing.PREFER_ORDERED)
|
||||
)
|
||||
await rc.release()
|
||||
|
||||
@ -65,7 +65,7 @@ async def test_routing_context_app_message_loopback():
|
||||
await api.debug("purge routes")
|
||||
|
||||
# make a routing context that uses a safety route
|
||||
rc = await (await api.new_routing_context()).with_privacy()
|
||||
rc = await api.new_routing_context()
|
||||
async with rc:
|
||||
# make a new local private route
|
||||
prl, blob = await api.new_private_route()
|
||||
@ -105,7 +105,7 @@ async def test_routing_context_app_call_loopback():
|
||||
await api.debug("purge routes")
|
||||
|
||||
# make a routing context that uses a safety route
|
||||
rc = await (await (await api.new_routing_context()).with_privacy()).with_sequencing(
|
||||
rc = await (await api.new_routing_context()).with_sequencing(
|
||||
veilid.Sequencing.ENSURE_ORDERED
|
||||
)
|
||||
async with rc:
|
||||
@ -160,7 +160,7 @@ async def test_routing_context_app_message_loopback_big_packets():
|
||||
await api.debug("purge routes")
|
||||
|
||||
# make a routing context that uses a safety route
|
||||
rc = await (await (await api.new_routing_context()).with_privacy()).with_sequencing(
|
||||
rc = await (await api.new_routing_context()).with_sequencing(
|
||||
veilid.Sequencing.ENSURE_ORDERED
|
||||
)
|
||||
async with rc:
|
||||
@ -225,7 +225,7 @@ async def test_routing_context_app_call_loopback_big_packets():
|
||||
app_call_task = asyncio.create_task(app_call_queue_task_handler(api), name="app call task")
|
||||
|
||||
# make a routing context that uses a safety route
|
||||
rc = await (await (await api.new_routing_context()).with_privacy()).with_sequencing(
|
||||
rc = await (await api.new_routing_context()).with_sequencing(
|
||||
veilid.Sequencing.ENSURE_ORDERED
|
||||
)
|
||||
async with rc:
|
||||
@ -269,8 +269,8 @@ async def test_routing_context_app_message_loopback_bandwidth():
|
||||
await api.debug("purge routes")
|
||||
|
||||
# make a routing context that uses a safety route
|
||||
# rc = await (await (await api.new_routing_context()).with_privacy()).with_sequencing(veilid.Sequencing.ENSURE_ORDERED)
|
||||
# rc = await (await api.new_routing_context()).with_privacy()
|
||||
# rc = await (await api.new_routing_context()).with_sequencing(veilid.Sequencing.ENSURE_ORDERED)
|
||||
# rc = await api.new_routing_context()
|
||||
rc = await api.new_routing_context()
|
||||
async with rc:
|
||||
# make a new local private route
|
||||
|
@ -22,11 +22,11 @@ class RoutingContext(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def with_privacy(self, release=True) -> Self:
|
||||
async def with_default_safety(self, release=True) -> Self:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def with_custom_privacy(
|
||||
async def with_safety(
|
||||
self, safety_selection: types.SafetySelection, release=True
|
||||
) -> Self:
|
||||
pass
|
||||
@ -35,6 +35,10 @@ class RoutingContext(ABC):
|
||||
async def with_sequencing(self, sequencing: types.Sequencing, release=True) -> Self:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def safety(self) -> types.SafetySelection:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def app_call(self, target: types.TypedKey | types.RouteId, request: bytes) -> bytes:
|
||||
pass
|
||||
|
@ -446,26 +446,26 @@ class _JsonRoutingContext(RoutingContext):
|
||||
)
|
||||
self.done = True
|
||||
|
||||
async def with_privacy(self, release=True) -> Self:
|
||||
async def with_default_safety(self, release=True) -> Self:
|
||||
new_rc_id = raise_api_result(
|
||||
await self.api.send_ndjson_request(
|
||||
Operation.ROUTING_CONTEXT,
|
||||
validate=validate_rc_op,
|
||||
rc_id=self.rc_id,
|
||||
rc_op=RoutingContextOperation.WITH_PRIVACY,
|
||||
rc_op=RoutingContextOperation.WITH_DEFAULT_SAFETY,
|
||||
)
|
||||
)
|
||||
if release:
|
||||
await self.release()
|
||||
return self.__class__(self.api, new_rc_id)
|
||||
|
||||
async def with_custom_privacy(self, safety_selection: SafetySelection, release=True) -> Self:
|
||||
async def with_safety(self, safety_selection: SafetySelection, release=True) -> Self:
|
||||
new_rc_id = raise_api_result(
|
||||
await self.api.send_ndjson_request(
|
||||
Operation.ROUTING_CONTEXT,
|
||||
validate=validate_rc_op,
|
||||
rc_id=self.rc_id,
|
||||
rc_op=RoutingContextOperation.WITH_CUSTOM_PRIVACY,
|
||||
rc_op=RoutingContextOperation.WITH_SAFETY,
|
||||
safety_selection=safety_selection,
|
||||
)
|
||||
)
|
||||
@ -487,6 +487,19 @@ class _JsonRoutingContext(RoutingContext):
|
||||
await self.release()
|
||||
return self.__class__(self.api, new_rc_id)
|
||||
|
||||
async def safety(
|
||||
self
|
||||
) -> SafetySelection:
|
||||
return SafetySelection.from_json(
|
||||
raise_api_result(
|
||||
await self.api.send_ndjson_request(
|
||||
Operation.ROUTING_CONTEXT,
|
||||
validate=validate_rc_op,
|
||||
rc_id=self.rc_id,
|
||||
rc_op=RoutingContextOperation.SAFETY,
|
||||
)
|
||||
)
|
||||
)
|
||||
async def app_call(self, target: TypedKey | RouteId, message: bytes) -> bytes:
|
||||
return urlsafe_b64decode_no_pad(
|
||||
raise_api_result(
|
||||
|
@ -33,9 +33,10 @@ class Operation(StrEnum):
|
||||
class RoutingContextOperation(StrEnum):
|
||||
INVALID_ID = "InvalidId"
|
||||
RELEASE = "Release"
|
||||
WITH_PRIVACY = "WithPrivacy"
|
||||
WITH_CUSTOM_PRIVACY = "WithCustomPrivacy"
|
||||
WITH_DEFAULT_SAFETY = "WithDefaultSafety"
|
||||
WITH_SAFETY = "WithSafety"
|
||||
WITH_SEQUENCING = "WithSequencing"
|
||||
SAFETY = "Safety"
|
||||
APP_CALL = "AppCall"
|
||||
APP_MESSAGE = "AppMessage"
|
||||
CREATE_DHT_RECORD = "CreateDhtRecord"
|
||||
|
@ -328,7 +328,7 @@ fn add_routing_context(routing_context: veilid_core::RoutingContext) -> u32 {
|
||||
pub fn routing_context() -> Promise {
|
||||
wrap_api_future_plain(async move {
|
||||
let veilid_api = get_veilid_api()?;
|
||||
let routing_context = veilid_api.routing_context();
|
||||
let routing_context = veilid_api.routing_context()?;
|
||||
let new_id = add_routing_context(routing_context);
|
||||
APIResult::Ok(new_id)
|
||||
})
|
||||
@ -344,7 +344,7 @@ pub fn release_routing_context(id: u32) -> i32 {
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn routing_context_with_privacy(id: u32) -> u32 {
|
||||
pub fn routing_context_with_default_safety(id: u32) -> u32 {
|
||||
let routing_context = {
|
||||
let rc = (*ROUTING_CONTEXTS).borrow();
|
||||
let Some(routing_context) = rc.get(&id) else {
|
||||
@ -352,14 +352,14 @@ pub fn routing_context_with_privacy(id: u32) -> u32 {
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
let Ok(routing_context) = routing_context.with_privacy() else {
|
||||
let Ok(routing_context) = routing_context.with_default_safety() else {
|
||||
return 0;
|
||||
};
|
||||
add_routing_context(routing_context)
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn routing_context_with_custom_privacy(id: u32, safety_selection: String) -> u32 {
|
||||
pub fn routing_context_with_safety(id: u32, safety_selection: String) -> u32 {
|
||||
let safety_selection: veilid_core::SafetySelection =
|
||||
veilid_core::deserialize_json(&safety_selection).unwrap();
|
||||
|
||||
@ -370,7 +370,7 @@ pub fn routing_context_with_custom_privacy(id: u32, safety_selection: String) ->
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
let Ok(routing_context) = routing_context.with_custom_privacy(safety_selection) else {
|
||||
let Ok(routing_context) = routing_context.with_safety(safety_selection) else {
|
||||
return 0;
|
||||
};
|
||||
add_routing_context(routing_context)
|
||||
@ -391,6 +391,26 @@ pub fn routing_context_with_sequencing(id: u32, sequencing: String) -> u32 {
|
||||
add_routing_context(routing_context)
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn routing_context_safety(id: u32) -> Promise {
|
||||
wrap_api_future_json(async move {
|
||||
let routing_context = {
|
||||
let rc = (*ROUTING_CONTEXTS).borrow();
|
||||
let Some(routing_context) = rc.get(&id) else {
|
||||
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument(
|
||||
"routing_context_safety",
|
||||
"id",
|
||||
id,
|
||||
));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
|
||||
let safety_selection = routing_context.safety();
|
||||
APIResult::Ok(safety_selection)
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn routing_context_app_call(id: u32, target_string: String, request: String) -> Promise {
|
||||
let request: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
|
@ -13,7 +13,7 @@ impl VeilidRoutingContext {
|
||||
pub fn new() -> APIResult<VeilidRoutingContext> {
|
||||
let veilid_api = get_veilid_api()?;
|
||||
APIResult::Ok(VeilidRoutingContext {
|
||||
inner_routing_context: veilid_api.routing_context(),
|
||||
inner_routing_context: veilid_api.routing_context()?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -105,30 +105,30 @@ impl VeilidRoutingContext {
|
||||
APIResult::Ok(self.inner_routing_context.clone())
|
||||
}
|
||||
|
||||
/// Turn on sender privacy, enabling the use of safety routes.
|
||||
/// Turn on sender privacy, enabling the use of safety routes. This is the default and
|
||||
/// calling this function is only necessary if you have previously disable safety or used other parameters.
|
||||
/// Returns a new instance of VeilidRoutingContext - does not mutate.
|
||||
///
|
||||
/// Default values for hop count, stability and sequencing preferences are used.
|
||||
///
|
||||
/// Hop count default is dependent on config, but is set to 1 extra hop.
|
||||
/// Stability default is to choose 'low latency' routes, preferring them over long-term reliability.
|
||||
/// Sequencing default is to have no preference for ordered vs unordered message delivery
|
||||
pub fn withPrivacy(&self) -> APIResult<VeilidRoutingContext> {
|
||||
/// * Hop count default is dependent on config, but is set to 1 extra hop.
|
||||
/// * Stability default is to choose 'low latency' routes, preferring them over long-term reliability.
|
||||
/// * Sequencing default is to have no preference for ordered vs unordered message delivery
|
||||
///
|
||||
/// To customize the safety selection in use, use [VeilidRoutingContext::withSafety].
|
||||
pub fn withDefaultSafety(&self) -> APIResult<VeilidRoutingContext> {
|
||||
let routing_context = self.getRoutingContext()?;
|
||||
APIResult::Ok(VeilidRoutingContext {
|
||||
inner_routing_context: routing_context.with_privacy()?,
|
||||
inner_routing_context: routing_context.with_default_safety()?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Turn on privacy using a custom `SafetySelection`.
|
||||
/// Use a custom [SafetySelection]. Can be used to disable safety via [SafetySelection::Unsafe]
|
||||
/// Returns a new instance of VeilidRoutingContext - does not mutate.
|
||||
pub fn withCustomPrivacy(
|
||||
&self,
|
||||
safety_selection: SafetySelection,
|
||||
) -> APIResult<VeilidRoutingContext> {
|
||||
pub fn withSafety(&self, safety_selection: SafetySelection) -> APIResult<VeilidRoutingContext> {
|
||||
let routing_context = self.getRoutingContext()?;
|
||||
APIResult::Ok(VeilidRoutingContext {
|
||||
inner_routing_context: routing_context.with_custom_privacy(safety_selection)?,
|
||||
inner_routing_context: routing_context.with_safety(safety_selection)?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -141,6 +141,14 @@ impl VeilidRoutingContext {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the safety selection in use on this routing context
|
||||
/// @returns the SafetySelection currently in use if successful.
|
||||
pub fn safety(&self) -> APIResult<SafetySelection> {
|
||||
let routing_context = self.getRoutingContext()?;
|
||||
|
||||
let safety_selection = routing_context.safety();
|
||||
APIResult::Ok(safety_selection)
|
||||
}
|
||||
/// App-level unidirectional message that does not expect any value to be returned.
|
||||
///
|
||||
/// Veilid apps may use this for arbitrary message passing.
|
||||
|
2518
veilid-wasm/tests/package-lock.json
generated
2518
veilid-wasm/tests/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -46,15 +46,15 @@ describe('VeilidRoutingContext', () => {
|
||||
routingContext.free();
|
||||
});
|
||||
|
||||
it('should create with privacy', async () => {
|
||||
const routingContext = VeilidRoutingContext.create().withPrivacy();
|
||||
it('should create with default safety', async () => {
|
||||
const routingContext = VeilidRoutingContext.create().withDefaultSafety();
|
||||
expect(routingContext instanceof VeilidRoutingContext).toBe(true);
|
||||
|
||||
routingContext.free();
|
||||
});
|
||||
|
||||
it('should create with custom privacy', async () => {
|
||||
const routingContext = VeilidRoutingContext.create().withCustomPrivacy({
|
||||
it('should create with safety', async () => {
|
||||
const routingContext = VeilidRoutingContext.create().withSafety({
|
||||
Safe: {
|
||||
hop_count: 2,
|
||||
sequencing: 'EnsureOrdered',
|
||||
@ -80,7 +80,6 @@ describe('VeilidRoutingContext', () => {
|
||||
|
||||
before('create routing context', () => {
|
||||
routingContext = VeilidRoutingContext.create()
|
||||
.withPrivacy()
|
||||
.withSequencing('EnsureOrdered');
|
||||
});
|
||||
|
||||
|
@ -16,7 +16,7 @@ wasm-pack build $WASM_PACK_FLAGS --target bundler --weak-refs
|
||||
cd tests
|
||||
npm install
|
||||
original_tmpdir=$TMPDIR
|
||||
mkdir --parents ~/tmp
|
||||
mkdir -p ~/tmp
|
||||
export TMPDIR=~/tmp
|
||||
npm run test:headless
|
||||
export TMPDIR=$original_tmpdir
|
||||
|
Loading…
Reference in New Issue
Block a user