diff --git a/veilid-core/src/lib.rs b/veilid-core/src/lib.rs index d57e2fd2..1c088e21 100644 --- a/veilid-core/src/lib.rs +++ b/veilid-core/src/lib.rs @@ -88,6 +88,11 @@ pub fn veilid_version() -> (u32, u32, u32) { ) } +/// Return the default veilid config as a json object +pub fn default_veilid_config() -> String { + serialize_json(VeilidConfigInner::default()) +} + #[cfg(target_os = "android")] pub use intf::android::veilid_core_setup_android; diff --git a/veilid-core/src/veilid_api/json_api/mod.rs b/veilid-core/src/veilid_api/json_api/mod.rs index 4ec0210c..3b1c3338 100644 --- a/veilid-core/src/veilid_api/json_api/mod.rs +++ b/veilid-core/src/veilid_api/json_api/mod.rs @@ -120,6 +120,7 @@ pub enum RequestOp { }, VeilidVersionString, VeilidVersion, + DefaultVeilidConfig, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] @@ -230,6 +231,9 @@ pub enum ResponseOp { minor: u32, patch: u32, }, + DefaultVeilidConfig { + value: String, + }, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] diff --git a/veilid-core/src/veilid_api/json_api/process.rs b/veilid-core/src/veilid_api/json_api/process.rs index 19c783d7..7a4beb02 100644 --- a/veilid-core/src/veilid_api/json_api/process.rs +++ b/veilid-core/src/veilid_api/json_api/process.rs @@ -792,6 +792,9 @@ impl JsonRequestProcessor { patch, } } + RequestOp::DefaultVeilidConfig => ResponseOp::DefaultVeilidConfig { + value: default_veilid_config(), + }, }; Response { id, op } diff --git a/veilid-flutter/lib/default_config.dart b/veilid-flutter/lib/default_config.dart index eeb1833a..44345b59 100644 --- a/veilid-flutter/lib/default_config.dart +++ b/veilid-flutter/lib/default_config.dart @@ -58,136 +58,135 @@ int getRemoteMaxStorageSpaceMb() { return 256; } -Future getDefaultVeilidConfig(String programName) async { - // ignore: do_not_use_environment - const bootstrap = String.fromEnvironment('BOOTSTRAP'); - return VeilidConfig( - programName: programName, - namespace: '', - capabilities: const VeilidConfigCapabilities(disable: []), - protectedStore: const VeilidConfigProtectedStore( - allowInsecureFallback: false, - alwaysUseInsecureStorage: false, - directory: '', - delete: false, - deviceEncryptionKeyPassword: '', - ), - tableStore: VeilidConfigTableStore( - directory: kIsWeb - ? '' - : p.join((await getApplicationSupportDirectory()).absolute.path, - 'table_store'), - delete: false, - ), - blockStore: VeilidConfigBlockStore( - directory: kIsWeb - ? '' - : p.join((await getApplicationSupportDirectory()).absolute.path, - 'block_store'), - delete: false, - ), - network: VeilidConfigNetwork( - connectionInitialTimeoutMs: 2000, - connectionInactivityTimeoutMs: 60000, - maxConnectionsPerIp4: 32, - maxConnectionsPerIp6Prefix: 32, - maxConnectionsPerIp6PrefixSize: 56, - maxConnectionFrequencyPerMin: 128, - clientAllowlistTimeoutMs: 300000, - reverseConnectionReceiptTimeMs: 5000, - holePunchReceiptTimeMs: 5000, - routingTable: VeilidConfigRoutingTable( - nodeId: [], - nodeIdSecret: [], - bootstrap: bootstrap.isNotEmpty - ? bootstrap.split(',') - : (kIsWeb - ? ['ws://bootstrap.veilid.net:5150/ws'] - : ['bootstrap.veilid.net']), - limitOverAttached: 64, - limitFullyAttached: 32, - limitAttachedStrong: 16, - limitAttachedGood: 8, - limitAttachedWeak: 4, +Future getDefaultVeilidConfig(String programName, + {String bootstrap = ''}) async => + VeilidConfig( + programName: programName, + namespace: '', + capabilities: const VeilidConfigCapabilities(disable: []), + protectedStore: const VeilidConfigProtectedStore( + allowInsecureFallback: false, + alwaysUseInsecureStorage: false, + directory: '', + delete: false, + deviceEncryptionKeyPassword: '', ), - rpc: const VeilidConfigRPC( - concurrency: 0, - queueSize: 1024, - maxTimestampBehindMs: 10000, - maxTimestampAheadMs: 10000, - timeoutMs: 5000, - maxRouteHopCount: 4, - defaultRouteHopCount: 1, + tableStore: VeilidConfigTableStore( + directory: kIsWeb + ? '' + : p.join((await getApplicationSupportDirectory()).absolute.path, + 'table_store'), + delete: false, ), - dht: VeilidConfigDHT( - maxFindNodeCount: 20, - resolveNodeTimeoutMs: 10000, - resolveNodeCount: 1, - resolveNodeFanout: 4, - getValueTimeoutMs: 10000, - getValueCount: 3, - getValueFanout: 4, - setValueTimeoutMs: 10000, - setValueCount: 5, - setValueFanout: 4, - minPeerCount: 20, - minPeerRefreshTimeMs: 60000, - validateDialInfoReceiptTimeMs: 2000, - localSubkeyCacheSize: getLocalSubkeyCacheSize(), - localMaxSubkeyCacheMemoryMb: await getLocalMaxSubkeyCacheMemoryMb(), - remoteSubkeyCacheSize: getRemoteSubkeyCacheSize(), - remoteMaxRecords: getRemoteMaxRecords(), - remoteMaxSubkeyCacheMemoryMb: await getRemoteMaxSubkeyCacheMemoryMb(), - remoteMaxStorageSpaceMb: getRemoteMaxStorageSpaceMb(), - publicWatchLimit: 32, - memberWatchLimit: 8, - maxWatchExpirationMs: 600000), - upnp: true, - detectAddressChanges: true, - restrictedNatRetries: 0, - tls: const VeilidConfigTLS( - certificatePath: '', - privateKeyPath: '', + blockStore: VeilidConfigBlockStore( + directory: kIsWeb + ? '' + : p.join((await getApplicationSupportDirectory()).absolute.path, + 'block_store'), + delete: false, + ), + network: VeilidConfigNetwork( connectionInitialTimeoutMs: 2000, - ), - application: const VeilidConfigApplication( - https: VeilidConfigHTTPS( - enabled: false, + connectionInactivityTimeoutMs: 60000, + maxConnectionsPerIp4: 32, + maxConnectionsPerIp6Prefix: 32, + maxConnectionsPerIp6PrefixSize: 56, + maxConnectionFrequencyPerMin: 128, + clientAllowlistTimeoutMs: 300000, + reverseConnectionReceiptTimeMs: 5000, + holePunchReceiptTimeMs: 5000, + routingTable: VeilidConfigRoutingTable( + nodeId: [], + nodeIdSecret: [], + bootstrap: bootstrap.isNotEmpty + ? bootstrap.split(',') + : (kIsWeb + ? ['ws://bootstrap.veilid.net:5150/ws'] + : ['bootstrap.veilid.net']), + limitOverAttached: 64, + limitFullyAttached: 32, + limitAttachedStrong: 16, + limitAttachedGood: 8, + limitAttachedWeak: 4, + ), + rpc: const VeilidConfigRPC( + concurrency: 0, + queueSize: 1024, + maxTimestampBehindMs: 10000, + maxTimestampAheadMs: 10000, + timeoutMs: 5000, + maxRouteHopCount: 4, + defaultRouteHopCount: 1, + ), + dht: VeilidConfigDHT( + maxFindNodeCount: 20, + resolveNodeTimeoutMs: 10000, + resolveNodeCount: 1, + resolveNodeFanout: 4, + getValueTimeoutMs: 10000, + getValueCount: 3, + getValueFanout: 4, + setValueTimeoutMs: 10000, + setValueCount: 5, + setValueFanout: 4, + minPeerCount: 20, + minPeerRefreshTimeMs: 60000, + validateDialInfoReceiptTimeMs: 2000, + localSubkeyCacheSize: getLocalSubkeyCacheSize(), + localMaxSubkeyCacheMemoryMb: await getLocalMaxSubkeyCacheMemoryMb(), + remoteSubkeyCacheSize: getRemoteSubkeyCacheSize(), + remoteMaxRecords: getRemoteMaxRecords(), + remoteMaxSubkeyCacheMemoryMb: + await getRemoteMaxSubkeyCacheMemoryMb(), + remoteMaxStorageSpaceMb: getRemoteMaxStorageSpaceMb(), + publicWatchLimit: 32, + memberWatchLimit: 8, + maxWatchExpirationMs: 600000), + upnp: true, + detectAddressChanges: true, + restrictedNatRetries: 0, + tls: const VeilidConfigTLS( + certificatePath: '', + privateKeyPath: '', + connectionInitialTimeoutMs: 2000, + ), + application: const VeilidConfigApplication( + https: VeilidConfigHTTPS( + enabled: false, + listenAddress: '', + path: '', + ), + http: VeilidConfigHTTP( + enabled: false, + listenAddress: '', + path: '', + )), + protocol: const VeilidConfigProtocol( + udp: VeilidConfigUDP( + enabled: !kIsWeb, + socketPoolSize: 0, listenAddress: '', - path: '', ), - http: VeilidConfigHTTP( - enabled: false, + tcp: VeilidConfigTCP( + connect: !kIsWeb, + listen: !kIsWeb, + maxConnections: 32, listenAddress: '', - path: '', - )), - protocol: const VeilidConfigProtocol( - udp: VeilidConfigUDP( - enabled: !kIsWeb, - socketPoolSize: 0, - listenAddress: '', - ), - tcp: VeilidConfigTCP( - connect: !kIsWeb, - listen: !kIsWeb, - maxConnections: 32, - listenAddress: '', - ), - ws: VeilidConfigWS( - connect: true, - listen: !kIsWeb, - maxConnections: 32, - listenAddress: '', - path: 'ws', - ), - wss: VeilidConfigWSS( - connect: true, - listen: false, - maxConnections: 32, - listenAddress: '', - path: 'ws', + ), + ws: VeilidConfigWS( + connect: true, + listen: !kIsWeb, + maxConnections: 32, + listenAddress: '', + path: 'ws', + ), + wss: VeilidConfigWSS( + connect: true, + listen: false, + maxConnections: 32, + listenAddress: '', + path: 'ws', + ), ), ), - ), - ); -} + ); diff --git a/veilid-flutter/lib/veilid.dart b/veilid-flutter/lib/veilid.dart index d404ffb2..0c3c0c56 100644 --- a/veilid-flutter/lib/veilid.dart +++ b/veilid-flutter/lib/veilid.dart @@ -162,5 +162,6 @@ abstract class Veilid { Timestamp now(); String veilidVersionString(); VeilidVersion veilidVersion(); + String defaultVeilidConfig(); Future debug(String command); } diff --git a/veilid-flutter/lib/veilid_ffi.dart b/veilid-flutter/lib/veilid_ffi.dart index 335b8a00..b6e00ba3 100644 --- a/veilid-flutter/lib/veilid_ffi.dart +++ b/veilid-flutter/lib/veilid_ffi.dart @@ -235,6 +235,9 @@ final class VeilidVersionFFI extends Struct { typedef _VeilidVersionDart = VeilidVersionFFI Function(); +// fn default_veilid_config() -> *mut c_char +typedef _DefaultVeilidConfigDart = Pointer Function(); + // Async message types const int messageOk = 0; const int messageErr = 1; @@ -1388,7 +1391,9 @@ class VeilidFFI extends Veilid { _veilidVersionString = dylib.lookupFunction Function(), _VeilidVersionStringDart>('veilid_version_string'), _veilidVersion = dylib.lookupFunction('veilid_version') { + _VeilidVersionDart>('veilid_version'), + _defaultVeilidConfig = dylib.lookupFunction Function(), + _DefaultVeilidConfigDart>('default_veilid_config') { // Get veilid_flutter initializer final initializeVeilidFlutter = _dylib.lookupFunction< Void Function(Pointer<_DartPostCObject>), @@ -1481,6 +1486,7 @@ class VeilidFFI extends Veilid { final _DebugDart _debug; final _VeilidVersionStringDart _veilidVersionString; final _VeilidVersionDart _veilidVersion; + final _DefaultVeilidConfigDart _defaultVeilidConfig; @override void initializeVeilidCore(Map platformConfigJson) { @@ -1714,4 +1720,12 @@ class VeilidFFI extends Veilid { version.patch, ); } + + @override + String defaultVeilidConfig() { + final defaultVeilidConfig = _defaultVeilidConfig(); + final ret = defaultVeilidConfig.toDartString(); + _freeString(defaultVeilidConfig); + return ret; + } } diff --git a/veilid-flutter/lib/veilid_js.dart b/veilid-flutter/lib/veilid_js.dart index bc7ad312..e00a691a 100644 --- a/veilid-flutter/lib/veilid_js.dart +++ b/veilid-flutter/lib/veilid_js.dart @@ -705,4 +705,8 @@ class VeilidJS extends Veilid { return VeilidVersion(jsonVersion['major'] as int, jsonVersion['minor'] as int, jsonVersion['patch'] as int); } + + @override + String defaultVeilidConfig() => + js_util.callMethod(wasm, 'default_veilid_config', []); } diff --git a/veilid-flutter/rust/src/dart_ffi.rs b/veilid-flutter/rust/src/dart_ffi.rs index 0ff83070..bedebad6 100644 --- a/veilid-flutter/rust/src/dart_ffi.rs +++ b/veilid-flutter/rust/src/dart_ffi.rs @@ -1765,3 +1765,8 @@ pub extern "C" fn veilid_version() -> VeilidVersion { patch, } } + +#[no_mangle] +pub extern "C" fn default_veilid_config() -> *mut c_char { + veilid_core::default_veilid_config().into_ffi_value() +} diff --git a/veilid-python/tests/test_basic.py b/veilid-python/tests/test_basic.py index 395d0a90..7daafc64 100644 --- a/veilid-python/tests/test_basic.py +++ b/veilid-python/tests/test_basic.py @@ -1,6 +1,8 @@ # Basic veilid tests import socket +import json +import dataclasses import pytest import veilid @@ -40,3 +42,19 @@ async def test_version(api_connection: veilid.VeilidAPI): vstr = await api_connection.veilid_version_string() print(f"veilid_version_string: {vstr}") + + +@pytest.mark.asyncio +async def test_config(api_connection: veilid.VeilidAPI): + cfgstr = await api_connection.default_veilid_config() + print(f"default_veilid_config:\n{cfgstr}") + cfgjson = json.loads(cfgstr) + + veilidConfigInstance = veilid.VeilidConfig(**cfgjson) + cfgstr2 = json.dumps(dataclasses.asdict(veilidConfigInstance)) + + cfgjson2 = json.loads(cfgstr2) + veilidConfigInstance2 = veilid.VeilidConfig(**cfgjson2) + + assert veilidConfigInstance == veilidConfigInstance2 + diff --git a/veilid-python/veilid/api.py b/veilid-python/veilid/api.py index eefadade..cc7e5baa 100644 --- a/veilid-python/veilid/api.py +++ b/veilid-python/veilid/api.py @@ -396,3 +396,7 @@ class VeilidAPI(ABC): @abstractmethod async def veilid_version(self) -> types.VeilidVersion: pass + + @abstractmethod + async def default_veilid_config(self) -> str: + pass diff --git a/veilid-python/veilid/json_api.py b/veilid-python/veilid/json_api.py index 7c56b474..a5337978 100644 --- a/veilid-python/veilid/json_api.py +++ b/veilid-python/veilid/json_api.py @@ -432,6 +432,9 @@ class _JsonVeilidAPI(VeilidAPI): v = await self.send_ndjson_request(Operation.VEILID_VERSION) return VeilidVersion(v["major"], v["minor"], v["patch"]) + async def default_veilid_config(self) -> str: + return raise_api_result(await self.send_ndjson_request(Operation.DEFAULT_VEILID_CONFIG)) + ###################################################### diff --git a/veilid-python/veilid/operations.py b/veilid-python/veilid/operations.py index 23fa6df1..3cd498a3 100644 --- a/veilid-python/veilid/operations.py +++ b/veilid-python/veilid/operations.py @@ -28,6 +28,7 @@ class Operation(StrEnum): DEBUG = "Debug" VEILID_VERSION_STRING = "VeilidVersionString" VEILID_VERSION = "VeilidVersion" + DEFAULT_VEILID_CONFIG = "DefaultVeilidConfig" class RoutingContextOperation(StrEnum): diff --git a/veilid-python/veilid/schema/RecvMessage.json b/veilid-python/veilid/schema/RecvMessage.json index cdd9bf60..d8e110e4 100644 --- a/veilid-python/veilid/schema/RecvMessage.json +++ b/veilid-python/veilid/schema/RecvMessage.json @@ -2349,6 +2349,24 @@ "minimum": 0.0 } } + }, + { + "type": "object", + "required": [ + "op", + "value" + ], + "properties": { + "op": { + "type": "string", + "enum": [ + "DefaultVeilidConfig" + ] + }, + "value": { + "type": "string" + } + } } ], "required": [ diff --git a/veilid-python/veilid/schema/Request.json b/veilid-python/veilid/schema/Request.json index 2e9ff5cb..1c9c4b9f 100644 --- a/veilid-python/veilid/schema/Request.json +++ b/veilid-python/veilid/schema/Request.json @@ -1499,6 +1499,20 @@ ] } } + }, + { + "type": "object", + "required": [ + "op" + ], + "properties": { + "op": { + "type": "string", + "enum": [ + "DefaultVeilidConfig" + ] + } + } } ], "properties": { diff --git a/veilid-wasm/src/lib.rs b/veilid-wasm/src/lib.rs index 02047328..bc47c465 100644 --- a/veilid-wasm/src/lib.rs +++ b/veilid-wasm/src/lib.rs @@ -1624,3 +1624,8 @@ pub fn veilid_version() -> JsValue { }; ::from_serde(&vv).unwrap() } + +#[wasm_bindgen()] +pub fn default_veilid_config() -> String { + veilid_core::default_veilid_config() +} diff --git a/veilid-wasm/src/veilid_client_js.rs b/veilid-wasm/src/veilid_client_js.rs index 11e8fcaa..9029720b 100644 --- a/veilid-wasm/src/veilid_client_js.rs +++ b/veilid-wasm/src/veilid_client_js.rs @@ -178,4 +178,9 @@ impl VeilidClient { pub fn versionString() -> String { veilid_core::veilid_version_string() } + + /// Return the default veilid configuration in json string format. + pub fn defaultConfig() -> String { + veilid_core::default_veilid_config() + } } diff --git a/veilid-wasm/tests/src/veilidClient.test.ts b/veilid-wasm/tests/src/veilidClient.test.ts index c3d04059..d6bb64dc 100644 --- a/veilid-wasm/tests/src/veilidClient.test.ts +++ b/veilid-wasm/tests/src/veilidClient.test.ts @@ -28,6 +28,19 @@ describe('veilidClient', () => { expect(version.length).toBeGreaterThan(0); }); + it('should get config string', async () => { + const defaultConfig = veilidClient.defaultConfig(); + expect(typeof defaultConfig).toBe('string'); + expect(defaultConfig.length).toBeGreaterThan(0); + + const cfgObject1 = JSON.parse(defaultConfig); + const defaultConfigStr = JSON.stringify(cfgObject1); + const cfgObject2 = JSON.parse(defaultConfigStr); + const defaultConfigStr2 = JSON.stringify(cfgObject2); + + expect(defaultConfigStr).toEqual(defaultConfigStr2); + }); + it('should attach and detach', async () => { await veilidClient.attach(); await waitForMs(2000);