From cbf8f30b96d40e38c213104f774b3bbdbbbbf939 Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 9 Feb 2022 21:40:01 -0500 Subject: [PATCH] ffi work --- veilid-flutter/ios/Classes/Bridging-Header.h | 1 - .../ios/Classes/SwiftVeilidPlugin.swift | 2 +- veilid-flutter/ios/Classes/bridge_generated.h | 134 --- veilid-flutter/lib/veilid.dart | 910 +++++++++++++----- veilid-flutter/lib/veilid_ffi.dart | 113 ++- 5 files changed, 760 insertions(+), 400 deletions(-) delete mode 100644 veilid-flutter/ios/Classes/bridge_generated.h diff --git a/veilid-flutter/ios/Classes/Bridging-Header.h b/veilid-flutter/ios/Classes/Bridging-Header.h index 55311329..e698229d 100644 --- a/veilid-flutter/ios/Classes/Bridging-Header.h +++ b/veilid-flutter/ios/Classes/Bridging-Header.h @@ -1,2 +1 @@ //#import "GeneratedPluginRegistrant.h" -#import "bridge_generated.h" \ No newline at end of file diff --git a/veilid-flutter/ios/Classes/SwiftVeilidPlugin.swift b/veilid-flutter/ios/Classes/SwiftVeilidPlugin.swift index 4e757642..98fffcca 100644 --- a/veilid-flutter/ios/Classes/SwiftVeilidPlugin.swift +++ b/veilid-flutter/ios/Classes/SwiftVeilidPlugin.swift @@ -4,7 +4,7 @@ import UIKit public class SwiftVeilidPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { // No channel, FFI plugin - print("dummy_value=\(dummy_method_to_enforce_bundling())"); + print("dummy_value"); } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { diff --git a/veilid-flutter/ios/Classes/bridge_generated.h b/veilid-flutter/ios/Classes/bridge_generated.h deleted file mode 100644 index 53a59aef..00000000 --- a/veilid-flutter/ios/Classes/bridge_generated.h +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include - -typedef struct wire_uint_8_list { - uint8_t *ptr; - int32_t len; -} wire_uint_8_list; - -typedef struct wire_StringList { - struct wire_uint_8_list **ptr; - int32_t len; -} wire_StringList; - -typedef struct wire_VeilidConfig { - struct wire_uint_8_list *program_name; - struct wire_uint_8_list *veilid_namespace; - int32_t api_log_level; - bool capabilities__protocol_udp; - bool capabilities__protocol_connect_tcp; - bool capabilities__protocol_accept_tcp; - bool capabilities__protocol_connect_ws; - bool capabilities__protocol_accept_ws; - bool capabilities__protocol_connect_wss; - bool capabilities__protocol_accept_wss; - bool protected_store__allow_insecure_fallback; - bool protected_store__always_use_insecure_storage; - struct wire_uint_8_list *protected_store__insecure_fallback_directory; - bool protected_store__delete; - struct wire_uint_8_list *table_store__directory; - bool table_store__delete; - struct wire_uint_8_list *block_store__directory; - bool block_store__delete; - uint32_t network__max_connections; - uint32_t network__connection_initial_timeout_ms; - struct wire_uint_8_list *network__node_id; - struct wire_uint_8_list *network__node_id_secret; - struct wire_StringList *network__bootstrap; - bool network__upnp; - bool network__natpmp; - bool network__enable_local_peer_scope; - uint32_t network__restricted_nat_retries; - uint32_t network__rpc__concurrency; - uint32_t network__rpc__queue_size; - uint32_t *network__rpc__max_timestamp_behind_ms; - uint32_t *network__rpc__max_timestamp_ahead_ms; - uint32_t network__rpc__timeout_ms; - uint8_t network__rpc__max_route_hop_count; - uint32_t *network__dht__resolve_node_timeout_ms; - uint32_t network__dht__resolve_node_count; - uint32_t network__dht__resolve_node_fanout; - uint32_t network__dht__max_find_node_count; - uint32_t *network__dht__get_value_timeout_ms; - uint32_t network__dht__get_value_count; - uint32_t network__dht__get_value_fanout; - uint32_t *network__dht__set_value_timeout_ms; - uint32_t network__dht__set_value_count; - uint32_t network__dht__set_value_fanout; - uint32_t network__dht__min_peer_count; - uint32_t network__dht__min_peer_refresh_time_ms; - uint32_t network__dht__validate_dial_info_receipt_time_ms; - bool network__protocol__udp__enabled; - uint32_t network__protocol__udp__socket_pool_size; - struct wire_uint_8_list *network__protocol__udp__listen_address; - struct wire_uint_8_list *network__protocol__udp__public_address; - bool network__protocol__tcp__connect; - bool network__protocol__tcp__listen; - uint32_t network__protocol__tcp__max_connections; - struct wire_uint_8_list *network__protocol__tcp__listen_address; - struct wire_uint_8_list *network__protocol__tcp__public_address; - bool network__protocol__ws__connect; - bool network__protocol__ws__listen; - uint32_t network__protocol__ws__max_connections; - struct wire_uint_8_list *network__protocol__ws__listen_address; - struct wire_uint_8_list *network__protocol__ws__path; - struct wire_uint_8_list *network__protocol__ws__url; - bool network__protocol__wss__connect; - uint32_t network__protocol__wss__max_connections; - uint32_t network__leases__max_server_signal_leases; - uint32_t network__leases__max_server_relay_leases; - uint32_t network__leases__max_client_signal_leases; - uint32_t network__leases__max_client_relay_leases; -} wire_VeilidConfig; - -typedef struct WireSyncReturnStruct { - uint8_t *ptr; - int32_t len; - bool success; -} WireSyncReturnStruct; - -typedef int64_t DartPort; - -typedef bool (*DartPostCObjectFnType)(DartPort port_id, void *message); - -void wire_startup_veilid_core(int64_t port_, struct wire_VeilidConfig *config); - -void wire_get_veilid_state(int64_t port_); - -void wire_change_api_log_level(int64_t port_, int32_t log_level); - -void wire_shutdown_veilid_core(int64_t port_); - -void wire_veilid_version_string(int64_t port_); - -void wire_veilid_version(int64_t port_); - -struct wire_StringList *new_StringList(int32_t len); - -uint32_t *new_box_autoadd_u32(uint32_t value); - -struct wire_VeilidConfig *new_box_autoadd_veilid_config(void); - -struct wire_uint_8_list *new_uint_8_list(int32_t len); - -void free_WireSyncReturnStruct(struct WireSyncReturnStruct val); - -void store_dart_post_cobject(DartPostCObjectFnType ptr); - -static int64_t dummy_method_to_enforce_bundling(void) { - int64_t dummy_var = 0; - dummy_var ^= ((int64_t) (void*) wire_startup_veilid_core); - dummy_var ^= ((int64_t) (void*) wire_get_veilid_state); - dummy_var ^= ((int64_t) (void*) wire_change_api_log_level); - dummy_var ^= ((int64_t) (void*) wire_shutdown_veilid_core); - dummy_var ^= ((int64_t) (void*) wire_veilid_version_string); - dummy_var ^= ((int64_t) (void*) wire_veilid_version); - dummy_var ^= ((int64_t) (void*) new_StringList); - dummy_var ^= ((int64_t) (void*) new_box_autoadd_u32); - dummy_var ^= ((int64_t) (void*) new_box_autoadd_veilid_config); - dummy_var ^= ((int64_t) (void*) new_uint_8_list); - dummy_var ^= ((int64_t) (void*) free_WireSyncReturnStruct); - dummy_var ^= ((int64_t) (void*) store_dart_post_cobject); - return dummy_var; -} \ No newline at end of file diff --git a/veilid-flutter/lib/veilid.dart b/veilid-flutter/lib/veilid.dart index 448e18a9..8e2ab46e 100644 --- a/veilid-flutter/lib/veilid.dart +++ b/veilid-flutter/lib/veilid.dart @@ -20,6 +20,8 @@ Object? veilidApiToEncodable(Object? value) { return (value as AttachmentState).json; case VeilidLogLevel: return (value as VeilidLogLevel).json; + case VeilidConfigLogLevel: + return (value as VeilidConfigLogLevel).json; } throw UnsupportedError('Cannot convert to JSON: $value'); } @@ -69,248 +71,703 @@ VeilidLogLevel veilidLogLevelFromJson(String j) { return VeilidLogLevel.values.byName(j.toCamelCase()); } +////////////////////////////////////// +/// VeilidConfigLogLevel + +enum VeilidConfigLogLevel { + off, + error, + warn, + info, + debug, + trace, +} + +extension VeilidConfigLogLevelExt on VeilidConfigLogLevel { + String get json { + return name.toPascalCase(); + } +} + +VeilidConfigLogLevel veilidConfigLogLevelFromJson(String j) { + return VeilidConfigLogLevel.values.byName(j.toCamelCase()); +} + ////////////////////////////////////// /// VeilidConfig +class VeilidConfigHTTPS { + bool enabled; + String listenAddress; + String path; + String? url; + + VeilidConfigHTTPS({ + required this.enabled, + required this.listenAddress, + required this.path, + this.url, + }); + + Map get json { + return { + 'enabled': enabled, + 'listen_address': listenAddress, + 'path': path, + 'url': url + }; + } + + VeilidConfigHTTPS.fromJson(Map json) + : enabled = json['enabled'], + listenAddress = json['listen_address'], + path = json['path'], + url = json['url']; +} + +//////////// + +class VeilidConfigHTTP { + bool enabled; + String listenAddress; + String path; + String? url; + + VeilidConfigHTTP({ + required this.enabled, + required this.listenAddress, + required this.path, + this.url, + }); + + Map get json { + return { + 'enabled': enabled, + 'listen_address': listenAddress, + 'path': path, + 'url': url + }; + } + + VeilidConfigHTTP.fromJson(Map json) + : enabled = json['enabled'], + listenAddress = json['listen_address'], + path = json['path'], + url = json['url']; +} + +//////////// + +class VeilidConfigApplication { + VeilidConfigHTTPS https; + VeilidConfigHTTP http; + + VeilidConfigApplication({ + required this.https, + required this.http, + }); + + Map get json { + return { + 'https': https.json, + 'http': http.json, + }; + } + + VeilidConfigApplication.fromJson(Map json) + : https = VeilidConfigHTTPS.fromJson(json['https']), + http = VeilidConfigHTTP.fromJson(json['http']); +} + +//////////// + +class VeilidConfigUDP { + bool enabled; + int socketPoolSize; + String listenAddress; + String? publicAddress; + + VeilidConfigUDP( + {required this.enabled, + required this.socketPoolSize, + required this.listenAddress, + this.publicAddress}); + + Map get json { + return { + 'enabled': enabled, + 'socket_pool_size': socketPoolSize, + 'listen_address': listenAddress, + 'public_address': publicAddress, + }; + } + + VeilidConfigUDP.fromJson(Map json) + : enabled = json['enabled'], + socketPoolSize = json['socket_pool_size'], + listenAddress = json['listen_address'], + publicAddress = json['publicAddress']; +} + +//////////// + +class VeilidConfigTCP { + bool connect; + bool listen; + int maxConnections; + String listenAddress; + String? publicAddress; + + VeilidConfigTCP( + {required this.connect, + required this.listen, + required this.maxConnections, + required this.listenAddress, + this.publicAddress}); + + Map get json { + return { + 'connect': connect, + 'listen': listen, + 'max_connections': maxConnections, + 'listen_address': listenAddress, + 'public_address': publicAddress, + }; + } + + VeilidConfigTCP.fromJson(Map json) + : connect = json['connect'], + listen = json['listen'], + maxConnections = json['max_connections'], + listenAddress = json['listen_address'], + publicAddress = json['publicAddress']; +} + +//////////// + +class VeilidConfigWS { + bool connect; + bool listen; + int maxConnections; + String listenAddress; + String path; + String? url; + + VeilidConfigWS( + {required this.connect, + required this.listen, + required this.maxConnections, + required this.listenAddress, + required this.path, + this.url}); + + Map get json { + return { + 'connect': connect, + 'listen': listen, + 'max_connections': maxConnections, + 'listen_address': listenAddress, + 'path': path, + 'url': url, + }; + } + + VeilidConfigWS.fromJson(Map json) + : connect = json['connect'], + listen = json['listen'], + maxConnections = json['max_connections'], + listenAddress = json['listen_address'], + path = json['path'], + url = json['url']; +} + +//////////// + +class VeilidConfigWSS { + bool connect; + bool listen; + int maxConnections; + String listenAddress; + String path; + String? url; + + VeilidConfigWSS( + {required this.connect, + required this.listen, + required this.maxConnections, + required this.listenAddress, + required this.path, + this.url}); + + Map get json { + return { + 'connect': connect, + 'listen': listen, + 'max_connections': maxConnections, + 'listen_address': listenAddress, + 'path': path, + 'url': url, + }; + } + + VeilidConfigWSS.fromJson(Map json) + : connect = json['connect'], + listen = json['listen'], + maxConnections = json['max_connections'], + listenAddress = json['listen_address'], + path = json['path'], + url = json['url']; +} + +//////////// + +class VeilidConfigProtocol { + VeilidConfigUDP udp; + VeilidConfigTCP tcp; + VeilidConfigWS ws; + VeilidConfigWSS wss; + + VeilidConfigProtocol({ + required this.udp, + required this.tcp, + required this.ws, + required this.wss, + }); + + Map get json { + return { + 'udp': udp.json, + 'tcp': tcp.json, + 'ws': ws.json, + 'wss': wss.json, + }; + } + + VeilidConfigProtocol.fromJson(Map json) + : udp = VeilidConfigUDP.fromJson(json['udp']), + tcp = VeilidConfigTCP.fromJson(json['tcp']), + ws = VeilidConfigWS.fromJson(json['ws']), + wss = VeilidConfigWSS.fromJson(json['wss']); +} + +//////////// + +class VeilidConfigTLS { + String certificatePath; + String privateKeyPath; + int connectionInitialTimeoutMs; + + VeilidConfigTLS({ + required this.certificatePath, + required this.privateKeyPath, + required this.connectionInitialTimeoutMs, + }); + + Map get json { + return { + 'certificate_path': certificatePath, + 'private_key_path': privateKeyPath, + 'connection_initial_timeout_ms': connectionInitialTimeoutMs, + }; + } + + VeilidConfigTLS.fromJson(Map json) + : certificatePath = json['certificate_path'], + privateKeyPath = json['private_key_path'], + connectionInitialTimeoutMs = json['connection_initial_timeout_ms']; +} + +//////////// + +class VeilidConfigDHT { + int? resolveNodeTimeoutMs; + int resolveNodeCount; + int resolveNodeFanout; + int maxFindNodeCount; + int? getValueTimeoutMs; + int getValueCount; + int getValueFanout; + int? setValueTimeoutMs; + int setValueCount; + int setValueFanout; + int minPeerCount; + int minPeerRefreshTimeMs; + int validateDialInfoReceiptTimeMs; + + VeilidConfigDHT( + {this.resolveNodeTimeoutMs, + required this.resolveNodeCount, + required this.resolveNodeFanout, + required this.maxFindNodeCount, + this.getValueTimeoutMs, + required this.getValueCount, + required this.getValueFanout, + this.setValueTimeoutMs, + required this.setValueCount, + required this.setValueFanout, + required this.minPeerCount, + required this.minPeerRefreshTimeMs, + required this.validateDialInfoReceiptTimeMs}); + + Map get json { + return { + 'resolve_node_timeout_ms': resolveNodeTimeoutMs, + 'resolve_node_count': resolveNodeCount, + 'resolve_node_fanout': resolveNodeFanout, + 'max_find_node_count': maxFindNodeCount, + 'get_value_timeout_ms': getValueTimeoutMs, + 'get_value_count': getValueCount, + 'get_value_fanout': getValueFanout, + 'set_value_timeout_ms': setValueTimeoutMs, + 'set_value_count': setValueCount, + 'set_value_fanout': setValueFanout, + 'min_peer_count': minPeerCount, + 'min_peer_refresh_time_ms': minPeerRefreshTimeMs, + 'validate_dial_info_receipt_time_ms': validateDialInfoReceiptTimeMs + }; + } + + VeilidConfigDHT.fromJson(Map json) + : resolveNodeTimeoutMs = json['resolve_node_timeout_ms'], + resolveNodeCount = json['resolve_node_count'], + resolveNodeFanout = json['resolve_node_fanout'], + maxFindNodeCount = json['max_find_node_count'], + getValueTimeoutMs = json['get_value_timeout_ms'], + getValueCount = json['get_value_count'], + getValueFanout = json['get_value_fanout'], + setValueTimeoutMs = json['set_value_timeout_ms'], + setValueCount = json['set_value_count'], + setValueFanout = json['set_value_fanout'], + minPeerCount = json['min_peer_count'], + minPeerRefreshTimeMs = json['min_peer_refresh_time_ms'], + validateDialInfoReceiptTimeMs = + json['validate_dial_info_receipt_time_ms']; +} + +//////////// + +class VeilidConfigRPC { + int concurrency; + int queueSize; + int? maxTimestampBehindMs; + int? maxTimestampAheadMs; + int timeoutMs; + int maxRouteHopCount; + + VeilidConfigRPC( + {required this.concurrency, + required this.queueSize, + this.maxTimestampBehindMs, + this.maxTimestampAheadMs, + required this.timeoutMs, + required this.maxRouteHopCount}); + + Map get json { + return { + 'concurrency': concurrency, + 'queue_size': queueSize, + 'max_timestamp_behind_ms': maxTimestampBehindMs, + 'max_timestamp_ahead_ms': maxTimestampAheadMs, + 'timeout_ms': timeoutMs, + 'max_route_hop_count': maxRouteHopCount, + }; + } + + VeilidConfigRPC.fromJson(Map json) + : concurrency = json['concurrency'], + queueSize = json['queue_size'], + maxTimestampBehindMs = json['max_timestamp_behind_ms'], + maxTimestampAheadMs = json['max_timestamp_ahead_ms'], + timeoutMs = json['timeout_ms'], + maxRouteHopCount = json['max_route_hop_count']; +} + +//////////// + +class VeilidConfigLeases { + int maxServerSignalLeases; + int maxServerRelayLeases; + int maxClientSignalLeases; + int maxClientRelayLeases; + + VeilidConfigLeases( + {required this.maxServerSignalLeases, + required this.maxServerRelayLeases, + required this.maxClientSignalLeases, + required this.maxClientRelayLeases}); + + Map get json { + return { + 'max_server_signal_leases': maxServerSignalLeases, + 'max_server_relay_leases': maxServerRelayLeases, + 'max_client_signal_leases': maxClientSignalLeases, + 'max_client_relay_leases': maxClientRelayLeases + }; + } + + VeilidConfigLeases.fromJson(Map json) + : maxServerSignalLeases = json['max_server_signal_leases'], + maxServerRelayLeases = json['max_server_relay_leases'], + maxClientSignalLeases = json['max_client_signal_leases'], + maxClientRelayLeases = json['max_client_relay_leases']; +} + +//////////// + +class VeilidConfigNetwork { + int maxConnections; + int connectionInitialTimeoutMs; + String nodeId; + String nodeIdSecret; + List bootstrap; + VeilidConfigRPC rpc; + VeilidConfigDHT dht; + bool upnp; + bool natpmp; + bool enableLocalPeerScope; + int restrictedNatRetries; + VeilidConfigTLS tls; + VeilidConfigApplication application; + VeilidConfigProtocol protocol; + VeilidConfigLeases leases; + + VeilidConfigNetwork({ + required this.maxConnections, + required this.connectionInitialTimeoutMs, + required this.nodeId, + required this.nodeIdSecret, + required this.bootstrap, + required this.rpc, + required this.dht, + required this.upnp, + required this.natpmp, + required this.enableLocalPeerScope, + required this.restrictedNatRetries, + required this.tls, + required this.application, + required this.protocol, + required this.leases, + }); + + Map get json { + return { + 'max_connections': maxConnections, + 'connection_initial_timeout_ms': connectionInitialTimeoutMs, + 'node_id': nodeId, + 'node_id_secret': nodeIdSecret, + 'bootstrap': bootstrap, + 'rpc': rpc.json, + 'dht': dht.json, + 'upnp': upnp, + 'natpmp': natpmp, + 'enable_local_peer_scope': enableLocalPeerScope, + 'restricted_nat_retries': restrictedNatRetries, + 'tls': tls.json, + 'application': application.json, + 'protocol': protocol.json, + 'leases': leases.json, + }; + } + + VeilidConfigNetwork.fromJson(Map json) + : maxConnections = json['max_connections'], + connectionInitialTimeoutMs = json['connection_initial_timeout_ms'], + nodeId = json['node_id'], + nodeIdSecret = json['node_id_secret'], + bootstrap = json['bootstrap'], + rpc = VeilidConfigRPC.fromJson(json['rpc']), + dht = VeilidConfigDHT.fromJson(json['dht']), + upnp = json['upnp'], + natpmp = json['natpmp'], + enableLocalPeerScope = json['enable_local_peer_scope'], + restrictedNatRetries = json['restricted_nat_retries'], + tls = VeilidConfigTLS.fromJson(json['tls']), + application = VeilidConfigApplication.fromJson(json['application']), + protocol = VeilidConfigProtocol.fromJson(json['protocol']), + leases = VeilidConfigLeases.fromJson(json['leases']); +} + +//////////// + +class VeilidConfigTableStore { + String directory; + bool delete; + + VeilidConfigTableStore({ + required this.directory, + required this.delete, + }); + + Map get json { + return {'directory': directory, 'delete': delete}; + } + + VeilidConfigTableStore.fromJson(Map json) + : directory = json['directory'], + delete = json['delete']; +} + +//////////// + +class VeilidConfigBlockStore { + String directory; + bool delete; + + VeilidConfigBlockStore({ + required this.directory, + required this.delete, + }); + + Map get json { + return {'directory': directory, 'delete': delete}; + } + + VeilidConfigBlockStore.fromJson(Map json) + : directory = json['directory'], + delete = json['delete']; +} + +//////////// + +class VeilidConfigProtectedStore { + bool allowInsecureFallback; + bool alwaysUseInsecureStorage; + String insecureFallbackDirectory; + bool delete; + + VeilidConfigProtectedStore({ + required this.allowInsecureFallback, + required this.alwaysUseInsecureStorage, + required this.insecureFallbackDirectory, + required this.delete, + }); + + Map get json { + return { + 'allow_insecure_fallback': allowInsecureFallback, + 'always_use_insecure_storage': alwaysUseInsecureStorage, + 'insecure_fallback_directory': insecureFallbackDirectory, + 'delete': delete, + }; + } + + VeilidConfigProtectedStore.fromJson(Map json) + : allowInsecureFallback = json['allow_insecure_fallback'], + alwaysUseInsecureStorage = json['always_use_insecure_storage'], + insecureFallbackDirectory = json['insecure_fallback_directory'], + delete = json['delete']; +} + +//////////// + +class VeilidConfigCapabilities { + bool protocolUDP; + bool protocolConnectTCP; + bool protocolAcceptTCP; + bool protocolConnectWS; + bool protocolAcceptWS; + bool protocolConnectWSS; + bool protocolAcceptWSS; + + VeilidConfigCapabilities({ + required this.protocolUDP, + required this.protocolConnectTCP, + required this.protocolAcceptTCP, + required this.protocolConnectWS, + required this.protocolAcceptWS, + required this.protocolConnectWSS, + required this.protocolAcceptWSS, + }); + + Map get json { + return { + 'protocol_udp': protocolUDP, + 'protocol_connect_tcp': protocolConnectTCP, + 'protocol_accept_tcp': protocolAcceptTCP, + 'protocol_connect_ws': protocolConnectWS, + 'protocol_accept_ws': protocolAcceptWS, + 'protocol_connect_wss': protocolConnectWSS, + 'protocol_accept_wss': protocolAcceptWSS, + }; + } + + VeilidConfigCapabilities.fromJson(Map json) + : protocolUDP = json['protocol_udp'], + protocolConnectTCP = json['protocol_connect_tcp'], + protocolAcceptTCP = json['protocol_accept_tcp'], + protocolConnectWS = json['protocol_connect_ws'], + protocolAcceptWS = json['protocol_accept_ws'], + protocolConnectWSS = json['protocol_connect_wss'], + protocolAcceptWSS = json['protocol_accept_wss']; +} + +//////////// + class VeilidConfig { String programName; - String veilidNamespace; - VeilidLogLevel apiLogLevel; - bool capabilitiesProtocolUdp; - bool capabilitiesProtocolConnectTcp; - bool capabilitiesProtocolAcceptTcp; - bool capabilitiesProtocolConnectWs; - bool capabilitiesProtocolAcceptWs; - bool capabilitiesProtocolConnectWss; - bool capabilitiesProtocolAcceptWss; - bool protectedStoreAllowInsecureFallback; - bool protectedStoreAlwaysUseInsecureStorage; - String protectedStoreInsecureFallbackDirectory; - bool protectedStoreDelete; - String tableStoreDirectory; - bool tableStoreDelete; - String blockStoreDirectory; - bool blockStoreDelete; - int networkMaxConnections; - int networkConnectionInitialTimeoutMs; - String networkNodeId; - String networkNodeIdSecret; - List networkBootstrap; - bool networkUpnp; - bool networkNatpmp; - bool networkEnableLocalPeerScope; - int networkRestrictedNatRetries; - int networkRpcConcurrency; - int networkRpcQueueSize; - int? networkRpcMaxTimestampBehindMs; - int? networkRpcMaxTimestampAheadMs; - int networkRpcTimeoutMs; - int networkRpcMaxRouteHopCount; - int? networkDhtResolveNodeTimeoutMs; - int networkDhtResolveNodeCount; - int networkDhtResolveNodeFanout; - int networkDhtMaxFindNodeCount; - int? networkDhtGetValueTimeoutMs; - int networkDhtGetValueCount; - int networkDhtGetValueFanout; - int? networkDhtSetValueTimeoutMs; - int networkDhtSetValueCount; - int networkDhtSetValueFanout; - int networkDhtMinPeerCount; - int networkDhtMinPeerRefreshTimeMs; - int networkDhtValidateDialInfoReceiptTimeMs; - bool networkProtocolUdpEnabled; - int networkProtocolUdpSocketPoolSize; - String networkProtocolUdpListenAddress; - String? networkProtocolUdpPublicAddress; - bool networkProtocolTcpConnect; - bool networkProtocolTcpListen; - int networkProtocolTcpMaxConnections; - String networkProtocolTcpListenAddress; - String? networkProtocolTcpPublicAddress; - bool networkProtocolWsConnect; - bool networkProtocolWsListen; - int networkProtocolWsMaxConnections; - String networkProtocolWsListenAddress; - String networkProtocolWsPath; - String? networkProtocolWsUrl; - bool networkProtocolWssConnect; - int networkProtocolWssMaxConnections; - int networkLeasesMaxServerSignalLeases; - int networkLeasesMaxServerRelayLeases; - int networkLeasesMaxClientSignalLeases; - int networkLeasesMaxClientRelayLeases; + String namespace; + VeilidConfigLogLevel apiLogLevel; + VeilidConfigCapabilities capabilities; + VeilidConfigProtectedStore protectedStore; + VeilidConfigTableStore tableStore; + VeilidConfigBlockStore blockStore; + VeilidConfigNetwork network; VeilidConfig({ required this.programName, - required this.veilidNamespace, + required this.namespace, required this.apiLogLevel, - required this.capabilitiesProtocolUdp, - required this.capabilitiesProtocolConnectTcp, - required this.capabilitiesProtocolAcceptTcp, - required this.capabilitiesProtocolConnectWs, - required this.capabilitiesProtocolAcceptWs, - required this.capabilitiesProtocolConnectWss, - required this.capabilitiesProtocolAcceptWss, - required this.protectedStoreAllowInsecureFallback, - required this.protectedStoreAlwaysUseInsecureStorage, - required this.protectedStoreInsecureFallbackDirectory, - required this.protectedStoreDelete, - required this.tableStoreDirectory, - required this.tableStoreDelete, - required this.blockStoreDirectory, - required this.blockStoreDelete, - required this.networkMaxConnections, - required this.networkConnectionInitialTimeoutMs, - required this.networkNodeId, - required this.networkNodeIdSecret, - required this.networkBootstrap, - required this.networkUpnp, - required this.networkNatpmp, - required this.networkEnableLocalPeerScope, - required this.networkRestrictedNatRetries, - required this.networkRpcConcurrency, - required this.networkRpcQueueSize, - this.networkRpcMaxTimestampBehindMs, - this.networkRpcMaxTimestampAheadMs, - required this.networkRpcTimeoutMs, - required this.networkRpcMaxRouteHopCount, - this.networkDhtResolveNodeTimeoutMs, - required this.networkDhtResolveNodeCount, - required this.networkDhtResolveNodeFanout, - required this.networkDhtMaxFindNodeCount, - this.networkDhtGetValueTimeoutMs, - required this.networkDhtGetValueCount, - required this.networkDhtGetValueFanout, - this.networkDhtSetValueTimeoutMs, - required this.networkDhtSetValueCount, - required this.networkDhtSetValueFanout, - required this.networkDhtMinPeerCount, - required this.networkDhtMinPeerRefreshTimeMs, - required this.networkDhtValidateDialInfoReceiptTimeMs, - required this.networkProtocolUdpEnabled, - required this.networkProtocolUdpSocketPoolSize, - required this.networkProtocolUdpListenAddress, - this.networkProtocolUdpPublicAddress, - required this.networkProtocolTcpConnect, - required this.networkProtocolTcpListen, - required this.networkProtocolTcpMaxConnections, - required this.networkProtocolTcpListenAddress, - this.networkProtocolTcpPublicAddress, - required this.networkProtocolWsConnect, - required this.networkProtocolWsListen, - required this.networkProtocolWsMaxConnections, - required this.networkProtocolWsListenAddress, - required this.networkProtocolWsPath, - this.networkProtocolWsUrl, - required this.networkProtocolWssConnect, - required this.networkProtocolWssMaxConnections, - required this.networkLeasesMaxServerSignalLeases, - required this.networkLeasesMaxServerRelayLeases, - required this.networkLeasesMaxClientSignalLeases, - required this.networkLeasesMaxClientRelayLeases, + required this.capabilities, + required this.protectedStore, + required this.tableStore, + required this.blockStore, + required this.network, }); - String get json { - return ""; + Map get json { + return { + 'program_name': programName, + 'namespace': namespace, + 'api_log_level': apiLogLevel.json, + 'capabilities': capabilities.json, + 'protected_store': protectedStore.json, + 'table_store': tableStore.json, + 'block_store': blockStore.json, + 'network': network.json + }; } - factory VeilidConfig.fromJson(String json) { - var parsed = jsonDecode(json); - VeilidConfig({ - programName: parsed["program_name"], - veilidNamespace: parsed["veilid_namespace"], - apiLogLevel: veilidLogLevelFromJson(parsed["api_log_level"]), - capabilitiesProtocolUdp: parsed["capabilities__protocol_udp"], - capabilitiesProtocolConnectTcp: parsed["capabilities__protocol_connect_tcp"], - capabilitiesProtocolAcceptTcp: parsed["capabilities__protocol_accept_tcp"], - capabilitiesProtocolConnectWs: parsed["capabilities__protocol_connect_ws"], - capabilitiesProtocolAcceptWs: parsed["capabilities__protocol_accept_ws"], - capabilitiesProtocolConnectWss: parsed["capabilities__protocol_connect_wss"] - // required this.capabilitiesProtocolAcceptWss, - // required this.protectedStoreAllowInsecureFallback, - // required this.protectedStoreAlwaysUseInsecureStorage, - // required this.protectedStoreInsecureFallbackDirectory, - // required this.protectedStoreDelete, - // required this.tableStoreDirectory, - // required this.tableStoreDelete, - // required this.blockStoreDirectory, - // required this.blockStoreDelete, - // required this.networkMaxConnections, - // required this.networkConnectionInitialTimeoutMs, - // required this.networkNodeId, - // required this.networkNodeIdSecret, - // required this.networkBootstrap, - // required this.networkUpnp, - // required this.networkNatpmp, - // required this.networkEnableLocalPeerScope, - // required this.networkRestrictedNatRetries, - // required this.networkRpcConcurrency, - // required this.networkRpcQueueSize, - // this.networkRpcMaxTimestampBehindMs, - // this.networkRpcMaxTimestampAheadMs, - // required this.networkRpcTimeoutMs, - // required this.networkRpcMaxRouteHopCount, - // this.networkDhtResolveNodeTimeoutMs, - // required this.networkDhtResolveNodeCount, - // required this.networkDhtResolveNodeFanout, - // required this.networkDhtMaxFindNodeCount, - // this.networkDhtGetValueTimeoutMs, - // required this.networkDhtGetValueCount, - // required this.networkDhtGetValueFanout, - // this.networkDhtSetValueTimeoutMs, - // required this.networkDhtSetValueCount, - // required this.networkDhtSetValueFanout, - // required this.networkDhtMinPeerCount, - // required this.networkDhtMinPeerRefreshTimeMs, - // required this.networkDhtValidateDialInfoReceiptTimeMs, - // required this.networkProtocolUdpEnabled, - // required this.networkProtocolUdpSocketPoolSize, - // required this.networkProtocolUdpListenAddress, - // this.networkProtocolUdpPublicAddress, - // required this.networkProtocolTcpConnect, - // required this.networkProtocolTcpListen, - // required this.networkProtocolTcpMaxConnections, - // required this.networkProtocolTcpListenAddress, - // this.networkProtocolTcpPublicAddress, - // required this.networkProtocolWsConnect, - // required this.networkProtocolWsListen, - // required this.networkProtocolWsMaxConnections, - // required this.networkProtocolWsListenAddress, - // required this.networkProtocolWsPath, - // this.networkProtocolWsUrl, - // required this.networkProtocolWssConnect, - // required this.networkProtocolWssMaxConnections, - // required this.networkLeasesMaxServerSignalLeases, - // required this.networkLeasesMaxServerRelayLeases, - // required this.networkLeasesMaxClientSignalLeases, - // required this.networkLeasesMaxClientRelayLeases, - }) - - } + VeilidConfig.fromJson(Map json) + : programName = json['program_name'], + namespace = json['namespace'], + apiLogLevel = json['api_log_level'], + capabilities = VeilidConfigCapabilities.fromJson(json['capabilities']), + protectedStore = + VeilidConfigProtectedStore.fromJson(json['protected_store']), + tableStore = VeilidConfigTableStore.fromJson(json['table_store']), + blockStore = VeilidConfigBlockStore.fromJson(json['block_store']), + network = VeilidConfigNetwork.fromJson(json['network']); } ////////////////////////////////////// /// VeilidUpdate abstract class VeilidUpdate { - factory VeilidUpdate.fromJson(String json) { - var parsed = jsonDecode(json); - switch (parsed["kind"]) { + factory VeilidUpdate.fromJson(Map json) { + switch (json["kind"]) { case "Log": { return VeilidUpdateLog( - veilidLogLevelFromJson(parsed["log_level"]), parsed["message"]); + veilidLogLevelFromJson(json["log_level"]), json["message"]); } case "Attachment": { - return VeilidUpdateAttachment( - attachmentStateFromJson(parsed["state"])); + return VeilidUpdateAttachment(attachmentStateFromJson(json["state"])); } default: { throw VeilidAPIExceptionInternal( - "Invalid VeilidAPIException type: ${parsed['kind']}"); + "Invalid VeilidAPIException type: ${json['kind']}"); } } } @@ -336,15 +793,17 @@ class VeilidState { final AttachmentState attachment; VeilidState(this.attachment); + + VeilidState.fromJson(Map json) + : attachment = attachmentStateFromJson(json['attachment']); } ////////////////////////////////////// /// VeilidAPIException abstract class VeilidAPIException implements Exception { - factory VeilidAPIException.fromJson(String json) { - var parsed = jsonDecode(json); - switch (parsed["kind"]) { + factory VeilidAPIException.fromJson(Map json) { + switch (json["kind"]) { case "NotInitialized": { return VeilidAPIExceptionNotInitialized(); @@ -363,39 +822,38 @@ abstract class VeilidAPIException implements Exception { } case "NodeNotFound": { - return VeilidAPIExceptionNodeNotFound(parsed["node_id"]); + return VeilidAPIExceptionNodeNotFound(json["node_id"]); } case "NoDialInfo": { - return VeilidAPIExceptionNoDialInfo(parsed["node_id"]); + return VeilidAPIExceptionNoDialInfo(json["node_id"]); } case "Internal": { - return VeilidAPIExceptionInternal(parsed["message"]); + return VeilidAPIExceptionInternal(json["message"]); } case "Unimplemented": { - return VeilidAPIExceptionUnimplemented(parsed["unimplemented"]); + return VeilidAPIExceptionUnimplemented(json["unimplemented"]); } case "ParseError": { - return VeilidAPIExceptionParseError( - parsed["message"], parsed["value"]); + return VeilidAPIExceptionParseError(json["message"], json["value"]); } case "InvalidArgument": { return VeilidAPIExceptionInvalidArgument( - parsed["context"], parsed["argument"], parsed["value"]); + json["context"], json["argument"], json["value"]); } case "MissingArgument": { return VeilidAPIExceptionMissingArgument( - parsed["context"], parsed["argument"]); + json["context"], json["argument"]); } default: { throw VeilidAPIExceptionInternal( - "Invalid VeilidAPIException type: ${parsed['kind']}"); + "Invalid VeilidAPIException type: ${json['kind']}"); } } } @@ -536,7 +994,7 @@ abstract class Veilid { Stream startupVeilidCore(VeilidConfig config); Future getVeilidState(); - Future changeApiLogLevel(VeilidLogLevel logLevel); + Future changeApiLogLevel(VeilidConfigLogLevel logLevel); Future shutdownVeilidCore(); String veilidVersionString(); VeilidVersion veilidVersion(); diff --git a/veilid-flutter/lib/veilid_ffi.dart b/veilid-flutter/lib/veilid_ffi.dart index 9faea64c..b7f5908e 100644 --- a/veilid-flutter/lib/veilid_ffi.dart +++ b/veilid-flutter/lib/veilid_ffi.dart @@ -74,39 +74,31 @@ const int MESSAGE_STREAM_CLOSE = 8; Veilid getVeilid() => VeilidFFI(_dylib); // Parse handle async returns -Future processSingleAsyncReturn(Future future) async { +Future processFuturePlain( + T Function(Map)? jsonConstructor, + Future future) { return future.then((value) { final list = value as List; switch (list[0] as int) { case MESSAGE_OK: { - if (list[1] != null) { - throw VeilidAPIExceptionInternal( - "Unexpected MESSAGE_OK value '${list[1]}' where null expected"); + if (list[1] == null) { + throw VeilidAPIExceptionInternal("Null MESSAGE_OK value"); } return list[1] as T; } case MESSAGE_ERR: { - throw VeilidAPIExceptionInternal("Internal API Error: ${value[1]}"); - } - case MESSAGE_OK_JSON: - { - var ret = jsonDecode(list[1] as String); - if (ret != null) { - throw VeilidAPIExceptionInternal( - "Unexpected MESSAGE_OK_JSON value '$ret' where null expected"); - } - return ret as T; + throw VeilidAPIExceptionInternal("Internal API Error: ${list[1]}"); } case MESSAGE_ERR_JSON: { - throw VeilidAPIException.fromJson(value[1] as String); + throw VeilidAPIException.fromJson(jsonDecode(list[1])); } default: { throw VeilidAPIExceptionInternal( - "Unexpected async return message type: ${value[0]}"); + "Unexpected async return message type: ${list[0]}"); } } }).catchError((e) { @@ -118,7 +110,44 @@ Future processSingleAsyncReturn(Future future) async { }); } -Future processSingleAsyncVoid(Future future) async { +Future processFutureJson( + T Function(Map) jsonConstructor, + Future future) { + return future.then((value) { + final list = value as List; + switch (list[0] as int) { + case MESSAGE_ERR: + { + throw VeilidAPIExceptionInternal("Internal API Error: ${list[1]}"); + } + case MESSAGE_OK_JSON: + { + if (list[1] == null) { + throw VeilidAPIExceptionInternal("Null MESSAGE_OK_JSON value"); + } + var ret = jsonDecode(list[1] as String); + return jsonConstructor(ret); + } + case MESSAGE_ERR_JSON: + { + throw VeilidAPIException.fromJson(jsonDecode(list[1])); + } + default: + { + throw VeilidAPIExceptionInternal( + "Unexpected async return message type: ${list[0]}"); + } + } + }).catchError((e) { + // Wrap all other errors in VeilidAPIExceptionInternal + throw VeilidAPIExceptionInternal(e.toString()); + }, test: (e) { + // Pass errors that are already VeilidAPIException through without wrapping + return e is! VeilidAPIException; + }); +} + +Future processFutureVoid(Future future) { return future.then((value) { final list = value as List; switch (list[0] as int) { @@ -132,7 +161,7 @@ Future processSingleAsyncVoid(Future future) async { } case MESSAGE_ERR: { - throw VeilidAPIExceptionInternal("Internal API Error: ${value[1]}"); + throw VeilidAPIExceptionInternal("Internal API Error: ${list[1]}"); } case MESSAGE_OK_JSON: { @@ -145,12 +174,12 @@ Future processSingleAsyncVoid(Future future) async { } case MESSAGE_ERR_JSON: { - throw VeilidAPIException.fromJson(value[1] as String); + throw VeilidAPIException.fromJson(jsonDecode(list[1] as String)); } default: { throw VeilidAPIExceptionInternal( - "Unexpected async return message type: ${value[0]}"); + "Unexpected async return message type: ${list[0]}"); } } }).catchError((e) { @@ -202,32 +231,40 @@ class VeilidFFI implements Veilid { } @override - Stream startupVeilidCore(VeilidConfig config) async* {} - - @override - Future getVeilidState() async { - final recv_port = ReceivePort("shutdown_veilid_core"); - final send_port = recv_port.sendPort; - _shutdownVeilidCore(send_port.nativePort); - processSingleAsyncReturn(recv_port.single); + Stream startupVeilidCore(VeilidConfig config) { + var nativeConfig = jsonEncode(config.json, toEncodable: veilidApiToEncodable).toNativeUtf8(); + final recvPort = ReceivePort("startup_veilid_core"); + final sendPort = recvPort.sendPort; + _startupVeilidCore(sendPort.nativePort, nativeConfig); + malloc.free(nativeConfig); +xxx + return processStreamJson(VeilidUpdate.fromJson, recvPort); } @override - Future changeApiLogLevel(VeilidLogLevel logLevel) async { - var nativeLogLevel = jsonEncode(logLevel).toNativeUtf8(); - final recv_port = ReceivePort("change_api_log_level"); - final send_port = recv_port.sendPort; - _changeApiLogLevel(send_port.nativePort, nativeLogLevel); + Future getVeilidState() async { + final recvPort = ReceivePort("get_veilid_state"); + final sendPort = recvPort.sendPort; + _shutdownVeilidCore(sendPort.nativePort); + return processFutureJson(VeilidState.fromJson, recvPort.single); + } + + @override + Future changeApiLogLevel(VeilidConfigLogLevel logLevel) async { + var nativeLogLevel = logLevel.json.toNativeUtf8(); + final recvPort = ReceivePort("change_api_log_level"); + final sendPort = recvPort.sendPort; + _changeApiLogLevel(sendPort.nativePort, nativeLogLevel); malloc.free(nativeLogLevel); - processSingleAsyncVoid(recv_port.single); + return processFutureVoid(recvPort.single); } @override Future shutdownVeilidCore() async { - final recv_port = ReceivePort("shutdown_veilid_core"); - final send_port = recv_port.sendPort; - _shutdownVeilidCore(send_port.nativePort); - processSingleAsyncVoid(recv_port.single); + final recvPort = ReceivePort("shutdown_veilid_core"); + final sendPort = recvPort.sendPort; + _shutdownVeilidCore(sendPort.nativePort); + return processFutureVoid(recvPort.single); } @override