removing dev branch, many changes
This commit is contained in:
@@ -32,7 +32,6 @@
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -97,11 +98,11 @@ class _MyAppState extends State<MyApp> with UiLoggy {
|
||||
if (update is VeilidLog) {
|
||||
await processLog(update);
|
||||
} else if (update is VeilidAppMessage) {
|
||||
loggy.info("AppMessage: ${update.json}");
|
||||
loggy.info("AppMessage: ${jsonEncode(update)}");
|
||||
} else if (update is VeilidAppCall) {
|
||||
loggy.info("AppCall: ${update.json}");
|
||||
loggy.info("AppCall: ${jsonEncode(update)}");
|
||||
} else {
|
||||
loggy.trace("Update: ${update.json}");
|
||||
loggy.trace("Update: ${jsonEncode(update)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:xterm/xterm.dart';
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:veilid/veilid.dart';
|
||||
import 'package:flutter_acrylic/flutter_acrylic.dart';
|
||||
|
||||
import 'veilid_theme.dart';
|
||||
|
||||
@@ -14,7 +14,7 @@ void veilidInit() {
|
||||
logsInConsole: false),
|
||||
api: VeilidWASMConfigLoggingApi(
|
||||
enabled: true, level: VeilidConfigLogLevel.info)));
|
||||
Veilid.instance.initializeVeilidCore(platformConfig.json);
|
||||
Veilid.instance.initializeVeilidCore(platformConfig.toJson());
|
||||
} else {
|
||||
var platformConfig = VeilidFFIConfig(
|
||||
logging: VeilidFFIConfigLogging(
|
||||
@@ -29,6 +29,6 @@ void veilidInit() {
|
||||
serviceName: "VeilidExample"),
|
||||
api: VeilidFFIConfigLoggingApi(
|
||||
enabled: true, level: VeilidConfigLogLevel.info)));
|
||||
Veilid.instance.initializeVeilidCore(platformConfig.json);
|
||||
Veilid.instance.initializeVeilidCore(platformConfig.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import flutter_acrylic
|
||||
import path_provider_macos
|
||||
import macos_window_utils
|
||||
import path_provider_foundation
|
||||
import veilid
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FlutterAcrylicPlugin.register(with: registry.registrar(forPlugin: "FlutterAcrylicPlugin"))
|
||||
MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
VeilidPlugin.register(with: registry.registrar(forPlugin: "VeilidPlugin"))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
platform :osx, '10.12.2'
|
||||
platform :osx, '10.14.6'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
PODS:
|
||||
- flutter_acrylic (0.1.0):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- path_provider_macos (0.0.1):
|
||||
- macos_window_utils (1.0.0):
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- veilid (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
|
||||
- macos_window_utils (from `Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- veilid (from `Flutter/ephemeral/.symlinks/plugins/veilid/macos`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
flutter_acrylic:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
path_provider_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
|
||||
macos_window_utils:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
veilid:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/veilid/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17
|
||||
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
|
||||
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19
|
||||
veilid: ef97d3a2d5fda3b25a4017eae65c37afa8035203
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
macos_window_utils: 933f91f64805e2eb91a5bd057cf97cd097276663
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
veilid: a54f57b7bcf0e4e072fe99272d76ca126b2026d0
|
||||
|
||||
PODFILE CHECKSUM: baac1aaddb7c3a00c396723592a2ffb396a7fed7
|
||||
PODFILE CHECKSUM: 73d2f470b1d889e27fcfda1d6e6efec66f98af3f
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
COCOAPODS: 1.12.1
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
@@ -261,6 +261,7 @@
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
@@ -409,7 +410,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12.2;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14.6;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
@@ -496,7 +497,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12.2;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14.6;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
@@ -543,7 +544,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12.2;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14.6;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
||||
@@ -5,93 +5,122 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: ansicolor
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.9.0"
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.1"
|
||||
change_case:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: change_case
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: f4e08feaa845e75e4f5ad2b0e15f24813d7ea6c27e7b78252f0c17f752cf1157
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
version: "1.1.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.3.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
version: "1.17.1"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: equatable
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.0.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
file_utils:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_utils
|
||||
sha256: d1e64389a22649095c8405c9e177272caf05139255931c9ff30d53b5c9bcaa34
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -101,14 +130,16 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_acrylic
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "5aea2c850c560c07717a62434ea9cb1565c2282dc78dd2e60f98a78c05f13d7b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0+2"
|
||||
version: "1.1.2"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
flutter_test:
|
||||
@@ -121,139 +152,166 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
globbing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: globbing
|
||||
sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.4"
|
||||
version: "0.6.7"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "2.1.0"
|
||||
loggy:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: loggy
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "981e03162bbd3a5a843026f75f73d26e4a0d8aa035ae060456ca7b30dfd1e339"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
macos_window_utils:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: macos_window_utils
|
||||
sha256: "510de576b5432dd9ef9e4c258abcc021c6dfbb17a78a344688848a6784b352b8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.12"
|
||||
version: "0.12.15"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.5"
|
||||
version: "0.2.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
version: "1.9.1"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
version: "1.8.3"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
version: "2.0.15"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
path_provider_ios:
|
||||
version: "2.0.27"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
name: path_provider_foundation
|
||||
sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
version: "2.2.3"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.7"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
version: "2.1.10"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.0.6"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.6"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
platform_info:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform_info
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "012e73712166cf0b56d3eb95c0d33491f56b428c169eca385f036448474147e4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.4"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
version: "3.2.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -263,58 +321,74 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
version: "1.9.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.11.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.1"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.2.0"
|
||||
system_info2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: system_info2
|
||||
sha256: af2f948e3f31a3367a049932a8ad59faf0063ecf836a020d975b9f41566d8bc9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.12"
|
||||
version: "0.5.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.3.2"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.1.4"
|
||||
veilid:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -326,23 +400,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "4.1.4"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0+2"
|
||||
version: "1.0.0"
|
||||
xterm:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: xterm
|
||||
url: "https://pub.dartlang.org"
|
||||
sha256: "6a02b15d03152b8186e12790902ff28c8a932fc441e89fa7255a7491661a8e69"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
version: "3.5.0"
|
||||
sdks:
|
||||
dart: ">=2.18.0 <3.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
||||
@@ -7,7 +7,7 @@ version: 1.0.0+1
|
||||
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
String base64UrlNoPadEncode(List<int> bytes) {
|
||||
var x = base64Url.encode(bytes);
|
||||
while (x.endsWith('=')) {
|
||||
x = x.substring(0, x.length - 1);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
Uint8List base64UrlNoPadDecode(String source) {
|
||||
source = base64.normalize(source);
|
||||
return base64.decode(source);
|
||||
}
|
||||
@@ -1,8 +1,53 @@
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:system_info2/system_info2.dart' as sysinfo;
|
||||
import 'veilid.dart';
|
||||
|
||||
const int megaByte = 1024 * 1024;
|
||||
|
||||
int getLocalSubkeyCacheSize() {
|
||||
if (kIsWeb) {
|
||||
return 128;
|
||||
}
|
||||
return 1024;
|
||||
}
|
||||
|
||||
int getLocalMaxSubkeyCacheMemoryMb() {
|
||||
if (kIsWeb) {
|
||||
return 256;
|
||||
}
|
||||
return sysinfo.SysInfo.getTotalPhysicalMemory() ~/ 32 ~/ megaByte;
|
||||
}
|
||||
|
||||
int getRemoteSubkeyCacheSize() {
|
||||
if (kIsWeb) {
|
||||
return 64;
|
||||
}
|
||||
return 128;
|
||||
}
|
||||
|
||||
int getRemoteMaxRecords() {
|
||||
if (kIsWeb) {
|
||||
return 64;
|
||||
}
|
||||
return 128;
|
||||
}
|
||||
|
||||
int getRemoteMaxSubkeyCacheMemoryMb() {
|
||||
if (kIsWeb) {
|
||||
return 256;
|
||||
}
|
||||
return sysinfo.SysInfo.getTotalPhysicalMemory() ~/ 32 ~/ megaByte;
|
||||
}
|
||||
|
||||
int getRemoteMaxStorageSpaceMb() {
|
||||
if (kIsWeb) {
|
||||
return 128;
|
||||
}
|
||||
return 256;
|
||||
}
|
||||
|
||||
Future<VeilidConfig> getDefaultVeilidConfig(String programName) async {
|
||||
return VeilidConfig(
|
||||
programName: programName,
|
||||
@@ -19,8 +64,10 @@ Future<VeilidConfig> getDefaultVeilidConfig(String programName) async {
|
||||
protectedStore: VeilidConfigProtectedStore(
|
||||
allowInsecureFallback: false,
|
||||
alwaysUseInsecureStorage: false,
|
||||
insecureFallbackDirectory: "",
|
||||
directory: "",
|
||||
delete: false,
|
||||
deviceEncryptionKey: "",
|
||||
newDeviceEncryptionKey: null,
|
||||
),
|
||||
tableStore: VeilidConfigTableStore(
|
||||
directory: kIsWeb
|
||||
@@ -63,25 +110,30 @@ Future<VeilidConfig> getDefaultVeilidConfig(String programName) async {
|
||||
queueSize: 1024,
|
||||
maxTimestampBehindMs: 10000,
|
||||
maxTimestampAheadMs: 10000,
|
||||
timeoutMs: 10000,
|
||||
timeoutMs: 5000,
|
||||
maxRouteHopCount: 4,
|
||||
defaultRouteHopCount: 1,
|
||||
),
|
||||
dht: VeilidConfigDHT(
|
||||
resolveNodeTimeoutMs: null,
|
||||
resolveNodeCount: 20,
|
||||
resolveNodeFanout: 3,
|
||||
maxFindNodeCount: 20,
|
||||
getValueTimeoutMs: null,
|
||||
getValueCount: 20,
|
||||
getValueFanout: 3,
|
||||
setValueTimeoutMs: null,
|
||||
setValueCount: 20,
|
||||
setValueFanout: 5,
|
||||
minPeerCount: 20,
|
||||
minPeerRefreshTimeMs: 2000,
|
||||
validateDialInfoReceiptTimeMs: 2000,
|
||||
),
|
||||
resolveNodeTimeoutMs: 10000,
|
||||
resolveNodeCount: 20,
|
||||
resolveNodeFanout: 3,
|
||||
maxFindNodeCount: 20,
|
||||
getValueTimeoutMs: 10000,
|
||||
getValueCount: 20,
|
||||
getValueFanout: 3,
|
||||
setValueTimeoutMs: 10000,
|
||||
setValueCount: 20,
|
||||
setValueFanout: 5,
|
||||
minPeerCount: 20,
|
||||
minPeerRefreshTimeMs: 2000,
|
||||
validateDialInfoReceiptTimeMs: 2000,
|
||||
localSubkeyCacheSize: getLocalSubkeyCacheSize(),
|
||||
localMaxSubkeyCacheMemoryMb: getLocalMaxSubkeyCacheMemoryMb(),
|
||||
remoteSubkeyCacheSize: getRemoteSubkeyCacheSize(),
|
||||
remoteMaxRecords: getRemoteMaxRecords(),
|
||||
remoteMaxSubkeyCacheMemoryMb: getRemoteMaxSubkeyCacheMemoryMb(),
|
||||
remoteMaxStorageSpaceMb: getRemoteMaxStorageSpaceMb()),
|
||||
upnp: true,
|
||||
detectAddressChanges: true,
|
||||
restrictedNatRetries: 0,
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:change_case/change_case.dart';
|
||||
|
||||
import 'veilid_encoding.dart';
|
||||
import 'veilid.dart';
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////
|
||||
/// DHT Schema
|
||||
|
||||
abstract class DHTSchema {
|
||||
factory DHTSchema.fromJson(dynamic json) {
|
||||
switch (json["kind"]) {
|
||||
case "DFLT":
|
||||
{
|
||||
return DHTSchemaDFLT(oCnt: json["o_cnt"]);
|
||||
}
|
||||
case "SMPL":
|
||||
{
|
||||
return DHTSchemaSMPL(
|
||||
oCnt: json["o_cnt"],
|
||||
members: List<DHTSchemaMember>.from(
|
||||
json['members'].map((j) => DHTSchemaMember.fromJson(j))));
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw VeilidAPIExceptionInternal(
|
||||
"Invalid VeilidAPIException type: ${json['kind']}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, dynamic> toJson();
|
||||
}
|
||||
|
||||
class DHTSchemaDFLT implements DHTSchema {
|
||||
final int oCnt;
|
||||
//
|
||||
DHTSchemaDFLT({
|
||||
required this.oCnt,
|
||||
}) {
|
||||
if (oCnt < 0 || oCnt > 65535) {
|
||||
throw VeilidAPIExceptionInvalidArgument(
|
||||
"value out of range", "oCnt", oCnt.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'kind': "DFLT",
|
||||
'o_cnt': oCnt,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class DHTSchemaMember {
|
||||
PublicKey mKey;
|
||||
int mCnt;
|
||||
|
||||
DHTSchemaMember({
|
||||
required this.mKey,
|
||||
required this.mCnt,
|
||||
}) {
|
||||
if (mCnt < 0 || mCnt > 65535) {
|
||||
throw VeilidAPIExceptionInvalidArgument(
|
||||
"value out of range", "mCnt", mCnt.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'm_key': mKey,
|
||||
'm_cnt': mCnt,
|
||||
};
|
||||
}
|
||||
|
||||
DHTSchemaMember.fromJson(dynamic json)
|
||||
: mKey = json['m_key'],
|
||||
mCnt = json['m_cnt'];
|
||||
}
|
||||
|
||||
class DHTSchemaSMPL implements DHTSchema {
|
||||
final int oCnt;
|
||||
final List<DHTSchemaMember> members;
|
||||
//
|
||||
DHTSchemaSMPL({
|
||||
required this.oCnt,
|
||||
required this.members,
|
||||
}) {
|
||||
if (oCnt < 0 || oCnt > 65535) {
|
||||
throw VeilidAPIExceptionInvalidArgument(
|
||||
"value out of range", "oCnt", oCnt.toString());
|
||||
}
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'kind': "SMPL",
|
||||
'o_cnt': oCnt,
|
||||
'members': members.map((p) => p.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// DHTRecordDescriptor
|
||||
|
||||
class DHTRecordDescriptor {
|
||||
TypedKey key;
|
||||
PublicKey owner;
|
||||
PublicKey? ownerSecret;
|
||||
DHTSchema schema;
|
||||
|
||||
DHTRecordDescriptor({
|
||||
required this.key,
|
||||
required this.owner,
|
||||
this.ownerSecret,
|
||||
required this.schema,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'key': key.toString(),
|
||||
'owner': owner,
|
||||
'owner_secret': ownerSecret,
|
||||
'schema': schema.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
DHTRecordDescriptor.fromJson(dynamic json)
|
||||
: key = TypedKey.fromString(json['key']),
|
||||
owner = json['owner'],
|
||||
ownerSecret = json['owner_secret'],
|
||||
schema = DHTSchema.fromJson(json['schema']);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// ValueSubkeyRange
|
||||
|
||||
class ValueSubkeyRange {
|
||||
final int low;
|
||||
final int high;
|
||||
|
||||
ValueSubkeyRange({
|
||||
required this.low,
|
||||
required this.high,
|
||||
}) {
|
||||
if (low < 0 || low > high) {
|
||||
throw VeilidAPIExceptionInvalidArgument(
|
||||
"invalid range", "low", low.toString());
|
||||
}
|
||||
if (high < 0) {
|
||||
throw VeilidAPIExceptionInvalidArgument(
|
||||
"invalid range", "high", high.toString());
|
||||
}
|
||||
}
|
||||
|
||||
ValueSubkeyRange.fromJson(dynamic json)
|
||||
: low = json[0],
|
||||
high = json[1] {
|
||||
if ((json as List<int>).length != 2) {
|
||||
throw VeilidAPIExceptionInvalidArgument(
|
||||
"not a pair of integers", "json", json.toString());
|
||||
}
|
||||
}
|
||||
|
||||
List<dynamic> toJson() {
|
||||
return [low, high];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// ValueData
|
||||
|
||||
class ValueData {
|
||||
final int seq;
|
||||
final Uint8List data;
|
||||
final PublicKey writer;
|
||||
|
||||
ValueData({
|
||||
required this.seq,
|
||||
required this.data,
|
||||
required this.writer,
|
||||
});
|
||||
|
||||
ValueData.fromJson(dynamic json)
|
||||
: seq = json['seq'],
|
||||
data = base64UrlNoPadDecode(json['data']),
|
||||
writer = json['writer'];
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'seq': seq, 'data': base64UrlNoPadEncode(data), 'writer': writer};
|
||||
}
|
||||
}
|
||||
|
||||
/// Stability
|
||||
|
||||
enum Stability {
|
||||
lowLatency,
|
||||
reliable;
|
||||
|
||||
String toJson() {
|
||||
return name.toPascalCase();
|
||||
}
|
||||
|
||||
factory Stability.fromJson(String j) {
|
||||
return Stability.values.byName(j.toCamelCase());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// Sequencing
|
||||
|
||||
enum Sequencing {
|
||||
noPreference,
|
||||
preferOrdered,
|
||||
ensureOrdered;
|
||||
|
||||
String toJson() {
|
||||
return name.toPascalCase();
|
||||
}
|
||||
|
||||
factory Sequencing.fromJson(String j) {
|
||||
return Sequencing.values.byName(j.toCamelCase());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// RouteBlob
|
||||
class RouteBlob {
|
||||
final String routeId;
|
||||
final Uint8List blob;
|
||||
|
||||
RouteBlob(this.routeId, this.blob);
|
||||
|
||||
RouteBlob.fromJson(dynamic json)
|
||||
: routeId = json['route_id'],
|
||||
blob = base64UrlNoPadDecode(json['blob']);
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'route_id': routeId, 'blob': base64UrlNoPadEncode(blob)};
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidRoutingContext
|
||||
|
||||
abstract class VeilidRoutingContext {
|
||||
// Modifiers
|
||||
VeilidRoutingContext withPrivacy();
|
||||
VeilidRoutingContext withCustomPrivacy(Stability stability);
|
||||
VeilidRoutingContext withSequencing(Sequencing sequencing);
|
||||
|
||||
// App call/message
|
||||
Future<Uint8List> appCall(String target, Uint8List request);
|
||||
Future<void> appMessage(String target, Uint8List message);
|
||||
|
||||
// DHT Operations
|
||||
Future<DHTRecordDescriptor> createDHTRecord(
|
||||
CryptoKind kind, DHTSchema schema);
|
||||
Future<DHTRecordDescriptor> openDHTRecord(TypedKey key, KeyPair? writer);
|
||||
Future<void> closeDHTRecord(TypedKey key);
|
||||
Future<void> deleteDHTRecord(TypedKey key);
|
||||
Future<ValueData?> getDHTValue(TypedKey key, int subkey, bool forceRefresh);
|
||||
Future<ValueData?> setDHTValue(TypedKey key, int subkey, Uint8List data);
|
||||
Future<Timestamp> watchDHTValues(
|
||||
TypedKey key, ValueSubkeyRange subkeys, Timestamp expiration, int count);
|
||||
Future<bool> cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys);
|
||||
}
|
||||
+74
-1847
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,286 @@
|
||||
//////////////////////////////////////
|
||||
/// VeilidAPIException
|
||||
|
||||
abstract class VeilidAPIException implements Exception {
|
||||
factory VeilidAPIException.fromJson(dynamic json) {
|
||||
switch (json["kind"]) {
|
||||
case "NotInitialized":
|
||||
{
|
||||
return VeilidAPIExceptionNotInitialized();
|
||||
}
|
||||
case "AlreadyInitialized":
|
||||
{
|
||||
return VeilidAPIExceptionAlreadyInitialized();
|
||||
}
|
||||
case "Timeout":
|
||||
{
|
||||
return VeilidAPIExceptionTimeout();
|
||||
}
|
||||
case "TryAgain":
|
||||
{
|
||||
return VeilidAPIExceptionTryAgain();
|
||||
}
|
||||
case "Shutdown":
|
||||
{
|
||||
return VeilidAPIExceptionShutdown();
|
||||
}
|
||||
case "InvalidTarget":
|
||||
{
|
||||
return VeilidAPIExceptionInvalidTarget();
|
||||
}
|
||||
case "NoConnection":
|
||||
{
|
||||
return VeilidAPIExceptionNoConnection(json["message"]);
|
||||
}
|
||||
case "KeyNotFound":
|
||||
{
|
||||
return VeilidAPIExceptionKeyNotFound(json["key"]);
|
||||
}
|
||||
case "Internal":
|
||||
{
|
||||
return VeilidAPIExceptionInternal(json["message"]);
|
||||
}
|
||||
case "Unimplemented":
|
||||
{
|
||||
return VeilidAPIExceptionUnimplemented(json["unimplemented"]);
|
||||
}
|
||||
case "ParseError":
|
||||
{
|
||||
return VeilidAPIExceptionParseError(json["message"], json["value"]);
|
||||
}
|
||||
case "InvalidArgument":
|
||||
{
|
||||
return VeilidAPIExceptionInvalidArgument(
|
||||
json["context"], json["argument"], json["value"]);
|
||||
}
|
||||
case "MissingArgument":
|
||||
{
|
||||
return VeilidAPIExceptionMissingArgument(
|
||||
json["context"], json["argument"]);
|
||||
}
|
||||
case "Generic":
|
||||
{
|
||||
return VeilidAPIExceptionGeneric(json["message"]);
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw VeilidAPIExceptionInternal(
|
||||
"Invalid VeilidAPIException type: ${json['kind']}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String toDisplayError();
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionNotInitialized implements VeilidAPIException {
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: NotInitialized";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Not initialized";
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionAlreadyInitialized implements VeilidAPIException {
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: AlreadyInitialized";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Already initialized";
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionTimeout implements VeilidAPIException {
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: Timeout";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Timeout";
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionTryAgain implements VeilidAPIException {
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: TryAgain";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Try again";
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionShutdown implements VeilidAPIException {
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: Shutdown";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Currently shut down";
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionInvalidTarget implements VeilidAPIException {
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: InvalidTarget";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Invalid target";
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionNoConnection implements VeilidAPIException {
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: NoConnection (message: $message)";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "No connection: $message";
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionNoConnection(this.message);
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionKeyNotFound implements VeilidAPIException {
|
||||
final String key;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: KeyNotFound (key: $key)";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Key not found: $key";
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionKeyNotFound(this.key);
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionInternal implements VeilidAPIException {
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: Internal ($message)";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Internal error: $message";
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionInternal(this.message);
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionUnimplemented implements VeilidAPIException {
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: Unimplemented ($message)";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Unimplemented: $message";
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionUnimplemented(this.message);
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionParseError implements VeilidAPIException {
|
||||
final String message;
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: ParseError ($message)\n value: $value";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Parse error: $message";
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionParseError(this.message, this.value);
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionInvalidArgument implements VeilidAPIException {
|
||||
final String context;
|
||||
final String argument;
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: InvalidArgument ($context:$argument)\n value: $value";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Invalid argument for $context: $argument";
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionInvalidArgument(this.context, this.argument, this.value);
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionMissingArgument implements VeilidAPIException {
|
||||
final String context;
|
||||
final String argument;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: MissingArgument ($context:$argument)";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return "Missing argument for $context: $argument";
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionMissingArgument(this.context, this.argument);
|
||||
}
|
||||
|
||||
class VeilidAPIExceptionGeneric implements VeilidAPIException {
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VeilidAPIException: Generic (message: $message)";
|
||||
}
|
||||
|
||||
@override
|
||||
String toDisplayError() {
|
||||
return message;
|
||||
}
|
||||
|
||||
//
|
||||
VeilidAPIExceptionGeneric(this.message);
|
||||
}
|
||||
@@ -0,0 +1,947 @@
|
||||
import 'package:change_case/change_case.dart';
|
||||
|
||||
import 'veilid.dart';
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// FFI Platform-specific config
|
||||
|
||||
class VeilidFFIConfigLoggingTerminal {
|
||||
bool enabled;
|
||||
VeilidConfigLogLevel level;
|
||||
|
||||
VeilidFFIConfigLoggingTerminal({
|
||||
required this.enabled,
|
||||
required this.level,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'level': level.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidFFIConfigLoggingTerminal.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
level = VeilidConfigLogLevel.fromJson(json['level']);
|
||||
}
|
||||
|
||||
class VeilidFFIConfigLoggingOtlp {
|
||||
bool enabled;
|
||||
VeilidConfigLogLevel level;
|
||||
String grpcEndpoint;
|
||||
String serviceName;
|
||||
|
||||
VeilidFFIConfigLoggingOtlp({
|
||||
required this.enabled,
|
||||
required this.level,
|
||||
required this.grpcEndpoint,
|
||||
required this.serviceName,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'level': level.toJson(),
|
||||
'grpc_endpoint': grpcEndpoint,
|
||||
'service_name': serviceName,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidFFIConfigLoggingOtlp.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
level = VeilidConfigLogLevel.fromJson(json['level']),
|
||||
grpcEndpoint = json['grpc_endpoint'],
|
||||
serviceName = json['service_name'];
|
||||
}
|
||||
|
||||
class VeilidFFIConfigLoggingApi {
|
||||
bool enabled;
|
||||
VeilidConfigLogLevel level;
|
||||
|
||||
VeilidFFIConfigLoggingApi({
|
||||
required this.enabled,
|
||||
required this.level,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'level': level.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidFFIConfigLoggingApi.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
level = VeilidConfigLogLevel.fromJson(json['level']);
|
||||
}
|
||||
|
||||
class VeilidFFIConfigLogging {
|
||||
VeilidFFIConfigLoggingTerminal terminal;
|
||||
VeilidFFIConfigLoggingOtlp otlp;
|
||||
VeilidFFIConfigLoggingApi api;
|
||||
|
||||
VeilidFFIConfigLogging(
|
||||
{required this.terminal, required this.otlp, required this.api});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'terminal': terminal.toJson(),
|
||||
'otlp': otlp.toJson(),
|
||||
'api': api.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidFFIConfigLogging.fromJson(dynamic json)
|
||||
: terminal = VeilidFFIConfigLoggingTerminal.fromJson(json['terminal']),
|
||||
otlp = VeilidFFIConfigLoggingOtlp.fromJson(json['otlp']),
|
||||
api = VeilidFFIConfigLoggingApi.fromJson(json['api']);
|
||||
}
|
||||
|
||||
class VeilidFFIConfig {
|
||||
VeilidFFIConfigLogging logging;
|
||||
|
||||
VeilidFFIConfig({
|
||||
required this.logging,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'logging': logging.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidFFIConfig.fromJson(Map<String, dynamic> json)
|
||||
: logging = VeilidFFIConfigLogging.fromJson(json['logging']);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidConfigLogLevel
|
||||
|
||||
enum VeilidConfigLogLevel {
|
||||
off,
|
||||
error,
|
||||
warn,
|
||||
info,
|
||||
debug,
|
||||
trace;
|
||||
|
||||
String toJson() {
|
||||
return name.toPascalCase();
|
||||
}
|
||||
|
||||
factory VeilidConfigLogLevel.fromJson(dynamic j) {
|
||||
return VeilidConfigLogLevel.values.byName((j as String).toCamelCase());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// WASM Platform-specific config
|
||||
|
||||
class VeilidWASMConfigLoggingPerformance {
|
||||
bool enabled;
|
||||
VeilidConfigLogLevel level;
|
||||
bool logsInTimings;
|
||||
bool logsInConsole;
|
||||
|
||||
VeilidWASMConfigLoggingPerformance({
|
||||
required this.enabled,
|
||||
required this.level,
|
||||
required this.logsInTimings,
|
||||
required this.logsInConsole,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'level': level.toJson(),
|
||||
'logs_in_timings': logsInTimings,
|
||||
'logs_in_console': logsInConsole,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidWASMConfigLoggingPerformance.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
level = VeilidConfigLogLevel.fromJson(json['level']),
|
||||
logsInTimings = json['logs_in_timings'],
|
||||
logsInConsole = json['logs_in_console'];
|
||||
}
|
||||
|
||||
class VeilidWASMConfigLoggingApi {
|
||||
bool enabled;
|
||||
VeilidConfigLogLevel level;
|
||||
|
||||
VeilidWASMConfigLoggingApi({
|
||||
required this.enabled,
|
||||
required this.level,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'level': level.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidWASMConfigLoggingApi.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
level = VeilidConfigLogLevel.fromJson(json['level']);
|
||||
}
|
||||
|
||||
class VeilidWASMConfigLogging {
|
||||
VeilidWASMConfigLoggingPerformance performance;
|
||||
VeilidWASMConfigLoggingApi api;
|
||||
|
||||
VeilidWASMConfigLogging({required this.performance, required this.api});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'performance': performance.toJson(),
|
||||
'api': api.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidWASMConfigLogging.fromJson(dynamic json)
|
||||
: performance =
|
||||
VeilidWASMConfigLoggingPerformance.fromJson(json['performance']),
|
||||
api = VeilidWASMConfigLoggingApi.fromJson(json['api']);
|
||||
}
|
||||
|
||||
class VeilidWASMConfig {
|
||||
VeilidWASMConfigLogging logging;
|
||||
|
||||
VeilidWASMConfig({
|
||||
required this.logging,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'logging': logging.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidWASMConfig.fromJson(dynamic json)
|
||||
: logging = VeilidWASMConfigLogging.fromJson(json['logging']);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidConfig
|
||||
|
||||
class VeilidConfigHTTPS {
|
||||
bool enabled;
|
||||
String listenAddress;
|
||||
String path;
|
||||
String? url;
|
||||
|
||||
VeilidConfigHTTPS({
|
||||
required this.enabled,
|
||||
required this.listenAddress,
|
||||
required this.path,
|
||||
this.url,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'listen_address': listenAddress,
|
||||
'path': path,
|
||||
'url': url
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigHTTPS.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
listenAddress = json['listen_address'],
|
||||
path = json['path'],
|
||||
url = json['url'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigHTTP {
|
||||
bool enabled;
|
||||
String listenAddress;
|
||||
String path;
|
||||
String? url;
|
||||
|
||||
VeilidConfigHTTP({
|
||||
required this.enabled,
|
||||
required this.listenAddress,
|
||||
required this.path,
|
||||
this.url,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'listen_address': listenAddress,
|
||||
'path': path,
|
||||
'url': url
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigHTTP.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
listenAddress = json['listen_address'],
|
||||
path = json['path'],
|
||||
url = json['url'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigApplication {
|
||||
VeilidConfigHTTPS https;
|
||||
VeilidConfigHTTP http;
|
||||
|
||||
VeilidConfigApplication({
|
||||
required this.https,
|
||||
required this.http,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'https': https.toJson(),
|
||||
'http': http.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigApplication.fromJson(dynamic json)
|
||||
: https = VeilidConfigHTTPS.fromJson(json['https']),
|
||||
http = VeilidConfigHTTP.fromJson(json['http']);
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigUDP {
|
||||
bool enabled;
|
||||
int socketPoolSize;
|
||||
String listenAddress;
|
||||
String? publicAddress;
|
||||
|
||||
VeilidConfigUDP(
|
||||
{required this.enabled,
|
||||
required this.socketPoolSize,
|
||||
required this.listenAddress,
|
||||
this.publicAddress});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'socket_pool_size': socketPoolSize,
|
||||
'listen_address': listenAddress,
|
||||
'public_address': publicAddress,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigUDP.fromJson(dynamic json)
|
||||
: enabled = json['enabled'],
|
||||
socketPoolSize = json['socket_pool_size'],
|
||||
listenAddress = json['listen_address'],
|
||||
publicAddress = json['publicAddress'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigTCP {
|
||||
bool connect;
|
||||
bool listen;
|
||||
int maxConnections;
|
||||
String listenAddress;
|
||||
String? publicAddress;
|
||||
|
||||
VeilidConfigTCP(
|
||||
{required this.connect,
|
||||
required this.listen,
|
||||
required this.maxConnections,
|
||||
required this.listenAddress,
|
||||
this.publicAddress});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'connect': connect,
|
||||
'listen': listen,
|
||||
'max_connections': maxConnections,
|
||||
'listen_address': listenAddress,
|
||||
'public_address': publicAddress,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigTCP.fromJson(dynamic json)
|
||||
: connect = json['connect'],
|
||||
listen = json['listen'],
|
||||
maxConnections = json['max_connections'],
|
||||
listenAddress = json['listen_address'],
|
||||
publicAddress = json['publicAddress'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigWS {
|
||||
bool connect;
|
||||
bool listen;
|
||||
int maxConnections;
|
||||
String listenAddress;
|
||||
String path;
|
||||
String? url;
|
||||
|
||||
VeilidConfigWS(
|
||||
{required this.connect,
|
||||
required this.listen,
|
||||
required this.maxConnections,
|
||||
required this.listenAddress,
|
||||
required this.path,
|
||||
this.url});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'connect': connect,
|
||||
'listen': listen,
|
||||
'max_connections': maxConnections,
|
||||
'listen_address': listenAddress,
|
||||
'path': path,
|
||||
'url': url,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigWS.fromJson(dynamic json)
|
||||
: connect = json['connect'],
|
||||
listen = json['listen'],
|
||||
maxConnections = json['max_connections'],
|
||||
listenAddress = json['listen_address'],
|
||||
path = json['path'],
|
||||
url = json['url'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigWSS {
|
||||
bool connect;
|
||||
bool listen;
|
||||
int maxConnections;
|
||||
String listenAddress;
|
||||
String path;
|
||||
String? url;
|
||||
|
||||
VeilidConfigWSS(
|
||||
{required this.connect,
|
||||
required this.listen,
|
||||
required this.maxConnections,
|
||||
required this.listenAddress,
|
||||
required this.path,
|
||||
this.url});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'connect': connect,
|
||||
'listen': listen,
|
||||
'max_connections': maxConnections,
|
||||
'listen_address': listenAddress,
|
||||
'path': path,
|
||||
'url': url,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigWSS.fromJson(dynamic json)
|
||||
: connect = json['connect'],
|
||||
listen = json['listen'],
|
||||
maxConnections = json['max_connections'],
|
||||
listenAddress = json['listen_address'],
|
||||
path = json['path'],
|
||||
url = json['url'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigProtocol {
|
||||
VeilidConfigUDP udp;
|
||||
VeilidConfigTCP tcp;
|
||||
VeilidConfigWS ws;
|
||||
VeilidConfigWSS wss;
|
||||
|
||||
VeilidConfigProtocol({
|
||||
required this.udp,
|
||||
required this.tcp,
|
||||
required this.ws,
|
||||
required this.wss,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'udp': udp.toJson(),
|
||||
'tcp': tcp.toJson(),
|
||||
'ws': ws.toJson(),
|
||||
'wss': wss.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigProtocol.fromJson(dynamic json)
|
||||
: udp = VeilidConfigUDP.fromJson(json['udp']),
|
||||
tcp = VeilidConfigTCP.fromJson(json['tcp']),
|
||||
ws = VeilidConfigWS.fromJson(json['ws']),
|
||||
wss = VeilidConfigWSS.fromJson(json['wss']);
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigTLS {
|
||||
String certificatePath;
|
||||
String privateKeyPath;
|
||||
int connectionInitialTimeoutMs;
|
||||
|
||||
VeilidConfigTLS({
|
||||
required this.certificatePath,
|
||||
required this.privateKeyPath,
|
||||
required this.connectionInitialTimeoutMs,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'certificate_path': certificatePath,
|
||||
'private_key_path': privateKeyPath,
|
||||
'connection_initial_timeout_ms': connectionInitialTimeoutMs,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigTLS.fromJson(dynamic json)
|
||||
: certificatePath = json['certificate_path'],
|
||||
privateKeyPath = json['private_key_path'],
|
||||
connectionInitialTimeoutMs = json['connection_initial_timeout_ms'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigDHT {
|
||||
int resolveNodeTimeoutMs;
|
||||
int resolveNodeCount;
|
||||
int resolveNodeFanout;
|
||||
int maxFindNodeCount;
|
||||
int getValueTimeoutMs;
|
||||
int getValueCount;
|
||||
int getValueFanout;
|
||||
int setValueTimeoutMs;
|
||||
int setValueCount;
|
||||
int setValueFanout;
|
||||
int minPeerCount;
|
||||
int minPeerRefreshTimeMs;
|
||||
int validateDialInfoReceiptTimeMs;
|
||||
int localSubkeyCacheSize;
|
||||
int localMaxSubkeyCacheMemoryMb;
|
||||
int remoteSubkeyCacheSize;
|
||||
int remoteMaxRecords;
|
||||
int remoteMaxSubkeyCacheMemoryMb;
|
||||
int remoteMaxStorageSpaceMb;
|
||||
|
||||
VeilidConfigDHT(
|
||||
{required this.resolveNodeTimeoutMs,
|
||||
required this.resolveNodeCount,
|
||||
required this.resolveNodeFanout,
|
||||
required this.maxFindNodeCount,
|
||||
required this.getValueTimeoutMs,
|
||||
required this.getValueCount,
|
||||
required this.getValueFanout,
|
||||
required this.setValueTimeoutMs,
|
||||
required this.setValueCount,
|
||||
required this.setValueFanout,
|
||||
required this.minPeerCount,
|
||||
required this.minPeerRefreshTimeMs,
|
||||
required this.validateDialInfoReceiptTimeMs,
|
||||
required this.localSubkeyCacheSize,
|
||||
required this.localMaxSubkeyCacheMemoryMb,
|
||||
required this.remoteSubkeyCacheSize,
|
||||
required this.remoteMaxRecords,
|
||||
required this.remoteMaxSubkeyCacheMemoryMb,
|
||||
required this.remoteMaxStorageSpaceMb});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'max_find_node_count': maxFindNodeCount,
|
||||
'resolve_node_timeout_ms': resolveNodeTimeoutMs,
|
||||
'resolve_node_count': resolveNodeCount,
|
||||
'resolve_node_fanout': resolveNodeFanout,
|
||||
'get_value_timeout_ms': getValueTimeoutMs,
|
||||
'get_value_count': getValueCount,
|
||||
'get_value_fanout': getValueFanout,
|
||||
'set_value_timeout_ms': setValueTimeoutMs,
|
||||
'set_value_count': setValueCount,
|
||||
'set_value_fanout': setValueFanout,
|
||||
'min_peer_count': minPeerCount,
|
||||
'min_peer_refresh_time_ms': minPeerRefreshTimeMs,
|
||||
'validate_dial_info_receipt_time_ms': validateDialInfoReceiptTimeMs,
|
||||
'local_subkey_cache_size': localSubkeyCacheSize,
|
||||
'local_max_subkey_cache_memory_mb': localMaxSubkeyCacheMemoryMb,
|
||||
'remote_subkey_cache_size': remoteSubkeyCacheSize,
|
||||
'remote_max_records': remoteMaxRecords,
|
||||
'remote_max_subkey_cache_memory_mb': remoteMaxSubkeyCacheMemoryMb,
|
||||
'remote_max_storage_space_mb': remoteMaxStorageSpaceMb,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigDHT.fromJson(dynamic json)
|
||||
: resolveNodeTimeoutMs = json['resolve_node_timeout_ms'],
|
||||
resolveNodeCount = json['resolve_node_count'],
|
||||
resolveNodeFanout = json['resolve_node_fanout'],
|
||||
maxFindNodeCount = json['max_find_node_count'],
|
||||
getValueTimeoutMs = json['get_value_timeout_ms'],
|
||||
getValueCount = json['get_value_count'],
|
||||
getValueFanout = json['get_value_fanout'],
|
||||
setValueTimeoutMs = json['set_value_timeout_ms'],
|
||||
setValueCount = json['set_value_count'],
|
||||
setValueFanout = json['set_value_fanout'],
|
||||
minPeerCount = json['min_peer_count'],
|
||||
minPeerRefreshTimeMs = json['min_peer_refresh_time_ms'],
|
||||
validateDialInfoReceiptTimeMs =
|
||||
json['validate_dial_info_receipt_time_ms'],
|
||||
localSubkeyCacheSize = json['local_subkey_cache_size'],
|
||||
localMaxSubkeyCacheMemoryMb = json['local_max_subkey_cache_memory_mb'],
|
||||
remoteSubkeyCacheSize = json['remote_subkey_cache_size'],
|
||||
remoteMaxRecords = json['remote_max_records'],
|
||||
remoteMaxSubkeyCacheMemoryMb =
|
||||
json['remote_max_subkey_cache_memory_mb'],
|
||||
remoteMaxStorageSpaceMb = json['remote_max_storage_space_mb'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigRPC {
|
||||
int concurrency;
|
||||
int queueSize;
|
||||
int? maxTimestampBehindMs;
|
||||
int? maxTimestampAheadMs;
|
||||
int timeoutMs;
|
||||
int maxRouteHopCount;
|
||||
int defaultRouteHopCount;
|
||||
|
||||
VeilidConfigRPC(
|
||||
{required this.concurrency,
|
||||
required this.queueSize,
|
||||
this.maxTimestampBehindMs,
|
||||
this.maxTimestampAheadMs,
|
||||
required this.timeoutMs,
|
||||
required this.maxRouteHopCount,
|
||||
required this.defaultRouteHopCount});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'concurrency': concurrency,
|
||||
'queue_size': queueSize,
|
||||
'max_timestamp_behind_ms': maxTimestampBehindMs,
|
||||
'max_timestamp_ahead_ms': maxTimestampAheadMs,
|
||||
'timeout_ms': timeoutMs,
|
||||
'max_route_hop_count': maxRouteHopCount,
|
||||
'default_route_hop_count': defaultRouteHopCount,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigRPC.fromJson(dynamic json)
|
||||
: concurrency = json['concurrency'],
|
||||
queueSize = json['queue_size'],
|
||||
maxTimestampBehindMs = json['max_timestamp_behind_ms'],
|
||||
maxTimestampAheadMs = json['max_timestamp_ahead_ms'],
|
||||
timeoutMs = json['timeout_ms'],
|
||||
maxRouteHopCount = json['max_route_hop_count'],
|
||||
defaultRouteHopCount = json['default_route_hop_count'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigRoutingTable {
|
||||
List<PublicKey> nodeId;
|
||||
List<PublicKey> nodeIdSecret;
|
||||
List<String> bootstrap;
|
||||
int limitOverAttached;
|
||||
int limitFullyAttached;
|
||||
int limitAttachedStrong;
|
||||
int limitAttachedGood;
|
||||
int limitAttachedWeak;
|
||||
|
||||
VeilidConfigRoutingTable({
|
||||
required this.nodeId,
|
||||
required this.nodeIdSecret,
|
||||
required this.bootstrap,
|
||||
required this.limitOverAttached,
|
||||
required this.limitFullyAttached,
|
||||
required this.limitAttachedStrong,
|
||||
required this.limitAttachedGood,
|
||||
required this.limitAttachedWeak,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'node_id': nodeId.map((p) => p.toJson()).toList(),
|
||||
'node_id_secret': nodeIdSecret.map((p) => p.toJson()).toList(),
|
||||
'bootstrap': bootstrap.map((p) => p).toList(),
|
||||
'limit_over_attached': limitOverAttached,
|
||||
'limit_fully_attached': limitFullyAttached,
|
||||
'limit_attached_strong': limitAttachedStrong,
|
||||
'limit_attached_good': limitAttachedGood,
|
||||
'limit_attached_weak': limitAttachedWeak,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigRoutingTable.fromJson(dynamic json)
|
||||
: nodeId = List<PublicKey>.from(
|
||||
json['node_id'].map((j) => PublicKey.fromJson(j))),
|
||||
nodeIdSecret = List<PublicKey>.from(
|
||||
json['node_id_secret'].map((j) => PublicKey.fromJson(j))),
|
||||
bootstrap = List<String>.from(json['bootstrap'].map((j) => j)),
|
||||
limitOverAttached = json['limit_over_attached'],
|
||||
limitFullyAttached = json['limit_fully_attached'],
|
||||
limitAttachedStrong = json['limit_attached_strong'],
|
||||
limitAttachedGood = json['limit_attached_good'],
|
||||
limitAttachedWeak = json['limit_attached_weak'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigNetwork {
|
||||
int connectionInitialTimeoutMs;
|
||||
int connectionInactivityTimeoutMs;
|
||||
int maxConnectionsPerIp4;
|
||||
int maxConnectionsPerIp6Prefix;
|
||||
int maxConnectionsPerIp6PrefixSize;
|
||||
int maxConnectionFrequencyPerMin;
|
||||
int clientWhitelistTimeoutMs;
|
||||
int reverseConnectionReceiptTimeMs;
|
||||
int holePunchReceiptTimeMs;
|
||||
VeilidConfigRoutingTable routingTable;
|
||||
VeilidConfigRPC rpc;
|
||||
VeilidConfigDHT dht;
|
||||
bool upnp;
|
||||
bool detectAddressChanges;
|
||||
int restrictedNatRetries;
|
||||
VeilidConfigTLS tls;
|
||||
VeilidConfigApplication application;
|
||||
VeilidConfigProtocol protocol;
|
||||
|
||||
VeilidConfigNetwork({
|
||||
required this.connectionInitialTimeoutMs,
|
||||
required this.connectionInactivityTimeoutMs,
|
||||
required this.maxConnectionsPerIp4,
|
||||
required this.maxConnectionsPerIp6Prefix,
|
||||
required this.maxConnectionsPerIp6PrefixSize,
|
||||
required this.maxConnectionFrequencyPerMin,
|
||||
required this.clientWhitelistTimeoutMs,
|
||||
required this.reverseConnectionReceiptTimeMs,
|
||||
required this.holePunchReceiptTimeMs,
|
||||
required this.routingTable,
|
||||
required this.rpc,
|
||||
required this.dht,
|
||||
required this.upnp,
|
||||
required this.detectAddressChanges,
|
||||
required this.restrictedNatRetries,
|
||||
required this.tls,
|
||||
required this.application,
|
||||
required this.protocol,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'connection_initial_timeout_ms': connectionInitialTimeoutMs,
|
||||
'connection_inactivity_timeout_ms': connectionInactivityTimeoutMs,
|
||||
'max_connections_per_ip4': maxConnectionsPerIp4,
|
||||
'max_connections_per_ip6_prefix': maxConnectionsPerIp6Prefix,
|
||||
'max_connections_per_ip6_prefix_size': maxConnectionsPerIp6PrefixSize,
|
||||
'max_connection_frequency_per_min': maxConnectionFrequencyPerMin,
|
||||
'client_whitelist_timeout_ms': clientWhitelistTimeoutMs,
|
||||
'reverse_connection_receipt_time_ms': reverseConnectionReceiptTimeMs,
|
||||
'hole_punch_receipt_time_ms': holePunchReceiptTimeMs,
|
||||
'routing_table': routingTable.toJson(),
|
||||
'rpc': rpc.toJson(),
|
||||
'dht': dht.toJson(),
|
||||
'upnp': upnp,
|
||||
'detect_address_changes': detectAddressChanges,
|
||||
'restricted_nat_retries': restrictedNatRetries,
|
||||
'tls': tls.toJson(),
|
||||
'application': application.toJson(),
|
||||
'protocol': protocol.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigNetwork.fromJson(dynamic json)
|
||||
: connectionInitialTimeoutMs = json['connection_initial_timeout_ms'],
|
||||
connectionInactivityTimeoutMs =
|
||||
json['connection_inactivity_timeout_ms'],
|
||||
maxConnectionsPerIp4 = json['max_connections_per_ip4'],
|
||||
maxConnectionsPerIp6Prefix = json['max_connections_per_ip6_prefix'],
|
||||
maxConnectionsPerIp6PrefixSize =
|
||||
json['max_connections_per_ip6_prefix_size'],
|
||||
maxConnectionFrequencyPerMin = json['max_connection_frequency_per_min'],
|
||||
clientWhitelistTimeoutMs = json['client_whitelist_timeout_ms'],
|
||||
reverseConnectionReceiptTimeMs =
|
||||
json['reverse_connection_receipt_time_ms'],
|
||||
holePunchReceiptTimeMs = json['hole_punch_receipt_time_ms'],
|
||||
routingTable = VeilidConfigRoutingTable.fromJson(json['routing_table']),
|
||||
rpc = VeilidConfigRPC.fromJson(json['rpc']),
|
||||
dht = VeilidConfigDHT.fromJson(json['dht']),
|
||||
upnp = json['upnp'],
|
||||
detectAddressChanges = json['detect_address_changes'],
|
||||
restrictedNatRetries = json['restricted_nat_retries'],
|
||||
tls = VeilidConfigTLS.fromJson(json['tls']),
|
||||
application = VeilidConfigApplication.fromJson(json['application']),
|
||||
protocol = VeilidConfigProtocol.fromJson(json['protocol']);
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigTableStore {
|
||||
String directory;
|
||||
bool delete;
|
||||
|
||||
VeilidConfigTableStore({
|
||||
required this.directory,
|
||||
required this.delete,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'directory': directory, 'delete': delete};
|
||||
}
|
||||
|
||||
VeilidConfigTableStore.fromJson(dynamic json)
|
||||
: directory = json['directory'],
|
||||
delete = json['delete'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigBlockStore {
|
||||
String directory;
|
||||
bool delete;
|
||||
|
||||
VeilidConfigBlockStore({
|
||||
required this.directory,
|
||||
required this.delete,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'directory': directory, 'delete': delete};
|
||||
}
|
||||
|
||||
VeilidConfigBlockStore.fromJson(dynamic json)
|
||||
: directory = json['directory'],
|
||||
delete = json['delete'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigProtectedStore {
|
||||
bool allowInsecureFallback;
|
||||
bool alwaysUseInsecureStorage;
|
||||
String directory;
|
||||
bool delete;
|
||||
String deviceEncryptionKey;
|
||||
String? newDeviceEncryptionKey;
|
||||
|
||||
VeilidConfigProtectedStore(
|
||||
{required this.allowInsecureFallback,
|
||||
required this.alwaysUseInsecureStorage,
|
||||
required this.directory,
|
||||
required this.delete,
|
||||
required this.deviceEncryptionKey,
|
||||
String? newDeviceEncryptionKey});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'allow_insecure_fallback': allowInsecureFallback,
|
||||
'always_use_insecure_storage': alwaysUseInsecureStorage,
|
||||
'directory': directory,
|
||||
'delete': delete,
|
||||
'device_encryption_key': deviceEncryptionKey,
|
||||
'new_device_encryption_key': newDeviceEncryptionKey,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigProtectedStore.fromJson(dynamic json)
|
||||
: allowInsecureFallback = json['allow_insecure_fallback'],
|
||||
alwaysUseInsecureStorage = json['always_use_insecure_storage'],
|
||||
directory = json['directory'],
|
||||
delete = json['delete'],
|
||||
deviceEncryptionKey = json['device_encryption_key'],
|
||||
newDeviceEncryptionKey = json['new_device_encryption_key'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfigCapabilities {
|
||||
bool protocolUDP;
|
||||
bool protocolConnectTCP;
|
||||
bool protocolAcceptTCP;
|
||||
bool protocolConnectWS;
|
||||
bool protocolAcceptWS;
|
||||
bool protocolConnectWSS;
|
||||
bool protocolAcceptWSS;
|
||||
|
||||
VeilidConfigCapabilities({
|
||||
required this.protocolUDP,
|
||||
required this.protocolConnectTCP,
|
||||
required this.protocolAcceptTCP,
|
||||
required this.protocolConnectWS,
|
||||
required this.protocolAcceptWS,
|
||||
required this.protocolConnectWSS,
|
||||
required this.protocolAcceptWSS,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'protocol_udp': protocolUDP,
|
||||
'protocol_connect_tcp': protocolConnectTCP,
|
||||
'protocol_accept_tcp': protocolAcceptTCP,
|
||||
'protocol_connect_ws': protocolConnectWS,
|
||||
'protocol_accept_ws': protocolAcceptWS,
|
||||
'protocol_connect_wss': protocolConnectWSS,
|
||||
'protocol_accept_wss': protocolAcceptWSS,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfigCapabilities.fromJson(dynamic json)
|
||||
: protocolUDP = json['protocol_udp'],
|
||||
protocolConnectTCP = json['protocol_connect_tcp'],
|
||||
protocolAcceptTCP = json['protocol_accept_tcp'],
|
||||
protocolConnectWS = json['protocol_connect_ws'],
|
||||
protocolAcceptWS = json['protocol_accept_ws'],
|
||||
protocolConnectWSS = json['protocol_connect_wss'],
|
||||
protocolAcceptWSS = json['protocol_accept_wss'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class VeilidConfig {
|
||||
String programName;
|
||||
String namespace;
|
||||
VeilidConfigCapabilities capabilities;
|
||||
VeilidConfigProtectedStore protectedStore;
|
||||
VeilidConfigTableStore tableStore;
|
||||
VeilidConfigBlockStore blockStore;
|
||||
VeilidConfigNetwork network;
|
||||
|
||||
VeilidConfig({
|
||||
required this.programName,
|
||||
required this.namespace,
|
||||
required this.capabilities,
|
||||
required this.protectedStore,
|
||||
required this.tableStore,
|
||||
required this.blockStore,
|
||||
required this.network,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'program_name': programName,
|
||||
'namespace': namespace,
|
||||
'capabilities': capabilities.toJson(),
|
||||
'protected_store': protectedStore.toJson(),
|
||||
'table_store': tableStore.toJson(),
|
||||
'block_store': blockStore.toJson(),
|
||||
'network': network.toJson()
|
||||
};
|
||||
}
|
||||
|
||||
VeilidConfig.fromJson(dynamic json)
|
||||
: programName = json['program_name'],
|
||||
namespace = json['namespace'],
|
||||
capabilities = VeilidConfigCapabilities.fromJson(json['capabilities']),
|
||||
protectedStore =
|
||||
VeilidConfigProtectedStore.fromJson(json['protected_store']),
|
||||
tableStore = VeilidConfigTableStore.fromJson(json['table_store']),
|
||||
blockStore = VeilidConfigBlockStore.fromJson(json['block_store']),
|
||||
network = VeilidConfigNetwork.fromJson(json['network']);
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:charcode/charcode.dart';
|
||||
|
||||
import 'veilid_encoding.dart';
|
||||
import 'veilid.dart';
|
||||
|
||||
//////////////////////////////////////
|
||||
/// CryptoKind
|
||||
|
||||
typedef CryptoKind = int;
|
||||
const CryptoKind cryptoKindVLD0 =
|
||||
$V << 0 | $L << 8 | $D << 16 | $0 << 24; // "VLD0"
|
||||
const CryptoKind cryptoKindNONE =
|
||||
$N << 0 | $O << 8 | $N << 16 | $E << 24; // "NONE"
|
||||
|
||||
String cryptoKindToString(CryptoKind kind) {
|
||||
return "${String.fromCharCode(kind & 0xFF)}${String.fromCharCode((kind >> 8) & 0xFF)}${String.fromCharCode((kind >> 16) & 0xFF)}${String.fromCharCode((kind >> 24) & 0xFF)}";
|
||||
}
|
||||
|
||||
CryptoKind cryptoKindFromString(String s) {
|
||||
if (s.codeUnits.length != 4) {
|
||||
throw const FormatException("malformed string");
|
||||
}
|
||||
CryptoKind kind = s.codeUnits[0] |
|
||||
s.codeUnits[1] << 8 |
|
||||
s.codeUnits[2] << 16 |
|
||||
s.codeUnits[3] << 24;
|
||||
return kind;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// Types
|
||||
|
||||
class Typed<V extends EncodedString> {
|
||||
late CryptoKind kind;
|
||||
late V value;
|
||||
Typed({required this.kind, required this.value});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "${cryptoKindToString(kind)}:$value";
|
||||
}
|
||||
|
||||
Typed.fromString(String s) {
|
||||
var parts = s.split(":");
|
||||
if (parts.length < 2 || parts[0].codeUnits.length != 4) {
|
||||
throw const FormatException("malformed string");
|
||||
}
|
||||
kind = parts[0].codeUnits[0] |
|
||||
parts[0].codeUnits[1] << 8 |
|
||||
parts[0].codeUnits[2] << 16 |
|
||||
parts[0].codeUnits[3] << 24;
|
||||
value = EncodedString.fromString<V>(parts.sublist(1).join(":"));
|
||||
}
|
||||
|
||||
String toJson() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
Typed.fromJson(dynamic json) : this.fromString(json as String);
|
||||
}
|
||||
|
||||
class KeyPair {
|
||||
late PublicKey key;
|
||||
late PublicKey secret;
|
||||
KeyPair({required this.key, required this.secret});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "${key.toString()}:${secret.toString()}";
|
||||
}
|
||||
|
||||
KeyPair.fromString(String s) {
|
||||
var parts = s.split(":");
|
||||
if (parts.length != 2 ||
|
||||
parts[0].codeUnits.length != 43 ||
|
||||
parts[1].codeUnits.length != 43) {
|
||||
throw const FormatException("malformed string");
|
||||
}
|
||||
key = PublicKey(parts[0]);
|
||||
secret = PublicKey(parts[1]);
|
||||
}
|
||||
|
||||
String toJson() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
KeyPair.fromJson(dynamic json) : this.fromString(json as String);
|
||||
}
|
||||
|
||||
class TypedKeyPair {
|
||||
late CryptoKind kind;
|
||||
late PublicKey key;
|
||||
late PublicKey secret;
|
||||
TypedKeyPair({required this.kind, required this.key, required this.secret});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "${cryptoKindToString(kind)}:${key.toString()}:${secret.toString()}";
|
||||
}
|
||||
|
||||
TypedKeyPair.fromString(String s) {
|
||||
var parts = s.split(":");
|
||||
if (parts.length != 3 ||
|
||||
parts[0].codeUnits.length != 4 ||
|
||||
parts[1].codeUnits.length != 43 ||
|
||||
parts[2].codeUnits.length != 43) {
|
||||
throw VeilidAPIExceptionInvalidArgument("malformed string", "s", s);
|
||||
}
|
||||
kind = cryptoKindFromString(parts[0]);
|
||||
key = PublicKey(parts[1]);
|
||||
secret = PublicKey(parts[2]);
|
||||
}
|
||||
|
||||
String toJson() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
TypedKeyPair.fromJson(dynamic json) : this.fromString(json as String);
|
||||
}
|
||||
|
||||
typedef CryptoKey = FixedEncodedString43;
|
||||
typedef Signature = FixedEncodedString86;
|
||||
typedef Nonce = FixedEncodedString32;
|
||||
|
||||
typedef PublicKey = CryptoKey;
|
||||
typedef SecretKey = CryptoKey;
|
||||
typedef HashDigest = CryptoKey;
|
||||
typedef SharedSecret = CryptoKey;
|
||||
typedef CryptoKeyDistance = CryptoKey;
|
||||
|
||||
typedef TypedKey = Typed<CryptoKey>;
|
||||
typedef TypedSignature = Typed<Signature>;
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidCryptoSystem
|
||||
|
||||
abstract class VeilidCryptoSystem {
|
||||
CryptoKind kind();
|
||||
Future<SharedSecret> cachedDH(PublicKey key, SecretKey secret);
|
||||
Future<SharedSecret> computeDH(PublicKey key, SecretKey secret);
|
||||
Future<Uint8List> randomBytes(int len);
|
||||
Future<int> defaultSaltLength();
|
||||
Future<String> hashPassword(Uint8List password, Uint8List salt);
|
||||
Future<bool> verifyPassword(Uint8List password, String passwordHash);
|
||||
Future<SharedSecret> deriveSharedSecret(Uint8List password, Uint8List salt);
|
||||
Future<Nonce> randomNonce();
|
||||
Future<SharedSecret> randomSharedSecret();
|
||||
Future<KeyPair> generateKeyPair();
|
||||
Future<HashDigest> generateHash(Uint8List data);
|
||||
//Future<HashDigest> generateHashReader(Stream<List<int>> reader);
|
||||
Future<bool> validateKeyPair(PublicKey key, SecretKey secret);
|
||||
Future<bool> validateHash(Uint8List data, HashDigest hash);
|
||||
//Future<bool> validateHashReader(Stream<List<int>> reader, HashDigest hash);
|
||||
Future<CryptoKeyDistance> distance(CryptoKey key1, CryptoKey key2);
|
||||
Future<Signature> sign(PublicKey key, SecretKey secret, Uint8List data);
|
||||
Future<void> verify(PublicKey key, Uint8List data, Signature signature);
|
||||
Future<int> aeadOverhead();
|
||||
Future<Uint8List> decryptAead(Uint8List body, Nonce nonce,
|
||||
SharedSecret sharedSecret, Uint8List? associatedData);
|
||||
Future<Uint8List> encryptAead(Uint8List body, Nonce nonce,
|
||||
SharedSecret sharedSecret, Uint8List? associatedData);
|
||||
Future<Uint8List> cryptNoAuth(
|
||||
Uint8List body, Nonce nonce, SharedSecret sharedSecret);
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
String base64UrlNoPadEncode(List<int> bytes) {
|
||||
var x = base64Url.encode(bytes);
|
||||
while (x.endsWith('=')) {
|
||||
x = x.substring(0, x.length - 1);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
Uint8List base64UrlNoPadDecode(String source) {
|
||||
source = base64.normalize(source);
|
||||
return base64.decode(source);
|
||||
}
|
||||
|
||||
Uint8List base64UrlNoPadDecodeDynamic(dynamic source) {
|
||||
source = source as String;
|
||||
source = base64.normalize(source);
|
||||
return base64.decode(source);
|
||||
}
|
||||
|
||||
abstract class EncodedString {
|
||||
late String contents;
|
||||
EncodedString(String s) {
|
||||
validate(s);
|
||||
contents = s;
|
||||
}
|
||||
EncodedString.encode(List<int> b) {
|
||||
var s = base64UrlNoPadEncode(b);
|
||||
validate(s);
|
||||
contents = s;
|
||||
}
|
||||
|
||||
int encodedLength();
|
||||
int decodedLength();
|
||||
void validate(String s) {
|
||||
var d = base64UrlNoPadDecode(s);
|
||||
if (d.length != decodedLength()) {
|
||||
throw Exception("length ${s.length} should be ${encodedLength()}");
|
||||
}
|
||||
}
|
||||
|
||||
Uint8List decode() {
|
||||
return base64UrlNoPadDecode(contents);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
static T fromString<T extends EncodedString>(String s) {
|
||||
switch (T) {
|
||||
case FixedEncodedString32:
|
||||
return FixedEncodedString32(s) as T;
|
||||
case FixedEncodedString43:
|
||||
return FixedEncodedString43(s) as T;
|
||||
case FixedEncodedString86:
|
||||
return FixedEncodedString86(s) as T;
|
||||
default:
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FixedEncodedString32 extends EncodedString {
|
||||
FixedEncodedString32(String s) : super(s);
|
||||
@override
|
||||
int encodedLength() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
@override
|
||||
int decodedLength() {
|
||||
return 24;
|
||||
}
|
||||
|
||||
String toJson() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
FixedEncodedString32.fromJson(dynamic json) : this(json as String);
|
||||
}
|
||||
|
||||
class FixedEncodedString43 extends EncodedString {
|
||||
FixedEncodedString43(String s) : super(s);
|
||||
@override
|
||||
int encodedLength() {
|
||||
return 43;
|
||||
}
|
||||
|
||||
@override
|
||||
int decodedLength() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
String toJson() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
FixedEncodedString43.fromJson(dynamic json) : this(json as String);
|
||||
}
|
||||
|
||||
class FixedEncodedString86 extends EncodedString {
|
||||
FixedEncodedString86(String s) : super(s);
|
||||
@override
|
||||
int encodedLength() {
|
||||
return 86;
|
||||
}
|
||||
|
||||
@override
|
||||
int decodedLength() {
|
||||
return 64;
|
||||
}
|
||||
|
||||
String toJson() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
FixedEncodedString86.fromJson(dynamic json) : this(json as String);
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import 'dart:typed_data';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
import 'veilid.dart';
|
||||
import 'base64url_no_pad.dart';
|
||||
import 'veilid_encoding.dart';
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
@@ -76,6 +76,46 @@ typedef _RoutingContextAppMessageC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _RoutingContextAppMessageDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn routing_context_create_dht_record(port: i64, id: u32, kind: u32, schema: FfiStr)
|
||||
typedef _RoutingContextCreateDHTRecordC = Void Function(
|
||||
Int64, Uint32, Uint32, Pointer<Utf8>);
|
||||
typedef _RoutingContextCreateDHTRecordDart = void Function(
|
||||
int, int, int, Pointer<Utf8>);
|
||||
// fn routing_context_open_dht_record(port: i64, id: u32, key: FfiStr, writer: FfiStr)
|
||||
typedef _RoutingContextOpenDHTRecordC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _RoutingContextOpenDHTRecordDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn routing_context_close_dht_record(port: i64, id: u32, key: FfiStr)
|
||||
typedef _RoutingContextCloseDHTRecordC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>);
|
||||
typedef _RoutingContextCloseDHTRecordDart = void Function(
|
||||
int, int, Pointer<Utf8>);
|
||||
// fn routing_context_delete_dht_record(port: i64, id: u32, key: FfiStr)
|
||||
typedef _RoutingContextDeleteDHTRecordC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>);
|
||||
typedef _RoutingContextDeleteDHTRecordDart = void Function(
|
||||
int, int, Pointer<Utf8>);
|
||||
// fn routing_context_get_dht_value(port: i64, id: u32, key: FfiStr, subkey: u32, force_refresh: bool)
|
||||
typedef _RoutingContextGetDHTValueC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Uint32, Bool);
|
||||
typedef _RoutingContextGetDHTValueDart = void Function(
|
||||
int, int, Pointer<Utf8>, int, bool);
|
||||
// fn routing_context_set_dht_value(port: i64, id: u32, key: FfiStr, subkey: u32, data: FfiStr)
|
||||
typedef _RoutingContextSetDHTValueC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Uint32, Pointer<Utf8>);
|
||||
typedef _RoutingContextSetDHTValueDart = void Function(
|
||||
int, int, Pointer<Utf8>, int, Pointer<Utf8>);
|
||||
// fn routing_context_watch_dht_values(port: i64, id: u32, key: FfiStr, subkeys: FfiStr, expiration: FfiStr, count: u32)
|
||||
typedef _RoutingContextWatchDHTValuesC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>, Uint64, Uint32);
|
||||
typedef _RoutingContextWatchDHTValuesDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>, int, int);
|
||||
// fn routing_context_cancel_dht_watch(port: i64, id: u32, key: FfiStr, subkeys: FfiStr)
|
||||
typedef _RoutingContextCancelDHTWatchC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _RoutingContextCancelDHTWatchDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
|
||||
// fn new_private_route(port: i64)
|
||||
typedef _NewPrivateRouteC = Void Function(Int64);
|
||||
@@ -108,9 +148,9 @@ typedef _DeleteTableDbDart = void Function(int, Pointer<Utf8>);
|
||||
// fn table_db_get_column_count(id: u32) -> u32
|
||||
typedef _TableDbGetColumnCountC = Uint32 Function(Uint32);
|
||||
typedef _TableDbGetColumnCountDart = int Function(int);
|
||||
// fn table_db_get_keys(id: u32, col: u32) -> *mut c_char
|
||||
typedef _TableDbGetKeysC = Pointer<Utf8> Function(Uint32, Uint32);
|
||||
typedef _TableDbGetKeysDart = Pointer<Utf8> Function(int, int);
|
||||
// fn table_db_get_keys(port: i64, id: u32, col: u32)
|
||||
typedef _TableDbGetKeysC = Pointer<Utf8> Function(Uint64, Uint32, Uint32);
|
||||
typedef _TableDbGetKeysDart = Pointer<Utf8> Function(int, int, int);
|
||||
// fn table_db_store(port: i64, id: u32, col: u32, key: FfiStr, value: FfiStr)
|
||||
typedef _TableDbStoreC = Void Function(
|
||||
Int64, Uint32, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
@@ -144,7 +184,116 @@ typedef _TableDbTransactionDeleteC = Void Function(
|
||||
Int64, Uint32, Uint32, Pointer<Utf8>);
|
||||
typedef _TableDbTransactionDeleteDart = void Function(
|
||||
int, int, int, Pointer<Utf8>);
|
||||
// fn valid_crypto_kinds() -> *mut c_char
|
||||
typedef _ValidCryptoKindsC = Pointer<Utf8> Function();
|
||||
typedef _ValidCryptoKindsDart = Pointer<Utf8> Function();
|
||||
// fn best_crypto_kind() -> u32
|
||||
typedef _BestCryptoKindC = Uint32 Function();
|
||||
typedef _BestCryptoKindDart = int Function();
|
||||
// fn verify_signatures(port: i64, node_ids: FfiStr, data: FfiStr, signatures: FfiStr)
|
||||
typedef _VerifySignaturesC = Void Function(
|
||||
Int64, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _VerifySignaturesDart = void Function(
|
||||
int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn generate_signatures(port: i64, data: FfiStr, key_pairs: FfiStr)
|
||||
typedef _GenerateSignaturesC = Void Function(
|
||||
Int64, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _GenerateSignaturesDart = void Function(
|
||||
int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn generate_key_pair(port: i64, kind: u32) {
|
||||
typedef _GenerateKeyPairC = Void Function(Int64, Uint32);
|
||||
typedef _GenerateKeyPairDart = void Function(int, int);
|
||||
// fn crypto_cached_dh(port: i64, kind: u32, key: FfiStr, secret: FfiStr)
|
||||
typedef _CryptoCachedDHC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoCachedDHDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_compute_dh(port: i64, kind: u32, key: FfiStr, secret: FfiStr)
|
||||
typedef _CryptoComputeDHC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoComputeDHDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_random_bytes(port: i64, kind: u32, len: u32)
|
||||
typedef _CryptoRandomBytesC = Void Function(Int64, Uint32, Uint32);
|
||||
typedef _CryptoRandomBytesDart = void Function(int, int, int);
|
||||
// fn crypto_default_salt_length(port: i64, kind: u32)
|
||||
typedef _CryptoDefaultSaltLengthC = Void Function(Int64, Uint32);
|
||||
typedef _CryptoDefaultSaltLengthDart = void Function(int, int);
|
||||
// fn crypto_hash_password(port: i64, kind: u32, password: FfiStr, salt: FfiStr )
|
||||
typedef _CryptoHashPasswordC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoHashPasswordDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_verify_password(port: i64, kind: u32, password: FfiStr, password_hash: FfiStr )
|
||||
typedef _CryptoVerifyPasswordC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoVerifyPasswordDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_derive_shared_secret(port: i64, kind: u32, password: FfiStr, salt: FfiStr )
|
||||
typedef _CryptoDeriveSharedSecretC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoDeriveSharedSecretDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
|
||||
// fn crypto_random_nonce(port: i64, kind: u32)
|
||||
typedef _CryptoRandomNonceC = Void Function(Int64, Uint32);
|
||||
typedef _CryptoRandomNonceDart = void Function(int, int);
|
||||
// fn crypto_random_shared_secret(port: i64, kind: u32)
|
||||
typedef _CryptoRandomSharedSecretC = Void Function(Int64, Uint32);
|
||||
typedef _CryptoRandomSharedSecretDart = void Function(int, int);
|
||||
// fn crypto_generate_key_pair(port: i64, kind: u32)
|
||||
typedef _CryptoGenerateKeyPairC = Void Function(Int64, Uint32);
|
||||
typedef _CryptoGenerateKeyPairDart = void Function(int, int);
|
||||
// fn crypto_generate_hash(port: i64, kind: u32, data: FfiStr)
|
||||
typedef _CryptoGenerateHashC = Void Function(Int64, Uint32, Pointer<Utf8>);
|
||||
typedef _CryptoGenerateHashDart = void Function(int, int, Pointer<Utf8>);
|
||||
// fn crypto_validate_key_pair(port: i64, kind: u32, key: FfiStr, secret: FfiStr)
|
||||
typedef _CryptoValidateKeyPairC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoValidateKeyPairDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_validate_hash(port: i64, kind: u32, data: FfiStr, hash: FfiStr)
|
||||
typedef _CryptoValidateHashC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoValidateHashDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_distance(port: i64, kind: u32, key1: FfiStr, key2: FfiStr)
|
||||
typedef _CryptoDistanceC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoDistanceDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_sign(port: i64, kind: u32, key: FfiStr, secret: FfiStr, data: FfiStr)
|
||||
typedef _CryptoSignC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoSignDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_verify(port: i64, kind: u32, key: FfiStr, data: FfiStr, signature: FfiStr)
|
||||
typedef _CryptoVerifyC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoVerifyDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_aead_overhead(port: i64, kind: u32)
|
||||
typedef _CryptoAeadOverheadC = Void Function(Int64, Uint32);
|
||||
typedef _CryptoAeadOverheadDart = void Function(int, int);
|
||||
// fn crypto_decrypt_aead(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr, associated_data: FfiStr)
|
||||
typedef _CryptoDecryptAeadC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoDecryptAeadDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_encrypt_aead(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr, associated_data: FfiStr)
|
||||
typedef _CryptoEncryptAeadC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoEncryptAeadDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn crypto_crypt_no_auth(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr)
|
||||
typedef _CryptoCryptNoAuthC = Void Function(
|
||||
Int64, Uint32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _CryptoCryptNoAuthDart = void Function(
|
||||
int, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
|
||||
|
||||
// fn now() -> u64
|
||||
typedef _NowC = Uint64 Function();
|
||||
typedef _NowDart = int Function();
|
||||
// fn debug(port: i64, log_level: FfiStr)
|
||||
typedef _DebugC = Void Function(Int64, Pointer<Utf8>);
|
||||
typedef _DebugDart = void Function(int, Pointer<Utf8>);
|
||||
@@ -156,7 +305,7 @@ typedef _VeilidVersionStringC = Pointer<Utf8> Function();
|
||||
typedef _VeilidVersionStringDart = Pointer<Utf8> Function();
|
||||
|
||||
// fn veilid_version() -> VeilidVersion
|
||||
class VeilidVersionFFI extends Struct {
|
||||
final class VeilidVersionFFI extends Struct {
|
||||
@Uint32()
|
||||
external int major;
|
||||
@Uint32()
|
||||
@@ -253,6 +402,42 @@ Future<T> processFutureJson<T>(
|
||||
});
|
||||
}
|
||||
|
||||
Future<T?> processFutureOptJson<T>(
|
||||
T Function(dynamic) jsonConstructor, Future<dynamic> future) {
|
||||
return future.then((value) {
|
||||
final list = value as List<dynamic>;
|
||||
switch (list[0] as int) {
|
||||
case messageErr:
|
||||
{
|
||||
throw VeilidAPIExceptionInternal("Internal API Error: ${list[1]}");
|
||||
}
|
||||
case messageOkJson:
|
||||
{
|
||||
if (list[1] == null) {
|
||||
return null;
|
||||
}
|
||||
var ret = jsonDecode(list[1] as String);
|
||||
return jsonConstructor(ret);
|
||||
}
|
||||
case messageErrJson:
|
||||
{
|
||||
throw VeilidAPIException.fromJson(jsonDecode(list[1]));
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw VeilidAPIExceptionInternal(
|
||||
"Unexpected async return message type: ${list[0]}");
|
||||
}
|
||||
}
|
||||
}).catchError((e) {
|
||||
// Wrap all other errors in VeilidAPIExceptionInternal
|
||||
throw VeilidAPIExceptionInternal(e.toString());
|
||||
}, test: (e) {
|
||||
// Pass errors that are already VeilidAPIException through without wrapping
|
||||
return e is! VeilidAPIException;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> processFutureVoid(Future<dynamic> future) {
|
||||
return future.then((value) {
|
||||
final list = value as List<dynamic>;
|
||||
@@ -397,7 +582,7 @@ class _Ctx {
|
||||
class VeilidRoutingContextFFI implements VeilidRoutingContext {
|
||||
final _Ctx _ctx;
|
||||
static final Finalizer<_Ctx> _finalizer =
|
||||
Finalizer((ctx) => {ctx.ffi._releaseRoutingContext(ctx.id)});
|
||||
Finalizer((ctx) => ctx.ffi._releaseRoutingContext(ctx.id));
|
||||
|
||||
VeilidRoutingContextFFI._(this._ctx) {
|
||||
_finalizer.attach(this, _ctx, detach: this);
|
||||
@@ -412,14 +597,14 @@ class VeilidRoutingContextFFI implements VeilidRoutingContext {
|
||||
@override
|
||||
VeilidRoutingContextFFI withCustomPrivacy(Stability stability) {
|
||||
final newId = _ctx.ffi._routingContextWithCustomPrivacy(
|
||||
_ctx.id, stability.json.toNativeUtf8());
|
||||
_ctx.id, jsonEncode(stability).toNativeUtf8());
|
||||
return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi));
|
||||
}
|
||||
|
||||
@override
|
||||
VeilidRoutingContextFFI withSequencing(Sequencing sequencing) {
|
||||
final newId = _ctx.ffi
|
||||
._routingContextWithSequencing(_ctx.id, sequencing.json.toNativeUtf8());
|
||||
final newId = _ctx.ffi._routingContextWithSequencing(
|
||||
_ctx.id, jsonEncode(sequencing).toNativeUtf8());
|
||||
return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi));
|
||||
}
|
||||
|
||||
@@ -437,7 +622,7 @@ class VeilidRoutingContextFFI implements VeilidRoutingContext {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> appMessage(String target, Uint8List message) async {
|
||||
Future<void> appMessage(String target, Uint8List message) {
|
||||
final nativeEncodedTarget = target.toNativeUtf8();
|
||||
final nativeEncodedMessage = base64UrlNoPadEncode(message).toNativeUtf8();
|
||||
|
||||
@@ -447,6 +632,111 @@ class VeilidRoutingContextFFI implements VeilidRoutingContext {
|
||||
nativeEncodedTarget, nativeEncodedMessage);
|
||||
return processFutureVoid(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DHTRecordDescriptor> createDHTRecord(
|
||||
CryptoKind kind, DHTSchema schema) async {
|
||||
final nativeSchema = jsonEncode(schema).toNativeUtf8();
|
||||
final recvPort = ReceivePort("routing_context_create_dht_record");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextCreateDHTRecord(
|
||||
sendPort.nativePort, _ctx.id, kind, nativeSchema);
|
||||
final dhtRecordDescriptor =
|
||||
await processFutureJson(DHTRecordDescriptor.fromJson, recvPort.first);
|
||||
return dhtRecordDescriptor;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DHTRecordDescriptor> openDHTRecord(
|
||||
TypedKey key, KeyPair? writer) async {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeWriter =
|
||||
writer != null ? jsonEncode(key).toNativeUtf8() : nullptr;
|
||||
final recvPort = ReceivePort("routing_context_open_dht_record");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextOpenDHTRecord(
|
||||
sendPort.nativePort, _ctx.id, nativeKey, nativeWriter);
|
||||
final dhtRecordDescriptor =
|
||||
await processFutureJson(DHTRecordDescriptor.fromJson, recvPort.first);
|
||||
return dhtRecordDescriptor;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> closeDHTRecord(TypedKey key) {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final recvPort = ReceivePort("routing_context_close_dht_record");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi
|
||||
._routingContextCloseDHTRecord(sendPort.nativePort, _ctx.id, nativeKey);
|
||||
return processFutureVoid(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteDHTRecord(TypedKey key) {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final recvPort = ReceivePort("routing_context_delete_dht_record");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextDeleteDHTRecord(
|
||||
sendPort.nativePort, _ctx.id, nativeKey);
|
||||
return processFutureVoid(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ValueData?> getDHTValue(
|
||||
TypedKey key, int subkey, bool forceRefresh) async {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final recvPort = ReceivePort("routing_context_get_dht_value");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextGetDHTValue(
|
||||
sendPort.nativePort, _ctx.id, nativeKey, subkey, forceRefresh);
|
||||
final valueData = await processFutureJson(
|
||||
optFromJson(ValueData.fromJson), recvPort.first);
|
||||
return valueData;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ValueData?> setDHTValue(
|
||||
TypedKey key, int subkey, Uint8List data) async {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeData = base64UrlNoPadEncode(data).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("routing_context_set_dht_value");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextSetDHTValue(
|
||||
sendPort.nativePort, _ctx.id, nativeKey, subkey, nativeData);
|
||||
final valueData = await processFutureJson(
|
||||
optFromJson(ValueData.fromJson), recvPort.first);
|
||||
return valueData;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Timestamp> watchDHTValues(TypedKey key, ValueSubkeyRange subkeys,
|
||||
Timestamp expiration, int count) async {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8();
|
||||
final nativeExpiration = expiration.value.toInt();
|
||||
|
||||
final recvPort = ReceivePort("routing_context_watch_dht_values");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextWatchDHTValues(sendPort.nativePort, _ctx.id,
|
||||
nativeKey, nativeSubkeys, nativeExpiration, count);
|
||||
final actualExpiration = Timestamp(
|
||||
value: BigInt.from(await processFuturePlain<int>(recvPort.first)));
|
||||
return actualExpiration;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys) async {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("routing_context_cancel_dht_watch");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ctx.ffi._routingContextCancelDHTWatch(
|
||||
sendPort.nativePort, _ctx.id, nativeKey, nativeSubkeys);
|
||||
final cancelled = await processFuturePlain<bool>(recvPort.first);
|
||||
return cancelled;
|
||||
}
|
||||
}
|
||||
|
||||
class _TDBT {
|
||||
@@ -461,7 +751,7 @@ class _TDBT {
|
||||
class VeilidTableDBTransactionFFI extends VeilidTableDBTransaction {
|
||||
final _TDBT _tdbt;
|
||||
static final Finalizer<_TDBT> _finalizer =
|
||||
Finalizer((tdbt) => {tdbt.ffi._releaseTableDbTransaction(tdbt.id)});
|
||||
Finalizer((tdbt) => tdbt.ffi._releaseTableDbTransaction(tdbt.id));
|
||||
|
||||
VeilidTableDBTransactionFFI._(this._tdbt) {
|
||||
_finalizer.attach(this, _tdbt, detach: this);
|
||||
@@ -532,7 +822,7 @@ class _TDB {
|
||||
class VeilidTableDBFFI extends VeilidTableDB {
|
||||
final _TDB _tdb;
|
||||
static final Finalizer<_TDB> _finalizer =
|
||||
Finalizer((tdb) => {tdb.ffi._releaseTableDb(tdb.id)});
|
||||
Finalizer((tdb) => tdb.ffi._releaseTableDb(tdb.id));
|
||||
|
||||
VeilidTableDBFFI._(this._tdb) {
|
||||
_finalizer.attach(this, _tdb, detach: this);
|
||||
@@ -544,15 +834,15 @@ class VeilidTableDBFFI extends VeilidTableDB {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Uint8List> getKeys(int col) {
|
||||
final s = _tdb.ffi._tableDbGetKeys(_tdb.id, col);
|
||||
if (s.address == nullptr.address) {
|
||||
throw VeilidAPIExceptionInternal("No db for id");
|
||||
}
|
||||
String ja = s.toDartString();
|
||||
_tdb.ffi._freeString(s);
|
||||
List<dynamic> jarr = jsonDecode(ja);
|
||||
return jarr.map((e) => base64UrlNoPadDecode(e)).toList();
|
||||
Future<List<Uint8List>> getKeys(int col) {
|
||||
final recvPort = ReceivePort("veilid_table_db_get_keys");
|
||||
final sendPort = recvPort.sendPort;
|
||||
|
||||
_tdb.ffi._tableDbGetKeys(sendPort.nativePort, _tdb.id, col);
|
||||
|
||||
return processFutureJson(
|
||||
jsonListConstructor<Uint8List>(base64UrlNoPadDecodeDynamic),
|
||||
recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -598,12 +888,12 @@ class VeilidTableDBFFI extends VeilidTableDB {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> delete(int col, Uint8List key) {
|
||||
Future<Uint8List?> delete(int col, Uint8List key) {
|
||||
final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("veilid_table_db_delete");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_tdb.ffi._tableDbLoad(
|
||||
_tdb.ffi._tableDbDelete(
|
||||
sendPort.nativePort,
|
||||
_tdb.id,
|
||||
col,
|
||||
@@ -613,6 +903,251 @@ class VeilidTableDBFFI extends VeilidTableDB {
|
||||
}
|
||||
}
|
||||
|
||||
// FFI implementation of VeilidCryptoSystem
|
||||
class VeilidCryptoSystemFFI implements VeilidCryptoSystem {
|
||||
final CryptoKind _kind;
|
||||
final VeilidFFI _ffi;
|
||||
|
||||
VeilidCryptoSystemFFI._(this._ffi, this._kind);
|
||||
|
||||
@override
|
||||
CryptoKind kind() {
|
||||
return _kind;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> cachedDH(PublicKey key, SecretKey secret) {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeSecret = jsonEncode(secret).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_cached_dh");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoCachedDH(sendPort.nativePort, _kind, nativeKey, nativeSecret);
|
||||
return processFutureJson(SharedSecret.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> computeDH(PublicKey key, SecretKey secret) {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeSecret = jsonEncode(secret).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_compute_dh");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoComputeDH(sendPort.nativePort, _kind, nativeKey, nativeSecret);
|
||||
return processFutureJson(SharedSecret.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> randomBytes(int len) async {
|
||||
final recvPort = ReceivePort("crypto_random_bytes");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoRandomBytes(sendPort.nativePort, _kind, len);
|
||||
final out = await processFuturePlain(recvPort.first);
|
||||
return base64UrlNoPadDecode(out);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> defaultSaltLength() {
|
||||
final recvPort = ReceivePort("crypto_default_salt_length");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoDefaultSaltLength(sendPort.nativePort, _kind);
|
||||
return processFuturePlain(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> hashPassword(Uint8List password, Uint8List salt) {
|
||||
final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8();
|
||||
final nativeEncodedSalt = base64UrlNoPadEncode(salt).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_hash_password");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoHashPassword(
|
||||
sendPort.nativePort, _kind, nativeEncodedPassword, nativeEncodedSalt);
|
||||
return processFuturePlain(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> verifyPassword(Uint8List password, String passwordHash) {
|
||||
final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8();
|
||||
final nativeEncodedPasswordHash = passwordHash.toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_verify_password");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoVerifyPassword(sendPort.nativePort, _kind,
|
||||
nativeEncodedPassword, nativeEncodedPasswordHash);
|
||||
return processFuturePlain(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> deriveSharedSecret(Uint8List password, Uint8List salt) {
|
||||
final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8();
|
||||
final nativeEncodedSalt = base64UrlNoPadEncode(salt).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_derive_shared_secret");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoDeriveSharedSecret(
|
||||
sendPort.nativePort, _kind, nativeEncodedPassword, nativeEncodedSalt);
|
||||
return processFutureJson(SharedSecret.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Nonce> randomNonce() {
|
||||
final recvPort = ReceivePort("crypto_random_nonce");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoRandomNonce(sendPort.nativePort, _kind);
|
||||
return processFutureJson(Nonce.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> randomSharedSecret() {
|
||||
final recvPort = ReceivePort("crypto_random_shared_secret");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoRandomSharedSecret(sendPort.nativePort, _kind);
|
||||
return processFutureJson(SharedSecret.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<KeyPair> generateKeyPair() {
|
||||
final recvPort = ReceivePort("crypto_generate_key_pair");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoGenerateKeyPair(sendPort.nativePort, _kind);
|
||||
return processFutureJson(KeyPair.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<HashDigest> generateHash(Uint8List data) {
|
||||
final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_generate_hash");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoGenerateHash(sendPort.nativePort, _kind, nativeEncodedData);
|
||||
return processFutureJson(HashDigest.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> validateKeyPair(PublicKey key, SecretKey secret) {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeSecret = jsonEncode(secret).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_validate_key_pair");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoValidateKeyPair(
|
||||
sendPort.nativePort, _kind, nativeKey, nativeSecret);
|
||||
return processFuturePlain(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> validateHash(Uint8List data, HashDigest hash) {
|
||||
final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8();
|
||||
final nativeHash = jsonEncode(hash).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_validate_hash");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoValidateHash(
|
||||
sendPort.nativePort, _kind, nativeEncodedData, nativeHash);
|
||||
return processFuturePlain(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CryptoKeyDistance> distance(CryptoKey key1, CryptoKey key2) {
|
||||
final nativeKey1 = jsonEncode(key1).toNativeUtf8();
|
||||
final nativeKey2 = jsonEncode(key2).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_distance");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoDistance(sendPort.nativePort, _kind, nativeKey1, nativeKey2);
|
||||
return processFutureJson(CryptoKeyDistance.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Signature> sign(PublicKey key, SecretKey secret, Uint8List data) {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeSecret = jsonEncode(secret).toNativeUtf8();
|
||||
final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_sign");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoSign(
|
||||
sendPort.nativePort, _kind, nativeKey, nativeSecret, nativeEncodedData);
|
||||
return processFutureJson(Signature.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> verify(PublicKey key, Uint8List data, Signature signature) {
|
||||
final nativeKey = jsonEncode(key).toNativeUtf8();
|
||||
final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8();
|
||||
final nativeSignature = jsonEncode(signature).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_verify");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoVerify(sendPort.nativePort, _kind, nativeKey, nativeEncodedData,
|
||||
nativeSignature);
|
||||
return processFutureVoid(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> aeadOverhead() {
|
||||
final recvPort = ReceivePort("crypto_aead_overhead");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoAeadOverhead(
|
||||
sendPort.nativePort,
|
||||
_kind,
|
||||
);
|
||||
return processFuturePlain(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> decryptAead(Uint8List body, Nonce nonce,
|
||||
SharedSecret sharedSecret, Uint8List? associatedData) async {
|
||||
final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8();
|
||||
final nativeNonce = jsonEncode(nonce).toNativeUtf8();
|
||||
final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8();
|
||||
final nativeSignature = (associatedData != null)
|
||||
? jsonEncode(associatedData).toNativeUtf8()
|
||||
: nullptr;
|
||||
|
||||
final recvPort = ReceivePort("crypto_decrypt_aead");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoDecryptAead(sendPort.nativePort, _kind, nativeEncodedBody,
|
||||
nativeNonce, nativeSharedSecret, nativeSignature);
|
||||
final out = await processFuturePlain(recvPort.first);
|
||||
return base64UrlNoPadDecode(out);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> encryptAead(Uint8List body, Nonce nonce,
|
||||
SharedSecret sharedSecret, Uint8List? associatedData) async {
|
||||
final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8();
|
||||
final nativeNonce = jsonEncode(nonce).toNativeUtf8();
|
||||
final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8();
|
||||
final nativeSignature = (associatedData != null)
|
||||
? jsonEncode(associatedData).toNativeUtf8()
|
||||
: nullptr;
|
||||
|
||||
final recvPort = ReceivePort("crypto_encrypt_aead");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoEncryptAead(sendPort.nativePort, _kind, nativeEncodedBody,
|
||||
nativeNonce, nativeSharedSecret, nativeSignature);
|
||||
final out = await processFuturePlain(recvPort.first);
|
||||
return base64UrlNoPadDecode(out);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> cryptNoAuth(
|
||||
Uint8List body, Nonce nonce, SharedSecret sharedSecret) async {
|
||||
final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8();
|
||||
final nativeNonce = jsonEncode(nonce).toNativeUtf8();
|
||||
final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("crypto_crypt_no_auth");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_ffi._cryptoCryptNoAuth(sendPort.nativePort, _kind, nativeEncodedBody,
|
||||
nativeNonce, nativeSharedSecret);
|
||||
final out = await processFuturePlain(recvPort.first);
|
||||
return base64UrlNoPadDecode(out);
|
||||
}
|
||||
}
|
||||
|
||||
// FFI implementation of high level Veilid API
|
||||
class VeilidFFI implements Veilid {
|
||||
// veilid_core shared library
|
||||
@@ -635,6 +1170,14 @@ class VeilidFFI implements Veilid {
|
||||
final _RoutingContextWithSequencingDart _routingContextWithSequencing;
|
||||
final _RoutingContextAppCallDart _routingContextAppCall;
|
||||
final _RoutingContextAppMessageDart _routingContextAppMessage;
|
||||
final _RoutingContextCreateDHTRecordDart _routingContextCreateDHTRecord;
|
||||
final _RoutingContextOpenDHTRecordDart _routingContextOpenDHTRecord;
|
||||
final _RoutingContextCloseDHTRecordDart _routingContextCloseDHTRecord;
|
||||
final _RoutingContextDeleteDHTRecordDart _routingContextDeleteDHTRecord;
|
||||
final _RoutingContextGetDHTValueDart _routingContextGetDHTValue;
|
||||
final _RoutingContextSetDHTValueDart _routingContextSetDHTValue;
|
||||
final _RoutingContextWatchDHTValuesDart _routingContextWatchDHTValues;
|
||||
final _RoutingContextCancelDHTWatchDart _routingContextCancelDHTWatch;
|
||||
|
||||
final _NewPrivateRouteDart _newPrivateRoute;
|
||||
final _NewCustomPrivateRouteDart _newCustomPrivateRoute;
|
||||
@@ -658,6 +1201,36 @@ class VeilidFFI implements Veilid {
|
||||
final _TableDbTransactionStoreDart _tableDbTransactionStore;
|
||||
final _TableDbTransactionDeleteDart _tableDbTransactionDelete;
|
||||
|
||||
final _ValidCryptoKindsDart _validCryptoKinds;
|
||||
final _BestCryptoKindDart _bestCryptoKind;
|
||||
final _VerifySignaturesDart _verifySignatures;
|
||||
final _GenerateSignaturesDart _generateSignatures;
|
||||
final _GenerateKeyPairDart _generateKeyPair;
|
||||
|
||||
final _CryptoCachedDHDart _cryptoCachedDH;
|
||||
final _CryptoComputeDHDart _cryptoComputeDH;
|
||||
|
||||
final _CryptoRandomBytesDart _cryptoRandomBytes;
|
||||
final _CryptoDefaultSaltLengthDart _cryptoDefaultSaltLength;
|
||||
final _CryptoHashPasswordDart _cryptoHashPassword;
|
||||
final _CryptoVerifyPasswordDart _cryptoVerifyPassword;
|
||||
final _CryptoDeriveSharedSecretDart _cryptoDeriveSharedSecret;
|
||||
|
||||
final _CryptoRandomNonceDart _cryptoRandomNonce;
|
||||
final _CryptoRandomSharedSecretDart _cryptoRandomSharedSecret;
|
||||
final _CryptoGenerateKeyPairDart _cryptoGenerateKeyPair;
|
||||
final _CryptoGenerateHashDart _cryptoGenerateHash;
|
||||
final _CryptoValidateKeyPairDart _cryptoValidateKeyPair;
|
||||
final _CryptoValidateHashDart _cryptoValidateHash;
|
||||
final _CryptoDistanceDart _cryptoDistance;
|
||||
final _CryptoSignDart _cryptoSign;
|
||||
final _CryptoVerifyDart _cryptoVerify;
|
||||
final _CryptoAeadOverheadDart _cryptoAeadOverhead;
|
||||
final _CryptoDecryptAeadDart _cryptoDecryptAead;
|
||||
final _CryptoEncryptAeadDart _cryptoEncryptAead;
|
||||
final _CryptoCryptNoAuthDart _cryptoCryptNoAuth;
|
||||
|
||||
final _NowDart _now;
|
||||
final _DebugDart _debug;
|
||||
final _VeilidVersionStringDart _veilidVersionString;
|
||||
final _VeilidVersionDart _veilidVersion;
|
||||
@@ -703,6 +1276,36 @@ class VeilidFFI implements Veilid {
|
||||
_routingContextAppMessage = dylib.lookupFunction<
|
||||
_RoutingContextAppMessageC,
|
||||
_RoutingContextAppMessageDart>('routing_context_app_message'),
|
||||
_routingContextCreateDHTRecord = dylib.lookupFunction<
|
||||
_RoutingContextCreateDHTRecordC,
|
||||
_RoutingContextCreateDHTRecordDart>(
|
||||
'routing_context_create_dht_record'),
|
||||
_routingContextOpenDHTRecord = dylib.lookupFunction<
|
||||
_RoutingContextOpenDHTRecordC,
|
||||
_RoutingContextOpenDHTRecordDart>(
|
||||
'routing_context_open_dht_record'),
|
||||
_routingContextCloseDHTRecord = dylib.lookupFunction<
|
||||
_RoutingContextCloseDHTRecordC,
|
||||
_RoutingContextCloseDHTRecordDart>(
|
||||
'routing_context_close_dht_record'),
|
||||
_routingContextDeleteDHTRecord = dylib.lookupFunction<
|
||||
_RoutingContextDeleteDHTRecordC,
|
||||
_RoutingContextDeleteDHTRecordDart>(
|
||||
'routing_context_delete_dht_record'),
|
||||
_routingContextGetDHTValue = dylib.lookupFunction<
|
||||
_RoutingContextGetDHTValueC,
|
||||
_RoutingContextGetDHTValueDart>('routing_context_get_dht_value'),
|
||||
_routingContextSetDHTValue = dylib.lookupFunction<
|
||||
_RoutingContextSetDHTValueC,
|
||||
_RoutingContextSetDHTValueDart>('routing_context_set_dht_value'),
|
||||
_routingContextWatchDHTValues = dylib.lookupFunction<
|
||||
_RoutingContextWatchDHTValuesC,
|
||||
_RoutingContextWatchDHTValuesDart>(
|
||||
'routing_context_watch_dht_values'),
|
||||
_routingContextCancelDHTWatch = dylib.lookupFunction<
|
||||
_RoutingContextCancelDHTWatchC,
|
||||
_RoutingContextCancelDHTWatchDart>(
|
||||
'routing_context_cancel_dht_watch'),
|
||||
_newPrivateRoute =
|
||||
dylib.lookupFunction<_NewPrivateRouteC, _NewPrivateRouteDart>(
|
||||
'new_private_route'),
|
||||
@@ -753,6 +1356,77 @@ class VeilidFFI implements Veilid {
|
||||
_tableDbTransactionDelete = dylib.lookupFunction<
|
||||
_TableDbTransactionDeleteC,
|
||||
_TableDbTransactionDeleteDart>('table_db_transaction_delete'),
|
||||
_validCryptoKinds =
|
||||
dylib.lookupFunction<_ValidCryptoKindsC, _ValidCryptoKindsDart>(
|
||||
'valid_crypto_kinds'),
|
||||
_bestCryptoKind =
|
||||
dylib.lookupFunction<_BestCryptoKindC, _BestCryptoKindDart>(
|
||||
'best_crypto_kind'),
|
||||
_verifySignatures =
|
||||
dylib.lookupFunction<_VerifySignaturesC, _VerifySignaturesDart>(
|
||||
'verify_signatures'),
|
||||
_generateSignatures =
|
||||
dylib.lookupFunction<_GenerateSignaturesC, _GenerateSignaturesDart>(
|
||||
'generate_signatures'),
|
||||
_generateKeyPair =
|
||||
dylib.lookupFunction<_GenerateKeyPairC, _GenerateKeyPairDart>(
|
||||
'generate_key_pair'),
|
||||
_cryptoCachedDH =
|
||||
dylib.lookupFunction<_CryptoCachedDHC, _CryptoCachedDHDart>(
|
||||
'crypto_cached_dh'),
|
||||
_cryptoComputeDH =
|
||||
dylib.lookupFunction<_CryptoComputeDHC, _CryptoComputeDHDart>(
|
||||
'crypto_compute_dh'),
|
||||
_cryptoRandomBytes =
|
||||
dylib.lookupFunction<_CryptoRandomBytesC, _CryptoRandomBytesDart>(
|
||||
'crypto_random_bytes'),
|
||||
_cryptoDefaultSaltLength = dylib.lookupFunction<
|
||||
_CryptoDefaultSaltLengthC,
|
||||
_CryptoDefaultSaltLengthDart>('crypto_default_salt_length'),
|
||||
_cryptoHashPassword =
|
||||
dylib.lookupFunction<_CryptoHashPasswordC, _CryptoHashPasswordDart>(
|
||||
'crypto_hash_password'),
|
||||
_cryptoVerifyPassword = dylib.lookupFunction<_CryptoVerifyPasswordC,
|
||||
_CryptoVerifyPasswordDart>('crypto_verify_password'),
|
||||
_cryptoDeriveSharedSecret = dylib.lookupFunction<
|
||||
_CryptoDeriveSharedSecretC,
|
||||
_CryptoVerifyPasswordDart>('crypto_derive_shared_secret'),
|
||||
_cryptoRandomNonce =
|
||||
dylib.lookupFunction<_CryptoRandomNonceC, _CryptoRandomNonceDart>(
|
||||
'crypto_random_nonce'),
|
||||
_cryptoRandomSharedSecret = dylib.lookupFunction<
|
||||
_CryptoRandomSharedSecretC,
|
||||
_CryptoRandomSharedSecretDart>('crypto_random_shared_secret'),
|
||||
_cryptoGenerateKeyPair = dylib.lookupFunction<_CryptoGenerateKeyPairC,
|
||||
_CryptoGenerateKeyPairDart>('crypto_generate_key_pair'),
|
||||
_cryptoGenerateHash =
|
||||
dylib.lookupFunction<_CryptoGenerateHashC, _CryptoGenerateHashDart>(
|
||||
'crypto_generate_hash'),
|
||||
_cryptoValidateKeyPair = dylib.lookupFunction<_CryptoValidateKeyPairC,
|
||||
_CryptoValidateKeyPairDart>('crypto_validate_key_pair'),
|
||||
_cryptoValidateHash =
|
||||
dylib.lookupFunction<_CryptoValidateHashC, _CryptoValidateHashDart>(
|
||||
'crypto_validate_hash'),
|
||||
_cryptoDistance =
|
||||
dylib.lookupFunction<_CryptoDistanceC, _CryptoDistanceDart>(
|
||||
'crypto_distance'),
|
||||
_cryptoSign =
|
||||
dylib.lookupFunction<_CryptoSignC, _CryptoSignDart>('crypto_sign'),
|
||||
_cryptoVerify = dylib
|
||||
.lookupFunction<_CryptoVerifyC, _CryptoVerifyDart>('crypto_verify'),
|
||||
_cryptoAeadOverhead =
|
||||
dylib.lookupFunction<_CryptoAeadOverheadC, _CryptoAeadOverheadDart>(
|
||||
'crypto_aead_overhead'),
|
||||
_cryptoDecryptAead =
|
||||
dylib.lookupFunction<_CryptoDecryptAeadC, _CryptoDecryptAeadDart>(
|
||||
'crypto_decrypt_aead'),
|
||||
_cryptoEncryptAead =
|
||||
dylib.lookupFunction<_CryptoEncryptAeadC, _CryptoEncryptAeadDart>(
|
||||
'crypto_encrypt_aead'),
|
||||
_cryptoCryptNoAuth =
|
||||
dylib.lookupFunction<_CryptoCryptNoAuthC, _CryptoCryptNoAuthDart>(
|
||||
'crypto_crypt_no_auth'),
|
||||
_now = dylib.lookupFunction<_NowC, _NowDart>('now'),
|
||||
_debug = dylib.lookupFunction<_DebugC, _DebugDart>('debug'),
|
||||
_veilidVersionString = dylib.lookupFunction<_VeilidVersionStringC,
|
||||
_VeilidVersionStringDart>('veilid_version_string'),
|
||||
@@ -768,9 +1442,7 @@ class VeilidFFI implements Veilid {
|
||||
|
||||
@override
|
||||
void initializeVeilidCore(Map<String, dynamic> platformConfigJson) {
|
||||
var nativePlatformConfig =
|
||||
jsonEncode(platformConfigJson, toEncodable: veilidApiToEncodable)
|
||||
.toNativeUtf8();
|
||||
var nativePlatformConfig = jsonEncode(platformConfigJson).toNativeUtf8();
|
||||
|
||||
_initializeVeilidCore(nativePlatformConfig);
|
||||
|
||||
@@ -779,9 +1451,7 @@ class VeilidFFI implements Veilid {
|
||||
|
||||
@override
|
||||
void changeLogLevel(String layer, VeilidConfigLogLevel logLevel) {
|
||||
var nativeLogLevel =
|
||||
jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable)
|
||||
.toNativeUtf8();
|
||||
var nativeLogLevel = jsonEncode(logLevel).toNativeUtf8();
|
||||
var nativeLayer = layer.toNativeUtf8();
|
||||
_changeLogLevel(nativeLayer, nativeLogLevel);
|
||||
malloc.free(nativeLayer);
|
||||
@@ -790,9 +1460,7 @@ class VeilidFFI implements Veilid {
|
||||
|
||||
@override
|
||||
Future<Stream<VeilidUpdate>> startupVeilidCore(VeilidConfig config) {
|
||||
var nativeConfig =
|
||||
jsonEncode(config.json, toEncodable: veilidApiToEncodable)
|
||||
.toNativeUtf8();
|
||||
var nativeConfig = jsonEncode(config).toNativeUtf8();
|
||||
final recvStreamPort = ReceivePort("veilid_api_stream");
|
||||
final sendStreamPort = recvStreamPort.sendPort;
|
||||
final recvPort = ReceivePort("startup_veilid_core");
|
||||
@@ -856,14 +1524,15 @@ class VeilidFFI implements Veilid {
|
||||
|
||||
@override
|
||||
Future<RouteBlob> newCustomPrivateRoute(
|
||||
Stability stability, Sequencing sequencing) async {
|
||||
Stability stability, Sequencing sequencing) {
|
||||
final recvPort = ReceivePort("new_custom_private_route");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_newCustomPrivateRoute(sendPort.nativePort, stability.json.toNativeUtf8(),
|
||||
sequencing.json.toNativeUtf8());
|
||||
final routeBlob =
|
||||
await processFutureJson(RouteBlob.fromJson, recvPort.first);
|
||||
return routeBlob;
|
||||
_newCustomPrivateRoute(
|
||||
sendPort.nativePort,
|
||||
jsonEncode(stability).toNativeUtf8(),
|
||||
jsonEncode(sequencing).toNativeUtf8());
|
||||
|
||||
return processFutureJson(RouteBlob.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -914,6 +1583,70 @@ class VeilidFFI implements Veilid {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@override
|
||||
List<CryptoKind> validCryptoKinds() {
|
||||
final vckString = _validCryptoKinds();
|
||||
final vck = jsonDecode(vckString.toDartString());
|
||||
_freeString(vckString);
|
||||
return vck;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<VeilidCryptoSystem> getCryptoSystem(CryptoKind kind) async {
|
||||
if (!validCryptoKinds().contains(kind)) {
|
||||
throw VeilidAPIExceptionGeneric("unsupported cryptosystem");
|
||||
}
|
||||
return VeilidCryptoSystemFFI._(this, kind);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<VeilidCryptoSystem> bestCryptoSystem() async {
|
||||
return VeilidCryptoSystemFFI._(this, _bestCryptoKind());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TypedKey>> verifySignatures(
|
||||
List<TypedKey> nodeIds, Uint8List data, List<TypedSignature> signatures) {
|
||||
final nativeNodeIds = jsonEncode(nodeIds).toNativeUtf8();
|
||||
final nativeData = base64UrlNoPadEncode(data).toNativeUtf8();
|
||||
final nativeSignatures = jsonEncode(signatures).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("verify_signatures");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_verifySignatures(
|
||||
sendPort.nativePort, nativeNodeIds, nativeData, nativeSignatures);
|
||||
return processFutureJson(
|
||||
jsonListConstructor<TypedKey>(TypedKey.fromJson), recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TypedSignature>> generateSignatures(
|
||||
Uint8List data, List<TypedKeyPair> keyPairs) {
|
||||
final nativeData = base64UrlNoPadEncode(data).toNativeUtf8();
|
||||
final nativeKeyPairs = jsonEncode(keyPairs).toNativeUtf8();
|
||||
|
||||
final recvPort = ReceivePort("generate_signatures");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_generateSignatures(sendPort.nativePort, nativeData, nativeKeyPairs);
|
||||
return processFutureJson(
|
||||
jsonListConstructor<TypedSignature>(TypedSignature.fromJson),
|
||||
recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Timestamp now() {
|
||||
final ts = _now();
|
||||
return Timestamp(value: BigInt.from(ts));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TypedKeyPair> generateKeyPair(CryptoKind kind) {
|
||||
final recvPort = ReceivePort("generate_key_pair");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_generateKeyPair(sendPort.nativePort, kind);
|
||||
return processFutureJson(TypedKeyPair.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> debug(String command) async {
|
||||
var nativeCommand = command.toNativeUtf8();
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'base64url_no_pad.dart';
|
||||
import 'veilid_encoding.dart';
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
@@ -30,9 +30,8 @@ class _Ctx {
|
||||
// JS implementation of VeilidRoutingContext
|
||||
class VeilidRoutingContextJS implements VeilidRoutingContext {
|
||||
final _Ctx _ctx;
|
||||
static final Finalizer<_Ctx> _finalizer = Finalizer((ctx) => {
|
||||
js_util.callMethod(wasm, "release_routing_context", [ctx.id])
|
||||
});
|
||||
static final Finalizer<_Ctx> _finalizer = Finalizer(
|
||||
(ctx) => js_util.callMethod(wasm, "release_routing_context", [ctx.id]));
|
||||
|
||||
VeilidRoutingContextJS._(this._ctx) {
|
||||
_finalizer.attach(this, _ctx, detach: this);
|
||||
@@ -48,15 +47,17 @@ class VeilidRoutingContextJS implements VeilidRoutingContext {
|
||||
@override
|
||||
VeilidRoutingContextJS withCustomPrivacy(Stability stability) {
|
||||
final newId = js_util.callMethod(
|
||||
wasm, "routing_context_with_custom_privacy", [_ctx.id, stability.json]);
|
||||
wasm,
|
||||
"routing_context_with_custom_privacy",
|
||||
[_ctx.id, jsonEncode(stability)]);
|
||||
|
||||
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
|
||||
}
|
||||
|
||||
@override
|
||||
VeilidRoutingContextJS withSequencing(Sequencing sequencing) {
|
||||
final newId = js_util.callMethod(
|
||||
wasm, "routing_context_with_sequencing", [_ctx.id, sequencing.json]);
|
||||
final newId = js_util.callMethod(wasm, "routing_context_with_sequencing",
|
||||
[_ctx.id, jsonEncode(sequencing)]);
|
||||
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
|
||||
}
|
||||
|
||||
@@ -75,6 +76,254 @@ class VeilidRoutingContextJS implements VeilidRoutingContext {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm,
|
||||
"routing_context_app_message", [_ctx.id, target, encodedMessage]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DHTRecordDescriptor> createDHTRecord(
|
||||
CryptoKind kind, DHTSchema schema) async {
|
||||
return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "routing_context_create_dht_record",
|
||||
[_ctx.id, kind, jsonEncode(schema)]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DHTRecordDescriptor> openDHTRecord(
|
||||
TypedKey key, KeyPair? writer) async {
|
||||
return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "routing_context_open_dht_record", [
|
||||
_ctx.id,
|
||||
jsonEncode(key),
|
||||
writer != null ? jsonEncode(writer) : null
|
||||
]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> closeDHTRecord(TypedKey key) {
|
||||
return _wrapApiPromise(js_util.callMethod(
|
||||
wasm, "routing_context_close_dht_record", [_ctx.id, jsonEncode(key)]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteDHTRecord(TypedKey key) {
|
||||
return _wrapApiPromise(js_util.callMethod(
|
||||
wasm, "routing_context_delete_dht_record", [_ctx.id, jsonEncode(key)]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ValueData?> getDHTValue(
|
||||
TypedKey key, int subkey, bool forceRefresh) async {
|
||||
final opt = await _wrapApiPromise(js_util.callMethod(
|
||||
wasm,
|
||||
"routing_context_get_dht_value",
|
||||
[_ctx.id, jsonEncode(key), subkey, forceRefresh]));
|
||||
return opt == null ? null : ValueData.fromJson(jsonDecode(opt));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ValueData?> setDHTValue(
|
||||
TypedKey key, int subkey, Uint8List data) async {
|
||||
final opt = await _wrapApiPromise(js_util.callMethod(
|
||||
wasm,
|
||||
"routing_context_set_dht_value",
|
||||
[_ctx.id, jsonEncode(key), subkey, base64UrlNoPadEncode(data)]));
|
||||
return opt == null ? null : ValueData.fromJson(jsonDecode(opt));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Timestamp> watchDHTValues(TypedKey key, ValueSubkeyRange subkeys,
|
||||
Timestamp expiration, int count) async {
|
||||
final ts = await _wrapApiPromise(js_util.callMethod(
|
||||
wasm, "routing_context_watch_dht_values", [
|
||||
_ctx.id,
|
||||
jsonEncode(key),
|
||||
jsonEncode(subkeys),
|
||||
expiration.toString(),
|
||||
count
|
||||
]));
|
||||
return Timestamp.fromString(ts);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> cancelDHTWatch(TypedKey key, ValueSubkeyRange subkeys) {
|
||||
return _wrapApiPromise(js_util.callMethod(
|
||||
wasm,
|
||||
"routing_context_cancel_dht_watch",
|
||||
[_ctx.id, jsonEncode(key), jsonEncode(subkeys)]));
|
||||
}
|
||||
}
|
||||
|
||||
// JS implementation of VeilidCryptoSystem
|
||||
class VeilidCryptoSystemJS implements VeilidCryptoSystem {
|
||||
final CryptoKind _kind;
|
||||
final VeilidJS _js;
|
||||
|
||||
VeilidCryptoSystemJS._(this._js, this._kind) {
|
||||
// Keep the reference
|
||||
_js;
|
||||
}
|
||||
|
||||
@override
|
||||
CryptoKind kind() {
|
||||
return _kind;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> cachedDH(PublicKey key, SecretKey secret) async {
|
||||
return SharedSecret.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "crypto_cached_dh",
|
||||
[_kind, jsonEncode(key), jsonEncode(secret)]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> computeDH(PublicKey key, SecretKey secret) async {
|
||||
return SharedSecret.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "crypto_compute_dh",
|
||||
[_kind, jsonEncode(key), jsonEncode(secret)]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> randomBytes(int len) async {
|
||||
return base64UrlNoPadDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "crypto_random_bytes", [_kind, len])));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> defaultSaltLength() {
|
||||
return _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "crypto_default_salt_length", [_kind]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> hashPassword(Uint8List password, Uint8List salt) {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm, "crypto_hash_password",
|
||||
[_kind, base64UrlNoPadEncode(password), base64UrlNoPadEncode(salt)]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> verifyPassword(Uint8List password, String passwordHash) {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm, "crypto_verify_password",
|
||||
[_kind, base64UrlNoPadEncode(password), passwordHash]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> deriveSharedSecret(
|
||||
Uint8List password, Uint8List salt) async {
|
||||
return SharedSecret.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "crypto_derive_shared_secret", [
|
||||
_kind,
|
||||
base64UrlNoPadEncode(password),
|
||||
base64UrlNoPadEncode(salt)
|
||||
]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Nonce> randomNonce() async {
|
||||
return Nonce.fromJson(jsonDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "crypto_random_nonce", [_kind]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SharedSecret> randomSharedSecret() async {
|
||||
return SharedSecret.fromJson(jsonDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "crypto_random_shared_secret", [_kind]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<KeyPair> generateKeyPair() async {
|
||||
return KeyPair.fromJson(jsonDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "crypto_generate_key_pair", [_kind]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<HashDigest> generateHash(Uint8List data) async {
|
||||
return HashDigest.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "crypto_generate_hash",
|
||||
[_kind, base64UrlNoPadEncode(data)]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> validateKeyPair(PublicKey key, SecretKey secret) {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm, "crypto_validate_key_pair",
|
||||
[_kind, jsonEncode(key), jsonEncode(secret)]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> validateHash(Uint8List data, HashDigest hash) {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm, "crypto_validate_hash",
|
||||
[_kind, base64UrlNoPadEncode(data), jsonEncode(hash)]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CryptoKeyDistance> distance(CryptoKey key1, CryptoKey key2) async {
|
||||
return CryptoKeyDistance.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "crypto_distance",
|
||||
[_kind, jsonEncode(key1), jsonEncode(key2)]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Signature> sign(
|
||||
PublicKey key, SecretKey secret, Uint8List data) async {
|
||||
return Signature.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(wasm, "crypto_sign", [
|
||||
_kind,
|
||||
jsonEncode(key),
|
||||
jsonEncode(secret),
|
||||
base64UrlNoPadEncode(data)
|
||||
]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> verify(PublicKey key, Uint8List data, Signature signature) {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm, "crypto_verify", [
|
||||
_kind,
|
||||
jsonEncode(key),
|
||||
base64UrlNoPadEncode(data),
|
||||
jsonEncode(signature),
|
||||
]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> aeadOverhead() {
|
||||
return _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "crypto_aead_overhead", [_kind]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> decryptAead(Uint8List body, Nonce nonce,
|
||||
SharedSecret sharedSecret, Uint8List? associatedData) async {
|
||||
return base64UrlNoPadDecode(
|
||||
await _wrapApiPromise(js_util.callMethod(wasm, "crypto_decrypt_aead", [
|
||||
_kind,
|
||||
base64UrlNoPadEncode(body),
|
||||
jsonEncode(nonce),
|
||||
jsonEncode(sharedSecret),
|
||||
associatedData != null ? base64UrlNoPadEncode(associatedData) : null
|
||||
])));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> encryptAead(Uint8List body, Nonce nonce,
|
||||
SharedSecret sharedSecret, Uint8List? associatedData) async {
|
||||
return base64UrlNoPadDecode(
|
||||
await _wrapApiPromise(js_util.callMethod(wasm, "crypto_encrypt_aead", [
|
||||
_kind,
|
||||
base64UrlNoPadEncode(body),
|
||||
jsonEncode(nonce),
|
||||
jsonEncode(sharedSecret),
|
||||
associatedData != null ? base64UrlNoPadEncode(associatedData) : null
|
||||
])));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> cryptNoAuth(
|
||||
Uint8List body, Nonce nonce, SharedSecret sharedSecret) async {
|
||||
return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod(
|
||||
wasm, "crypto_crypt_no_auth", [
|
||||
_kind,
|
||||
base64UrlNoPadEncode(body),
|
||||
jsonEncode(nonce),
|
||||
jsonEncode(sharedSecret)
|
||||
])));
|
||||
}
|
||||
}
|
||||
|
||||
class _TDBT {
|
||||
@@ -88,9 +337,8 @@ class _TDBT {
|
||||
// JS implementation of VeilidTableDBTransaction
|
||||
class VeilidTableDBTransactionJS extends VeilidTableDBTransaction {
|
||||
final _TDBT _tdbt;
|
||||
static final Finalizer<_TDBT> _finalizer = Finalizer((tdbt) => {
|
||||
js_util.callMethod(wasm, "release_table_db_transaction", [tdbt.id])
|
||||
});
|
||||
static final Finalizer<_TDBT> _finalizer = Finalizer((tdbt) =>
|
||||
js_util.callMethod(wasm, "release_table_db_transaction", [tdbt.id]));
|
||||
|
||||
VeilidTableDBTransactionJS._(this._tdbt) {
|
||||
_finalizer.attach(this, _tdbt, detach: this);
|
||||
@@ -138,9 +386,8 @@ class _TDB {
|
||||
// JS implementation of VeilidTableDB
|
||||
class VeilidTableDBJS extends VeilidTableDB {
|
||||
final _TDB _tdb;
|
||||
static final Finalizer<_TDB> _finalizer = Finalizer((tdb) => {
|
||||
js_util.callMethod(wasm, "release_table_db", [tdb.id])
|
||||
});
|
||||
static final Finalizer<_TDB> _finalizer = Finalizer(
|
||||
(tdb) => js_util.callMethod(wasm, "release_table_db", [tdb.id]));
|
||||
|
||||
VeilidTableDBJS._(this._tdb) {
|
||||
_finalizer.attach(this, _tdb, detach: this);
|
||||
@@ -152,13 +399,9 @@ class VeilidTableDBJS extends VeilidTableDB {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Uint8List> getKeys(int col) {
|
||||
String? s = js_util.callMethod(wasm, "table_db_get_keys", [_tdb.id, col]);
|
||||
if (s == null) {
|
||||
throw VeilidAPIExceptionInternal("No db for id");
|
||||
}
|
||||
List<dynamic> jarr = jsonDecode(s);
|
||||
return jarr.map((e) => base64UrlNoPadDecode(e)).toList();
|
||||
Future<List<Uint8List>> getKeys(int col) async {
|
||||
return jsonListConstructor(base64UrlNoPadDecodeDynamic)(jsonDecode(
|
||||
await js_util.callMethod(wasm, "table_db_get_keys", [_tdb.id, col])));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -190,7 +433,7 @@ class VeilidTableDBJS extends VeilidTableDB {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> delete(int col, Uint8List key) {
|
||||
Future<Uint8List?> delete(int col, Uint8List key) {
|
||||
final encodedKey = base64UrlNoPadEncode(key);
|
||||
|
||||
return _wrapApiPromise(js_util
|
||||
@@ -203,16 +446,14 @@ class VeilidTableDBJS extends VeilidTableDB {
|
||||
class VeilidJS implements Veilid {
|
||||
@override
|
||||
void initializeVeilidCore(Map<String, dynamic> platformConfigJson) {
|
||||
var platformConfigJsonString =
|
||||
jsonEncode(platformConfigJson, toEncodable: veilidApiToEncodable);
|
||||
var platformConfigJsonString = jsonEncode(platformConfigJson);
|
||||
js_util
|
||||
.callMethod(wasm, "initialize_veilid_core", [platformConfigJsonString]);
|
||||
}
|
||||
|
||||
@override
|
||||
void changeLogLevel(String layer, VeilidConfigLogLevel logLevel) {
|
||||
var logLevelJsonString =
|
||||
jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable);
|
||||
var logLevelJsonString = jsonEncode(logLevel);
|
||||
js_util.callMethod(wasm, "change_log_level", [layer, logLevelJsonString]);
|
||||
}
|
||||
|
||||
@@ -229,10 +470,8 @@ class VeilidJS implements Veilid {
|
||||
}
|
||||
}
|
||||
|
||||
await _wrapApiPromise(js_util.callMethod(wasm, "startup_veilid_core", [
|
||||
js.allowInterop(updateCallback),
|
||||
jsonEncode(config.json, toEncodable: veilidApiToEncodable)
|
||||
]));
|
||||
await _wrapApiPromise(js_util.callMethod(wasm, "startup_veilid_core",
|
||||
[js.allowInterop(updateCallback), jsonEncode(config)]));
|
||||
|
||||
return streamController.stream;
|
||||
}
|
||||
@@ -259,6 +498,50 @@ class VeilidJS implements Veilid {
|
||||
js_util.callMethod(wasm, "shutdown_veilid_core", []));
|
||||
}
|
||||
|
||||
@override
|
||||
List<CryptoKind> validCryptoKinds() {
|
||||
return jsonDecode(js_util.callMethod(wasm, "valid_crypto_kinds", []));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<VeilidCryptoSystem> getCryptoSystem(CryptoKind kind) async {
|
||||
if (!validCryptoKinds().contains(kind)) {
|
||||
throw VeilidAPIExceptionGeneric("unsupported cryptosystem");
|
||||
}
|
||||
return VeilidCryptoSystemJS._(this, kind);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<VeilidCryptoSystem> bestCryptoSystem() async {
|
||||
return VeilidCryptoSystemJS._(
|
||||
this, js_util.callMethod(wasm, "best_crypto_kind", []));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TypedKey>> verifySignatures(List<TypedKey> nodeIds,
|
||||
Uint8List data, List<TypedSignature> signatures) async {
|
||||
return jsonListConstructor(TypedKey.fromJson)(jsonDecode(
|
||||
await _wrapApiPromise(js_util.callMethod(wasm, "verify_signatures", [
|
||||
jsonEncode(nodeIds),
|
||||
base64UrlNoPadEncode(data),
|
||||
jsonEncode(signatures)
|
||||
]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TypedSignature>> generateSignatures(
|
||||
Uint8List data, List<TypedKeyPair> keyPairs) async {
|
||||
return jsonListConstructor(TypedSignature.fromJson)(jsonDecode(
|
||||
await _wrapApiPromise(js_util.callMethod(wasm, "generate_signatures",
|
||||
[base64UrlNoPadEncode(data), jsonEncode(keyPairs)]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TypedKeyPair> generateKeyPair(CryptoKind kind) async {
|
||||
return TypedKeyPair.fromJson(jsonDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "generate_key_pair", [kind]))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<VeilidRoutingContext> routingContext() async {
|
||||
int id =
|
||||
@@ -268,23 +551,19 @@ class VeilidJS implements Veilid {
|
||||
|
||||
@override
|
||||
Future<RouteBlob> newPrivateRoute() async {
|
||||
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "new_private_route", [])));
|
||||
return RouteBlob.fromJson(blobJson);
|
||||
return RouteBlob.fromJson(jsonDecode(await _wrapApiPromise(
|
||||
js_util.callMethod(wasm, "new_private_route", []))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<RouteBlob> newCustomPrivateRoute(
|
||||
Stability stability, Sequencing sequencing) async {
|
||||
var stabilityString =
|
||||
jsonEncode(stability, toEncodable: veilidApiToEncodable);
|
||||
var sequencingString =
|
||||
jsonEncode(sequencing, toEncodable: veilidApiToEncodable);
|
||||
var stabilityString = jsonEncode(stability);
|
||||
var sequencingString = jsonEncode(sequencing);
|
||||
|
||||
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(js_util
|
||||
return RouteBlob.fromJson(jsonDecode(await _wrapApiPromise(js_util
|
||||
.callMethod(
|
||||
wasm, "new_private_route", [stabilityString, sequencingString])));
|
||||
return RouteBlob.fromJson(blobJson);
|
||||
wasm, "new_private_route", [stabilityString, sequencingString]))));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -319,6 +598,11 @@ class VeilidJS implements Veilid {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm, "delete_table_db", [name]));
|
||||
}
|
||||
|
||||
@override
|
||||
Timestamp now() {
|
||||
return Timestamp.fromString(js_util.callMethod(wasm, "now", []));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> debug(String command) async {
|
||||
return await _wrapApiPromise(js_util.callMethod(wasm, "debug", [command]));
|
||||
|
||||
@@ -0,0 +1,547 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:change_case/change_case.dart';
|
||||
|
||||
import 'veilid_encoding.dart';
|
||||
import 'veilid.dart';
|
||||
|
||||
//////////////////////////////////////
|
||||
/// AttachmentState
|
||||
|
||||
enum AttachmentState {
|
||||
detached,
|
||||
attaching,
|
||||
attachedWeak,
|
||||
attachedGood,
|
||||
attachedStrong,
|
||||
fullyAttached,
|
||||
overAttached,
|
||||
detaching;
|
||||
|
||||
String toJson() {
|
||||
return name.toPascalCase();
|
||||
}
|
||||
|
||||
factory AttachmentState.fromJson(String j) {
|
||||
return AttachmentState.values.byName(j.toCamelCase());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidLogLevel
|
||||
|
||||
enum VeilidLogLevel {
|
||||
error,
|
||||
warn,
|
||||
info,
|
||||
debug,
|
||||
trace;
|
||||
|
||||
String toJson() {
|
||||
return name.toPascalCase();
|
||||
}
|
||||
|
||||
factory VeilidLogLevel.fromJson(String j) {
|
||||
return VeilidLogLevel.values.byName(j.toCamelCase());
|
||||
}
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class LatencyStats {
|
||||
TimestampDuration fastest;
|
||||
TimestampDuration average;
|
||||
TimestampDuration slowest;
|
||||
|
||||
LatencyStats({
|
||||
required this.fastest,
|
||||
required this.average,
|
||||
required this.slowest,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'fastest': fastest.toJson(),
|
||||
'average': average.toJson(),
|
||||
'slowest': slowest.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
LatencyStats.fromJson(dynamic json)
|
||||
: fastest = TimestampDuration.fromJson(json['fastest']),
|
||||
average = TimestampDuration.fromJson(json['average']),
|
||||
slowest = TimestampDuration.fromJson(json['slowest']);
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class TransferStats {
|
||||
BigInt total;
|
||||
BigInt maximum;
|
||||
BigInt average;
|
||||
BigInt minimum;
|
||||
|
||||
TransferStats({
|
||||
required this.total,
|
||||
required this.maximum,
|
||||
required this.average,
|
||||
required this.minimum,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'total': total.toString(),
|
||||
'maximum': maximum.toString(),
|
||||
'average': average.toString(),
|
||||
'minimum': minimum.toString(),
|
||||
};
|
||||
}
|
||||
|
||||
TransferStats.fromJson(dynamic json)
|
||||
: total = BigInt.parse(json['total']),
|
||||
maximum = BigInt.parse(json['maximum']),
|
||||
average = BigInt.parse(json['average']),
|
||||
minimum = BigInt.parse(json['minimum']);
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class TransferStatsDownUp {
|
||||
TransferStats down;
|
||||
TransferStats up;
|
||||
|
||||
TransferStatsDownUp({
|
||||
required this.down,
|
||||
required this.up,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'down': down.toJson(),
|
||||
'up': up.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
TransferStatsDownUp.fromJson(dynamic json)
|
||||
: down = TransferStats.fromJson(json['down']),
|
||||
up = TransferStats.fromJson(json['up']);
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class RPCStats {
|
||||
int messagesSent;
|
||||
int messagesRcvd;
|
||||
int questionsInFlight;
|
||||
Timestamp? lastQuestion;
|
||||
Timestamp? lastSeenTs;
|
||||
Timestamp? firstConsecutiveSeenTs;
|
||||
int recentLostAnswers;
|
||||
int failedToSend;
|
||||
|
||||
RPCStats({
|
||||
required this.messagesSent,
|
||||
required this.messagesRcvd,
|
||||
required this.questionsInFlight,
|
||||
required this.lastQuestion,
|
||||
required this.lastSeenTs,
|
||||
required this.firstConsecutiveSeenTs,
|
||||
required this.recentLostAnswers,
|
||||
required this.failedToSend,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'messages_sent': messagesSent,
|
||||
'messages_rcvd': messagesRcvd,
|
||||
'questions_in_flight': questionsInFlight,
|
||||
'last_question': lastQuestion?.toJson(),
|
||||
'last_seen_ts': lastSeenTs?.toJson(),
|
||||
'first_consecutive_seen_ts': firstConsecutiveSeenTs?.toJson(),
|
||||
'recent_lost_answers': recentLostAnswers,
|
||||
'failed_to_send': failedToSend,
|
||||
};
|
||||
}
|
||||
|
||||
RPCStats.fromJson(dynamic json)
|
||||
: messagesSent = json['messages_sent'],
|
||||
messagesRcvd = json['messages_rcvd'],
|
||||
questionsInFlight = json['questions_in_flight'],
|
||||
lastQuestion = json['last_question'] != null
|
||||
? Timestamp.fromJson(json['last_question'])
|
||||
: null,
|
||||
lastSeenTs = json['last_seen_ts'] != null
|
||||
? Timestamp.fromJson(json['last_seen_ts'])
|
||||
: null,
|
||||
firstConsecutiveSeenTs = json['first_consecutive_seen_ts'] != null
|
||||
? Timestamp.fromJson(json['first_consecutive_seen_ts'])
|
||||
: null,
|
||||
recentLostAnswers = json['recent_lost_answers'],
|
||||
failedToSend = json['failed_to_send'];
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class PeerStats {
|
||||
Timestamp timeAdded;
|
||||
RPCStats rpcStats;
|
||||
LatencyStats? latency;
|
||||
TransferStatsDownUp transfer;
|
||||
|
||||
PeerStats({
|
||||
required this.timeAdded,
|
||||
required this.rpcStats,
|
||||
required this.latency,
|
||||
required this.transfer,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'time_added': timeAdded.toJson(),
|
||||
'rpc_stats': rpcStats.toJson(),
|
||||
'latency': latency?.toJson(),
|
||||
'transfer': transfer.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
PeerStats.fromJson(dynamic json)
|
||||
: timeAdded = Timestamp.fromJson(json['time_added']),
|
||||
rpcStats = RPCStats.fromJson(json['rpc_stats']),
|
||||
latency = json['latency'] != null
|
||||
? LatencyStats.fromJson(json['latency'])
|
||||
: null,
|
||||
transfer = TransferStatsDownUp.fromJson(json['transfer']);
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
class PeerTableData {
|
||||
List<TypedKey> nodeIds;
|
||||
String peerAddress;
|
||||
PeerStats peerStats;
|
||||
|
||||
PeerTableData({
|
||||
required this.nodeIds,
|
||||
required this.peerAddress,
|
||||
required this.peerStats,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'node_ids': nodeIds.map((p) => p.toJson()).toList(),
|
||||
'peer_address': peerAddress,
|
||||
'peer_stats': peerStats.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
PeerTableData.fromJson(dynamic json)
|
||||
: nodeIds = List<TypedKey>.from(
|
||||
json['node_ids'].map((j) => TypedKey.fromJson(j))),
|
||||
peerAddress = json['peer_address'],
|
||||
peerStats = PeerStats.fromJson(json['peer_stats']);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidUpdate
|
||||
|
||||
abstract class VeilidUpdate {
|
||||
factory VeilidUpdate.fromJson(dynamic json) {
|
||||
switch (json["kind"]) {
|
||||
case "Log":
|
||||
{
|
||||
return VeilidLog(
|
||||
logLevel: VeilidLogLevel.fromJson(json["log_level"]),
|
||||
message: json["message"],
|
||||
backtrace: json["backtrace"]);
|
||||
}
|
||||
case "AppMessage":
|
||||
{
|
||||
return VeilidAppMessage(
|
||||
sender: json["sender"], message: json["message"]);
|
||||
}
|
||||
case "AppCall":
|
||||
{
|
||||
return VeilidAppCall(
|
||||
sender: json["sender"], message: json["message"], id: json["id"]);
|
||||
}
|
||||
case "Attachment":
|
||||
{
|
||||
return VeilidUpdateAttachment(
|
||||
state: VeilidStateAttachment.fromJson(json));
|
||||
}
|
||||
case "Network":
|
||||
{
|
||||
return VeilidUpdateNetwork(state: VeilidStateNetwork.fromJson(json));
|
||||
}
|
||||
case "Config":
|
||||
{
|
||||
return VeilidUpdateConfig(state: VeilidStateConfig.fromJson(json));
|
||||
}
|
||||
case "RouteChange":
|
||||
{
|
||||
return VeilidUpdateRouteChange(
|
||||
deadRoutes: List<String>.from(json['dead_routes'].map((j) => j)),
|
||||
deadRemoteRoutes:
|
||||
List<String>.from(json['dead_remote_routes'].map((j) => j)));
|
||||
}
|
||||
case "ValueChange":
|
||||
{
|
||||
return VeilidUpdateValueChange(
|
||||
key: TypedKey.fromJson(json['key']),
|
||||
subkeys: List<ValueSubkeyRange>.from(
|
||||
json['subkeys'].map((j) => ValueSubkeyRange.fromJson(j))),
|
||||
count: json['count'],
|
||||
valueData: ValueData.fromJson(json['value_data']));
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw VeilidAPIExceptionInternal(
|
||||
"Invalid VeilidAPIException type: ${json['kind']}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, dynamic> toJson();
|
||||
}
|
||||
|
||||
class VeilidLog implements VeilidUpdate {
|
||||
final VeilidLogLevel logLevel;
|
||||
final String message;
|
||||
final String? backtrace;
|
||||
//
|
||||
VeilidLog({
|
||||
required this.logLevel,
|
||||
required this.message,
|
||||
required this.backtrace,
|
||||
});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'kind': "Log",
|
||||
'log_level': logLevel.toJson(),
|
||||
'message': message,
|
||||
'backtrace': backtrace
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAppMessage implements VeilidUpdate {
|
||||
final TypedKey? sender;
|
||||
final Uint8List message;
|
||||
|
||||
//
|
||||
VeilidAppMessage({
|
||||
required this.sender,
|
||||
required this.message,
|
||||
});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'kind': "AppMessage",
|
||||
'sender': sender,
|
||||
'message': base64UrlNoPadEncode(message)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidAppCall implements VeilidUpdate {
|
||||
final String? sender;
|
||||
final Uint8List message;
|
||||
final String id;
|
||||
|
||||
//
|
||||
VeilidAppCall({
|
||||
required this.sender,
|
||||
required this.message,
|
||||
required this.id,
|
||||
});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'kind': "AppMessage",
|
||||
'sender': sender,
|
||||
'message': base64UrlNoPadEncode(message),
|
||||
'id': id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidUpdateAttachment implements VeilidUpdate {
|
||||
final VeilidStateAttachment state;
|
||||
//
|
||||
VeilidUpdateAttachment({required this.state});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
var jsonRep = state.toJson();
|
||||
jsonRep['kind'] = "Attachment";
|
||||
return jsonRep;
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidUpdateNetwork implements VeilidUpdate {
|
||||
final VeilidStateNetwork state;
|
||||
//
|
||||
VeilidUpdateNetwork({required this.state});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
var jsonRep = state.toJson();
|
||||
jsonRep['kind'] = "Network";
|
||||
return jsonRep;
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidUpdateConfig implements VeilidUpdate {
|
||||
final VeilidStateConfig state;
|
||||
//
|
||||
VeilidUpdateConfig({required this.state});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
var jsonRep = state.toJson();
|
||||
jsonRep['kind'] = "Config";
|
||||
return jsonRep;
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidUpdateRouteChange implements VeilidUpdate {
|
||||
final List<String> deadRoutes;
|
||||
final List<String> deadRemoteRoutes;
|
||||
//
|
||||
VeilidUpdateRouteChange({
|
||||
required this.deadRoutes,
|
||||
required this.deadRemoteRoutes,
|
||||
});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'dead_routes': deadRoutes.map((p) => p).toList(),
|
||||
'dead_remote_routes': deadRemoteRoutes.map((p) => p).toList()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidUpdateValueChange implements VeilidUpdate {
|
||||
final TypedKey key;
|
||||
final List<ValueSubkeyRange> subkeys;
|
||||
final int count;
|
||||
final ValueData valueData;
|
||||
|
||||
//
|
||||
VeilidUpdateValueChange({
|
||||
required this.key,
|
||||
required this.subkeys,
|
||||
required this.count,
|
||||
required this.valueData,
|
||||
});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'key': key.toJson(),
|
||||
'subkeys': subkeys.map((p) => p.toJson()).toList(),
|
||||
'count': count,
|
||||
'value_data': valueData.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidStateAttachment
|
||||
|
||||
class VeilidStateAttachment {
|
||||
final AttachmentState state;
|
||||
final bool publicInternetReady;
|
||||
final bool localNetworkReady;
|
||||
|
||||
VeilidStateAttachment(
|
||||
this.state, this.publicInternetReady, this.localNetworkReady);
|
||||
|
||||
VeilidStateAttachment.fromJson(dynamic json)
|
||||
: state = AttachmentState.fromJson(json['state']),
|
||||
publicInternetReady = json['public_internet_ready'],
|
||||
localNetworkReady = json['local_network_ready'];
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'state': state.toJson(),
|
||||
'public_internet_ready': publicInternetReady,
|
||||
'local_network_ready': localNetworkReady,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidStateNetwork
|
||||
|
||||
class VeilidStateNetwork {
|
||||
final bool started;
|
||||
final BigInt bpsDown;
|
||||
final BigInt bpsUp;
|
||||
final List<PeerTableData> peers;
|
||||
|
||||
VeilidStateNetwork(
|
||||
{required this.started,
|
||||
required this.bpsDown,
|
||||
required this.bpsUp,
|
||||
required this.peers});
|
||||
|
||||
VeilidStateNetwork.fromJson(dynamic json)
|
||||
: started = json['started'],
|
||||
bpsDown = BigInt.parse(json['bps_down']),
|
||||
bpsUp = BigInt.parse(json['bps_up']),
|
||||
peers = List<PeerTableData>.from(
|
||||
json['peers'].map((j) => PeerTableData.fromJson(j)));
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'started': started,
|
||||
'bps_down': bpsDown.toString(),
|
||||
'bps_up': bpsUp.toString(),
|
||||
'peers': peers.map((p) => p.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidStateConfig
|
||||
|
||||
class VeilidStateConfig {
|
||||
final Map<String, dynamic> config;
|
||||
|
||||
VeilidStateConfig({
|
||||
required this.config,
|
||||
});
|
||||
|
||||
VeilidStateConfig.fromJson(dynamic json) : config = json['config'];
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'config': config};
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
/// VeilidState
|
||||
|
||||
class VeilidState {
|
||||
final VeilidStateAttachment attachment;
|
||||
final VeilidStateNetwork network;
|
||||
final VeilidStateConfig config;
|
||||
|
||||
VeilidState.fromJson(dynamic json)
|
||||
: attachment = VeilidStateAttachment.fromJson(json['attachment']),
|
||||
network = VeilidStateNetwork.fromJson(json['network']),
|
||||
config = VeilidStateConfig.fromJson(json['config']);
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'attachment': attachment.toJson(),
|
||||
'network': network.toJson(),
|
||||
'config': config.toJson()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:convert';
|
||||
|
||||
/////////////////////////////////////
|
||||
/// VeilidTableDB
|
||||
abstract class VeilidTableDBTransaction {
|
||||
Future<void> commit();
|
||||
Future<void> rollback();
|
||||
Future<void> store(int col, Uint8List key, Uint8List value);
|
||||
Future<bool> delete(int col, Uint8List key);
|
||||
|
||||
Future<void> storeJson(int col, Uint8List key, Object? object,
|
||||
{Object? Function(Object? nonEncodable)? toEncodable}) async {
|
||||
return store(col, key,
|
||||
utf8.encoder.convert(jsonEncode(object, toEncodable: toEncodable)));
|
||||
}
|
||||
|
||||
Future<void> storeStringJson(int col, String key, Object? object,
|
||||
{Object? Function(Object? nonEncodable)? toEncodable}) {
|
||||
return storeJson(col, utf8.encoder.convert(key), object,
|
||||
toEncodable: toEncodable);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class VeilidTableDB {
|
||||
int getColumnCount();
|
||||
Future<List<Uint8List>> getKeys(int col);
|
||||
VeilidTableDBTransaction transact();
|
||||
Future<void> store(int col, Uint8List key, Uint8List value);
|
||||
Future<Uint8List?> load(int col, Uint8List key);
|
||||
Future<Uint8List?> delete(int col, Uint8List key);
|
||||
|
||||
Future<void> storeJson(int col, Uint8List key, Object? object,
|
||||
{Object? Function(Object? nonEncodable)? toEncodable}) {
|
||||
return store(col, key,
|
||||
utf8.encoder.convert(jsonEncode(object, toEncodable: toEncodable)));
|
||||
}
|
||||
|
||||
Future<void> storeStringJson(int col, String key, Object? object,
|
||||
{Object? Function(Object? nonEncodable)? toEncodable}) {
|
||||
return storeJson(col, utf8.encoder.convert(key), object,
|
||||
toEncodable: toEncodable);
|
||||
}
|
||||
|
||||
Future<Object?> loadJson(int col, Uint8List key,
|
||||
{Object? Function(Object? key, Object? value)? reviver}) async {
|
||||
var s = await load(col, key);
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
return jsonDecode(utf8.decode(s, allowMalformed: false), reviver: reviver);
|
||||
}
|
||||
|
||||
Future<Object?> loadStringJson(int col, String key,
|
||||
{Object? Function(Object? key, Object? value)? reviver}) {
|
||||
return loadJson(col, utf8.encoder.convert(key), reviver: reviver);
|
||||
}
|
||||
|
||||
Future<Object?> deleteJson(int col, Uint8List key,
|
||||
{Object? Function(Object? key, Object? value)? reviver}) async {
|
||||
var s = await delete(col, key);
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
return jsonDecode(utf8.decode(s, allowMalformed: false), reviver: reviver);
|
||||
}
|
||||
|
||||
Future<Object?> deleteStringJson(int col, String key,
|
||||
{Object? Function(Object? key, Object? value)? reviver}) {
|
||||
return deleteJson(col, utf8.encoder.convert(key), reviver: reviver);
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,8 @@ Veilid Network Plugin
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.dependency 'FlutterMacOS'
|
||||
|
||||
s.platform = :osx, '10.12.2'
|
||||
s.osx.deployment_target = '10.12.2'
|
||||
s.platform = :osx, '10.14.6'
|
||||
s.osx.deployment_target = '10.14.6'
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
||||
s.swift_version = '5.0'
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ homepage: https://veilid.com
|
||||
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
environment:
|
||||
sdk: ">=2.16.1 <3.0.0"
|
||||
flutter: ">=2.5.0"
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
@@ -17,6 +16,8 @@ dependencies:
|
||||
change_case: ^1.0.1
|
||||
path_provider: ^2.0.9
|
||||
path: ^1.8.0
|
||||
system_info2: ^3.0.2
|
||||
charcode: ^1.3.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -27,10 +27,10 @@ data-encoding = { version = "^2" }
|
||||
# Dependencies for native builds only
|
||||
# Linux, Windows, Mac, iOS, Android
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
tracing-opentelemetry = "^0"
|
||||
opentelemetry = { version = "^0" }
|
||||
opentelemetry-otlp = { version = "^0" }
|
||||
opentelemetry-semantic-conventions = "^0"
|
||||
tracing-opentelemetry = "0.18"
|
||||
opentelemetry = { version = "0.18" }
|
||||
opentelemetry-otlp = { version = "0.11" }
|
||||
opentelemetry-semantic-conventions = "0.10"
|
||||
async-std = { version = "^1", features = ["unstable"], optional = true }
|
||||
tokio = { version = "^1", features = ["full"], optional = true }
|
||||
tokio-stream = { version = "^0", features = ["net"], optional = true }
|
||||
|
||||
@@ -33,7 +33,7 @@ lazy_static! {
|
||||
Mutex::new(BTreeMap::new());
|
||||
}
|
||||
|
||||
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||
async fn get_veilid_api() -> veilid_core::VeilidAPIResult<veilid_core::VeilidAPI> {
|
||||
let api_lock = VEILID_API.lock().await;
|
||||
api_lock
|
||||
.as_ref()
|
||||
@@ -41,7 +41,7 @@ async fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidA
|
||||
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||
}
|
||||
|
||||
async fn take_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||
async fn take_veilid_api() -> veilid_core::VeilidAPIResult<veilid_core::VeilidAPI> {
|
||||
let mut api_lock = VEILID_API.lock().await;
|
||||
api_lock
|
||||
.take()
|
||||
@@ -55,7 +55,7 @@ async fn take_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::Veilid
|
||||
define_string_destructor!(free_string);
|
||||
|
||||
// Utility types for async API results
|
||||
type APIResult<T> = Result<T, veilid_core::VeilidAPIError>;
|
||||
type APIResult<T> = veilid_core::VeilidAPIResult<T>;
|
||||
const APIRESULT_VOID: APIResult<()> = APIResult::Ok(());
|
||||
|
||||
// Parse target
|
||||
@@ -74,7 +74,7 @@ async fn parse_target(s: String) -> APIResult<veilid_core::Target> {
|
||||
}
|
||||
|
||||
// Is this a node id?
|
||||
if let Ok(nid) = veilid_core::PublicKey::from_str(&s) {
|
||||
if let Ok(nid) = veilid_core::TypedKey::from_str(&s) {
|
||||
return Ok(veilid_core::Target::NodeId(nid));
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr
|
||||
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));
|
||||
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("routing_context_app_message", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
@@ -492,6 +492,158 @@ pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_create_dht_record(port: i64, id: u32, kind: u32, schema: FfiStr) {
|
||||
let crypto_kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
let schema: veilid_core::DHTSchema = veilid_core::deserialize_opt_json(schema.into_opt_string()).unwrap();
|
||||
|
||||
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_create_dht_record", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
|
||||
let dht_record_descriptor = routing_context.create_dht_record(crypto_kind, schema).await?;
|
||||
APIResult::Ok(dht_record_descriptor)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_open_dht_record(port: i64, id: u32, key: FfiStr, writer: FfiStr) {
|
||||
let key: veilid_core::TypedKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let writer: Option<veilid_core::KeyPair> = writer.into_opt_string().map(|s| veilid_core::deserialize_json(&s).unwrap());
|
||||
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_open_dht_record", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
let dht_record_descriptor = routing_context.open_dht_record(key, writer).await?;
|
||||
APIResult::Ok(dht_record_descriptor)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_close_dht_record(port: i64, id: u32, key: FfiStr) {
|
||||
let key: veilid_core::TypedKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
DartIsolateWrapper::new(port).spawn_result(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_close_dht_record", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
routing_context.close_dht_record(key).await?;
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_delete_dht_record(port: i64, id: u32, key: FfiStr) {
|
||||
let key: veilid_core::TypedKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
DartIsolateWrapper::new(port).spawn_result(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_delete_dht_record", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
routing_context.delete_dht_record(key).await?;
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_get_dht_value(port: i64, id: u32, key: FfiStr, subkey: u32, force_refresh: bool) {
|
||||
let key: veilid_core::TypedKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
DartIsolateWrapper::new(port).spawn_result_opt_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_get_dht_value", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
let res = routing_context.get_dht_value(key, subkey, force_refresh).await?;
|
||||
APIResult::Ok(res)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_set_dht_value(port: i64, id: u32, key: FfiStr, subkey: u32, data: FfiStr) {
|
||||
let key: veilid_core::TypedKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
data.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_opt_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_set_dht_value", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
let res = routing_context.set_dht_value(key, subkey, data).await?;
|
||||
APIResult::Ok(res)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_watch_dht_values(port: i64, id: u32, key: FfiStr, subkeys: FfiStr, expiration: u64, count: u32) {
|
||||
let key: veilid_core::TypedKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let subkeys: veilid_core::ValueSubkeyRangeSet = veilid_core::deserialize_opt_json(subkeys.into_opt_string()).unwrap();
|
||||
let expiration = veilid_core::Timestamp::from(expiration);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(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_watch_dht_values", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
let res = routing_context.watch_dht_values(key, subkeys, expiration, count).await?;
|
||||
APIResult::Ok(res.as_u64())
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn routing_context_cancel_dht_watch(port: i64, id: u32, key: FfiStr, subkeys: FfiStr) {
|
||||
let key: veilid_core::TypedKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let subkeys: veilid_core::ValueSubkeyRangeSet = veilid_core::deserialize_opt_json(subkeys.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(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_set_dht_value", "id", id));
|
||||
};
|
||||
routing_context.clone()
|
||||
};
|
||||
let res = routing_context.cancel_dht_watch(key, subkeys).await?;
|
||||
APIResult::Ok(res)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn new_private_route(port: i64) {
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
@@ -629,17 +781,20 @@ pub extern "C" fn table_db_get_column_count(id: u32) -> u32 {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn table_db_get_keys(id: u32, col: u32) -> *mut c_char {
|
||||
let table_dbs = TABLE_DBS.lock();
|
||||
let Some(table_db) = table_dbs.get(&id) else {
|
||||
return std::ptr::null_mut();
|
||||
};
|
||||
let Ok(keys) = table_db.clone().get_keys(col) else {
|
||||
return std::ptr::null_mut();
|
||||
};
|
||||
let keys: Vec<String> = keys.into_iter().map(|k| BASE64URL_NOPAD.encode(&k)).collect();
|
||||
let out = veilid_core::serialize_json(keys);
|
||||
out.into_ffi_value()
|
||||
pub extern "C" fn table_db_get_keys(port: i64, id: u32, col: u32) {
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let table_db = {
|
||||
let table_dbs = TABLE_DBS.lock();
|
||||
let Some(table_db) = table_dbs.get(&id) else {
|
||||
return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("table_db_get_keys", "id", id));
|
||||
};
|
||||
table_db.clone()
|
||||
};
|
||||
|
||||
let keys = table_db.get_keys(col).await?;
|
||||
let out: Vec<String> = keys.into_iter().map(|k| BASE64URL_NOPAD.encode(&k)).collect();
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
fn add_table_db_transaction(tdbt: veilid_core::TableDBTransaction) -> u32 {
|
||||
@@ -684,7 +839,7 @@ pub extern "C" fn table_db_transaction_commit(port: i64, id: u32) {
|
||||
tdbt.clone()
|
||||
};
|
||||
|
||||
tdbt.commit().await.map_err(veilid_core::VeilidAPIError::generic)?;
|
||||
tdbt.commit().await?;
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
@@ -783,7 +938,7 @@ pub extern "C" fn table_db_store(port: i64, id: u32, col: u32, key: FfiStr, valu
|
||||
table_db.clone()
|
||||
};
|
||||
|
||||
table_db.store(col, &key, &value).await.map_err(veilid_core::VeilidAPIError::generic)?;
|
||||
table_db.store(col, &key, &value).await?;
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
@@ -805,7 +960,7 @@ pub extern "C" fn table_db_load(port: i64, id: u32, col: u32, key: FfiStr) {
|
||||
table_db.clone()
|
||||
};
|
||||
|
||||
let out = table_db.load(col, &key).map_err(veilid_core::VeilidAPIError::generic)?;
|
||||
let out = table_db.load(col, &key).await?;
|
||||
let out = out.map(|x| data_encoding::BASE64URL_NOPAD.encode(&x));
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
@@ -829,11 +984,501 @@ pub extern "C" fn table_db_delete(port: i64, id: u32, col: u32, key: FfiStr) {
|
||||
table_db.clone()
|
||||
};
|
||||
|
||||
let out = table_db.delete(col, &key).await.map_err(veilid_core::VeilidAPIError::generic)?;
|
||||
let out = table_db.delete(col, &key).await?;
|
||||
let out = out.map(|x| data_encoding::BASE64URL_NOPAD.encode(&x));
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn valid_crypto_kinds() -> *mut c_char {
|
||||
veilid_core::serialize_json(veilid_core::VALID_CRYPTO_KINDS.iter().map(|k| (*k).into()).collect::<Vec<u32>>()).into_ffi_value()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn best_crypto_kind() -> u32 {
|
||||
veilid_core::best_crypto_kind().into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn verify_signatures(port: i64, node_ids: FfiStr, data: FfiStr, signatures: FfiStr) {
|
||||
let node_ids: Vec<veilid_core::TypedKey> =
|
||||
veilid_core::deserialize_opt_json(node_ids.into_opt_string()).unwrap();
|
||||
|
||||
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
data.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let typed_signatures: Vec<veilid_core::TypedSignature> =
|
||||
veilid_core::deserialize_opt_json(signatures.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let out = crypto.verify_signatures(&node_ids, &data, &typed_signatures)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn generate_signatures(port: i64, data: FfiStr, key_pairs: FfiStr) {
|
||||
|
||||
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
data.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let key_pairs: Vec<veilid_core::TypedKeyPair> =
|
||||
veilid_core::deserialize_opt_json(key_pairs.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let out = crypto.generate_signatures(&data, &key_pairs, |k, s| {
|
||||
veilid_core::TypedSignature::new(k.kind, s)
|
||||
})?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn generate_key_pair(port: i64, kind: u32) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let out = veilid_core::Crypto::generate_keypair(kind)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_cached_dh(port: i64, kind: u32, key: FfiStr, secret: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let key: veilid_core::PublicKey =
|
||||
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let secret: veilid_core::SecretKey =
|
||||
veilid_core::deserialize_opt_json(secret.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_cached_dh", "kind", kind.to_string()))?;
|
||||
let out = csv.cached_dh(&key, &secret)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_compute_dh(port: i64, kind: u32, key: FfiStr, secret: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let key: veilid_core::PublicKey =
|
||||
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let secret: veilid_core::SecretKey =
|
||||
veilid_core::deserialize_opt_json(secret.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_compute_dh", "kind", kind.to_string()))?;
|
||||
let out = csv.compute_dh(&key, &secret)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_random_bytes(port: i64, kind: u32, len: u32) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_random_bytes", "kind", kind.to_string()))?;
|
||||
let out = csv.random_bytes(len);
|
||||
let out = data_encoding::BASE64URL_NOPAD.encode(&out);
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_default_salt_length(port: i64, kind: u32) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_default_salt_length", "kind", kind.to_string()))?;
|
||||
let out = csv.default_salt_length();
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_hash_password(port: i64, kind: u32, password: FfiStr, salt: FfiStr ) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
let password: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
password.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
let salt: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
salt.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_hash_password", "kind", kind.to_string()))?;
|
||||
let out = csv.hash_password(&password, &salt)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_verify_password(port: i64, kind: u32, password: FfiStr, password_hash: FfiStr ) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
let password: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
password.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
let password_hash = password_hash.into_opt_string().unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_verify_password", "kind", kind.to_string()))?;
|
||||
let out = csv.verify_password(&password, &password_hash)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_derive_shared_secret(port: i64, kind: u32, password: FfiStr, salt: FfiStr ) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
let password: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
password.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
let salt: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
salt.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_derive_shared_secret", "kind", kind.to_string()))?;
|
||||
let out = csv.derive_shared_secret(&password, &salt)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_random_nonce(port: i64, kind: u32) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_random_nonce", "kind", kind.to_string()))?;
|
||||
let out = csv.random_nonce();
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_random_shared_secret(port: i64, kind: u32) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_random_shared_secret", "kind", kind.to_string()))?;
|
||||
let out = csv.random_shared_secret();
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_generate_key_pair(port: i64, kind: u32) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_generate_key_pair", "kind", kind.to_string()))?;
|
||||
let out = csv.generate_keypair();
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_generate_hash(port: i64, kind: u32, data: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
data.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_generate_hash", "kind", kind.to_string()))?;
|
||||
let out = csv.generate_hash(&data);
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_validate_key_pair(port: i64, kind: u32, key: FfiStr, secret: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let key: veilid_core::PublicKey =
|
||||
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let secret: veilid_core::SecretKey =
|
||||
veilid_core::deserialize_opt_json(secret.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_validate_key_pair", "kind", kind.to_string()))?;
|
||||
let out = csv.validate_keypair(&key, &secret);
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_validate_hash(port: i64, kind: u32, data: FfiStr, hash: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
data.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let hash: veilid_core::HashDigest =
|
||||
veilid_core::deserialize_opt_json(hash.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_validate_hash", "kind", kind.to_string()))?;
|
||||
let out = csv.validate_hash(&data, &hash);
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_distance(port: i64, kind: u32, key1: FfiStr, key2: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let key1: veilid_core::CryptoKey =
|
||||
veilid_core::deserialize_opt_json(key1.into_opt_string()).unwrap();
|
||||
let key2: veilid_core::CryptoKey =
|
||||
veilid_core::deserialize_opt_json(key2.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_distance", "kind", kind.to_string()))?;
|
||||
let out = csv.distance(&key1, &key2);
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_sign(port: i64, kind: u32, key: FfiStr, secret: FfiStr, data: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let key: veilid_core::CryptoKey =
|
||||
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let secret: veilid_core::CryptoKey =
|
||||
veilid_core::deserialize_opt_json(secret.into_opt_string()).unwrap();
|
||||
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
data.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_sign", "kind", kind.to_string()))?;
|
||||
let out = csv.sign(&key, &secret, &data)?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_verify(port: i64, kind: u32, key: FfiStr, data: FfiStr, signature: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let key: veilid_core::CryptoKey =
|
||||
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||
let data: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
data.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
let signature: veilid_core::Signature =
|
||||
veilid_core::deserialize_opt_json(signature.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_verify", "kind", kind.to_string()))?;
|
||||
csv.verify(&key, &data, &signature)?;
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_aead_overhead(port: i64, kind: u32) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_aead_overhead", "kind", kind.to_string()))?;
|
||||
let out = csv.aead_overhead();
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_decrypt_aead(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr, associated_data: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let body: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
body.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let nonce: veilid_core::Nonce =
|
||||
veilid_core::deserialize_opt_json(nonce.into_opt_string()).unwrap();
|
||||
|
||||
let shared_secret: veilid_core::SharedSecret =
|
||||
veilid_core::deserialize_opt_json(shared_secret.into_opt_string()).unwrap();
|
||||
|
||||
let associated_data: Option<Vec<u8>> = associated_data.into_opt_string().map(|s| data_encoding::BASE64URL_NOPAD.decode(s.as_bytes()).unwrap());
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_decrypt_aead", "kind", kind.to_string()))?;
|
||||
let out = csv.decrypt_aead(&body, &nonce, &shared_secret, match &associated_data {
|
||||
Some(ad) => Some(ad.as_slice()),
|
||||
None => None
|
||||
})?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_encrypt_aead(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr, associated_data: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let body: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
body.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let nonce: veilid_core::Nonce =
|
||||
veilid_core::deserialize_opt_json(nonce.into_opt_string()).unwrap();
|
||||
|
||||
let shared_secret: veilid_core::SharedSecret =
|
||||
veilid_core::deserialize_opt_json(shared_secret.into_opt_string()).unwrap();
|
||||
|
||||
let associated_data: Option<Vec<u8>> = associated_data.into_opt_string().map(|s| data_encoding::BASE64URL_NOPAD.decode(s.as_bytes()).unwrap());
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_encrypt_aead", "kind", kind.to_string()))?;
|
||||
let out = csv.encrypt_aead(&body, &nonce, &shared_secret, match &associated_data {
|
||||
Some(ad) => Some(ad.as_slice()),
|
||||
None => None
|
||||
})?;
|
||||
APIResult::Ok(out)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn crypto_crypt_no_auth(port: i64, kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr) {
|
||||
let kind: veilid_core::CryptoKind = veilid_core::FourCC::from(kind);
|
||||
|
||||
let mut body: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||
.decode(
|
||||
body.into_opt_string()
|
||||
.unwrap()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let nonce: veilid_core::Nonce =
|
||||
veilid_core::deserialize_opt_json(nonce.into_opt_string()).unwrap();
|
||||
|
||||
let shared_secret: veilid_core::SharedSecret =
|
||||
veilid_core::deserialize_opt_json(shared_secret.into_opt_string()).unwrap();
|
||||
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let veilid_api = get_veilid_api().await?;
|
||||
let crypto = veilid_api.crypto()?;
|
||||
let csv = crypto.get(kind).ok_or_else(|| veilid_core::VeilidAPIError::invalid_argument("crypto_crypt_no_auth", "kind", kind.to_string()))?;
|
||||
csv.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret);
|
||||
APIResult::Ok(body)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn now() -> u64 {
|
||||
veilid_core::get_aligned_timestamp().as_u64()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn debug(port: i64, command: FfiStr) {
|
||||
let command = command.into_opt_string().unwrap_or_default();
|
||||
|
||||
@@ -52,6 +52,17 @@ impl DartIsolateWrapper {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn spawn_result_opt_json<F, T, E>(self, future: F)
|
||||
where
|
||||
F: Future<Output = Result<Option<T>, E>> + Send + 'static,
|
||||
T: Serialize + Debug,
|
||||
E: Serialize + Debug,
|
||||
{
|
||||
spawn(async move {
|
||||
self.result_opt_json(future.await);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn result<T: IntoDart + Debug, E: Serialize + Debug>(self, result: Result<T, E>) -> bool {
|
||||
match result {
|
||||
Ok(v) => self.ok(v),
|
||||
@@ -67,6 +78,16 @@ impl DartIsolateWrapper {
|
||||
Err(e) => self.err_json(e),
|
||||
}
|
||||
}
|
||||
pub fn result_opt_json<T: Serialize + Debug, E: Serialize + Debug>(
|
||||
self,
|
||||
result: Result<Option<T>, E>,
|
||||
) -> bool {
|
||||
match result {
|
||||
Ok(Some(v)) => self.ok_json(v),
|
||||
Ok(None) => self.ok(()),
|
||||
Err(e) => self.err_json(e),
|
||||
}
|
||||
}
|
||||
pub fn ok<T: IntoDart>(self, value: T) -> bool {
|
||||
self.isolate
|
||||
.post(vec![MESSAGE_OK.into_dart(), value.into_dart()])
|
||||
|
||||
@@ -11,6 +11,6 @@ void main() {
|
||||
tearDown(() {});
|
||||
|
||||
test('veilidVersionString', () async {
|
||||
expect(Veilid.instance.veilidVersionString(), '0.1.0');
|
||||
expect(api.veilidVersionString(), '0.1.0');
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user