Bugfixes for 0.5.7

This commit is contained in:
Christien Rioux committed 2026-08-15 18:17:44 -04:00
1 parent 76b2176926
commit e9a95f9cd4
148 files changed
+7923 -2210

No files matched your search

@@ -18,205 +18,217 @@ import 'test_table_db.dart';
import 'test_veilid_config.dart';
void main() => runWithIntegrationLog(() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
runApp(const IntegrationLogApp());
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
runApp(const IntegrationLogApp());
final fixture = DefaultVeilidFixture(
programName: 'veilid_flutter integration test',
logFixture: LogFixture.instance);
final updateProcessorFixture =
UpdateProcessorFixture(veilidFixture: fixture);
final fixture = DefaultVeilidFixture(
programName: 'veilid_flutter integration test',
logFixture: LogFixture.instance);
final updateProcessorFixture =
UpdateProcessorFixture(veilidFixture: fixture);
// setUp(() {
// final liveTest = Invoker.current?.liveTest;
// print('setUp ${liveTest?.test.name}');
// });
// tearDown(() {
// final liveTest = Invoker.current?.liveTest;
// print('tearDown ${liveTest?.test.name}');
// });
// setUp(() {
// final liveTest = Invoker.current?.liveTest;
// print('setUp ${liveTest?.test.name}');
// });
// tearDown(() {
// final liveTest = Invoker.current?.liveTest;
// print('tearDown ${liveTest?.test.name}');
// });
group('Uninitialized', () {
test('veilid config defaults', testVeilidConfigDefaults, tags: ['config']);
});
group('Initialized', () {
setUpAll(fixture.setUp);
tearDownAll(fixture.tearDown);
setUpAll(updateProcessorFixture.setUp);
tearDownAll(updateProcessorFixture.tearDown);
// Fail the run if any subsystem (online/relay/route/connection/readiness) flapped
tearDownAll(LogFixture.instance.assertNoFlapping);
group('Crypto', () {
test('list cryptosystems', testListCryptoSystems, tags: ['crypto']);
test('get cryptosystem', testGetCryptoSystems, tags: ['crypto']);
test('get cryptosystem invalid', testGetCryptoSystemInvalid,
tags: ['crypto']);
test('hash and verify password', testHashAndVerifyPassword,
tags: ['crypto']);
test('sign and verify signature', testSignAndVerifySignature);
test('sign and verify signatures', testSignAndVerifySignatures,
tags: ['crypto']);
test('generate shared secret', testGenerateSharedSecret,
tags: ['crypto']);
test('hpke seal and open', testHpkeSealOpen, tags: ['crypto']);
test('kem bridge from signing keys', testKemBridgeFromSigningKeys,
tags: ['crypto']);
});
group('Table DB', () {
test('delete table db nonexistent', testDeleteTableDbNonExistent,
tags: ['table_db']);
test('open delete table db', testOpenDeleteTableDb, tags: ['table_db']);
test('open twice table db', testOpenTwiceTableDb, tags: ['table_db']);
test('open twice table db store load', testOpenTwiceTableDbStoreLoad,
tags: ['table_db']);
test('open twice table db store delete load',
testOpenTwiceTableDbStoreDeleteLoad,
tags: ['table_db']);
test('resize table db', testResizeTableDb, tags: ['table_db']);
});
group('Protected Store', () {
test('save load remove user secret', testSaveLoadRemoveUserSecret,
tags: ['protected_store']);
test('binary user secret roundtrip', testBinaryUserSecretRoundtrip,
tags: ['protected_store']);
test('missing user secret', testMissingUserSecret,
tags: ['protected_store']);
test('list user secrets', testListUserSecrets, tags: ['protected_store']);
test('list never returns reserved keys', testListNeverReturnsReservedKeys,
tags: ['protected_store']);
test('reserved keys are rejected', testReservedKeysAreRejected,
tags: ['protected_store']);
test('delete all user secrets', testDeleteAllUserSecrets,
tags: ['protected_store']);
});
group('Attached', () {
setUpAll(fixture.attach);
tearDownAll(fixture.detach);
group('Routing Contexts', () {
test('routing contexts', testRoutingContexts);
test('app message loopback',
() => testAppMessageLoopback(fixture.updateStream),
tags: ['routing_context', 'app_message']);
test('app call loopback',
() => testAppCallLoopback(fixture.updateStream),
tags: ['routing_context', 'app_call']);
test('app message loopback big packets',
() => testAppMessageLoopbackBigPackets(fixture.updateStream),
tags: ['routing_context', 'app_message_big']);
test('app call loopback big packets',
() => testAppCallLoopbackBigPackets(fixture.updateStream),
tags: ['routing_context', 'app_call_big']);
group('Uninitialized', () {
test('veilid config defaults', testVeilidConfigDefaults,
tags: ['config']);
});
for (final cryptoKind in Veilid.instance.validCryptoKinds()) {
group('DHT $cryptoKind', () {
final testDHT = TestDHT(cryptoKind);
setUpAll(testDHT.setUpAll);
tearDownAll(testDHT.tearDownAll);
group('Initialized', () {
setUpAll(fixture.setUp);
tearDownAll(fixture.tearDown);
setUpAll(updateProcessorFixture.setUp);
tearDownAll(updateProcessorFixture.tearDown);
// Fail the run if any subsystem (online/relay/route/connection/readiness) flapped
tearDownAll(LogFixture.instance.assertNoFlapping);
test('get dht value unopened', testDHT.testGetDHTValueUnopened,
tags: ['dht']);
test('open dht record nonexistent no writer',
testDHT.testOpenDHTRecordNonexistentNoWriter,
tags: ['dht']);
test('close dht record nonexistent',
testDHT.testCloseDHTRecordNonexistent,
tags: ['dht']);
test('delete dht record nonexistent',
testDHT.testDeleteDHTRecordNonexistent,
tags: ['dht']);
test('create delete dht record simple',
testDHT.testCreateDeleteDHTRecordSimple,
tags: ['dht']);
test('create delete dht record no close',
testDHT.testCreateDeleteDHTRecordNoClose,
tags: ['dht']);
test('create delete dht record with deterministic key',
testDHT.testCreateDHTRecordWithDeterministicKey,
tags: ['dht']);
test('get dht value nonexistent', testDHT.testGetDHTValueNonexistent);
test('set get dht value', testDHT.testSetGetDHTValue, tags: ['dht']);
test('set get dht value with owner',
testDHT.testSetGetDHTValueWithOwner,
tags: ['dht']);
test('open writer dht value', testDHT.testOpenWriterDHTValue,
tags: ['dht']);
test('inspect dht record', testDHT.testInspectDHTRecord,
tags: ['dht']);
test('flush dht record', testDHT.testFlushDHTRecord, tags: ['dht']);
group('Crypto', () {
test('list cryptosystems', testListCryptoSystems, tags: ['crypto']);
test('get cryptosystem', testGetCryptoSystems, tags: ['crypto']);
test('get cryptosystem invalid', testGetCryptoSystemInvalid,
tags: ['crypto']);
test('hash and verify password', testHashAndVerifyPassword,
tags: ['crypto']);
test('sign and verify signature', testSignAndVerifySignature);
test('sign and verify signatures', testSignAndVerifySignatures,
tags: ['crypto']);
test('generate shared secret', testGenerateSharedSecret,
tags: ['crypto']);
test('hpke seal and open', testHpkeSealOpen, tags: ['crypto']);
test('kem bridge from signing keys', testKemBridgeFromSigningKeys,
tags: ['crypto']);
});
group('DHT Transactions $cryptoKind', () {
final testDHTTransactions =
TestDHTTransactions(cryptoKind, updateProcessorFixture);
setUpAll(testDHTTransactions.setUpAll);
tearDownAll(testDHTTransactions.tearDownAll);
setUp(testDHTTransactions.setUp);
tearDown(testDHTTransactions.tearDown);
test('should create empty transaction and drop it explicitly',
testDHTTransactions.testEmptyTxAndDrop,
tags: ['dht_transactions']);
test('should create empty transaction and rollback',
testDHTTransactions.testEmptyTxAndRollback,
tags: ['dht_transactions']);
test('should create empty transaction and commit',
testDHTTransactions.testEmptyTxAndCommit,
tags: ['dht_transactions']);
test('should create transaction, add sets, and rollback',
testDHTTransactions.testTxAddSetsAndRollback,
tags: ['dht_transactions']);
test('should create transaction, add sets, and commit',
testDHTTransactions.testTxAddSetsAndCommit,
tags: ['dht_transactions']);
test('should extend transaction with new record and commit',
testDHTTransactions.testTxExtendAndCommit,
tags: ['dht_transactions']);
test('should extend transaction with new record and rollback',
testDHTTransactions.testTxExtendAndRollback,
tags: ['dht_transactions']);
test('should create transaction, add sets, gets, and commit',
testDHTTransactions.testTxAddSetsGetsAndCommit,
tags: ['dht_transactions']);
test(
'should create empty transaction, fail non-transactional sets and'
' then rollback',
testDHTTransactions.testTxFailNonTxSetsAndRollback,
tags: ['dht_transactions']);
test(
'should create transaction, inspect, add sets to subkey 1, '
' inspect and commit. Then a new transaction inspect, and gets, '
'and commit',
testDHTTransactions.testTxInspectAddInspectCommit,
tags: ['dht_transactions']);
group('Table DB', () {
test('delete table db nonexistent', testDeleteTableDbNonExistent,
tags: ['table_db']);
test('open delete table db', testOpenDeleteTableDb,
tags: ['table_db']);
test('open twice table db', testOpenTwiceTableDb, tags: ['table_db']);
test('open twice table db store load', testOpenTwiceTableDbStoreLoad,
tags: ['table_db']);
test('open twice table db store delete load',
testOpenTwiceTableDbStoreDeleteLoad,
tags: ['table_db']);
test('resize table db', testResizeTableDb, tags: ['table_db']);
});
group('Veilid DHT Transactions Full $cryptoKind', () {
final testDHTTransactionsFull = TestDHTTransactionsFull(cryptoKind);
setUpAll(testDHTTransactionsFull.setUpAll);
tearDownAll(testDHTTransactionsFull.tearDownAll);
setUp(testDHTTransactionsFull.setUp);
tearDown(testDHTTransactionsFull.tearDown);
test('should create empty transaction, inspect, add gets and commit',
testDHTTransactionsFull.testEmptyTxInspectGetsAndCommit,
timeout: const Timeout(Duration(seconds: 120)), tags: ['stress']);
test(
'should create transaction, fill all records, commit, and then'
' get all records and rollback',
testDHTTransactionsFull.testTxFillCommitTxGetRollback,
timeout: const Timeout(Duration(seconds: 300)),
tags: ['stress']);
group('Protected Store', () {
test('save load remove user secret', testSaveLoadRemoveUserSecret,
tags: ['protected_store']);
test('binary user secret roundtrip', testBinaryUserSecretRoundtrip,
tags: ['protected_store']);
test('missing user secret', testMissingUserSecret,
tags: ['protected_store']);
test('list user secrets', testListUserSecrets,
tags: ['protected_store']);
test('list never returns reserved keys',
testListNeverReturnsReservedKeys,
tags: ['protected_store']);
test('reserved keys are rejected', testReservedKeysAreRejected,
tags: ['protected_store']);
test('delete all user secrets', testDeleteAllUserSecrets,
tags: ['protected_store']);
});
}
group('Attached', () {
setUpAll(fixture.attach);
tearDownAll(fixture.detach);
group('Routing Contexts', () {
test('routing contexts', testRoutingContexts);
test('app message loopback',
() => testAppMessageLoopback(fixture.updateStream),
tags: ['routing_context', 'app_message']);
test('app call loopback',
() => testAppCallLoopback(fixture.updateStream),
tags: ['routing_context', 'app_call']);
test('app message loopback big packets',
() => testAppMessageLoopbackBigPackets(fixture.updateStream),
tags: ['routing_context', 'app_message_big']);
test('app call loopback big packets',
() => testAppCallLoopbackBigPackets(fixture.updateStream),
tags: ['routing_context', 'app_call_big']);
});
for (final cryptoKind in Veilid.instance.validCryptoKinds()) {
group('DHT $cryptoKind', () {
final testDHT = TestDHT(cryptoKind);
setUpAll(testDHT.setUpAll);
tearDownAll(testDHT.tearDownAll);
test('get dht value unopened', testDHT.testGetDHTValueUnopened,
tags: ['dht']);
test('open dht record nonexistent no writer',
testDHT.testOpenDHTRecordNonexistentNoWriter,
tags: ['dht']);
test('close dht record nonexistent',
testDHT.testCloseDHTRecordNonexistent,
tags: ['dht']);
test('delete dht record nonexistent',
testDHT.testDeleteDHTRecordNonexistent,
tags: ['dht']);
test('create delete dht record simple',
testDHT.testCreateDeleteDHTRecordSimple,
tags: ['dht']);
test('create delete dht record no close',
testDHT.testCreateDeleteDHTRecordNoClose,
tags: ['dht']);
test('create delete dht record with deterministic key',
testDHT.testCreateDHTRecordWithDeterministicKey,
tags: ['dht']);
test('get dht value nonexistent',
testDHT.testGetDHTValueNonexistent);
test('set get dht value', testDHT.testSetGetDHTValue,
tags: ['dht']);
test('set get dht value with owner',
testDHT.testSetGetDHTValueWithOwner,
tags: ['dht']);
test('open writer dht value', testDHT.testOpenWriterDHTValue,
tags: ['dht']);
test('inspect dht record', testDHT.testInspectDHTRecord,
tags: ['dht']);
test('min seqnum dht record', testDHT.testMinSeqnumDHTRecord,
tags: ['dht']);
test('flush dht record', testDHT.testFlushDHTRecord,
tags: ['dht']);
});
group('DHT Transactions $cryptoKind', () {
final testDHTTransactions =
TestDHTTransactions(cryptoKind, updateProcessorFixture);
setUpAll(testDHTTransactions.setUpAll);
tearDownAll(testDHTTransactions.tearDownAll);
setUp(testDHTTransactions.setUp);
tearDown(testDHTTransactions.tearDown);
test('should create empty transaction and drop it explicitly',
testDHTTransactions.testEmptyTxAndDrop,
tags: ['dht_transactions']);
test('should create empty transaction and rollback',
testDHTTransactions.testEmptyTxAndRollback,
tags: ['dht_transactions']);
test('should create empty transaction and commit',
testDHTTransactions.testEmptyTxAndCommit,
tags: ['dht_transactions']);
test('should create transaction, add sets, and rollback',
testDHTTransactions.testTxAddSetsAndRollback,
tags: ['dht_transactions']);
test('should create transaction, add sets, and commit',
testDHTTransactions.testTxAddSetsAndCommit,
tags: ['dht_transactions']);
test('should extend transaction with new record and commit',
testDHTTransactions.testTxExtendAndCommit,
tags: ['dht_transactions']);
test('should extend transaction with new record and rollback',
testDHTTransactions.testTxExtendAndRollback,
tags: ['dht_transactions']);
test('should create transaction, add sets, gets, and commit',
testDHTTransactions.testTxAddSetsGetsAndCommit,
tags: ['dht_transactions']);
test(
'should create empty transaction, fail non-transactional sets and'
' then rollback',
testDHTTransactions.testTxFailNonTxSetsAndRollback,
tags: ['dht_transactions']);
test(
'should create transaction, inspect, add sets to subkey 1, '
' inspect and commit. Then a new transaction inspect, and gets, '
'and commit',
testDHTTransactions.testTxInspectAddInspectCommit,
tags: ['dht_transactions']);
});
group('Veilid DHT Transactions Full $cryptoKind', () {
final testDHTTransactionsFull =
TestDHTTransactionsFull(cryptoKind);
setUpAll(testDHTTransactionsFull.setUpAll);
tearDownAll(testDHTTransactionsFull.tearDownAll);
setUp(testDHTTransactionsFull.setUp);
tearDown(testDHTTransactionsFull.tearDown);
test(
'should create empty transaction, inspect, add gets and commit',
testDHTTransactionsFull.testEmptyTxInspectGetsAndCommit,
timeout: const Timeout(Duration(seconds: 120)),
tags: ['stress']);
test(
'should create transaction, fill all records, commit, and then'
' get all records and rollback',
testDHTTransactionsFull.testTxFillCommitTxGetRollback,
timeout: const Timeout(Duration(seconds: 300)),
tags: ['stress']);
});
}
});
});
});
});
});
@@ -122,8 +122,7 @@ Future<void> testHpkeSealOpen() async {
expect(await cs.hpkeOpen(kkp1.secret, aad, sealed), equals(plaintext));
// empty aad and empty plaintext round-trip
final sealedEmpty =
await cs.hpkeSeal(kkp1.key, Uint8List(0), Uint8List(0));
final sealedEmpty = await cs.hpkeSeal(kkp1.key, Uint8List(0), Uint8List(0));
expect(await cs.hpkeOpen(kkp1.secret, Uint8List(0), sealedEmpty),
equals(Uint8List(0)));
@@ -12,6 +12,17 @@ class TestDHT {
TestDHT(this.cryptoKind);
// A closing write has no next write to recover with, so it reports TryAgain
static final _closingWriteRetry = RetryStrategy(
timeout: const Duration(seconds: 30),
rules: [
RetryRule.delay(
matches: (e) => e is VeilidAPIExceptionTryAgain,
delay: const Duration(milliseconds: 250),
),
],
);
Future<void> setUpAll() async {
routingContext = await Veilid.instance.routingContext();
}
@@ -297,6 +308,50 @@ class TestDHT {
await routingContext.deleteDHTRecord(rec.key);
}
Future<void> testMinSeqnumDHTRecord() async {
final rec = await routingContext.createDHTRecord(
cryptoKind, const DHTSchema.dflt(oCnt: 1));
const noOffline = SetDHTValueOptions(allowOffline: false);
final va = utf8.encode('Qwertyuiop Asdfghjkl Zxcvbnm');
final vb = utf8.encode('1234567890');
// maxSeqnum - 1 leaves exactly one write
expect(
await routingContext.setDHTValue(rec.key, 0, va,
options: noOffline.copyWith(minSeqnum: ValueData.maxSeqnum - 1)),
isNull);
var rr = await routingContext.inspectDHTRecord(rec.key);
expect(rr.localSeqs, equals([ValueData.maxSeqnum - 1]));
expect(
await _closingWriteRetry.retry(() =>
routingContext.setDHTValue(rec.key, 0, vb, options: noOffline)),
isNull);
rr = await routingContext.inspectDHTRecord(rec.key);
expect(rr.localSeqs, equals([ValueData.maxSeqnum]));
// Nothing writes after maxSeqnum
await expectLater(
routingContext.setDHTValue(rec.key, 0, va, options: noOffline),
throwsA(isA<VeilidAPIExceptionGeneric>()));
// A resend at the same minimum reuses the seqnum instead of failing
expect(
await _closingWriteRetry.retry(() => routingContext.setDHTValue(
rec.key, 0, vb,
options: noOffline.copyWith(minSeqnum: ValueData.maxSeqnum))),
isNull);
rr = await routingContext.inspectDHTRecord(rec.key);
expect(rr.localSeqs, equals([ValueData.maxSeqnum]));
await routingContext.closeDHTRecord(rec.key);
await routingContext.deleteDHTRecord(rec.key);
}
Future<void> testFlushDHTRecord() async {
final rec = await routingContext.createDHTRecord(
cryptoKind, const DHTSchema.dflt(oCnt: 1));
@@ -112,13 +112,15 @@ class TestDHTTransactionsFull {
// Commit
final startCommit = Veilid.instance.now();
await tx.commit();
debugPrint('commit transaction: ${Veilid.instance.now().diff(startCommit)}');
debugPrint(
'commit transaction: ${Veilid.instance.now().diff(startCommit)}');
// Transaction 2
final startCommit2 = Veilid.instance.now();
final tx2 = await Veilid.instance.transactDHTRecords(dhtRecords);
expect(tx2, isInstanceOf<VeilidDHTTransaction>());
debugPrint('begin transaction 2: ${Veilid.instance.now().diff(startCommit2)}');
debugPrint(
'begin transaction 2: ${Veilid.instance.now().diff(startCommit2)}');
// Gets
for (var subkey = 0; subkey < dhtSubkeyCount; subkey++) {
@@ -19,8 +19,7 @@ Future<void> testSaveLoadRemoveUserSecret() async {
await _cleanup();
// Saving a new secret reports that nothing was there before.
expect(
await Veilid.instance.saveUserSecret(testKey, utf8.encode('hello')),
expect(await Veilid.instance.saveUserSecret(testKey, utf8.encode('hello')),
isFalse);
expect(utf8.decode((await Veilid.instance.loadUserSecret(testKey))!),
equals('hello'));
@@ -54,7 +53,8 @@ Future<void> testBinaryUserSecretRoundtrip() async {
Future<void> testMissingUserSecret() async {
expect(await Veilid.instance.loadUserSecret('__dart_never_stored'), isNull);
expect(await Veilid.instance.removeUserSecret('__dart_never_stored'), isFalse);
expect(
await Veilid.instance.removeUserSecret('__dart_never_stored'), isFalse);
}
Future<void> testListUserSecrets() async {
@@ -118,8 +118,8 @@ Future<void> testDeleteAllUserSecrets() async {
}
// The store is still usable afterwards.
expect(await Veilid.instance.saveUserSecret(testKey, utf8.encode('c')),
isFalse);
expect(
await Veilid.instance.saveUserSecret(testKey, utf8.encode('c')), isFalse);
keys = await Veilid.instance.listUserSecrets();
expect(keys, contains(testKey));
+1 -2
View File
@@ -18,8 +18,7 @@ void main() {
// Verify that platform version is retrieved.
expect(
find.byWidgetPredicate(
(widget) =>
widget is Text && widget.data!.startsWith('Running on:'),
(widget) => widget is Text && widget.data!.startsWith('Running on:'),
),
findsOneWidget,
);
+1
View File
@@ -1,5 +1,6 @@
// Builds veilid-flutter/rust as the code asset lib/veilid_ffi.dart resolves against.
// `assetName` below and that file's @DefaultAsset must move together.
import 'package:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_rust/native_toolchain_rust.dart';
+41 -36
View File
@@ -24,41 +24,46 @@ Future<VeilidConfig> getDefaultVeilidConfig({
final defaultConfigStr = Veilid.instance.defaultVeilidConfig();
final defaultConfig = VeilidConfig.fromJson(jsonDecode(defaultConfigStr));
return defaultConfig.copyWith(
programName: programName,
namespace: namespace,
tableStore: defaultConfig.tableStore.copyWith(
directory: isWeb
? ''
: p.join((await getApplicationSupportDirectory()).absolute.path,
'table_store'),
programName: programName,
namespace: namespace,
tableStore: defaultConfig.tableStore.copyWith(
directory: isWeb
? ''
: p.join(
(await getApplicationSupportDirectory()).absolute.path,
'table_store',
),
),
blockStore: defaultConfig.blockStore.copyWith(
directory: isWeb
? ''
: p.join(
(await getApplicationSupportDirectory()).absolute.path,
'block_store',
),
),
protectedStore: defaultConfig.protectedStore.copyWith(
directory: isWeb
? ''
: p.join(
(await getApplicationSupportDirectory()).absolute.path,
'protected_store',
),
deviceEncryptionKeyPassword: deviceEncryptionKeyPassword,
newDeviceEncryptionKeyPassword: newDeviceEncryptionKeyPassword,
),
network: defaultConfig.network.copyWith(
networkKeyPassword: networkKeyPassword,
routingTable: defaultConfig.network.routingTable.copyWith(
bootstrap: bootstrap.isNotEmpty
? bootstrap.split(',')
: defaultConfig.network.routingTable.bootstrap,
bootstrapKeys: bootstrapKeys != null
? bootstrapKeys.isNotEmpty
? bootstrapKeys.split(',').map(PublicKey.fromString).toList()
: []
: defaultConfig.network.routingTable.bootstrapKeys,
),
blockStore: defaultConfig.blockStore.copyWith(
directory: isWeb
? ''
: p.join((await getApplicationSupportDirectory()).absolute.path,
'block_store'),
),
protectedStore: defaultConfig.protectedStore.copyWith(
directory: isWeb
? ''
: p.join((await getApplicationSupportDirectory()).absolute.path,
'protected_store'),
deviceEncryptionKeyPassword: deviceEncryptionKeyPassword,
newDeviceEncryptionKeyPassword: newDeviceEncryptionKeyPassword,
),
network: defaultConfig.network.copyWith(
networkKeyPassword: networkKeyPassword,
routingTable: defaultConfig.network.routingTable.copyWith(
bootstrap: bootstrap.isNotEmpty
? bootstrap.split(',')
: defaultConfig.network.routingTable.bootstrap,
bootstrapKeys: bootstrapKeys != null
? bootstrapKeys.isNotEmpty
? bootstrapKeys
.split(',')
.map(PublicKey.fromString)
.toList()
: []
: defaultConfig.network.routingTable.bootstrapKeys),
));
),
);
}
+4 -6
View File
@@ -27,8 +27,9 @@ extension VeilidProcessorRetry on VeilidProcessorInterface {
if (processorConnectionState.isPublicInternetReady) {
return;
}
var stream = streamProcessorConnectionState()
.where((s) => s.isPublicInternetReady);
var stream = streamProcessorConnectionState().where(
(s) => s.isPublicInternetReady,
);
if (timeout != null) {
stream = stream.timeout(timeout);
}
@@ -50,10 +51,7 @@ extension VeilidProcessorRetry on VeilidProcessorInterface {
/// Run [closure], retrying VeilidAPI transients per [strategy] (default
/// [VeilidAPIRetryStrategy], waiting on network readiness before a tryAgain
/// retry).
Future<T> retry<T>(
Future<T> Function() closure, {
RetryStrategy? strategy,
}) =>
Future<T> retry<T>(Future<T> Function() closure, {RetryStrategy? strategy}) =>
(strategy ??
VeilidAPIRetryStrategy(
tryAgainRetry: (attemptNumber) async {
+38 -39
View File
@@ -21,19 +21,16 @@ class RetryRule {
/// Retry up to [maxAttempts] times (null = unbounded), waiting [delay] (or
/// not, if null) between tries.
RetryRule.delay({
required this.matches,
int? maxAttempts,
Duration? delay,
}) : beforeRetry = ((n) async {
if (maxAttempts != null && n >= maxAttempts) {
return false;
}
if (delay != null) {
await Future<void>.delayed(delay);
}
return true;
});
RetryRule.delay({required this.matches, int? maxAttempts, Duration? delay})
: beforeRetry = ((n) async {
if (maxAttempts != null && n >= maxAttempts) {
return false;
}
if (delay != null) {
await Future<void>.delayed(delay);
}
return true;
});
/// Retry up to [maxAttempts] times (null = unbounded), awaiting [wait] (e.g.
/// network readiness) between tries.
@@ -42,20 +39,19 @@ class RetryRule {
int? maxAttempts,
required Future<void> Function() wait,
}) : beforeRetry = ((n) async {
if (maxAttempts != null && n >= maxAttempts) {
return false;
}
await wait();
return true;
});
if (maxAttempts != null && n >= maxAttempts) {
return false;
}
await wait();
return true;
});
/// A copy whose action is [chain], which receives the attempt number and this
/// rule's current action so it can do its own work and defer to it, e.g.
/// `rule.withBeforeRetry((n, prev) async { record(); return prev(n); })`.
RetryRule withBeforeRetry(
Future<bool> Function(int attemptNumber, RetryAction previous) chain,
) =>
RetryRule(matches: matches, beforeRetry: (n) => chain(n, beforeRetry));
) => RetryRule(matches: matches, beforeRetry: (n) => chain(n, beforeRetry));
/// A copy that runs [onRetry] (e.g. telemetry) before this rule's action, or
/// this rule unchanged if [onRetry] is null.
@@ -127,8 +123,8 @@ class RetryStrategy {
}
/// VeilidAPI-level policy: retry the transients that clear once online. Each
/// rule's action defaults to a bounded fixed delay; override either to change
/// the wait (e.g. block on network readiness) or add telemetry.
/// rule's action defaults to a bounded doubling delay; override either to
/// change the wait (e.g. block on network readiness) or add telemetry.
class VeilidAPIRetryStrategy extends RetryStrategy {
/// [tryAgainRetry] handles [VeilidAPIExceptionTryAgain]; [transientRetry]
/// handles timeout and no-connection errors. Either defaults to
@@ -139,27 +135,30 @@ class VeilidAPIRetryStrategy extends RetryStrategy {
RetryAction? transientRetry,
Duration? timeout,
}) : super(
rules: [
RetryRule(
matches: (e) => e is VeilidAPIExceptionTryAgain,
beforeRetry: tryAgainRetry ?? defaultRetry,
),
RetryRule(
matches: (e) =>
e is VeilidAPIExceptionTimeout ||
e is VeilidAPIExceptionNoConnection,
beforeRetry: transientRetry ?? defaultRetry,
),
],
timeout: timeout,
);
rules: [
RetryRule(
matches: (e) => e is VeilidAPIExceptionTryAgain,
beforeRetry: tryAgainRetry ?? defaultRetry,
),
RetryRule(
matches: (e) =>
e is VeilidAPIExceptionTimeout ||
e is VeilidAPIExceptionNoConnection,
beforeRetry: transientRetry ?? defaultRetry,
),
],
timeout: timeout,
);
/// Up to 3 tries, 250ms apart.
/// Up to 3 tries, waiting 500ms then 1s. The delay doubles because a flat one
/// re-offers the whole load to a congested network at once.
static Future<bool> defaultRetry(int attemptNumber) async {
if (attemptNumber >= 3) {
return false;
}
await Future<void>.delayed(const Duration(milliseconds: 250));
await Future<void>.delayed(
Duration(milliseconds: 250 * (1 << attemptNumber)),
);
return true;
}
}
+23 -9
View File
@@ -52,22 +52,30 @@ abstract class VeilidAPIException implements Exception {
case 'Unimplemented':
{
return VeilidAPIExceptionUnimplemented(
json['unimplemented']! as String);
json['unimplemented']! as String,
);
}
case 'ParseError':
{
return VeilidAPIExceptionParseError(
json['message']! as String, json['value']! as String);
json['message']! as String,
json['value']! as String,
);
}
case 'InvalidArgument':
{
return VeilidAPIExceptionInvalidArgument(json['context']! as String,
json['argument']! as String, json['value']! as String);
return VeilidAPIExceptionInvalidArgument(
json['context']! as String,
json['argument']! as String,
json['value']! as String,
);
}
case 'MissingArgument':
{
return VeilidAPIExceptionMissingArgument(
json['context']! as String, json['argument']! as String);
json['context']! as String,
json['argument']! as String,
);
}
case 'Generic':
{
@@ -76,12 +84,14 @@ abstract class VeilidAPIException implements Exception {
case 'TransactionNotFound':
{
return VeilidAPIExceptionTransactionNotFound(
json['message']! as String);
json['message']! as String,
);
}
default:
{
throw VeilidAPIExceptionInternal(
"Invalid VeilidAPIException type: ${json['kind']! as String}");
"Invalid VeilidAPIException type: ${json['kind']! as String}",
);
}
}
}
@@ -261,10 +271,14 @@ class VeilidAPIExceptionInvalidArgument implements VeilidAPIException {
/// Construct with the calling context, argument name, and rejected value.
const VeilidAPIExceptionInvalidArgument(
this.context, this.argument, this.value);
this.context,
this.argument,
this.value,
);
@override
String toString() => 'VeilidAPIException: InvalidArgument'
String toString() =>
'VeilidAPIException: InvalidArgument'
' ($context:$argument)\n value: $value';
@override
+17 -17
View File
@@ -105,7 +105,9 @@ sealed class VeilidFFIConfigLogging with _$VeilidFFIConfigLogging {
VeilidFFIConfigLoggingOtlp otlp,
@Default(VeilidFFIConfigLoggingFlame(enabled: false, path: ''))
VeilidFFIConfigLoggingFlame flame,
@Default(VeilidFFIConfigLoggingStats(enabled: false, intervalSecs: 10, path: ''))
@Default(
VeilidFFIConfigLoggingStats(enabled: false, intervalSecs: 10, path: ''),
)
VeilidFFIConfigLoggingStats stats,
}) = _VeilidFFIConfigLogging;
@@ -385,9 +387,8 @@ sealed class VeilidConfigDHT with _$VeilidConfigDHT {
/// RPC configuration.
@freezed
sealed class VeilidConfigRPC with _$VeilidConfigRPC {
const factory VeilidConfigRPC({
required int defaultRouteHopCount,
}) = _VeilidConfigRPC;
const factory VeilidConfigRPC({required int defaultRouteHopCount}) =
_VeilidConfigRPC;
factory VeilidConfigRPC.fromJson(dynamic json) =>
_$VeilidConfigRPCFromJson(json as Map<String, dynamic>);
@@ -424,17 +425,16 @@ enum VeilidConfigAddressType {
/// Parse from its JSON name (`IPV4`/`IPV6`).
factory VeilidConfigAddressType.fromJson(dynamic j) => switch (j as String) {
'IPV4' => VeilidConfigAddressType.ipv4,
'IPV6' => VeilidConfigAddressType.ipv6,
_ =>
throw ArgumentError.value(j, 'j', 'invalid VeilidConfigAddressType'),
};
'IPV4' => VeilidConfigAddressType.ipv4,
'IPV6' => VeilidConfigAddressType.ipv6,
_ => throw ArgumentError.value(j, 'j', 'invalid VeilidConfigAddressType'),
};
/// The JSON name (`IPV4`/`IPV6`).
String toJson() => switch (this) {
VeilidConfigAddressType.ipv4 => 'IPV4',
VeilidConfigAddressType.ipv6 => 'IPV6',
};
VeilidConfigAddressType.ipv4 => 'IPV4',
VeilidConfigAddressType.ipv6 => 'IPV6',
};
}
////////////
@@ -514,8 +514,8 @@ enum VeilidConfigProtectedStoreBackend {
/// WebExtension storage.
extensionStorage;
// /// Delegate to a registered secret-resolver callback.
// callback;
// /// Delegate to a registered secret-resolver callback.
// callback;
/// Parse from its JSON (PascalCase) name.
factory VeilidConfigProtectedStoreBackend.fromJson(dynamic j) =>
@@ -566,9 +566,8 @@ sealed class VeilidConfigCapabilities with _$VeilidConfigCapabilities {
/// Internal "footgun" UDP tuning. See [VeilidConfigInternal].
@freezed
sealed class VeilidConfigInternalUDP with _$VeilidConfigInternalUDP {
const factory VeilidConfigInternalUDP({
required int socketPoolSize,
}) = _VeilidConfigInternalUDP;
const factory VeilidConfigInternalUDP({required int socketPoolSize}) =
_VeilidConfigInternalUDP;
factory VeilidConfigInternalUDP.fromJson(dynamic json) =>
_$VeilidConfigInternalUDPFromJson(json as Map<String, dynamic>);
@@ -640,6 +639,7 @@ sealed class VeilidConfigInternalDHT with _$VeilidConfigInternalDHT {
sealed class VeilidConfigInternalNetwork with _$VeilidConfigInternalNetwork {
const factory VeilidConfigInternalNetwork({
required int connectionInitialTimeoutMs,
required int singleSendTimeoutMs,
required int connectionInactivityTimeoutMs,
required int maxConnectionsPerIp4,
required int maxConnectionsPerIp6Prefix,
+23 -20
View File
@@ -9119,7 +9119,7 @@ as int,
/// @nodoc
mixin _$VeilidConfigInternalNetwork implements DiagnosticableTreeMixin {
int get connectionInitialTimeoutMs; int get connectionInactivityTimeoutMs; int get maxConnectionsPerIp4; int get maxConnectionsPerIp6Prefix; int get maxConnectionsPerIp6PrefixSize; int get maxConnectionFrequencyPerMin; int get clientAllowlistTimeoutMs; int get reverseConnectionReceiptTimeMs; int get holePunchReceiptTimeMs; int get restrictedNatRetries; VeilidConfigInternalRPC get rpc; VeilidConfigInternalDHT get dht; VeilidConfigInternalProtocol get protocol;
int get connectionInitialTimeoutMs; int get singleSendTimeoutMs; int get connectionInactivityTimeoutMs; int get maxConnectionsPerIp4; int get maxConnectionsPerIp6Prefix; int get maxConnectionsPerIp6PrefixSize; int get maxConnectionFrequencyPerMin; int get clientAllowlistTimeoutMs; int get reverseConnectionReceiptTimeMs; int get holePunchReceiptTimeMs; int get restrictedNatRetries; VeilidConfigInternalRPC get rpc; VeilidConfigInternalDHT get dht; VeilidConfigInternalProtocol get protocol;
/// Create a copy of VeilidConfigInternalNetwork
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -9133,21 +9133,21 @@ $VeilidConfigInternalNetworkCopyWith<VeilidConfigInternalNetwork> get copyWith =
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties
..add(DiagnosticsProperty('type', 'VeilidConfigInternalNetwork'))
..add(DiagnosticsProperty('connectionInitialTimeoutMs', connectionInitialTimeoutMs))..add(DiagnosticsProperty('connectionInactivityTimeoutMs', connectionInactivityTimeoutMs))..add(DiagnosticsProperty('maxConnectionsPerIp4', maxConnectionsPerIp4))..add(DiagnosticsProperty('maxConnectionsPerIp6Prefix', maxConnectionsPerIp6Prefix))..add(DiagnosticsProperty('maxConnectionsPerIp6PrefixSize', maxConnectionsPerIp6PrefixSize))..add(DiagnosticsProperty('maxConnectionFrequencyPerMin', maxConnectionFrequencyPerMin))..add(DiagnosticsProperty('clientAllowlistTimeoutMs', clientAllowlistTimeoutMs))..add(DiagnosticsProperty('reverseConnectionReceiptTimeMs', reverseConnectionReceiptTimeMs))..add(DiagnosticsProperty('holePunchReceiptTimeMs', holePunchReceiptTimeMs))..add(DiagnosticsProperty('restrictedNatRetries', restrictedNatRetries))..add(DiagnosticsProperty('rpc', rpc))..add(DiagnosticsProperty('dht', dht))..add(DiagnosticsProperty('protocol', protocol));
..add(DiagnosticsProperty('connectionInitialTimeoutMs', connectionInitialTimeoutMs))..add(DiagnosticsProperty('singleSendTimeoutMs', singleSendTimeoutMs))..add(DiagnosticsProperty('connectionInactivityTimeoutMs', connectionInactivityTimeoutMs))..add(DiagnosticsProperty('maxConnectionsPerIp4', maxConnectionsPerIp4))..add(DiagnosticsProperty('maxConnectionsPerIp6Prefix', maxConnectionsPerIp6Prefix))..add(DiagnosticsProperty('maxConnectionsPerIp6PrefixSize', maxConnectionsPerIp6PrefixSize))..add(DiagnosticsProperty('maxConnectionFrequencyPerMin', maxConnectionFrequencyPerMin))..add(DiagnosticsProperty('clientAllowlistTimeoutMs', clientAllowlistTimeoutMs))..add(DiagnosticsProperty('reverseConnectionReceiptTimeMs', reverseConnectionReceiptTimeMs))..add(DiagnosticsProperty('holePunchReceiptTimeMs', holePunchReceiptTimeMs))..add(DiagnosticsProperty('restrictedNatRetries', restrictedNatRetries))..add(DiagnosticsProperty('rpc', rpc))..add(DiagnosticsProperty('dht', dht))..add(DiagnosticsProperty('protocol', protocol));
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is VeilidConfigInternalNetwork&&(identical(other.connectionInitialTimeoutMs, connectionInitialTimeoutMs) || other.connectionInitialTimeoutMs == connectionInitialTimeoutMs)&&(identical(other.connectionInactivityTimeoutMs, connectionInactivityTimeoutMs) || other.connectionInactivityTimeoutMs == connectionInactivityTimeoutMs)&&(identical(other.maxConnectionsPerIp4, maxConnectionsPerIp4) || other.maxConnectionsPerIp4 == maxConnectionsPerIp4)&&(identical(other.maxConnectionsPerIp6Prefix, maxConnectionsPerIp6Prefix) || other.maxConnectionsPerIp6Prefix == maxConnectionsPerIp6Prefix)&&(identical(other.maxConnectionsPerIp6PrefixSize, maxConnectionsPerIp6PrefixSize) || other.maxConnectionsPerIp6PrefixSize == maxConnectionsPerIp6PrefixSize)&&(identical(other.maxConnectionFrequencyPerMin, maxConnectionFrequencyPerMin) || other.maxConnectionFrequencyPerMin == maxConnectionFrequencyPerMin)&&(identical(other.clientAllowlistTimeoutMs, clientAllowlistTimeoutMs) || other.clientAllowlistTimeoutMs == clientAllowlistTimeoutMs)&&(identical(other.reverseConnectionReceiptTimeMs, reverseConnectionReceiptTimeMs) || other.reverseConnectionReceiptTimeMs == reverseConnectionReceiptTimeMs)&&(identical(other.holePunchReceiptTimeMs, holePunchReceiptTimeMs) || other.holePunchReceiptTimeMs == holePunchReceiptTimeMs)&&(identical(other.restrictedNatRetries, restrictedNatRetries) || other.restrictedNatRetries == restrictedNatRetries)&&(identical(other.rpc, rpc) || other.rpc == rpc)&&(identical(other.dht, dht) || other.dht == dht)&&(identical(other.protocol, protocol) || other.protocol == protocol));
return identical(this, other) || (other.runtimeType == runtimeType&&other is VeilidConfigInternalNetwork&&(identical(other.connectionInitialTimeoutMs, connectionInitialTimeoutMs) || other.connectionInitialTimeoutMs == connectionInitialTimeoutMs)&&(identical(other.singleSendTimeoutMs, singleSendTimeoutMs) || other.singleSendTimeoutMs == singleSendTimeoutMs)&&(identical(other.connectionInactivityTimeoutMs, connectionInactivityTimeoutMs) || other.connectionInactivityTimeoutMs == connectionInactivityTimeoutMs)&&(identical(other.maxConnectionsPerIp4, maxConnectionsPerIp4) || other.maxConnectionsPerIp4 == maxConnectionsPerIp4)&&(identical(other.maxConnectionsPerIp6Prefix, maxConnectionsPerIp6Prefix) || other.maxConnectionsPerIp6Prefix == maxConnectionsPerIp6Prefix)&&(identical(other.maxConnectionsPerIp6PrefixSize, maxConnectionsPerIp6PrefixSize) || other.maxConnectionsPerIp6PrefixSize == maxConnectionsPerIp6PrefixSize)&&(identical(other.maxConnectionFrequencyPerMin, maxConnectionFrequencyPerMin) || other.maxConnectionFrequencyPerMin == maxConnectionFrequencyPerMin)&&(identical(other.clientAllowlistTimeoutMs, clientAllowlistTimeoutMs) || other.clientAllowlistTimeoutMs == clientAllowlistTimeoutMs)&&(identical(other.reverseConnectionReceiptTimeMs, reverseConnectionReceiptTimeMs) || other.reverseConnectionReceiptTimeMs == reverseConnectionReceiptTimeMs)&&(identical(other.holePunchReceiptTimeMs, holePunchReceiptTimeMs) || other.holePunchReceiptTimeMs == holePunchReceiptTimeMs)&&(identical(other.restrictedNatRetries, restrictedNatRetries) || other.restrictedNatRetries == restrictedNatRetries)&&(identical(other.rpc, rpc) || other.rpc == rpc)&&(identical(other.dht, dht) || other.dht == dht)&&(identical(other.protocol, protocol) || other.protocol == protocol));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,connectionInitialTimeoutMs,connectionInactivityTimeoutMs,maxConnectionsPerIp4,maxConnectionsPerIp6Prefix,maxConnectionsPerIp6PrefixSize,maxConnectionFrequencyPerMin,clientAllowlistTimeoutMs,reverseConnectionReceiptTimeMs,holePunchReceiptTimeMs,restrictedNatRetries,rpc,dht,protocol);
int get hashCode => Object.hash(runtimeType,connectionInitialTimeoutMs,singleSendTimeoutMs,connectionInactivityTimeoutMs,maxConnectionsPerIp4,maxConnectionsPerIp6Prefix,maxConnectionsPerIp6PrefixSize,maxConnectionFrequencyPerMin,clientAllowlistTimeoutMs,reverseConnectionReceiptTimeMs,holePunchReceiptTimeMs,restrictedNatRetries,rpc,dht,protocol);
@override
String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'VeilidConfigInternalNetwork(connectionInitialTimeoutMs: $connectionInitialTimeoutMs, connectionInactivityTimeoutMs: $connectionInactivityTimeoutMs, maxConnectionsPerIp4: $maxConnectionsPerIp4, maxConnectionsPerIp6Prefix: $maxConnectionsPerIp6Prefix, maxConnectionsPerIp6PrefixSize: $maxConnectionsPerIp6PrefixSize, maxConnectionFrequencyPerMin: $maxConnectionFrequencyPerMin, clientAllowlistTimeoutMs: $clientAllowlistTimeoutMs, reverseConnectionReceiptTimeMs: $reverseConnectionReceiptTimeMs, holePunchReceiptTimeMs: $holePunchReceiptTimeMs, restrictedNatRetries: $restrictedNatRetries, rpc: $rpc, dht: $dht, protocol: $protocol)';
return 'VeilidConfigInternalNetwork(connectionInitialTimeoutMs: $connectionInitialTimeoutMs, singleSendTimeoutMs: $singleSendTimeoutMs, connectionInactivityTimeoutMs: $connectionInactivityTimeoutMs, maxConnectionsPerIp4: $maxConnectionsPerIp4, maxConnectionsPerIp6Prefix: $maxConnectionsPerIp6Prefix, maxConnectionsPerIp6PrefixSize: $maxConnectionsPerIp6PrefixSize, maxConnectionFrequencyPerMin: $maxConnectionFrequencyPerMin, clientAllowlistTimeoutMs: $clientAllowlistTimeoutMs, reverseConnectionReceiptTimeMs: $reverseConnectionReceiptTimeMs, holePunchReceiptTimeMs: $holePunchReceiptTimeMs, restrictedNatRetries: $restrictedNatRetries, rpc: $rpc, dht: $dht, protocol: $protocol)';
}
@@ -9158,7 +9158,7 @@ abstract mixin class $VeilidConfigInternalNetworkCopyWith<$Res> {
factory $VeilidConfigInternalNetworkCopyWith(VeilidConfigInternalNetwork value, $Res Function(VeilidConfigInternalNetwork) _then) = _$VeilidConfigInternalNetworkCopyWithImpl;
@useResult
$Res call({
int connectionInitialTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol
int connectionInitialTimeoutMs, int singleSendTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol
});
@@ -9175,9 +9175,10 @@ class _$VeilidConfigInternalNetworkCopyWithImpl<$Res>
/// Create a copy of VeilidConfigInternalNetwork
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? connectionInitialTimeoutMs = null,Object? connectionInactivityTimeoutMs = null,Object? maxConnectionsPerIp4 = null,Object? maxConnectionsPerIp6Prefix = null,Object? maxConnectionsPerIp6PrefixSize = null,Object? maxConnectionFrequencyPerMin = null,Object? clientAllowlistTimeoutMs = null,Object? reverseConnectionReceiptTimeMs = null,Object? holePunchReceiptTimeMs = null,Object? restrictedNatRetries = null,Object? rpc = null,Object? dht = null,Object? protocol = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? connectionInitialTimeoutMs = null,Object? singleSendTimeoutMs = null,Object? connectionInactivityTimeoutMs = null,Object? maxConnectionsPerIp4 = null,Object? maxConnectionsPerIp6Prefix = null,Object? maxConnectionsPerIp6PrefixSize = null,Object? maxConnectionFrequencyPerMin = null,Object? clientAllowlistTimeoutMs = null,Object? reverseConnectionReceiptTimeMs = null,Object? holePunchReceiptTimeMs = null,Object? restrictedNatRetries = null,Object? rpc = null,Object? dht = null,Object? protocol = null,}) {
return _then(_self.copyWith(
connectionInitialTimeoutMs: null == connectionInitialTimeoutMs ? _self.connectionInitialTimeoutMs : connectionInitialTimeoutMs // ignore: cast_nullable_to_non_nullable
as int,singleSendTimeoutMs: null == singleSendTimeoutMs ? _self.singleSendTimeoutMs : singleSendTimeoutMs // ignore: cast_nullable_to_non_nullable
as int,connectionInactivityTimeoutMs: null == connectionInactivityTimeoutMs ? _self.connectionInactivityTimeoutMs : connectionInactivityTimeoutMs // ignore: cast_nullable_to_non_nullable
as int,maxConnectionsPerIp4: null == maxConnectionsPerIp4 ? _self.maxConnectionsPerIp4 : maxConnectionsPerIp4 // ignore: cast_nullable_to_non_nullable
as int,maxConnectionsPerIp6Prefix: null == maxConnectionsPerIp6Prefix ? _self.maxConnectionsPerIp6Prefix : maxConnectionsPerIp6Prefix // ignore: cast_nullable_to_non_nullable
@@ -9299,10 +9300,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int connectionInitialTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int connectionInitialTimeoutMs, int singleSendTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _VeilidConfigInternalNetwork() when $default != null:
return $default(_that.connectionInitialTimeoutMs,_that.connectionInactivityTimeoutMs,_that.maxConnectionsPerIp4,_that.maxConnectionsPerIp6Prefix,_that.maxConnectionsPerIp6PrefixSize,_that.maxConnectionFrequencyPerMin,_that.clientAllowlistTimeoutMs,_that.reverseConnectionReceiptTimeMs,_that.holePunchReceiptTimeMs,_that.restrictedNatRetries,_that.rpc,_that.dht,_that.protocol);case _:
return $default(_that.connectionInitialTimeoutMs,_that.singleSendTimeoutMs,_that.connectionInactivityTimeoutMs,_that.maxConnectionsPerIp4,_that.maxConnectionsPerIp6Prefix,_that.maxConnectionsPerIp6PrefixSize,_that.maxConnectionFrequencyPerMin,_that.clientAllowlistTimeoutMs,_that.reverseConnectionReceiptTimeMs,_that.holePunchReceiptTimeMs,_that.restrictedNatRetries,_that.rpc,_that.dht,_that.protocol);case _:
return orElse();
}
@@ -9320,10 +9321,10 @@ return $default(_that.connectionInitialTimeoutMs,_that.connectionInactivityTimeo
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int connectionInitialTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int connectionInitialTimeoutMs, int singleSendTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol) $default,) {final _that = this;
switch (_that) {
case _VeilidConfigInternalNetwork():
return $default(_that.connectionInitialTimeoutMs,_that.connectionInactivityTimeoutMs,_that.maxConnectionsPerIp4,_that.maxConnectionsPerIp6Prefix,_that.maxConnectionsPerIp6PrefixSize,_that.maxConnectionFrequencyPerMin,_that.clientAllowlistTimeoutMs,_that.reverseConnectionReceiptTimeMs,_that.holePunchReceiptTimeMs,_that.restrictedNatRetries,_that.rpc,_that.dht,_that.protocol);}
return $default(_that.connectionInitialTimeoutMs,_that.singleSendTimeoutMs,_that.connectionInactivityTimeoutMs,_that.maxConnectionsPerIp4,_that.maxConnectionsPerIp6Prefix,_that.maxConnectionsPerIp6PrefixSize,_that.maxConnectionFrequencyPerMin,_that.clientAllowlistTimeoutMs,_that.reverseConnectionReceiptTimeMs,_that.holePunchReceiptTimeMs,_that.restrictedNatRetries,_that.rpc,_that.dht,_that.protocol);}
}
/// A variant of `when` that fallback to returning `null`
///
@@ -9337,10 +9338,10 @@ return $default(_that.connectionInitialTimeoutMs,_that.connectionInactivityTimeo
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int connectionInitialTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int connectionInitialTimeoutMs, int singleSendTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol)? $default,) {final _that = this;
switch (_that) {
case _VeilidConfigInternalNetwork() when $default != null:
return $default(_that.connectionInitialTimeoutMs,_that.connectionInactivityTimeoutMs,_that.maxConnectionsPerIp4,_that.maxConnectionsPerIp6Prefix,_that.maxConnectionsPerIp6PrefixSize,_that.maxConnectionFrequencyPerMin,_that.clientAllowlistTimeoutMs,_that.reverseConnectionReceiptTimeMs,_that.holePunchReceiptTimeMs,_that.restrictedNatRetries,_that.rpc,_that.dht,_that.protocol);case _:
return $default(_that.connectionInitialTimeoutMs,_that.singleSendTimeoutMs,_that.connectionInactivityTimeoutMs,_that.maxConnectionsPerIp4,_that.maxConnectionsPerIp6Prefix,_that.maxConnectionsPerIp6PrefixSize,_that.maxConnectionFrequencyPerMin,_that.clientAllowlistTimeoutMs,_that.reverseConnectionReceiptTimeMs,_that.holePunchReceiptTimeMs,_that.restrictedNatRetries,_that.rpc,_that.dht,_that.protocol);case _:
return null;
}
@@ -9352,10 +9353,11 @@ return $default(_that.connectionInitialTimeoutMs,_that.connectionInactivityTimeo
@JsonSerializable()
class _VeilidConfigInternalNetwork with DiagnosticableTreeMixin implements VeilidConfigInternalNetwork {
const _VeilidConfigInternalNetwork({required this.connectionInitialTimeoutMs, required this.connectionInactivityTimeoutMs, required this.maxConnectionsPerIp4, required this.maxConnectionsPerIp6Prefix, required this.maxConnectionsPerIp6PrefixSize, required this.maxConnectionFrequencyPerMin, required this.clientAllowlistTimeoutMs, required this.reverseConnectionReceiptTimeMs, required this.holePunchReceiptTimeMs, required this.restrictedNatRetries, required this.rpc, required this.dht, required this.protocol});
const _VeilidConfigInternalNetwork({required this.connectionInitialTimeoutMs, required this.singleSendTimeoutMs, required this.connectionInactivityTimeoutMs, required this.maxConnectionsPerIp4, required this.maxConnectionsPerIp6Prefix, required this.maxConnectionsPerIp6PrefixSize, required this.maxConnectionFrequencyPerMin, required this.clientAllowlistTimeoutMs, required this.reverseConnectionReceiptTimeMs, required this.holePunchReceiptTimeMs, required this.restrictedNatRetries, required this.rpc, required this.dht, required this.protocol});
factory _VeilidConfigInternalNetwork.fromJson(Map<String, dynamic> json) => _$VeilidConfigInternalNetworkFromJson(json);
@override final int connectionInitialTimeoutMs;
@override final int singleSendTimeoutMs;
@override final int connectionInactivityTimeoutMs;
@override final int maxConnectionsPerIp4;
@override final int maxConnectionsPerIp6Prefix;
@@ -9383,21 +9385,21 @@ Map<String, dynamic> toJson() {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties
..add(DiagnosticsProperty('type', 'VeilidConfigInternalNetwork'))
..add(DiagnosticsProperty('connectionInitialTimeoutMs', connectionInitialTimeoutMs))..add(DiagnosticsProperty('connectionInactivityTimeoutMs', connectionInactivityTimeoutMs))..add(DiagnosticsProperty('maxConnectionsPerIp4', maxConnectionsPerIp4))..add(DiagnosticsProperty('maxConnectionsPerIp6Prefix', maxConnectionsPerIp6Prefix))..add(DiagnosticsProperty('maxConnectionsPerIp6PrefixSize', maxConnectionsPerIp6PrefixSize))..add(DiagnosticsProperty('maxConnectionFrequencyPerMin', maxConnectionFrequencyPerMin))..add(DiagnosticsProperty('clientAllowlistTimeoutMs', clientAllowlistTimeoutMs))..add(DiagnosticsProperty('reverseConnectionReceiptTimeMs', reverseConnectionReceiptTimeMs))..add(DiagnosticsProperty('holePunchReceiptTimeMs', holePunchReceiptTimeMs))..add(DiagnosticsProperty('restrictedNatRetries', restrictedNatRetries))..add(DiagnosticsProperty('rpc', rpc))..add(DiagnosticsProperty('dht', dht))..add(DiagnosticsProperty('protocol', protocol));
..add(DiagnosticsProperty('connectionInitialTimeoutMs', connectionInitialTimeoutMs))..add(DiagnosticsProperty('singleSendTimeoutMs', singleSendTimeoutMs))..add(DiagnosticsProperty('connectionInactivityTimeoutMs', connectionInactivityTimeoutMs))..add(DiagnosticsProperty('maxConnectionsPerIp4', maxConnectionsPerIp4))..add(DiagnosticsProperty('maxConnectionsPerIp6Prefix', maxConnectionsPerIp6Prefix))..add(DiagnosticsProperty('maxConnectionsPerIp6PrefixSize', maxConnectionsPerIp6PrefixSize))..add(DiagnosticsProperty('maxConnectionFrequencyPerMin', maxConnectionFrequencyPerMin))..add(DiagnosticsProperty('clientAllowlistTimeoutMs', clientAllowlistTimeoutMs))..add(DiagnosticsProperty('reverseConnectionReceiptTimeMs', reverseConnectionReceiptTimeMs))..add(DiagnosticsProperty('holePunchReceiptTimeMs', holePunchReceiptTimeMs))..add(DiagnosticsProperty('restrictedNatRetries', restrictedNatRetries))..add(DiagnosticsProperty('rpc', rpc))..add(DiagnosticsProperty('dht', dht))..add(DiagnosticsProperty('protocol', protocol));
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _VeilidConfigInternalNetwork&&(identical(other.connectionInitialTimeoutMs, connectionInitialTimeoutMs) || other.connectionInitialTimeoutMs == connectionInitialTimeoutMs)&&(identical(other.connectionInactivityTimeoutMs, connectionInactivityTimeoutMs) || other.connectionInactivityTimeoutMs == connectionInactivityTimeoutMs)&&(identical(other.maxConnectionsPerIp4, maxConnectionsPerIp4) || other.maxConnectionsPerIp4 == maxConnectionsPerIp4)&&(identical(other.maxConnectionsPerIp6Prefix, maxConnectionsPerIp6Prefix) || other.maxConnectionsPerIp6Prefix == maxConnectionsPerIp6Prefix)&&(identical(other.maxConnectionsPerIp6PrefixSize, maxConnectionsPerIp6PrefixSize) || other.maxConnectionsPerIp6PrefixSize == maxConnectionsPerIp6PrefixSize)&&(identical(other.maxConnectionFrequencyPerMin, maxConnectionFrequencyPerMin) || other.maxConnectionFrequencyPerMin == maxConnectionFrequencyPerMin)&&(identical(other.clientAllowlistTimeoutMs, clientAllowlistTimeoutMs) || other.clientAllowlistTimeoutMs == clientAllowlistTimeoutMs)&&(identical(other.reverseConnectionReceiptTimeMs, reverseConnectionReceiptTimeMs) || other.reverseConnectionReceiptTimeMs == reverseConnectionReceiptTimeMs)&&(identical(other.holePunchReceiptTimeMs, holePunchReceiptTimeMs) || other.holePunchReceiptTimeMs == holePunchReceiptTimeMs)&&(identical(other.restrictedNatRetries, restrictedNatRetries) || other.restrictedNatRetries == restrictedNatRetries)&&(identical(other.rpc, rpc) || other.rpc == rpc)&&(identical(other.dht, dht) || other.dht == dht)&&(identical(other.protocol, protocol) || other.protocol == protocol));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _VeilidConfigInternalNetwork&&(identical(other.connectionInitialTimeoutMs, connectionInitialTimeoutMs) || other.connectionInitialTimeoutMs == connectionInitialTimeoutMs)&&(identical(other.singleSendTimeoutMs, singleSendTimeoutMs) || other.singleSendTimeoutMs == singleSendTimeoutMs)&&(identical(other.connectionInactivityTimeoutMs, connectionInactivityTimeoutMs) || other.connectionInactivityTimeoutMs == connectionInactivityTimeoutMs)&&(identical(other.maxConnectionsPerIp4, maxConnectionsPerIp4) || other.maxConnectionsPerIp4 == maxConnectionsPerIp4)&&(identical(other.maxConnectionsPerIp6Prefix, maxConnectionsPerIp6Prefix) || other.maxConnectionsPerIp6Prefix == maxConnectionsPerIp6Prefix)&&(identical(other.maxConnectionsPerIp6PrefixSize, maxConnectionsPerIp6PrefixSize) || other.maxConnectionsPerIp6PrefixSize == maxConnectionsPerIp6PrefixSize)&&(identical(other.maxConnectionFrequencyPerMin, maxConnectionFrequencyPerMin) || other.maxConnectionFrequencyPerMin == maxConnectionFrequencyPerMin)&&(identical(other.clientAllowlistTimeoutMs, clientAllowlistTimeoutMs) || other.clientAllowlistTimeoutMs == clientAllowlistTimeoutMs)&&(identical(other.reverseConnectionReceiptTimeMs, reverseConnectionReceiptTimeMs) || other.reverseConnectionReceiptTimeMs == reverseConnectionReceiptTimeMs)&&(identical(other.holePunchReceiptTimeMs, holePunchReceiptTimeMs) || other.holePunchReceiptTimeMs == holePunchReceiptTimeMs)&&(identical(other.restrictedNatRetries, restrictedNatRetries) || other.restrictedNatRetries == restrictedNatRetries)&&(identical(other.rpc, rpc) || other.rpc == rpc)&&(identical(other.dht, dht) || other.dht == dht)&&(identical(other.protocol, protocol) || other.protocol == protocol));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,connectionInitialTimeoutMs,connectionInactivityTimeoutMs,maxConnectionsPerIp4,maxConnectionsPerIp6Prefix,maxConnectionsPerIp6PrefixSize,maxConnectionFrequencyPerMin,clientAllowlistTimeoutMs,reverseConnectionReceiptTimeMs,holePunchReceiptTimeMs,restrictedNatRetries,rpc,dht,protocol);
int get hashCode => Object.hash(runtimeType,connectionInitialTimeoutMs,singleSendTimeoutMs,connectionInactivityTimeoutMs,maxConnectionsPerIp4,maxConnectionsPerIp6Prefix,maxConnectionsPerIp6PrefixSize,maxConnectionFrequencyPerMin,clientAllowlistTimeoutMs,reverseConnectionReceiptTimeMs,holePunchReceiptTimeMs,restrictedNatRetries,rpc,dht,protocol);
@override
String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'VeilidConfigInternalNetwork(connectionInitialTimeoutMs: $connectionInitialTimeoutMs, connectionInactivityTimeoutMs: $connectionInactivityTimeoutMs, maxConnectionsPerIp4: $maxConnectionsPerIp4, maxConnectionsPerIp6Prefix: $maxConnectionsPerIp6Prefix, maxConnectionsPerIp6PrefixSize: $maxConnectionsPerIp6PrefixSize, maxConnectionFrequencyPerMin: $maxConnectionFrequencyPerMin, clientAllowlistTimeoutMs: $clientAllowlistTimeoutMs, reverseConnectionReceiptTimeMs: $reverseConnectionReceiptTimeMs, holePunchReceiptTimeMs: $holePunchReceiptTimeMs, restrictedNatRetries: $restrictedNatRetries, rpc: $rpc, dht: $dht, protocol: $protocol)';
return 'VeilidConfigInternalNetwork(connectionInitialTimeoutMs: $connectionInitialTimeoutMs, singleSendTimeoutMs: $singleSendTimeoutMs, connectionInactivityTimeoutMs: $connectionInactivityTimeoutMs, maxConnectionsPerIp4: $maxConnectionsPerIp4, maxConnectionsPerIp6Prefix: $maxConnectionsPerIp6Prefix, maxConnectionsPerIp6PrefixSize: $maxConnectionsPerIp6PrefixSize, maxConnectionFrequencyPerMin: $maxConnectionFrequencyPerMin, clientAllowlistTimeoutMs: $clientAllowlistTimeoutMs, reverseConnectionReceiptTimeMs: $reverseConnectionReceiptTimeMs, holePunchReceiptTimeMs: $holePunchReceiptTimeMs, restrictedNatRetries: $restrictedNatRetries, rpc: $rpc, dht: $dht, protocol: $protocol)';
}
@@ -9408,7 +9410,7 @@ abstract mixin class _$VeilidConfigInternalNetworkCopyWith<$Res> implements $Vei
factory _$VeilidConfigInternalNetworkCopyWith(_VeilidConfigInternalNetwork value, $Res Function(_VeilidConfigInternalNetwork) _then) = __$VeilidConfigInternalNetworkCopyWithImpl;
@override @useResult
$Res call({
int connectionInitialTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol
int connectionInitialTimeoutMs, int singleSendTimeoutMs, int connectionInactivityTimeoutMs, int maxConnectionsPerIp4, int maxConnectionsPerIp6Prefix, int maxConnectionsPerIp6PrefixSize, int maxConnectionFrequencyPerMin, int clientAllowlistTimeoutMs, int reverseConnectionReceiptTimeMs, int holePunchReceiptTimeMs, int restrictedNatRetries, VeilidConfigInternalRPC rpc, VeilidConfigInternalDHT dht, VeilidConfigInternalProtocol protocol
});
@@ -9425,9 +9427,10 @@ class __$VeilidConfigInternalNetworkCopyWithImpl<$Res>
/// Create a copy of VeilidConfigInternalNetwork
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? connectionInitialTimeoutMs = null,Object? connectionInactivityTimeoutMs = null,Object? maxConnectionsPerIp4 = null,Object? maxConnectionsPerIp6Prefix = null,Object? maxConnectionsPerIp6PrefixSize = null,Object? maxConnectionFrequencyPerMin = null,Object? clientAllowlistTimeoutMs = null,Object? reverseConnectionReceiptTimeMs = null,Object? holePunchReceiptTimeMs = null,Object? restrictedNatRetries = null,Object? rpc = null,Object? dht = null,Object? protocol = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? connectionInitialTimeoutMs = null,Object? singleSendTimeoutMs = null,Object? connectionInactivityTimeoutMs = null,Object? maxConnectionsPerIp4 = null,Object? maxConnectionsPerIp6Prefix = null,Object? maxConnectionsPerIp6PrefixSize = null,Object? maxConnectionFrequencyPerMin = null,Object? clientAllowlistTimeoutMs = null,Object? reverseConnectionReceiptTimeMs = null,Object? holePunchReceiptTimeMs = null,Object? restrictedNatRetries = null,Object? rpc = null,Object? dht = null,Object? protocol = null,}) {
return _then(_VeilidConfigInternalNetwork(
connectionInitialTimeoutMs: null == connectionInitialTimeoutMs ? _self.connectionInitialTimeoutMs : connectionInitialTimeoutMs // ignore: cast_nullable_to_non_nullable
as int,singleSendTimeoutMs: null == singleSendTimeoutMs ? _self.singleSendTimeoutMs : singleSendTimeoutMs // ignore: cast_nullable_to_non_nullable
as int,connectionInactivityTimeoutMs: null == connectionInactivityTimeoutMs ? _self.connectionInactivityTimeoutMs : connectionInactivityTimeoutMs // ignore: cast_nullable_to_non_nullable
as int,maxConnectionsPerIp4: null == maxConnectionsPerIp4 ? _self.maxConnectionsPerIp4 : maxConnectionsPerIp4 // ignore: cast_nullable_to_non_nullable
as int,maxConnectionsPerIp6Prefix: null == maxConnectionsPerIp6Prefix ? _self.maxConnectionsPerIp6Prefix : maxConnectionsPerIp6Prefix // ignore: cast_nullable_to_non_nullable
+2
View File
@@ -637,6 +637,7 @@ _VeilidConfigInternalNetwork _$VeilidConfigInternalNetworkFromJson(
) => _VeilidConfigInternalNetwork(
connectionInitialTimeoutMs: (json['connectionInitialTimeoutMs'] as num)
.toInt(),
singleSendTimeoutMs: (json['singleSendTimeoutMs'] as num).toInt(),
connectionInactivityTimeoutMs: (json['connectionInactivityTimeoutMs'] as num)
.toInt(),
maxConnectionsPerIp4: (json['maxConnectionsPerIp4'] as num).toInt(),
@@ -660,6 +661,7 @@ Map<String, dynamic> _$VeilidConfigInternalNetworkToJson(
_VeilidConfigInternalNetwork instance,
) => <String, dynamic>{
'connectionInitialTimeoutMs': instance.connectionInitialTimeoutMs,
'singleSendTimeoutMs': instance.singleSendTimeoutMs,
'connectionInactivityTimeoutMs': instance.connectionInactivityTimeoutMs,
'maxConnectionsPerIp4': instance.maxConnectionsPerIp4,
'maxConnectionsPerIp6Prefix': instance.maxConnectionsPerIp6Prefix,
@@ -16,15 +16,17 @@ part 'veilid_dht_transaction.g.dart';
sealed class DHTTransactionSetValueOptions
with _$DHTTransactionSetValueOptions {
/// Builds set options, optionally overriding the record's default [writer].
const factory DHTTransactionSetValueOptions({KeyPair? writer}) =
_DHTTransactionSetValueOptions;
/// `minSeqnum` raises the sequence number to at least that value after the
/// automatic increment; [ValueData.maxSeqnum] minus n leaves n writes after
/// this one.
const factory DHTTransactionSetValueOptions({
KeyPair? writer,
int? minSeqnum,
}) = _DHTTransactionSetValueOptions;
/// Decodes options from JSON.
factory DHTTransactionSetValueOptions.fromJson(dynamic json) =>
_$DHTTransactionSetValueOptionsFromJson(json as Map<String, dynamic>);
@override
Map<String, dynamic> toJson() => {'writer': writer};
}
//////////////////////////////////////
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$DHTTransactionSetValueOptions {
KeyPair? get writer;
KeyPair? get writer; int? get minSeqnum;
/// Create a copy of DHTTransactionSetValueOptions
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +28,16 @@ $DHTTransactionSetValueOptionsCopyWith<DHTTransactionSetValueOptions> get copyWi
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is DHTTransactionSetValueOptions&&(identical(other.writer, writer) || other.writer == writer));
return identical(this, other) || (other.runtimeType == runtimeType&&other is DHTTransactionSetValueOptions&&(identical(other.writer, writer) || other.writer == writer)&&(identical(other.minSeqnum, minSeqnum) || other.minSeqnum == minSeqnum));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,writer);
int get hashCode => Object.hash(runtimeType,writer,minSeqnum);
@override
String toString() {
return 'DHTTransactionSetValueOptions(writer: $writer)';
return 'DHTTransactionSetValueOptions(writer: $writer, minSeqnum: $minSeqnum)';
}
@@ -48,7 +48,7 @@ abstract mixin class $DHTTransactionSetValueOptionsCopyWith<$Res> {
factory $DHTTransactionSetValueOptionsCopyWith(DHTTransactionSetValueOptions value, $Res Function(DHTTransactionSetValueOptions) _then) = _$DHTTransactionSetValueOptionsCopyWithImpl;
@useResult
$Res call({
KeyPair? writer
KeyPair? writer, int? minSeqnum
});
@@ -65,10 +65,11 @@ class _$DHTTransactionSetValueOptionsCopyWithImpl<$Res>
/// Create a copy of DHTTransactionSetValueOptions
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? writer = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? writer = freezed,Object? minSeqnum = freezed,}) {
return _then(_self.copyWith(
writer: freezed == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable
as KeyPair?,
as KeyPair?,minSeqnum: freezed == minSeqnum ? _self.minSeqnum : minSeqnum // ignore: cast_nullable_to_non_nullable
as int?,
));
}
@@ -150,10 +151,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( KeyPair? writer)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( KeyPair? writer, int? minSeqnum)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _DHTTransactionSetValueOptions() when $default != null:
return $default(_that.writer);case _:
return $default(_that.writer,_that.minSeqnum);case _:
return orElse();
}
@@ -171,10 +172,10 @@ return $default(_that.writer);case _:
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( KeyPair? writer) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( KeyPair? writer, int? minSeqnum) $default,) {final _that = this;
switch (_that) {
case _DHTTransactionSetValueOptions():
return $default(_that.writer);}
return $default(_that.writer,_that.minSeqnum);}
}
/// A variant of `when` that fallback to returning `null`
///
@@ -188,10 +189,10 @@ return $default(_that.writer);}
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( KeyPair? writer)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( KeyPair? writer, int? minSeqnum)? $default,) {final _that = this;
switch (_that) {
case _DHTTransactionSetValueOptions() when $default != null:
return $default(_that.writer);case _:
return $default(_that.writer,_that.minSeqnum);case _:
return null;
}
@@ -203,10 +204,11 @@ return $default(_that.writer);case _:
@JsonSerializable()
class _DHTTransactionSetValueOptions implements DHTTransactionSetValueOptions {
const _DHTTransactionSetValueOptions({this.writer});
const _DHTTransactionSetValueOptions({this.writer, this.minSeqnum});
factory _DHTTransactionSetValueOptions.fromJson(Map<String, dynamic> json) => _$DHTTransactionSetValueOptionsFromJson(json);
@override final KeyPair? writer;
@override final int? minSeqnum;
/// Create a copy of DHTTransactionSetValueOptions
/// with the given fields replaced by the non-null parameter values.
@@ -221,16 +223,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DHTTransactionSetValueOptions&&(identical(other.writer, writer) || other.writer == writer));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DHTTransactionSetValueOptions&&(identical(other.writer, writer) || other.writer == writer)&&(identical(other.minSeqnum, minSeqnum) || other.minSeqnum == minSeqnum));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,writer);
int get hashCode => Object.hash(runtimeType,writer,minSeqnum);
@override
String toString() {
return 'DHTTransactionSetValueOptions(writer: $writer)';
return 'DHTTransactionSetValueOptions(writer: $writer, minSeqnum: $minSeqnum)';
}
@@ -241,7 +243,7 @@ abstract mixin class _$DHTTransactionSetValueOptionsCopyWith<$Res> implements $D
factory _$DHTTransactionSetValueOptionsCopyWith(_DHTTransactionSetValueOptions value, $Res Function(_DHTTransactionSetValueOptions) _then) = __$DHTTransactionSetValueOptionsCopyWithImpl;
@override @useResult
$Res call({
KeyPair? writer
KeyPair? writer, int? minSeqnum
});
@@ -258,10 +260,11 @@ class __$DHTTransactionSetValueOptionsCopyWithImpl<$Res>
/// Create a copy of DHTTransactionSetValueOptions
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? writer = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? writer = freezed,Object? minSeqnum = freezed,}) {
return _then(_DHTTransactionSetValueOptions(
writer: freezed == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable
as KeyPair?,
as KeyPair?,minSeqnum: freezed == minSeqnum ? _self.minSeqnum : minSeqnum // ignore: cast_nullable_to_non_nullable
as int?,
));
}
@@ -10,8 +10,12 @@ _DHTTransactionSetValueOptions _$DHTTransactionSetValueOptionsFromJson(
Map<String, dynamic> json,
) => _DHTTransactionSetValueOptions(
writer: json['writer'] == null ? null : KeyPair.fromJson(json['writer']),
minSeqnum: (json['minSeqnum'] as num?)?.toInt(),
);
Map<String, dynamic> _$DHTTransactionSetValueOptionsToJson(
_DHTTransactionSetValueOptions instance,
) => <String, dynamic>{'writer': instance.writer?.toJson()};
) => <String, dynamic>{
'writer': instance.writer?.toJson(),
'minSeqnum': instance.minSeqnum,
};
+11 -11
View File
@@ -1,6 +1,6 @@
// ignore_for_file: public_member_api_docs
// Low-level platform binding to veilid-core; not part of the documented public API.
// The asset id below must match `assetName` in hook/build.dart.
// @DefaultAsset below names the asset hook/build.dart declares as `assetName`.
@DefaultAsset('package:veilid/veilid_ffi.dart')
library;
@@ -20,7 +20,7 @@ import 'veilid.dart';
typedef _DartPostCObject =
NativeFunction<Int8 Function(Int64, Pointer<Dart_CObject>)>;
// fn veilid_version() -> VeilidVersion
// Return layout of veilid_version()
final class VeilidVersionFFI extends Struct {
@Uint32()
external int major;
@@ -1591,7 +1591,7 @@ class VeilidFFI extends Veilid {
)
external static int _changeLogLevel(
Pointer<Utf8> layer,
Pointer<Utf8> logLevel,
Pointer<Utf8> directives,
);
@Native<Void Function(Pointer<Utf8>, Pointer<Utf8>)>(
@@ -1642,7 +1642,7 @@ class VeilidFFI extends Veilid {
)
external static int _routingContextWithSafety(
int id,
Pointer<Utf8> stability,
Pointer<Utf8> safetySelection,
);
@Native<Uint32 Function(Uint32, Pointer<Utf8>)>(
@@ -1673,7 +1673,7 @@ class VeilidFFI extends Veilid {
int port,
int id,
Pointer<Utf8> target,
Pointer<Utf8> request,
Pointer<Utf8> message,
);
@Native<Void Function(Int64, Uint32, Uint32, Pointer<Utf8>, Pointer<Utf8>)>(
@@ -1742,7 +1742,7 @@ class VeilidFFI extends Veilid {
Pointer<Utf8> key,
int subkey,
Pointer<Utf8> data,
Pointer<Utf8> writer,
Pointer<Utf8> options,
);
@Native<
@@ -1806,8 +1806,8 @@ class VeilidFFI extends Veilid {
)
external static void _transactDHTRecords(
int port,
Pointer<Utf8> records,
Pointer<Utf8> defaultSigningKey,
Pointer<Utf8> recordKeys,
Pointer<Utf8> options,
);
@Native<Void Function(Int64)>(symbol: 'new_private_route')
@@ -1827,14 +1827,14 @@ class VeilidFFI extends Veilid {
external static void _importRemotePrivateRoute(int port, Pointer<Utf8> blob);
@Native<Void Function(Int64, Pointer<Utf8>)>(symbol: 'release_private_route')
external static void _releasePrivateRoute(int port, Pointer<Utf8> key);
external static void _releasePrivateRoute(int port, Pointer<Utf8> routeId);
@Native<Void Function(Int64, Pointer<Utf8>, Pointer<Utf8>)>(
symbol: 'app_call_reply',
)
external static void _appCallReply(
int port,
Pointer<Utf8> id,
Pointer<Utf8> callId,
Pointer<Utf8> message,
);
@@ -2319,7 +2319,7 @@ class VeilidFFI extends Veilid {
external static int _nowIncreasing();
@Native<Void Function(Int64, Pointer<Utf8>)>(symbol: 'debug')
external static void _debug(int port, Pointer<Utf8> logLevel);
external static void _debug(int port, Pointer<Utf8> command);
@Native<Void Function(Int64, Pointer<Utf8>, Pointer<Utf8>)>(
symbol: 'save_user_secret',
+23 -26
View File
@@ -451,26 +451,24 @@ class VeilidCryptoSystemJS extends VeilidCryptoSystem {
EncapsulationKey recipient,
Uint8List aad,
Uint8List plaintext,
) =>
_wasmPromiseUint8List('crypto_hpke_seal', [
_kind.toJS,
jsonEncode(recipient).toJS,
base64UrlNoPadEncode(aad).toJS,
base64UrlNoPadEncode(plaintext).toJS,
]);
) => _wasmPromiseUint8List('crypto_hpke_seal', [
_kind.toJS,
jsonEncode(recipient).toJS,
base64UrlNoPadEncode(aad).toJS,
base64UrlNoPadEncode(plaintext).toJS,
]);
@override
Future<Uint8List> hpkeOpen(
DecapsulationKey secret,
Uint8List aad,
Uint8List sealed,
) =>
_wasmPromiseUint8List('crypto_hpke_open', [
_kind.toJS,
jsonEncode(secret).toJS,
base64UrlNoPadEncode(aad).toJS,
base64UrlNoPadEncode(sealed).toJS,
]);
) => _wasmPromiseUint8List('crypto_hpke_open', [
_kind.toJS,
jsonEncode(secret).toJS,
base64UrlNoPadEncode(aad).toJS,
base64UrlNoPadEncode(sealed).toJS,
]);
@override
Future<Uint8List> randomBytes(int len) =>
@@ -603,21 +601,20 @@ class VeilidCryptoSystemJS extends VeilidCryptoSystem {
@override
Future<EncapsulationKey> encapsulationKeyFromSigningKey(PublicKey key) =>
_wasmPromiseJson('crypto_encapsulation_key_from_signing_key',
EncapsulationKey.fromJson, [
_kind.toJS,
jsonEncode(key).toJS,
]);
_wasmPromiseJson(
'crypto_encapsulation_key_from_signing_key',
EncapsulationKey.fromJson,
[_kind.toJS, jsonEncode(key).toJS],
);
@override
Future<DecapsulationKey> decapsulationKeyFromSigningSecret(
SecretKey secret,
) =>
_wasmPromiseJson('crypto_decapsulation_key_from_signing_secret',
DecapsulationKey.fromJson, [
_kind.toJS,
jsonEncode(secret).toJS,
]);
) => _wasmPromiseJson(
'crypto_decapsulation_key_from_signing_secret',
DecapsulationKey.fromJson,
[_kind.toJS, jsonEncode(secret).toJS],
);
@override
Future<HashDigest> generateHash(Uint8List data) => _wasmPromiseJson(
@@ -1253,4 +1250,4 @@ class VeilidJS extends Veilid {
@override
String defaultVeilidConfig() => _wasmCallString('default_veilid_config', []);
}
}
@@ -17,4 +17,4 @@ class VeilidPluginStubWeb {
details: "Veilid for Web doesn't implement '${call.method}'",
);
}
}
}
+1 -1
View File
@@ -9,4 +9,4 @@ Veilid getVeilid() => throw UnsupportedError('Cannot create Veilid object');
Uint8List convertUint8ListFromJson(dynamic json) =>
throw UnsupportedError('Cannot convertUint8ListFromJson');
dynamic convertUint8ListToJson(Uint8List data) =>
throw UnsupportedError('Cannot convertUint8ListToJson');
throw UnsupportedError('Cannot convertUint8ListToJson');
+11 -9
View File
@@ -226,6 +226,9 @@ sealed class ValueData with _$ValueData {
/// Maximum length in bytes of the data a single subkey may hold.
static const maxLen = 32768;
/// The largest sequence number. Subtract n for a `minSeqnum` leaving n writes.
static const maxSeqnum = 0xFFFFFFFE;
/// `seq` time-orders changes to the subkey; `writer` is the public identity
/// key of the writer. In debug builds, throws [AssertionError] if `seq` is
/// outside `0..=4294967295` or `data` exceeds [maxLen] bytes.
@@ -517,19 +520,18 @@ enum DHTReportScope {
sealed class SetDHTValueOptions with _$SetDHTValueOptions {
/// `writer` overrides the writer key pair for the operation. `allowOffline`
/// defaults to true; when false, an offline node returns a TryAgain error
/// instead of writing.
const factory SetDHTValueOptions({KeyPair? writer, bool? allowOffline}) =
_SetDHTValueOptions;
/// instead of writing. `minSeqnum` raises the sequence number to at least
/// that value after the automatic increment; [ValueData.maxSeqnum] minus n
/// leaves n writes after this one.
const factory SetDHTValueOptions({
KeyPair? writer,
bool? allowOffline,
int? minSeqnum,
}) = _SetDHTValueOptions;
/// Decode a [SetDHTValueOptions] from its JSON representation.
factory SetDHTValueOptions.fromJson(dynamic json) =>
_$SetDHTValueOptionsFromJson(json as Map<String, dynamic>);
@override
Map<String, dynamic> toJson() => {
'writer': writer,
'allow_offline': allowOffline,
};
}
//////////////////////////////////////
+23 -20
View File
@@ -2281,7 +2281,7 @@ as List<int?>,
/// @nodoc
mixin _$SetDHTValueOptions {
KeyPair? get writer; bool? get allowOffline;
KeyPair? get writer; bool? get allowOffline; int? get minSeqnum;
/// Create a copy of SetDHTValueOptions
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -2294,16 +2294,16 @@ $SetDHTValueOptionsCopyWith<SetDHTValueOptions> get copyWith => _$SetDHTValueOpt
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SetDHTValueOptions&&(identical(other.writer, writer) || other.writer == writer)&&(identical(other.allowOffline, allowOffline) || other.allowOffline == allowOffline));
return identical(this, other) || (other.runtimeType == runtimeType&&other is SetDHTValueOptions&&(identical(other.writer, writer) || other.writer == writer)&&(identical(other.allowOffline, allowOffline) || other.allowOffline == allowOffline)&&(identical(other.minSeqnum, minSeqnum) || other.minSeqnum == minSeqnum));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,writer,allowOffline);
int get hashCode => Object.hash(runtimeType,writer,allowOffline,minSeqnum);
@override
String toString() {
return 'SetDHTValueOptions(writer: $writer, allowOffline: $allowOffline)';
return 'SetDHTValueOptions(writer: $writer, allowOffline: $allowOffline, minSeqnum: $minSeqnum)';
}
@@ -2314,7 +2314,7 @@ abstract mixin class $SetDHTValueOptionsCopyWith<$Res> {
factory $SetDHTValueOptionsCopyWith(SetDHTValueOptions value, $Res Function(SetDHTValueOptions) _then) = _$SetDHTValueOptionsCopyWithImpl;
@useResult
$Res call({
KeyPair? writer, bool? allowOffline
KeyPair? writer, bool? allowOffline, int? minSeqnum
});
@@ -2331,11 +2331,12 @@ class _$SetDHTValueOptionsCopyWithImpl<$Res>
/// Create a copy of SetDHTValueOptions
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? writer = freezed,Object? allowOffline = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? writer = freezed,Object? allowOffline = freezed,Object? minSeqnum = freezed,}) {
return _then(_self.copyWith(
writer: freezed == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable
as KeyPair?,allowOffline: freezed == allowOffline ? _self.allowOffline : allowOffline // ignore: cast_nullable_to_non_nullable
as bool?,
as bool?,minSeqnum: freezed == minSeqnum ? _self.minSeqnum : minSeqnum // ignore: cast_nullable_to_non_nullable
as int?,
));
}
@@ -2417,10 +2418,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( KeyPair? writer, bool? allowOffline)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( KeyPair? writer, bool? allowOffline, int? minSeqnum)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SetDHTValueOptions() when $default != null:
return $default(_that.writer,_that.allowOffline);case _:
return $default(_that.writer,_that.allowOffline,_that.minSeqnum);case _:
return orElse();
}
@@ -2438,10 +2439,10 @@ return $default(_that.writer,_that.allowOffline);case _:
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( KeyPair? writer, bool? allowOffline) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( KeyPair? writer, bool? allowOffline, int? minSeqnum) $default,) {final _that = this;
switch (_that) {
case _SetDHTValueOptions():
return $default(_that.writer,_that.allowOffline);}
return $default(_that.writer,_that.allowOffline,_that.minSeqnum);}
}
/// A variant of `when` that fallback to returning `null`
///
@@ -2455,10 +2456,10 @@ return $default(_that.writer,_that.allowOffline);}
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( KeyPair? writer, bool? allowOffline)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( KeyPair? writer, bool? allowOffline, int? minSeqnum)? $default,) {final _that = this;
switch (_that) {
case _SetDHTValueOptions() when $default != null:
return $default(_that.writer,_that.allowOffline);case _:
return $default(_that.writer,_that.allowOffline,_that.minSeqnum);case _:
return null;
}
@@ -2470,11 +2471,12 @@ return $default(_that.writer,_that.allowOffline);case _:
@JsonSerializable()
class _SetDHTValueOptions implements SetDHTValueOptions {
const _SetDHTValueOptions({this.writer, this.allowOffline});
const _SetDHTValueOptions({this.writer, this.allowOffline, this.minSeqnum});
factory _SetDHTValueOptions.fromJson(Map<String, dynamic> json) => _$SetDHTValueOptionsFromJson(json);
@override final KeyPair? writer;
@override final bool? allowOffline;
@override final int? minSeqnum;
/// Create a copy of SetDHTValueOptions
/// with the given fields replaced by the non-null parameter values.
@@ -2489,16 +2491,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SetDHTValueOptions&&(identical(other.writer, writer) || other.writer == writer)&&(identical(other.allowOffline, allowOffline) || other.allowOffline == allowOffline));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SetDHTValueOptions&&(identical(other.writer, writer) || other.writer == writer)&&(identical(other.allowOffline, allowOffline) || other.allowOffline == allowOffline)&&(identical(other.minSeqnum, minSeqnum) || other.minSeqnum == minSeqnum));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,writer,allowOffline);
int get hashCode => Object.hash(runtimeType,writer,allowOffline,minSeqnum);
@override
String toString() {
return 'SetDHTValueOptions(writer: $writer, allowOffline: $allowOffline)';
return 'SetDHTValueOptions(writer: $writer, allowOffline: $allowOffline, minSeqnum: $minSeqnum)';
}
@@ -2509,7 +2511,7 @@ abstract mixin class _$SetDHTValueOptionsCopyWith<$Res> implements $SetDHTValueO
factory _$SetDHTValueOptionsCopyWith(_SetDHTValueOptions value, $Res Function(_SetDHTValueOptions) _then) = __$SetDHTValueOptionsCopyWithImpl;
@override @useResult
$Res call({
KeyPair? writer, bool? allowOffline
KeyPair? writer, bool? allowOffline, int? minSeqnum
});
@@ -2526,11 +2528,12 @@ class __$SetDHTValueOptionsCopyWithImpl<$Res>
/// Create a copy of SetDHTValueOptions
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? writer = freezed,Object? allowOffline = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? writer = freezed,Object? allowOffline = freezed,Object? minSeqnum = freezed,}) {
return _then(_SetDHTValueOptions(
writer: freezed == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable
as KeyPair?,allowOffline: freezed == allowOffline ? _self.allowOffline : allowOffline // ignore: cast_nullable_to_non_nullable
as bool?,
as bool?,minSeqnum: freezed == minSeqnum ? _self.minSeqnum : minSeqnum // ignore: cast_nullable_to_non_nullable
as int?,
));
}
+2
View File
@@ -153,12 +153,14 @@ _SetDHTValueOptions _$SetDHTValueOptionsFromJson(Map<String, dynamic> json) =>
_SetDHTValueOptions(
writer: json['writer'] == null ? null : KeyPair.fromJson(json['writer']),
allowOffline: json['allowOffline'] as bool?,
minSeqnum: (json['minSeqnum'] as num?)?.toInt(),
);
Map<String, dynamic> _$SetDHTValueOptionsToJson(_SetDHTValueOptions instance) =>
<String, dynamic>{
'writer': instance.writer?.toJson(),
'allowOffline': instance.allowOffline,
'minSeqnum': instance.minSeqnum,
};
_TransactDHTRecordsOptions _$TransactDHTRecordsOptionsFromJson(
@@ -162,8 +162,9 @@ void runWithIntegrationLog(void Function() body) {
}
/// Two-pane debug app for integration tests: scrollable xterm log on top,
/// test-status pane on the bottom. Call `runApp(const IntegrationLogApp())`
/// right after `IntegrationTestWidgetsFlutterBinding.ensureInitialized()`.
/// test-status pane on the bottom, separated by a drag-resizable divider.
/// Call `runApp(const IntegrationLogApp())` right after
/// `IntegrationTestWidgetsFlutterBinding.ensureInitialized()`.
class IntegrationLogApp extends StatefulWidget {
const IntegrationLogApp({super.key});
@@ -172,8 +173,13 @@ class IntegrationLogApp extends StatefulWidget {
}
class _IntegrationLogAppState extends State<IntegrationLogApp> {
static const _statusPaneMinHeight = 48.0;
static const _logPaneMinHeight = 64.0;
static const _dividerHeight = 5.0;
final _terminalController = TerminalController();
final _scrollController = ScrollController();
double _statusPaneHeight = 180;
@override
void initState() {
@@ -212,37 +218,84 @@ class _IntegrationLogAppState extends State<IntegrationLogApp> {
await Clipboard.setData(ClipboardData(text: text));
}
Widget _divider(double maxStatusHeight) => MouseRegion(
cursor: SystemMouseCursors.resizeRow,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onVerticalDragUpdate: (details) => setState(() {
_statusPaneHeight = (_statusPaneHeight - details.delta.dy).clamp(
_statusPaneMinHeight,
maxStatusHeight,
);
}),
child: Container(
height: _dividerHeight,
color: Colors.grey.shade600,
alignment: Alignment.center,
child: Container(width: 64, height: 2, color: Colors.grey.shade900),
),
),
);
@override
Widget build(BuildContext context) => MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
home: Scaffold(
body: Column(
children: [
Expanded(
child: Scrollbar(
controller: _scrollController,
thumbVisibility: true,
child: TerminalView(
IntegrationLogSink.instance.terminal,
controller: _terminalController,
scrollController: _scrollController,
autofocus: true,
textStyle: const TerminalStyle(fontSize: 10),
body: LayoutBuilder(
builder: (context, constraints) {
final maxStatusHeight =
(constraints.maxHeight - _dividerHeight - _logPaneMinHeight)
.clamp(_statusPaneMinHeight, double.infinity);
return Column(
children: [
Expanded(
child: Scrollbar(
controller: _scrollController,
thumbVisibility: true,
child: TerminalView(
IntegrationLogSink.instance.terminal,
controller: _terminalController,
scrollController: _scrollController,
autofocus: true,
textStyle: const TerminalStyle(fontSize: 10),
),
),
),
),
),
Container(height: 1, color: Colors.grey.shade800),
const SizedBox(height: 180, child: IntegrationTestStatusPane()),
],
_divider(maxStatusHeight),
SizedBox(
// clamp at render so a resize keeps the dragged height
height: _statusPaneHeight.clamp(
_statusPaneMinHeight,
maxStatusHeight,
),
child: const IntegrationTestStatusPane(),
),
],
);
},
),
),
);
}
class IntegrationTestStatusPane extends StatelessWidget {
class IntegrationTestStatusPane extends StatefulWidget {
const IntegrationTestStatusPane({super.key});
@override
State<IntegrationTestStatusPane> createState() =>
_IntegrationTestStatusPaneState();
}
class _IntegrationTestStatusPaneState extends State<IntegrationTestStatusPane> {
final _scrollController = ScrollController();
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => AnimatedBuilder(
animation: IntegrationTestStatusSink.instance,
@@ -294,30 +347,36 @@ class IntegrationTestStatusPane extends StatelessWidget {
),
),
Expanded(
child: ListView.builder(
reverse: true,
itemCount: sink.results.length,
itemBuilder: (context, i) {
final r = sink.results[sink.results.length - 1 - i];
final icon = r.status == TestStatus.passed ? '✓' : '✗';
final color = r.status == TestStatus.passed
? Colors.greenAccent
: Colors.redAccent;
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 1,
),
child: Text(
'$icon ${r.name} (${r.elapsedMs}ms)',
style: TextStyle(
color: color,
fontSize: 11,
fontFamily: 'monospace',
child: Scrollbar(
controller: _scrollController,
thumbVisibility: true,
child: ListView.builder(
controller: _scrollController,
reverse: true,
primary: false,
itemCount: sink.results.length,
itemBuilder: (context, i) {
final r = sink.results[sink.results.length - 1 - i];
final icon = r.status == TestStatus.passed ? '✓' : '✗';
final color = r.status == TestStatus.passed
? Colors.greenAccent
: Colors.redAccent;
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 1,
),
),
);
},
child: Text(
'$icon ${r.name} (${r.elapsedMs}ms)',
style: TextStyle(
color: color,
fontSize: 11,
fontFamily: 'monospace',
),
),
);
},
),
),
),
],
@@ -33,8 +33,7 @@ class LogFixture {
}
void _log(VeilidConfigLogLevel level, String message) {
final line =
'${_timestamp()} ${level.name.toUpperCase()} [test] $message';
final line = '${_timestamp()} ${level.name.toUpperCase()} [test] $message';
// ignore: avoid_print
print(line);
for (final listener in _listeners) {
@@ -12,8 +12,10 @@ class PeriodicTicker {
int? _intervalId;
void start(Duration interval, void Function() onTick) {
_intervalId = web.window
.setInterval((() => onTick()).toJS, interval.inMilliseconds.toJS);
_intervalId = web.window.setInterval(
(() => onTick()).toJS,
interval.inMilliseconds.toJS,
);
}
void stop() {
@@ -0,0 +1,83 @@
// Running veilid-core inside a plain `flutter test` process.
//
// A `flutter test` process has no plugins, and veilid-core startup needs
// exactly one platform channel: `path_provider`, for its storage directory.
// Mocking that channel starts core normally, which gives unit tests crypto
// (keypairs, member ids, signing, nonces) and TableDB.
//
// Core does not attach here: no network, no DHT records, no peers. Tests
// needing those belong in the integration harness.
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'veilid_fixture.dart';
/// Point `path_provider` at a fresh temporary directory and return it.
///
/// Every method on that channel answers with a path, so one handler covers all
/// of them. The directory is new on every call, so concurrent test processes
/// never share a storage root.
Directory mockVeilidStorageDirectories({String prefix = 'veilid_unit'}) {
TestWidgetsFlutterBinding.ensureInitialized();
final dir = Directory.systemTemp.createTempSync(prefix);
for (final channel in const [
'plugins.flutter.io/path_provider',
'plugins.flutter.io/path_provider_macos',
'plugins.flutter.io/path_provider_linux',
'plugins.flutter.io/path_provider_windows',
'plugins.flutter.io/path_provider_android',
]) {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(
MethodChannel(channel),
(call) async => dir.path,
);
}
return dir;
}
/// A program name no concurrently-running test process can share.
///
/// [DefaultVeilidFixture] joins the program name into its table, protected and
/// block store directories, so it is the isolation key: two processes sharing
/// one share their stores. `flutter test` runs test files in separate
/// processes, so the pid separates them. A Dart program holds at most one
/// veilid instance, so no instance counter is needed on top.
String veilidUnitProgramName([String base = 'VeilidUnitTest']) => '$base-$pid';
/// Start veilid-core for this test file and shut it down afterwards.
///
/// Call once at the top of `main()`. veilid-core is a process singleton, so
/// this registers `setUpAll`/`tearDownAll`, not per-test hooks.
///
/// Startup is [DefaultVeilidFixture], the same one the integration tests use,
/// so logging and config honour the same environment variables; this adds the
/// mocked storage directory a pluginless process lacks and a per-process
/// program name (see [veilidUnitProgramName]).
///
/// [base] only labels the run; the pid supplies uniqueness, so two files may
/// share a base.
void useVeilidUnitCore({String base = 'VeilidUnitTest'}) {
TestWidgetsFlutterBinding.ensureInitialized();
late Directory storageDir;
final programName = veilidUnitProgramName(base);
final fixture = DefaultVeilidFixture(programName: programName);
setUpAll(() async {
storageDir = mockVeilidStorageDirectories(prefix: programName);
await fixture.setUp();
});
tearDownAll(() async {
await fixture.tearDown();
try {
storageDir.deleteSync(recursive: true);
} on FileSystemException {
// A leftover temp directory is not worth failing a suite over
}
});
}
@@ -11,8 +11,7 @@ class UpdateProcessorFixture implements VeilidProcessorInterface {
VeilidFixture veilidFixture;
@override
ProcessorConnectionState processorConnectionState =
ProcessorConnectionState(
ProcessorConnectionState processorConnectionState = ProcessorConnectionState(
attachment: VeilidStateAttachment(
state: AttachmentState.detached,
publicInternetReady: false,
@@ -3,5 +3,6 @@ library;
export 'src/log_fixture.dart';
export 'src/ticker_fixture.dart';
export 'src/unit_fixture.dart';
export 'src/update_processor_fixture.dart';
export 'src/veilid_fixture.dart';
@@ -14,6 +14,13 @@ dependencies:
web: ^1.1.1
veilid:
path: ../..
# For the unit fixture, which mocks a platform channel and registers test
# hooks. This package already depends on veilid, a Flutter plugin, so it was
# never usable outside Flutter.
flutter:
sdk: flutter
flutter_test:
sdk: flutter
dev_dependencies:
flutter_lints: ^6.0.0
+2 -2
View File
@@ -1,8 +1,8 @@
#!/bin/bash
pushd example 2>/dev/null
# Cargo features come from the `hooks: user_defines:` block in example/pubspec.yaml;
# hooks run under a fixed environment allowlist, so nothing can be passed from here.
# Set cargo features in example/pubspec.yaml under `hooks: user_defines:`; hooks run
# under a fixed environment allowlist, so this script cannot pass any through
# Default to the #common=debug log tag group unless the caller overrides LOG_DIRECTIVES
case "$*" in
+1 -1
View File
@@ -12,7 +12,7 @@ const knownVectors = [
['foo', 'Zm9v'],
['foob', 'Zm9vYg'],
['fooba', 'Zm9vYmE'],
['foobar', 'Zm9vYmFy']
['foobar', 'Zm9vYmFy'],
];
Future<void> _testEncodingKnownVector(Uint8List k, String v) async {
+2 -2
View File
@@ -1,8 +1,8 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:veilid/veilid.dart';
// Renaming either side of the @DefaultAsset/assetName pair still compiles, and only
// fails when the first FFI call runs.
// Renaming either side of the @DefaultAsset/assetName pair still compiles and
// fails only at the first FFI call.
void testNativeAssetResolves() {
expect(Veilid.instance.veilidVersionString(), isNotEmpty);
expect(Veilid.instance.veilidFeatures(), isNotEmpty);
@@ -13,12 +13,14 @@ ValueSubkeyRange? vsrIntersect(ValueSubkeyRange a, ValueSubkeyRange b) =>
a.intersect(b);
List<ValueSubkeyRange> lvsrUnion(
List<ValueSubkeyRange> a, List<ValueSubkeyRange> b) =>
a.unionSubkeys(b);
List<ValueSubkeyRange> a,
List<ValueSubkeyRange> b,
) => a.unionSubkeys(b);
List<ValueSubkeyRange> lvsrIntersect(
List<ValueSubkeyRange> a, List<ValueSubkeyRange> b) =>
a.intersectSubkeys(b);
List<ValueSubkeyRange> a,
List<ValueSubkeyRange> b,
) => a.intersectSubkeys(b);
Future<void> testValueSubkeyRange() async {
final a = ValueSubkeyRange.single(1);
@@ -45,7 +47,11 @@ Future<void> testValueSubkeyRangeList() async {
expectCommute(lvsrUnion, a, a, a);
expectCommute(lvsrUnion, a, b, [const ValueSubkeyRange(low: 1, high: 3)]);
expectCommute<List<ValueSubkeyRange>>(
lvsrUnion, a, c, ListValueSubkeyRangeExt.fromIntPairs([(1, 1), (3, 4)]));
lvsrUnion,
a,
c,
ListValueSubkeyRangeExt.fromIntPairs([(1, 1), (3, 4)]),
);
expectCommute(lvsrUnion, b, c, [const ValueSubkeyRange(low: 2, high: 4)]);
const d = [ValueSubkeyRange(low: 0, high: 3)];
@@ -60,8 +66,12 @@ Future<void> testValueSubkeyRangeList() async {
expectCommute(lvsrUnion, e, f, g);
final h = ListValueSubkeyRangeExt.fromIntPairs(
[(2, 5), (10, 10), (12, 14), (16, 18)]);
final h = ListValueSubkeyRangeExt.fromIntPairs([
(2, 5),
(10, 10),
(12, 14),
(16, 18),
]);
expectCommute(lvsrIntersect, e, f, h);
expectCommute<List<ValueSubkeyRange>>(lvsrUnion, [], [], []);