import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; import 'dart:isolate'; import 'dart:typed_data'; import 'package:ffi/ffi.dart'; import 'veilid.dart'; ////////////////////////////////////////////////////////// // Load the veilid_flutter library once const _base = 'veilid_flutter'; final _path = Platform.isWindows ? '$_base.dll' : Platform.isMacOS ? 'lib$_base.dylib' : 'lib$_base.so'; final _dylib = Platform.isIOS ? DynamicLibrary.process() : DynamicLibrary.open(_path); // Linkage for initialization typedef _DartPostCObject = NativeFunction)>; // fn free_string(s: *mut std::os::raw::c_char) typedef _FreeStringDart = void Function(Pointer); // fn initialize_veilid_flutter( // dart_post_c_object_ptr: ffi::DartPostCObjectFnType) // fn initialize_veilid_core(platform_config: FfiStr) typedef _InitializeVeilidCoreDart = void Function(Pointer); // fn change_log_level(layer: FfiStr, log_level: FfiStr) typedef _ChangeLogLevelDart = void Function(Pointer, Pointer); // fn startup_veilid_core(port: i64, config: FfiStr) typedef _StartupVeilidCoreDart = void Function(int, int, Pointer); // fn get_veilid_state(port: i64) typedef _GetVeilidStateDart = void Function(int); // fn attach(port: i64) typedef _AttachDart = void Function(int); // fn detach(port: i64) typedef _DetachDart = void Function(int); // fn routing_context(port: i64) typedef _RoutingContextDart = void Function(int); // fn release_routing_context(id: u32) typedef _ReleaseRoutingContextDart = int Function(int); // fn routing_context_with_default_safety(id: u32) -> u32 typedef _RoutingContextWithDefaultSafetyDart = int Function(int); // fn routing_context_with_safety(id: u32, stability: FfiStr) typedef _RoutingContextWithSafetyDart = int Function(int, Pointer); // fn routing_context_with_sequencing(id: u32, sequencing: FfiStr) typedef _RoutingContextWithSequencingDart = int Function(int, Pointer); // fn routing_context_safety(port: i64, // id: u32) typedef _RoutingContextSafetyDart = void Function(int, int); // fn routing_context_app_call(port: i64, // id: u32, target: FfiStr, request: FfiStr) typedef _RoutingContextAppCallDart = void Function( int, int, Pointer, Pointer); // fn routing_context_app_message(port: i64, // id: u32, target: FfiStr, request: FfiStr) typedef _RoutingContextAppMessageDart = void Function( int, int, Pointer, Pointer); // fn routing_context_create_dht_record(port: i64, // id: u32, kind: u32, schema: FfiStr) typedef _RoutingContextCreateDHTRecordDart = void Function( int, int, Pointer, int); // fn routing_context_open_dht_record(port: i64, // id: u32, key: FfiStr, writer: FfiStr) typedef _RoutingContextOpenDHTRecordDart = void Function( int, int, Pointer, Pointer); // fn routing_context_close_dht_record(port: i64, id: u32, key: FfiStr) typedef _RoutingContextCloseDHTRecordDart = void Function( int, int, Pointer); // fn routing_context_delete_dht_record(port: i64, id: u32, key: FfiStr) typedef _RoutingContextDeleteDHTRecordDart = void Function( int, int, Pointer); // fn routing_context_get_dht_value(port: i64, // id: u32, key: FfiStr, subkey: u32, force_refresh: bool) typedef _RoutingContextGetDHTValueDart = void Function( int, int, Pointer, int, bool); // fn routing_context_set_dht_value(port: i64, // id: u32, key: FfiStr, subkey: u32, data: FfiStr) typedef _RoutingContextSetDHTValueDart = void Function( int, int, Pointer, int, Pointer); // fn routing_context_watch_dht_values(port: i64, // id: u32, key: FfiStr, subkeys: FfiStr, expiration: FfiStr, count: u32) typedef _RoutingContextWatchDHTValuesDart = void Function( int, int, Pointer, Pointer, int, int); // fn routing_context_cancel_dht_watch(port: i64, // id: u32, key: FfiStr, subkeys: FfiStr) typedef _RoutingContextCancelDHTWatchDart = void Function( int, int, Pointer, Pointer); // fn new_private_route(port: i64) typedef _NewPrivateRouteDart = void Function(int); // fn new_custom_private_route(port: i64, stability: FfiStr, sequencing: FfiStr) typedef _NewCustomPrivateRouteDart = void Function( int, Pointer, Pointer); // fn import_remote_private_route(port: i64, blob: FfiStr) typedef _ImportRemotePrivateRouteDart = void Function(int, Pointer); // fn release_private_route(port:i64, key: FfiStr) typedef _ReleasePrivateRouteDart = void Function(int, Pointer); // fn app_call_reply(port: i64, id: FfiStr, message: FfiStr) typedef _AppCallReplyDart = void Function(int, Pointer, Pointer); // fn open_table_db(port: i64, name: FfiStr, column_count: u32) typedef _OpenTableDbDart = void Function(int, Pointer, int); // fn release_table_db(id: u32) -> i32 typedef _ReleaseTableDbDart = int Function(int); // fn delete_table_db(port: i64, name: FfiStr) typedef _DeleteTableDbDart = void Function(int, Pointer); // fn table_db_get_column_count(id: u32) -> u32 typedef _TableDbGetColumnCountDart = int Function(int); // fn table_db_get_keys(port: i64, id: u32, col: u32) typedef _TableDbGetKeysDart = Pointer Function(int, int, int); // fn table_db_store(port: i64, id: u32, col: u32, key: FfiStr, value: FfiStr) typedef _TableDbStoreDart = void Function( int, int, int, Pointer, Pointer); // fn table_db_load(port: i64, id: u32, col: u32, key: FfiStr) typedef _TableDbLoadDart = void Function(int, int, int, Pointer); // fn table_db_delete(port: i64, id: u32, col: u32, key: FfiStr) typedef _TableDbDeleteDart = void Function(int, int, int, Pointer); // fn table_db_transact(id: u32) -> u32 typedef _TableDbTransactDart = int Function(int); // fn release_table_db_transaction(id: u32) -> i32 typedef _ReleaseTableDbTransactionDart = int Function(int); // fn table_db_transaction_commit(port: i64, id: u32) typedef _TableDbTransactionCommitDart = void Function(int, int); // fn table_db_transaction_rollback(port: i64, id: u32) typedef _TableDbTransactionRollbackDart = void Function(int, int); // fn table_db_transaction_store(port: i64, // id: u32, col: u32, key: FfiStr, value: FfiStr) typedef _TableDbTransactionStoreDart = void Function( int, int, int, Pointer, Pointer); // fn table_db_transaction_delete(port: i64, id: u32, col: u32, key: FfiStr) typedef _TableDbTransactionDeleteDart = void Function( int, int, int, Pointer); // fn valid_crypto_kinds() -> *mut c_char typedef _ValidCryptoKindsDart = Pointer Function(); // fn best_crypto_kind() -> u32 typedef _BestCryptoKindDart = int Function(); // fn verify_signatures(port: i64, // node_ids: FfiStr, data: FfiStr, signatures: FfiStr) typedef _VerifySignaturesDart = void Function( int, Pointer, Pointer, Pointer); // fn generate_signatures(port: i64, data: FfiStr, key_pairs: FfiStr) typedef _GenerateSignaturesDart = void Function( int, Pointer, Pointer); // fn generate_key_pair(port: i64, kind: u32) { typedef _GenerateKeyPairDart = void Function(int, int); // fn crypto_cached_dh(port: i64, kind: u32, key: FfiStr, secret: FfiStr) typedef _CryptoCachedDHDart = void Function( int, int, Pointer, Pointer); // fn crypto_compute_dh(port: i64, kind: u32, key: FfiStr, secret: FfiStr) typedef _CryptoComputeDHDart = void Function( int, int, Pointer, Pointer); // fn crypto_random_bytes(port: i64, kind: u32, len: u32) typedef _CryptoRandomBytesDart = void Function(int, int, int); // fn crypto_default_salt_length(port: i64, kind: u32) typedef _CryptoDefaultSaltLengthDart = void Function(int, int); // fn crypto_hash_password(port: i64, kind: u32, password: FfiStr, salt: FfiStr) typedef _CryptoHashPasswordDart = void Function( int, int, Pointer, Pointer); // fn crypto_verify_password(port: i64, // kind: u32, password: FfiStr, password_hash: FfiStr ) typedef _CryptoVerifyPasswordDart = void Function( int, int, Pointer, Pointer); // fn crypto_derive_shared_secret(port: i64, // kind: u32, password: FfiStr, salt: FfiStr ) // fn crypto_random_nonce(port: i64, kind: u32) typedef _CryptoRandomNonceDart = void Function(int, int); // fn crypto_random_shared_secret(port: i64, kind: u32) typedef _CryptoRandomSharedSecretDart = void Function(int, int); // fn crypto_generate_key_pair(port: i64, kind: u32) typedef _CryptoGenerateKeyPairDart = void Function(int, int); // fn crypto_generate_hash(port: i64, kind: u32, data: FfiStr) typedef _CryptoGenerateHashDart = void Function(int, int, Pointer); // fn crypto_validate_key_pair(port: i64, // kind: u32, key: FfiStr, secret: FfiStr) typedef _CryptoValidateKeyPairDart = void Function( int, int, Pointer, Pointer); // fn crypto_validate_hash(port: i64, kind: u32, data: FfiStr, hash: FfiStr) typedef _CryptoValidateHashDart = void Function( int, int, Pointer, Pointer); // fn crypto_distance(port: i64, kind: u32, key1: FfiStr, key2: FfiStr) typedef _CryptoDistanceDart = void Function( int, int, Pointer, Pointer); // fn crypto_sign(port: i64, // kind: u32, key: FfiStr, secret: FfiStr, data: FfiStr) typedef _CryptoSignDart = void Function( int, int, Pointer, Pointer, Pointer); // fn crypto_verify(port: i64, // kind: u32, key: FfiStr, data: FfiStr, signature: FfiStr) typedef _CryptoVerifyDart = void Function( int, int, Pointer, Pointer, Pointer); // fn crypto_aead_overhead(port: i64, kind: u32) typedef _CryptoAeadOverheadDart = void Function(int, int); // fn crypto_decrypt_aead(port: i64, // kind: u32, body: FfiStr, nonce: FfiStr, // shared_secret: FfiStr, associated_data: FfiStr) typedef _CryptoDecryptAeadDart = void Function( int, int, Pointer, Pointer, Pointer, Pointer); // fn crypto_encrypt_aead(port: i64, // kind: u32, body: FfiStr, nonce: FfiStr, // shared_secret: FfiStr, associated_data: FfiStr) typedef _CryptoEncryptAeadDart = void Function( int, int, Pointer, Pointer, Pointer, Pointer); // fn crypto_crypt_no_auth(port: i64, // kind: u32, body: FfiStr, nonce: FfiStr, shared_secret: FfiStr) typedef _CryptoCryptNoAuthDart = void Function( int, int, Pointer, Pointer, Pointer); // fn now() -> u64 typedef _NowDart = int Function(); // fn debug(port: i64, log_level: FfiStr) typedef _DebugDart = void Function(int, Pointer); // fn shutdown_veilid_core(port: i64) typedef _ShutdownVeilidCoreDart = void Function(int); // fn veilid_version_string() -> *mut c_char typedef _VeilidVersionStringDart = Pointer Function(); // fn veilid_version() -> VeilidVersion final class VeilidVersionFFI extends Struct { @Uint32() external int major; @Uint32() external int minor; @Uint32() external int patch; } typedef _VeilidVersionDart = VeilidVersionFFI Function(); // Async message types const int messageOk = 0; const int messageErr = 1; const int messageOkJson = 2; const int messageErrJson = 3; const int messageStreamItem = 4; const int messageStreamItemJson = 5; const int messageStreamAbort = 6; const int messageStreamAbortJson = 7; const int messageStreamClose = 8; // Interface factory for high level Veilid API Veilid getVeilid() => VeilidFFI(_dylib); // Uint8List marshaling Uint8List convertUint8ListFromJson(dynamic json) => base64UrlNoPadDecode(json as String); dynamic convertUint8ListToJson(Uint8List data) => base64UrlNoPadEncode(data); // Parse handle async returns Future processFuturePlain(Future future) async => future.then((value) { final list = value as List; switch (list[0] as int) { case messageOk: { if (list[1] == null && null is! T) { throw const VeilidAPIExceptionInternal( 'Null MESSAGE_OK value on non-nullable type'); } return list[1] as T; } case messageErr: { throw VeilidAPIExceptionInternal('Internal API Error: ${list[1]}'); } case messageErrJson: { throw VeilidAPIException.fromJson(jsonDecode(list[1] as String)); } default: { throw VeilidAPIExceptionInternal( 'Unexpected async return message type: ${list[0]}'); } } // ignore: inference_failure_on_untyped_parameter }).catchError((e) { // Wrap all other errors in VeilidAPIExceptionInternal throw VeilidAPIExceptionInternal(e.toString()); }, test: (e) => e is! VeilidAPIException); Future processFutureJson( T Function(dynamic) jsonConstructor, Future future) async => future.then((value) { final list = value as List; switch (list[0] as int) { case messageErr: { throw VeilidAPIExceptionInternal('Internal API Error: ${list[1]}'); } case messageOkJson: { if (list[1] is! String) { throw const VeilidAPIExceptionInternal( 'Non-string MESSAGE_OK_JSON value'); } final ret = jsonDecode(list[1] as String); if (ret == null) { throw const VeilidAPIExceptionInternal( 'Null JSON object on non nullable type'); } return jsonConstructor(ret); } case messageErrJson: { throw VeilidAPIException.fromJson(jsonDecode(list[1] as String)); } default: { throw VeilidAPIExceptionInternal( 'Unexpected async return message type: ${list[0]}'); } } // ignore: inference_failure_on_untyped_parameter }).catchError((e) { // Wrap all other errors in VeilidAPIExceptionInternal throw VeilidAPIExceptionInternal(e.toString()); }, test: (e) => e is! VeilidAPIException); Future processFutureOptJson( T Function(dynamic) jsonConstructor, Future future) async => future.then((value) { final list = value as List; switch (list[0] as int) { case messageErr: { throw VeilidAPIExceptionInternal('Internal API Error: ${list[1]}'); } case messageOkJson: { if (list[1] == null) { return null; } if (list[1] is! String) { throw const VeilidAPIExceptionInternal( 'Non-string MESSAGE_OK_JSON optional value'); } final ret = jsonDecode(list[1] as String); if (ret == null) { return null; } return jsonConstructor(ret); } case messageErrJson: { throw VeilidAPIException.fromJson(jsonDecode(list[1] as String)); } default: { throw VeilidAPIExceptionInternal( 'Unexpected async return message type: ${list[0]}'); } } // ignore: inference_failure_on_untyped_parameter }).catchError((e) { // Wrap all other errors in VeilidAPIExceptionInternal throw VeilidAPIExceptionInternal(e.toString()); }, test: (e) => e is! VeilidAPIException); Future processFutureVoid(Future future) async => future.then((value) { final list = value as List; switch (list[0] as int) { case messageOk: { if (list[1] != null) { throw VeilidAPIExceptionInternal('Unexpected MESSAGE_OK value' ' "${list[1]}" where null expected'); } return; } case messageErr: { throw VeilidAPIExceptionInternal('Internal API Error: ${list[1]}'); } case messageOkJson: { final ret = jsonDecode(list[1] as String); if (ret != null) { throw VeilidAPIExceptionInternal( 'Unexpected MESSAGE_OK_JSON value' ' "$ret" where null expected'); } return; } case messageErrJson: { throw VeilidAPIException.fromJson(jsonDecode(list[1] as String)); } default: { throw VeilidAPIExceptionInternal( 'Unexpected async return message type: ${list[0]}'); } } // ignore: inference_failure_on_untyped_parameter }).catchError((e) { // Wrap all other errors in VeilidAPIExceptionInternal throw VeilidAPIExceptionInternal(e.toString()); }, test: (e) => e is! VeilidAPIException); Future> processFutureStream( Stream returnStream, Future future) async => future.then((value) { final list = value as List; switch (list[0] as int) { case messageOk: { if (list[1] != null) { throw VeilidAPIExceptionInternal('Unexpected MESSAGE_OK value' ' "${list[1]}" where null expected'); } return returnStream; } case messageErr: { throw VeilidAPIExceptionInternal('Internal API Error: ${list[1]}'); } case messageOkJson: { final ret = jsonDecode(list[1] as String); if (ret != null) { throw VeilidAPIExceptionInternal( 'Unexpected MESSAGE_OK_JSON value' ' "$ret" where null expected'); } return returnStream; } case messageErrJson: { throw VeilidAPIException.fromJson(jsonDecode(list[1] as String)); } default: { throw VeilidAPIExceptionInternal( 'Unexpected async return message type: ${list[0]}'); } } // ignore: inference_failure_on_untyped_parameter }).catchError((e) { // Wrap all other errors in VeilidAPIExceptionInternal throw VeilidAPIExceptionInternal(e.toString()); }, test: (e) => e is! VeilidAPIException); Stream processStreamJson( T Function(dynamic) jsonConstructor, ReceivePort port) async* { try { await for (final value in port) { final list = value as List; switch (list[0] as int) { case messageStreamItemJson: { if (list[1] == null) { throw const VeilidAPIExceptionInternal( 'Null MESSAGE_STREAM_ITEM_JSON value'); } final ret = jsonDecode(list[1] as String); yield jsonConstructor(ret); break; } case messageStreamAbort: { throw VeilidAPIExceptionInternal('Internal API Error: ${list[1]}'); } case messageStreamAbortJson: { throw VeilidAPIException.fromJson(jsonDecode(list[1] as String)); } case messageStreamClose: { break; } default: { throw VeilidAPIExceptionInternal( 'Unexpected async return message type: ${list[0]}'); } } } } on VeilidAPIException catch (_) { rethrow; } on Exception catch (e, s) { // Wrap all other errors in VeilidAPIExceptionInternal throw VeilidAPIExceptionInternal('$e\nStack Trace:\n$s'); } finally { port.close(); } } class _Ctx { _Ctx(int this.id, this.ffi); int? id; final VeilidFFI ffi; void ensureValid() { if (id == null) { throw VeilidAPIExceptionNotInitialized(); } } void close() { if (id != null) { ffi._releaseRoutingContext(id!); id = null; } } } // FFI implementation of VeilidRoutingContext class VeilidRoutingContextFFI extends VeilidRoutingContext { VeilidRoutingContextFFI._(this._ctx) { _finalizer.attach(this, _ctx, detach: this); } final _Ctx _ctx; static final Finalizer<_Ctx> _finalizer = Finalizer((ctx) => ctx.close()); @override void close() { _ctx.close(); } @override VeilidRoutingContextFFI withDefaultSafety() { _ctx.ensureValid(); final newId = _ctx.ffi._routingContextWithDefaultSafety(_ctx.id!); return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi)); } @override VeilidRoutingContextFFI withSafety(SafetySelection safetySelection) { _ctx.ensureValid(); final newId = _ctx.ffi._routingContextWithSafety( _ctx.id!, jsonEncode(safetySelection).toNativeUtf8()); return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi)); } @override VeilidRoutingContextFFI withSequencing(Sequencing sequencing) { _ctx.ensureValid(); final newId = _ctx.ffi._routingContextWithSequencing( _ctx.id!, jsonEncode(sequencing).toNativeUtf8()); return VeilidRoutingContextFFI._(_Ctx(newId, _ctx.ffi)); } @override Future safety() async { _ctx.ensureValid(); final recvPort = ReceivePort('routing_context_safety'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextSafety(sendPort.nativePort, _ctx.id!); final out = await processFutureJson( SafetySelection.fromJson, recvPort.first); return out; } @override Future appCall(String target, Uint8List request) async { _ctx.ensureValid(); final nativeEncodedTarget = target.toNativeUtf8(); final nativeEncodedRequest = base64UrlNoPadEncode(request).toNativeUtf8(); final recvPort = ReceivePort('routing_context_app_call'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextAppCall(sendPort.nativePort, _ctx.id!, nativeEncodedTarget, nativeEncodedRequest); final out = await processFuturePlain(recvPort.first); return base64UrlNoPadDecode(out); } @override Future appMessage(String target, Uint8List message) async { _ctx.ensureValid(); final nativeEncodedTarget = target.toNativeUtf8(); final nativeEncodedMessage = base64UrlNoPadEncode(message).toNativeUtf8(); final recvPort = ReceivePort('routing_context_app_message'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextAppMessage(sendPort.nativePort, _ctx.id!, nativeEncodedTarget, nativeEncodedMessage); return await processFutureVoid(recvPort.first); } @override Future createDHTRecord(DHTSchema schema, {CryptoKind kind = 0}) async { _ctx.ensureValid(); final nativeSchema = jsonEncode(schema).toNativeUtf8(); final recvPort = ReceivePort('routing_context_create_dht_record'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextCreateDHTRecord( sendPort.nativePort, _ctx.id!, nativeSchema, kind); final dhtRecordDescriptor = await processFutureJson(DHTRecordDescriptor.fromJson, recvPort.first); return dhtRecordDescriptor; } @override Future openDHTRecord( TypedKey key, KeyPair? writer) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeWriter = writer != null ? jsonEncode(writer).toNativeUtf8() : nullptr; final recvPort = ReceivePort('routing_context_open_dht_record'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextOpenDHTRecord( sendPort.nativePort, _ctx.id!, nativeKey, nativeWriter); final dhtRecordDescriptor = await processFutureJson(DHTRecordDescriptor.fromJson, recvPort.first); return dhtRecordDescriptor; } @override Future closeDHTRecord(TypedKey key) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final recvPort = ReceivePort('routing_context_close_dht_record'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextCloseDHTRecord( sendPort.nativePort, _ctx.id!, nativeKey); return await processFutureVoid(recvPort.first); } @override Future deleteDHTRecord(TypedKey key) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final recvPort = ReceivePort('routing_context_delete_dht_record'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextDeleteDHTRecord( sendPort.nativePort, _ctx.id!, nativeKey); return await processFutureVoid(recvPort.first); } @override Future getDHTValue( TypedKey key, int subkey, bool forceRefresh) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final recvPort = ReceivePort('routing_context_get_dht_value'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextGetDHTValue( sendPort.nativePort, _ctx.id!, nativeKey, subkey, forceRefresh); final valueData = await processFutureOptJson(ValueData.fromJson, recvPort.first); return valueData; } @override Future setDHTValue( TypedKey key, int subkey, Uint8List data) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeData = base64UrlNoPadEncode(data).toNativeUtf8(); final recvPort = ReceivePort('routing_context_set_dht_value'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextSetDHTValue( sendPort.nativePort, _ctx.id!, nativeKey, subkey, nativeData); final valueData = await processFutureOptJson(ValueData.fromJson, recvPort.first); return valueData; } @override Future watchDHTValues(TypedKey key, List subkeys, Timestamp expiration, int count) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8(); final nativeExpiration = expiration.value.toInt(); final recvPort = ReceivePort('routing_context_watch_dht_values'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextWatchDHTValues(sendPort.nativePort, _ctx.id!, nativeKey, nativeSubkeys, nativeExpiration, count); final actualExpiration = Timestamp( value: BigInt.from(await processFuturePlain(recvPort.first))); return actualExpiration; } @override Future cancelDHTWatch( TypedKey key, List subkeys) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSubkeys = jsonEncode(subkeys).toNativeUtf8(); final recvPort = ReceivePort('routing_context_cancel_dht_watch'); final sendPort = recvPort.sendPort; _ctx.ffi._routingContextCancelDHTWatch( sendPort.nativePort, _ctx.id!, nativeKey, nativeSubkeys); final cancelled = await processFuturePlain(recvPort.first); return cancelled; } } class _TDBT { _TDBT(int this.id, this.tdbffi, this.ffi); int? id; final VeilidTableDBFFI tdbffi; final VeilidFFI ffi; void ensureValid() { if (id == null) { throw VeilidAPIExceptionNotInitialized(); } } void close() { if (id != null) { ffi._releaseTableDbTransaction(id!); id = null; } } } // FFI implementation of VeilidTableDBTransaction class VeilidTableDBTransactionFFI extends VeilidTableDBTransaction { VeilidTableDBTransactionFFI._(this._tdbt) { _finalizer.attach(this, _tdbt, detach: this); } final _TDBT _tdbt; static final Finalizer<_TDBT> _finalizer = Finalizer((tdbt) => tdbt.close()); @override bool isDone() => _tdbt.id == null; @override Future commit() async { _tdbt.ensureValid(); final recvPort = ReceivePort('veilid_table_db_transaction_commit'); final sendPort = recvPort.sendPort; _tdbt.ffi._tableDbTransactionCommit( sendPort.nativePort, _tdbt.id!, ); await processFutureVoid(recvPort.first); _tdbt.close(); } @override Future rollback() async { _tdbt.ensureValid(); final recvPort = ReceivePort('veilid_table_db_transaction_rollback'); final sendPort = recvPort.sendPort; _tdbt.ffi._tableDbTransactionRollback( sendPort.nativePort, _tdbt.id!, ); await processFutureVoid(recvPort.first); _tdbt.close(); } @override Future store(int col, Uint8List key, Uint8List value) async { _tdbt.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); final nativeEncodedValue = base64UrlNoPadEncode(value).toNativeUtf8(); final recvPort = ReceivePort('veilid_table_db_transaction_store'); final sendPort = recvPort.sendPort; _tdbt.ffi._tableDbTransactionStore( sendPort.nativePort, _tdbt.id!, col, nativeEncodedKey, nativeEncodedValue, ); return await processFutureVoid(recvPort.first); } @override Future delete(int col, Uint8List key) async { _tdbt.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); final recvPort = ReceivePort('veilid_table_db_transaction_delete'); final sendPort = recvPort.sendPort; _tdbt.ffi._tableDbTransactionDelete( sendPort.nativePort, _tdbt.id!, col, nativeEncodedKey, ); return await processFuturePlain(recvPort.first); } } class _TDB { _TDB(int this.id, this.ffi); int? id; final VeilidFFI ffi; void ensureValid() { if (id == null) { throw VeilidAPIExceptionNotInitialized(); } } void close() { if (id != null) { ffi._releaseTableDb(id!); id = null; } } } // FFI implementation of VeilidTableDB class VeilidTableDBFFI extends VeilidTableDB { VeilidTableDBFFI._(this._tdb) { _finalizer.attach(this, _tdb, detach: this); } final _TDB _tdb; static final Finalizer<_TDB> _finalizer = Finalizer((tdb) => tdb.close()); @override void close() { _tdb.close(); } @override int getColumnCount() { _tdb.ensureValid(); return _tdb.ffi._tableDbGetColumnCount(_tdb.id!); } @override Future> getKeys(int col) async { _tdb.ensureValid(); final recvPort = ReceivePort('veilid_table_db_get_keys'); final sendPort = recvPort.sendPort; _tdb.ffi._tableDbGetKeys(sendPort.nativePort, _tdb.id!, col); return await processFutureJson( jsonListConstructor(base64UrlNoPadDecodeDynamic), recvPort.first); } @override VeilidTableDBTransaction transact() { _tdb.ensureValid(); final id = _tdb.ffi._tableDbTransact(_tdb.id!); return VeilidTableDBTransactionFFI._(_TDBT(id, this, _tdb.ffi)); } @override Future store(int col, Uint8List key, Uint8List value) async { _tdb.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); final nativeEncodedValue = base64UrlNoPadEncode(value).toNativeUtf8(); final recvPort = ReceivePort('veilid_table_db_store'); final sendPort = recvPort.sendPort; _tdb.ffi._tableDbStore( sendPort.nativePort, _tdb.id!, col, nativeEncodedKey, nativeEncodedValue, ); return await processFutureVoid(recvPort.first); } @override Future load(int col, Uint8List key) async { _tdb.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); final recvPort = ReceivePort('veilid_table_db_load'); final sendPort = recvPort.sendPort; _tdb.ffi._tableDbLoad( sendPort.nativePort, _tdb.id!, col, nativeEncodedKey, ); final out = await processFuturePlain(recvPort.first); if (out == null) { return null; } return base64UrlNoPadDecode(out); } @override Future delete(int col, Uint8List key) async { _tdb.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); final recvPort = ReceivePort('veilid_table_db_delete'); final sendPort = recvPort.sendPort; _tdb.ffi._tableDbDelete( sendPort.nativePort, _tdb.id!, col, nativeEncodedKey, ); final out = await processFuturePlain(recvPort.first); if (out == null) { return null; } return base64UrlNoPadDecode(out); } } // FFI implementation of VeilidCryptoSystem class VeilidCryptoSystemFFI extends VeilidCryptoSystem { VeilidCryptoSystemFFI._(this._ffi, this._kind); final CryptoKind _kind; final VeilidFFI _ffi; @override CryptoKind kind() => _kind; @override Future cachedDH(PublicKey key, SecretKey secret) async { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); final recvPort = ReceivePort('crypto_cached_dh'); final sendPort = recvPort.sendPort; _ffi._cryptoCachedDH(sendPort.nativePort, _kind, nativeKey, nativeSecret); return await processFutureJson(SharedSecret.fromJson, recvPort.first); } @override Future computeDH(PublicKey key, SecretKey secret) async { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); final recvPort = ReceivePort('crypto_compute_dh'); final sendPort = recvPort.sendPort; _ffi._cryptoComputeDH(sendPort.nativePort, _kind, nativeKey, nativeSecret); return await processFutureJson(SharedSecret.fromJson, recvPort.first); } @override Future randomBytes(int len) async { final recvPort = ReceivePort('crypto_random_bytes'); final sendPort = recvPort.sendPort; _ffi._cryptoRandomBytes(sendPort.nativePort, _kind, len); final out = await processFuturePlain(recvPort.first); return base64UrlNoPadDecode(out); } @override Future defaultSaltLength() async { final recvPort = ReceivePort('crypto_default_salt_length'); final sendPort = recvPort.sendPort; _ffi._cryptoDefaultSaltLength(sendPort.nativePort, _kind); return await processFuturePlain(recvPort.first); } @override Future hashPassword(Uint8List password, Uint8List salt) async { final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8(); final nativeEncodedSalt = base64UrlNoPadEncode(salt).toNativeUtf8(); final recvPort = ReceivePort('crypto_hash_password'); final sendPort = recvPort.sendPort; _ffi._cryptoHashPassword( sendPort.nativePort, _kind, nativeEncodedPassword, nativeEncodedSalt); return await processFuturePlain(recvPort.first); } @override Future verifyPassword(Uint8List password, String passwordHash) async { final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8(); final nativeEncodedPasswordHash = passwordHash.toNativeUtf8(); final recvPort = ReceivePort('crypto_verify_password'); final sendPort = recvPort.sendPort; _ffi._cryptoVerifyPassword(sendPort.nativePort, _kind, nativeEncodedPassword, nativeEncodedPasswordHash); return await processFuturePlain(recvPort.first); } @override Future deriveSharedSecret( Uint8List password, Uint8List salt) async { final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8(); final nativeEncodedSalt = base64UrlNoPadEncode(salt).toNativeUtf8(); final recvPort = ReceivePort('crypto_derive_shared_secret'); final sendPort = recvPort.sendPort; _ffi._cryptoDeriveSharedSecret( sendPort.nativePort, _kind, nativeEncodedPassword, nativeEncodedSalt); return await processFutureJson(SharedSecret.fromJson, recvPort.first); } @override Future randomNonce() async { final recvPort = ReceivePort('crypto_random_nonce'); final sendPort = recvPort.sendPort; _ffi._cryptoRandomNonce(sendPort.nativePort, _kind); return await processFutureJson(Nonce.fromJson, recvPort.first); } @override Future randomSharedSecret() async { final recvPort = ReceivePort('crypto_random_shared_secret'); final sendPort = recvPort.sendPort; _ffi._cryptoRandomSharedSecret(sendPort.nativePort, _kind); return await processFutureJson(SharedSecret.fromJson, recvPort.first); } @override Future generateKeyPair() async { final recvPort = ReceivePort('crypto_generate_key_pair'); final sendPort = recvPort.sendPort; _ffi._cryptoGenerateKeyPair(sendPort.nativePort, _kind); return await processFutureJson(KeyPair.fromJson, recvPort.first); } @override Future generateHash(Uint8List data) async { final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); final recvPort = ReceivePort('crypto_generate_hash'); final sendPort = recvPort.sendPort; _ffi._cryptoGenerateHash(sendPort.nativePort, _kind, nativeEncodedData); return await processFutureJson(HashDigest.fromJson, recvPort.first); } @override Future validateKeyPair(PublicKey key, SecretKey secret) async { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); final recvPort = ReceivePort('crypto_validate_key_pair'); final sendPort = recvPort.sendPort; _ffi._cryptoValidateKeyPair( sendPort.nativePort, _kind, nativeKey, nativeSecret); return await processFuturePlain(recvPort.first); } @override Future validateHash(Uint8List data, HashDigest hash) async { final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeHash = jsonEncode(hash).toNativeUtf8(); final recvPort = ReceivePort('crypto_validate_hash'); final sendPort = recvPort.sendPort; _ffi._cryptoValidateHash( sendPort.nativePort, _kind, nativeEncodedData, nativeHash); return await processFuturePlain(recvPort.first); } @override Future distance(CryptoKey key1, CryptoKey key2) async { final nativeKey1 = jsonEncode(key1).toNativeUtf8(); final nativeKey2 = jsonEncode(key2).toNativeUtf8(); final recvPort = ReceivePort('crypto_distance'); final sendPort = recvPort.sendPort; _ffi._cryptoDistance(sendPort.nativePort, _kind, nativeKey1, nativeKey2); return await processFutureJson(CryptoKeyDistance.fromJson, recvPort.first); } @override Future sign( PublicKey key, SecretKey secret, Uint8List data) async { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); final recvPort = ReceivePort('crypto_sign'); final sendPort = recvPort.sendPort; _ffi._cryptoSign( sendPort.nativePort, _kind, nativeKey, nativeSecret, nativeEncodedData); return await processFutureJson(Signature.fromJson, recvPort.first); } @override Future verify( PublicKey key, Uint8List data, Signature signature) async { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeSignature = jsonEncode(signature).toNativeUtf8(); final recvPort = ReceivePort('crypto_verify'); final sendPort = recvPort.sendPort; _ffi._cryptoVerify(sendPort.nativePort, _kind, nativeKey, nativeEncodedData, nativeSignature); return await processFutureVoid(recvPort.first); } @override Future aeadOverhead() async { final recvPort = ReceivePort('crypto_aead_overhead'); final sendPort = recvPort.sendPort; _ffi._cryptoAeadOverhead( sendPort.nativePort, _kind, ); return await processFuturePlain(recvPort.first); } @override Future decryptAead(Uint8List body, Nonce nonce, SharedSecret sharedSecret, Uint8List? associatedData) async { final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8(); final nativeNonce = jsonEncode(nonce).toNativeUtf8(); final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8(); final nativeSignature = (associatedData != null) ? jsonEncode(associatedData).toNativeUtf8() : nullptr; final recvPort = ReceivePort('crypto_decrypt_aead'); final sendPort = recvPort.sendPort; _ffi._cryptoDecryptAead(sendPort.nativePort, _kind, nativeEncodedBody, nativeNonce, nativeSharedSecret, nativeSignature); final out = await processFuturePlain(recvPort.first); return base64UrlNoPadDecode(out); } @override Future encryptAead(Uint8List body, Nonce nonce, SharedSecret sharedSecret, Uint8List? associatedData) async { final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8(); final nativeNonce = jsonEncode(nonce).toNativeUtf8(); final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8(); final nativeSignature = (associatedData != null) ? jsonEncode(associatedData).toNativeUtf8() : nullptr; final recvPort = ReceivePort('crypto_encrypt_aead'); final sendPort = recvPort.sendPort; _ffi._cryptoEncryptAead(sendPort.nativePort, _kind, nativeEncodedBody, nativeNonce, nativeSharedSecret, nativeSignature); final out = await processFuturePlain(recvPort.first); return base64UrlNoPadDecode(out); } @override Future cryptNoAuth( Uint8List body, Nonce nonce, SharedSecret sharedSecret) async { final nativeEncodedBody = base64UrlNoPadEncode(body).toNativeUtf8(); final nativeNonce = jsonEncode(nonce).toNativeUtf8(); final nativeSharedSecret = jsonEncode(sharedSecret).toNativeUtf8(); final recvPort = ReceivePort('crypto_crypt_no_auth'); final sendPort = recvPort.sendPort; _ffi._cryptoCryptNoAuth(sendPort.nativePort, _kind, nativeEncodedBody, nativeNonce, nativeSharedSecret); final out = await processFuturePlain(recvPort.first); return base64UrlNoPadDecode(out); } } // FFI implementation of high level Veilid API class VeilidFFI extends Veilid { VeilidFFI(DynamicLibrary dylib) : _dylib = dylib, _freeString = dylib.lookupFunction), _FreeStringDart>( 'free_string'), _initializeVeilidCore = dylib.lookupFunction< Void Function(Pointer), _InitializeVeilidCoreDart>('initialize_veilid_core'), _changeLogLevel = dylib.lookupFunction< Void Function(Pointer, Pointer), _ChangeLogLevelDart>('change_log_level'), _startupVeilidCore = dylib.lookupFunction< Void Function(Int64, Int64, Pointer), _StartupVeilidCoreDart>('startup_veilid_core'), _getVeilidState = dylib.lookupFunction( 'get_veilid_state'), _attach = dylib.lookupFunction('attach'), _detach = dylib.lookupFunction('detach'), _shutdownVeilidCore = dylib.lookupFunction( 'shutdown_veilid_core'), _routingContext = dylib.lookupFunction( 'routing_context'), _releaseRoutingContext = dylib.lookupFunction('release_routing_context'), _routingContextWithDefaultSafety = dylib.lookupFunction< Uint32 Function(Uint32), _RoutingContextWithDefaultSafetyDart>( 'routing_context_with_default_safety'), _routingContextWithSafety = dylib.lookupFunction< Uint32 Function(Uint32, Pointer), _RoutingContextWithSafetyDart>('routing_context_with_safety'), _routingContextWithSequencing = dylib.lookupFunction< Uint32 Function(Uint32, Pointer), _RoutingContextWithSequencingDart>( 'routing_context_with_sequencing'), _routingContextSafety = dylib.lookupFunction< Void Function(Int64, Uint32), _RoutingContextSafetyDart>('routing_context_safety'), _routingContextAppCall = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _RoutingContextAppCallDart>('routing_context_app_call'), _routingContextAppMessage = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _RoutingContextAppMessageDart>('routing_context_app_message'), _routingContextCreateDHTRecord = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Uint32), _RoutingContextCreateDHTRecordDart>( 'routing_context_create_dht_record'), _routingContextOpenDHTRecord = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _RoutingContextOpenDHTRecordDart>( 'routing_context_open_dht_record'), _routingContextCloseDHTRecord = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer), _RoutingContextCloseDHTRecordDart>( 'routing_context_close_dht_record'), _routingContextDeleteDHTRecord = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer), _RoutingContextDeleteDHTRecordDart>( 'routing_context_delete_dht_record'), _routingContextGetDHTValue = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Uint32, Bool), _RoutingContextGetDHTValueDart>('routing_context_get_dht_value'), _routingContextSetDHTValue = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Uint32, Pointer), _RoutingContextSetDHTValueDart>('routing_context_set_dht_value'), _routingContextWatchDHTValues = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer, Uint64, Uint32), _RoutingContextWatchDHTValuesDart>( 'routing_context_watch_dht_values'), _routingContextCancelDHTWatch = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _RoutingContextCancelDHTWatchDart>( 'routing_context_cancel_dht_watch'), _newPrivateRoute = dylib.lookupFunction( 'new_private_route'), _newCustomPrivateRoute = dylib.lookupFunction< Void Function(Int64, Pointer, Pointer), _NewCustomPrivateRouteDart>('new_custom_private_route'), _importRemotePrivateRoute = dylib.lookupFunction< Void Function(Int64, Pointer), _ImportRemotePrivateRouteDart>('import_remote_private_route'), _releasePrivateRoute = dylib.lookupFunction< Void Function(Int64, Pointer), _ReleasePrivateRouteDart>('release_private_route'), _appCallReply = dylib.lookupFunction< Void Function(Int64, Pointer, Pointer), _AppCallReplyDart>('app_call_reply'), _openTableDb = dylib.lookupFunction< Void Function(Int64, Pointer, Uint32), _OpenTableDbDart>('open_table_db'), _releaseTableDb = dylib.lookupFunction( 'release_table_db'), _deleteTableDb = dylib.lookupFunction< Void Function(Int64, Pointer), _DeleteTableDbDart>('delete_table_db'), _tableDbGetColumnCount = dylib.lookupFunction('table_db_get_column_count'), _tableDbGetKeys = dylib.lookupFunction< Pointer Function(Uint64, Uint32, Uint32), _TableDbGetKeysDart>('table_db_get_keys'), _tableDbStore = dylib.lookupFunction< Void Function(Int64, Uint32, Uint32, Pointer, Pointer), _TableDbStoreDart>('table_db_store'), _tableDbLoad = dylib.lookupFunction< Void Function(Int64, Uint32, Uint32, Pointer), _TableDbLoadDart>('table_db_load'), _tableDbDelete = dylib.lookupFunction< Void Function(Int64, Uint32, Uint32, Pointer), _TableDbDeleteDart>('table_db_delete'), _tableDbTransact = dylib.lookupFunction( 'table_db_transact'), _releaseTableDbTransaction = dylib.lookupFunction< Int32 Function(Uint32), _ReleaseTableDbTransactionDart>('release_table_db_transaction'), _tableDbTransactionCommit = dylib.lookupFunction< Void Function(Uint64, Uint32), _TableDbTransactionCommitDart>('table_db_transaction_commit'), _tableDbTransactionRollback = dylib.lookupFunction< Void Function(Uint64, Uint32), _TableDbTransactionRollbackDart>('table_db_transaction_rollback'), _tableDbTransactionStore = dylib.lookupFunction< Void Function(Int64, Uint32, Uint32, Pointer, Pointer), _TableDbTransactionStoreDart>('table_db_transaction_store'), _tableDbTransactionDelete = dylib.lookupFunction< Void Function(Int64, Uint32, Uint32, Pointer), _TableDbTransactionDeleteDart>('table_db_transaction_delete'), _validCryptoKinds = dylib.lookupFunction Function(), _ValidCryptoKindsDart>('valid_crypto_kinds'), _bestCryptoKind = dylib.lookupFunction( 'best_crypto_kind'), _verifySignatures = dylib.lookupFunction< Void Function(Int64, Pointer, Pointer, Pointer), _VerifySignaturesDart>('verify_signatures'), _generateSignatures = dylib.lookupFunction< Void Function(Int64, Pointer, Pointer), _GenerateSignaturesDart>('generate_signatures'), _generateKeyPair = dylib.lookupFunction('generate_key_pair'), _cryptoCachedDH = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoCachedDHDart>('crypto_cached_dh'), _cryptoComputeDH = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoComputeDHDart>('crypto_compute_dh'), _cryptoRandomBytes = dylib.lookupFunction< Void Function(Int64, Uint32, Uint32), _CryptoRandomBytesDart>('crypto_random_bytes'), _cryptoDefaultSaltLength = dylib.lookupFunction< Void Function(Int64, Uint32), _CryptoDefaultSaltLengthDart>('crypto_default_salt_length'), _cryptoHashPassword = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoHashPasswordDart>('crypto_hash_password'), _cryptoVerifyPassword = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoVerifyPasswordDart>('crypto_verify_password'), _cryptoDeriveSharedSecret = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoVerifyPasswordDart>('crypto_derive_shared_secret'), _cryptoRandomNonce = dylib.lookupFunction('crypto_random_nonce'), _cryptoRandomSharedSecret = dylib.lookupFunction< Void Function(Int64, Uint32), _CryptoRandomSharedSecretDart>('crypto_random_shared_secret'), _cryptoGenerateKeyPair = dylib.lookupFunction< Void Function(Int64, Uint32), _CryptoGenerateKeyPairDart>('crypto_generate_key_pair'), _cryptoGenerateHash = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer), _CryptoGenerateHashDart>('crypto_generate_hash'), _cryptoValidateKeyPair = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoValidateKeyPairDart>('crypto_validate_key_pair'), _cryptoValidateHash = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoValidateHashDart>('crypto_validate_hash'), _cryptoDistance = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoDistanceDart>('crypto_distance'), _cryptoSign = dylib.lookupFunction< Void Function( Int64, Uint32, Pointer, Pointer, Pointer), _CryptoSignDart>('crypto_sign'), _cryptoVerify = dylib.lookupFunction< Void Function( Int64, Uint32, Pointer, Pointer, Pointer), _CryptoVerifyDart>('crypto_verify'), _cryptoAeadOverhead = dylib.lookupFunction('crypto_aead_overhead'), _cryptoDecryptAead = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer, Pointer, Pointer), _CryptoDecryptAeadDart>('crypto_decrypt_aead'), _cryptoEncryptAead = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer, Pointer, Pointer), _CryptoEncryptAeadDart>('crypto_encrypt_aead'), _cryptoCryptNoAuth = dylib.lookupFunction< Void Function( Int64, Uint32, Pointer, Pointer, Pointer), _CryptoCryptNoAuthDart>('crypto_crypt_no_auth'), _now = dylib.lookupFunction('now'), _debug = dylib.lookupFunction), _DebugDart>('debug'), _veilidVersionString = dylib.lookupFunction Function(), _VeilidVersionStringDart>('veilid_version_string'), _veilidVersion = dylib.lookupFunction('veilid_version') { // Get veilid_flutter initializer final initializeVeilidFlutter = _dylib.lookupFunction< Void Function(Pointer<_DartPostCObject>), void Function(Pointer<_DartPostCObject>)>('initialize_veilid_flutter'); initializeVeilidFlutter(NativeApi.postCObject); } // veilid_core shared library final DynamicLibrary _dylib; // Shared library functions final _FreeStringDart _freeString; final _InitializeVeilidCoreDart _initializeVeilidCore; final _ChangeLogLevelDart _changeLogLevel; final _StartupVeilidCoreDart _startupVeilidCore; final _GetVeilidStateDart _getVeilidState; final _AttachDart _attach; final _DetachDart _detach; final _ShutdownVeilidCoreDart _shutdownVeilidCore; final _RoutingContextDart _routingContext; final _ReleaseRoutingContextDart _releaseRoutingContext; final _RoutingContextWithDefaultSafetyDart _routingContextWithDefaultSafety; final _RoutingContextWithSafetyDart _routingContextWithSafety; final _RoutingContextWithSequencingDart _routingContextWithSequencing; final _RoutingContextSafetyDart _routingContextSafety; final _RoutingContextAppCallDart _routingContextAppCall; final _RoutingContextAppMessageDart _routingContextAppMessage; final _RoutingContextCreateDHTRecordDart _routingContextCreateDHTRecord; final _RoutingContextOpenDHTRecordDart _routingContextOpenDHTRecord; final _RoutingContextCloseDHTRecordDart _routingContextCloseDHTRecord; final _RoutingContextDeleteDHTRecordDart _routingContextDeleteDHTRecord; final _RoutingContextGetDHTValueDart _routingContextGetDHTValue; final _RoutingContextSetDHTValueDart _routingContextSetDHTValue; final _RoutingContextWatchDHTValuesDart _routingContextWatchDHTValues; final _RoutingContextCancelDHTWatchDart _routingContextCancelDHTWatch; final _NewPrivateRouteDart _newPrivateRoute; final _NewCustomPrivateRouteDart _newCustomPrivateRoute; final _ImportRemotePrivateRouteDart _importRemotePrivateRoute; final _ReleasePrivateRouteDart _releasePrivateRoute; final _AppCallReplyDart _appCallReply; final _OpenTableDbDart _openTableDb; final _ReleaseTableDbDart _releaseTableDb; final _DeleteTableDbDart _deleteTableDb; final _TableDbGetColumnCountDart _tableDbGetColumnCount; final _TableDbGetKeysDart _tableDbGetKeys; final _TableDbStoreDart _tableDbStore; final _TableDbLoadDart _tableDbLoad; final _TableDbDeleteDart _tableDbDelete; final _TableDbTransactDart _tableDbTransact; final _ReleaseTableDbTransactionDart _releaseTableDbTransaction; final _TableDbTransactionCommitDart _tableDbTransactionCommit; final _TableDbTransactionRollbackDart _tableDbTransactionRollback; final _TableDbTransactionStoreDart _tableDbTransactionStore; final _TableDbTransactionDeleteDart _tableDbTransactionDelete; final _ValidCryptoKindsDart _validCryptoKinds; final _BestCryptoKindDart _bestCryptoKind; final _VerifySignaturesDart _verifySignatures; final _GenerateSignaturesDart _generateSignatures; final _GenerateKeyPairDart _generateKeyPair; final _CryptoCachedDHDart _cryptoCachedDH; final _CryptoComputeDHDart _cryptoComputeDH; final _CryptoRandomBytesDart _cryptoRandomBytes; final _CryptoDefaultSaltLengthDart _cryptoDefaultSaltLength; final _CryptoHashPasswordDart _cryptoHashPassword; final _CryptoVerifyPasswordDart _cryptoVerifyPassword; final void Function(int, int, Pointer, Pointer) _cryptoDeriveSharedSecret; final _CryptoRandomNonceDart _cryptoRandomNonce; final _CryptoRandomSharedSecretDart _cryptoRandomSharedSecret; final _CryptoGenerateKeyPairDart _cryptoGenerateKeyPair; final _CryptoGenerateHashDart _cryptoGenerateHash; final _CryptoValidateKeyPairDart _cryptoValidateKeyPair; final _CryptoValidateHashDart _cryptoValidateHash; final _CryptoDistanceDart _cryptoDistance; final _CryptoSignDart _cryptoSign; final _CryptoVerifyDart _cryptoVerify; final _CryptoAeadOverheadDart _cryptoAeadOverhead; final _CryptoDecryptAeadDart _cryptoDecryptAead; final _CryptoEncryptAeadDart _cryptoEncryptAead; final _CryptoCryptNoAuthDart _cryptoCryptNoAuth; final _NowDart _now; final _DebugDart _debug; final _VeilidVersionStringDart _veilidVersionString; final _VeilidVersionDart _veilidVersion; @override void initializeVeilidCore(Map platformConfigJson) { final nativePlatformConfig = jsonEncode(platformConfigJson).toNativeUtf8(); _initializeVeilidCore(nativePlatformConfig); malloc.free(nativePlatformConfig); } @override void changeLogLevel(String layer, VeilidConfigLogLevel logLevel) { final nativeLogLevel = jsonEncode(logLevel).toNativeUtf8(); final nativeLayer = layer.toNativeUtf8(); _changeLogLevel(nativeLayer, nativeLogLevel); malloc ..free(nativeLayer) ..free(nativeLogLevel); } @override Future> startupVeilidCore(VeilidConfig config) async { final nativeConfig = jsonEncode(config).toNativeUtf8(); final recvStreamPort = ReceivePort('veilid_api_stream'); final sendStreamPort = recvStreamPort.sendPort; final recvPort = ReceivePort('startup_veilid_core'); final sendPort = recvPort.sendPort; _startupVeilidCore( sendPort.nativePort, sendStreamPort.nativePort, nativeConfig); malloc.free(nativeConfig); return await processFutureStream( processStreamJson(VeilidUpdate.fromJson, recvStreamPort), recvPort.first); } @override Future getVeilidState() async { final recvPort = ReceivePort('get_veilid_state'); final sendPort = recvPort.sendPort; _getVeilidState(sendPort.nativePort); return await processFutureJson(VeilidState.fromJson, recvPort.first); } @override Future attach() async { final recvPort = ReceivePort('attach'); final sendPort = recvPort.sendPort; _attach(sendPort.nativePort); return await processFutureVoid(recvPort.first); } @override Future detach() async { final recvPort = ReceivePort('detach'); final sendPort = recvPort.sendPort; _detach(sendPort.nativePort); return await processFutureVoid(recvPort.first); } @override Future shutdownVeilidCore() async { final recvPort = ReceivePort('shutdown_veilid_core'); final sendPort = recvPort.sendPort; _shutdownVeilidCore(sendPort.nativePort); return await processFutureVoid(recvPort.first); } @override Future routingContext() async { final recvPort = ReceivePort('routing_context'); final sendPort = recvPort.sendPort; _routingContext(sendPort.nativePort); final id = await processFuturePlain(recvPort.first); return VeilidRoutingContextFFI._(_Ctx(id, this)); } @override Future newPrivateRoute() async { final recvPort = ReceivePort('new_private_route'); final sendPort = recvPort.sendPort; _newPrivateRoute(sendPort.nativePort); return await processFutureJson(RouteBlob.fromJson, recvPort.first); } @override Future newCustomPrivateRoute( Stability stability, Sequencing sequencing) async { final recvPort = ReceivePort('new_custom_private_route'); final sendPort = recvPort.sendPort; _newCustomPrivateRoute( sendPort.nativePort, jsonEncode(stability).toNativeUtf8(), jsonEncode(sequencing).toNativeUtf8()); return await processFutureJson(RouteBlob.fromJson, recvPort.first); } @override Future importRemotePrivateRoute(Uint8List blob) async { final nativeEncodedBlob = base64UrlNoPadEncode(blob).toNativeUtf8(); final recvPort = ReceivePort('import_remote_private_route'); final sendPort = recvPort.sendPort; _importRemotePrivateRoute(sendPort.nativePort, nativeEncodedBlob); return await processFuturePlain(recvPort.first); } @override Future releasePrivateRoute(String key) async { final nativeEncodedKey = key.toNativeUtf8(); final recvPort = ReceivePort('release_private_route'); final sendPort = recvPort.sendPort; _releasePrivateRoute(sendPort.nativePort, nativeEncodedKey); return await processFutureVoid(recvPort.first); } @override Future appCallReply(String callId, Uint8List message) async { final nativeCallId = callId.toNativeUtf8(); final nativeEncodedMessage = base64UrlNoPadEncode(message).toNativeUtf8(); final recvPort = ReceivePort('app_call_reply'); final sendPort = recvPort.sendPort; _appCallReply(sendPort.nativePort, nativeCallId, nativeEncodedMessage); return await processFutureVoid(recvPort.first); } @override Future openTableDB(String name, int columnCount) async { final recvPort = ReceivePort('open_table_db'); final sendPort = recvPort.sendPort; _openTableDb(sendPort.nativePort, name.toNativeUtf8(), columnCount); final id = await processFuturePlain(recvPort.first); return VeilidTableDBFFI._(_TDB(id, this)); } @override Future deleteTableDB(String name) async { final recvPort = ReceivePort('delete_table_db'); final sendPort = recvPort.sendPort; _deleteTableDb(sendPort.nativePort, name.toNativeUtf8()); return await processFuturePlain(recvPort.first); } @override List validCryptoKinds() { final vckString = _validCryptoKinds(); final vck = jsonDecode(vckString.toDartString()) as List; _freeString(vckString); return vck.map((v) => v as CryptoKind).toList(); } @override Future getCryptoSystem(CryptoKind kind) async { if (!validCryptoKinds().contains(kind)) { throw const VeilidAPIExceptionGeneric('unsupported cryptosystem'); } return VeilidCryptoSystemFFI._(this, kind); } @override Future bestCryptoSystem() async => VeilidCryptoSystemFFI._(this, _bestCryptoKind()); @override Future> verifySignatures(List nodeIds, Uint8List data, List signatures) async { final nativeNodeIds = jsonEncode(nodeIds).toNativeUtf8(); final nativeData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeSignatures = jsonEncode(signatures).toNativeUtf8(); final recvPort = ReceivePort('verify_signatures'); final sendPort = recvPort.sendPort; _verifySignatures( sendPort.nativePort, nativeNodeIds, nativeData, nativeSignatures); return await processFutureJson( jsonListConstructor(TypedKey.fromJson), recvPort.first); } @override Future> generateSignatures( Uint8List data, List keyPairs) async { final nativeData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeKeyPairs = jsonEncode(keyPairs).toNativeUtf8(); final recvPort = ReceivePort('generate_signatures'); final sendPort = recvPort.sendPort; _generateSignatures(sendPort.nativePort, nativeData, nativeKeyPairs); return await processFutureJson( jsonListConstructor(TypedSignature.fromJson), recvPort.first); } @override Timestamp now() { final ts = _now(); return Timestamp(value: BigInt.from(ts)); } @override Future generateKeyPair(CryptoKind kind) async { final recvPort = ReceivePort('generate_key_pair'); final sendPort = recvPort.sendPort; _generateKeyPair(sendPort.nativePort, kind); return await processFutureJson(TypedKeyPair.fromJson, recvPort.first); } @override Future debug(String command) async { final nativeCommand = command.toNativeUtf8(); final recvPort = ReceivePort('debug'); final sendPort = recvPort.sendPort; _debug(sendPort.nativePort, nativeCommand); return processFuturePlain(recvPort.first); } @override String veilidVersionString() { final versionString = _veilidVersionString(); final ret = versionString.toDartString(); _freeString(versionString); return ret; } @override VeilidVersion veilidVersion() { final version = _veilidVersion(); return VeilidVersion( version.major, version.minor, version.patch, ); } }