diff --git a/app/lib/config/init.dart b/app/lib/config/init.dart index 9e675f22..bd8ed692 100644 --- a/app/lib/config/init.dart +++ b/app/lib/config/init.dart @@ -216,9 +216,9 @@ Future postInit(BuildContext context, Ref ref, bool appStart) async { } try { - ref.redux(nearbyDevicesProvider).dispatchAsync(StartMulticastListener()); // ignore: unawaited_futures + ref.redux(nearbyDevicesProvider).dispatchAsync(StartDiscoveryListener()); // ignore: unawaited_futures } catch (e) { - _logger.warning('Starting multicast listener failed', e); + _logger.warning('Starting discovery listener failed', e); } // ignore: dead_code diff --git a/app/lib/pages/tabs/settings_tab_controller.dart b/app/lib/pages/tabs/settings_tab_controller.dart index 2e53cf33..f4966f8b 100644 --- a/app/lib/pages/tabs/settings_tab_controller.dart +++ b/app/lib/pages/tabs/settings_tab_controller.dart @@ -135,7 +135,7 @@ class SettingsTabController extends ReduxNotifier { state.portController.text = newServerState.port.toString(); await _settingsService.setAlias(newServerState.alias); await _settingsService.setPort(newServerState.port); - external(_isolateController).dispatch(IsolateSendMulticastRestartListenerAction()); + external(_isolateController).dispatch(IsolateDiscoveryRestartAction()); external(_localIpService).dispatchAsync(FetchLocalIpAction()); // ignore: unawaited_futures } } catch (e) { diff --git a/app/lib/provider/network/nearby_devices_provider.dart b/app/lib/provider/network/nearby_devices_provider.dart index ab05dae1..72ee9d3c 100644 --- a/app/lib/provider/network/nearby_devices_provider.dart +++ b/app/lib/provider/network/nearby_devices_provider.dart @@ -44,14 +44,17 @@ class NearbyDevicesService extends ReduxNotifier { ); } -/// Binds the UDP port and listens for incoming announcements. +/// Starts the discovery (which binds the UDP port) and registers every +/// confirmed device: answered announcements, scan results and devices fed in +/// via [IsolateDiscoveryAddDeviceAction] all arrive on this one stream. /// This should run forever as long as the app is running. -class StartMulticastListener extends AsyncReduxAction { +class StartDiscoveryListener extends AsyncReduxAction { @override Future reduce() async { - await for (final device in notifier._isolateController.state.multicastDiscovery!.receiveFromIsolate) { + final stream = external(notifier._isolateController).dispatchTakeResult(IsolateDiscoveryListenAction()); + await for (final device in stream) { await dispatchAsync(RegisterDeviceAction(device)); - notifier._discoveryLogger.addLog('[DISCOVER/UDP] ${device.alias} (${device.ip}, model: ${device.deviceModel})'); + notifier._discoveryLogger.addLog('[DISCOVER] ${device.alias} (${device.ip}, model: ${device.deviceModel})'); } return state; } @@ -138,7 +141,7 @@ class UnregisterSignalingDeviceAction extends ReduxAction { @override NearbyDevicesState reduce() { - external(notifier._isolateController).dispatch(IsolateSendMulticastAnnouncementAction()); + external(notifier._isolateController).dispatch(IsolateDiscoveryAnnouncementAction()); return state; } } @@ -166,18 +169,17 @@ class StartLegacyScan extends AsyncReduxAction(); return state.copyWith( runningIps: state.runningIps.where((ip) => ip != localIp).toSet(), @@ -201,17 +203,16 @@ class StartFavoriteScan extends AsyncReduxAction (e.ip, e.port)).toList(), - https: https, - ), - ); - - await for (final device in stream) { - notifier._discoveryLogger.addLog('[DISCOVER/TCP] ${device.alias} (${device.ip}, model: ${device.deviceModel})'); - await dispatchAsync(RegisterDeviceAction(device)); - } + // The found devices arrive on the [StartDiscoveryListener] stream; + // this stream only signals when every favorite has been probed. + await external(notifier._isolateController) + .dispatchTakeResult( + IsolateDiscoveryFavoriteScanAction( + favorites: devices.map((e) => (e.ip, e.port)).toList(), + https: https, + ), + ) + .drain(); return state.copyWith( runningFavoriteScan: false, diff --git a/app/lib/provider/network/server/controller/receive_controller.dart b/app/lib/provider/network/server/controller/receive_controller.dart index 219dd561..2f2ac6d8 100644 --- a/app/lib/provider/network/server/controller/receive_controller.dart +++ b/app/lib/provider/network/server/controller/receive_controller.dart @@ -13,7 +13,6 @@ import 'package:localsend_app/provider/device_info_provider.dart'; import 'package:localsend_app/provider/favorites_provider.dart'; import 'package:localsend_app/provider/http_provider.dart'; import 'package:localsend_app/provider/logging/discovery_logs_provider.dart'; -import 'package:localsend_app/provider/network/nearby_devices_provider.dart'; import 'package:localsend_app/provider/network/send_provider.dart'; import 'package:localsend_app/provider/network/server/server_provider.dart'; import 'package:localsend_app/provider/network/server/server_utils.dart'; @@ -59,7 +58,11 @@ class ReceiveController { return; } - await server.ref.redux(nearbyDevicesProvider).dispatchAsync(RegisterDeviceAction(event.info.toDevice(event.ip, HttpDiscovery(ip: event.ip)))); + // Feed the device into the discovery store; it comes back (and is + // registered) via the [StartDiscoveryListener] stream. + server.ref + .redux(parentIsolateProvider) + .dispatch(IsolateDiscoveryAddDeviceAction(device: event.info.toDevice(event.ip, HttpDiscovery(ip: event.ip)))); server.ref.notifier(discoveryLoggerProvider).addLog('[DISCOVER/TCP] Received "/register" HTTP request: ${event.info.alias} (${event.ip})'); } diff --git a/packages/core/src/discovery/mod.rs b/packages/core/src/discovery/mod.rs index 16a1dfab..0a76e609 100644 --- a/packages/core/src/discovery/mod.rs +++ b/packages/core/src/discovery/mod.rs @@ -15,6 +15,7 @@ use futures_util::StreamExt; use std::collections::HashSet; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::{Duration, SystemTime}; use store::DeviceStore; use tokio::sync::{mpsc, oneshot}; @@ -105,6 +106,10 @@ struct DiscoveryState { store: DeviceStore, event_tx: Option>, + /// Whether announcements of other devices are answered, see + /// [`DiscoveryHandle::set_answer_announcements`]. + answering: AtomicBool, + /// The interface addresses a subnet scan is currently running for. scanning: std::sync::Mutex>, } @@ -279,6 +284,16 @@ impl DiscoveryHandle { Ok(found) } + /// Sets whether announcements of other devices are answered with a + /// register request (the answer is what makes the announcing device + /// enter the store). On by default. + /// + /// An application whose server is not running turns this off: the answer + /// would advertise an HTTP port that nobody listens on. + pub fn set_answer_announcements(&self, answer: bool) { + self.state.answering.store(answer, Ordering::Relaxed); + } + /// Puts a device confirmed outside of discovery into the store, e.g. one /// that answered an announcement by registering with this device's HTTP /// server. The confirmation is emitted as `Discovered` or `Updated`; @@ -353,6 +368,7 @@ pub async fn start(config: DiscoveryConfig, stop_rx: oneshot::Receiver<()>) -> D timeout: config.timeout, store: DeviceStore::new(), event_tx: config.event_tx, + answering: AtomicBool::new(true), scanning: std::sync::Mutex::new(HashSet::new()), }); @@ -362,6 +378,9 @@ pub async fn start(config: DiscoveryConfig, stop_rx: oneshot::Receiver<()>) -> D let state = state.clone(); async move { while let Some(event) = multicast_rx.recv().await { + if !state.answering.load(Ordering::Relaxed) { + continue; + } let MulticastEvent::Discovered { ip, scope_id, diff --git a/packages/localsend_isolates/lib/rust/api/crypto.dart b/packages/localsend_isolates/lib/rust/api/crypto.dart index 98691793..d5e7ad7d 100644 --- a/packages/localsend_isolates/lib/rust/api/crypto.dart +++ b/packages/localsend_isolates/lib/rust/api/crypto.dart @@ -10,6 +10,8 @@ import 'package:localsend_isolates/rust/frb_generated.dart'; part 'crypto.freezed.dart'; +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone` + Future verifyCert({required String cert, required String publicKey}) => RustLib.instance.api.crateApiCryptoVerifyCert(cert: cert, publicKey: publicKey); diff --git a/packages/localsend_isolates/lib/rust/api/discovery.dart b/packages/localsend_isolates/lib/rust/api/discovery.dart new file mode 100644 index 00000000..67a53474 --- /dev/null +++ b/packages/localsend_isolates/lib/rust/api/discovery.dart @@ -0,0 +1,188 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:localsend_isolates/rust/api/model.dart'; +import 'package:localsend_isolates/rust/api/server.dart'; +import 'package:localsend_isolates/rust/frb_generated.dart'; + +// These functions are ignored because they are not marked as `pub`: `rs_device` + +/// Starts the discovery: binds the UDP multicast sockets on all usable +/// network interfaces, answers announcements of other devices with an HTTP +/// register request, and keeps the store of confirmed devices. +/// +/// Announcements are received from the IPv4 [group] and, as a LocalSend +/// extension, from the (currently hardcoded) IPv6 group `ff12::fd3a:e420`. +/// +/// [port] is used both to bind the multicast sockets and as the HTTP server +/// port announced to other devices. [cert_pem] and [private_key_pem] are this +/// device's TLS identity, sent as client certificate with every register +/// request; [fingerprint] must be the certificate's SHA-256 fingerprint. +/// +/// Nothing is announced until [RsDiscovery::announce] is called. +/// +/// Cannot fail besides an invalid [group]: when no multicast socket could be +/// bound (e.g. the port is taken by another process), discovery still runs +/// without multicast — see [RsDiscovery::multicast_error] — and still learns +/// about devices through [RsDiscovery::discover], [RsDiscovery::scan_subnet] +/// and [RsDiscovery::add_device]. +Future startDiscovery({ + required String group, + required int port, + List? networkWhitelist, + List? networkBlacklist, + required String alias, + required String version, + String? deviceModel, + DeviceType? deviceType, + required String fingerprint, + required ProtocolTypeV2 protocol, + required bool download, + required String certPem, + required String privateKeyPem, + required BigInt timeoutMs, +}) => RustLib.instance.api.crateApiDiscoveryStartDiscovery( + group: group, + port: port, + networkWhitelist: networkWhitelist, + networkBlacklist: networkBlacklist, + alias: alias, + version: version, + deviceModel: deviceModel, + deviceType: deviceType, + fingerprint: fingerprint, + protocol: protocol, + download: download, + certPem: certPem, + privateKeyPem: privateKeyPem, + timeoutMs: timeoutMs, +); + +// Rust type: RustOpaqueMoi> +abstract class RsDiscovery implements RustOpaqueInterface { + /// Puts a device confirmed outside of the discovery into the store, e.g. + /// one that answered an announcement by registering with this device's + /// HTTP server. The device is emitted on [RsDiscovery::listen]. + Future addDevice({required RsDiscoveredDevice device}); + + /// Announces this device to the network, which makes every other LocalSend + /// device on it register with this device over HTTP. + /// + /// Devices registering in response arrive at the application as server + /// events, not here: feed them back via [RsDiscovery::add_device]. + /// + /// Returns once the whole announcement burst has been sent, which takes a + /// few seconds, or immediately once the discovery has been stopped or + /// multicast is unavailable. + Future announce(); + + /// Discovers a device at a known address, e.g. a favorite or a peer that + /// multicast does not reach, by sending it a register request. + /// + /// The confirmed device is also emitted on [RsDiscovery::listen]. + /// Returns `None` when the device did not answer or answered with this + /// device's own fingerprint (i.e. the device discovered itself). + Future discover({required String host, required int port, required ProtocolTypeV2 protocol}); + + /// Emits a [RsDiscoveredDevice] for every device confirmation until the + /// discovery is stopped. Can only be listened to once. + Stream listen(); + + /// The reason the multicast sockets could not be bound, when they could + /// not. Discovery then neither hears nor sends announcements. + Future multicastError(); + + /// Scans the `/24` subnet of the local interface address [interface_ip] + /// by sending every other host a register request, for networks that do + /// not carry multicast. + /// + /// The found devices are emitted on [RsDiscovery::listen] as they answer; + /// this method returns once the whole scan has finished. At most one scan + /// runs per interface: a call for an address that is still being scanned + /// returns immediately. + Future scanSubnet({required String interfaceIp, required int port, required ProtocolTypeV2 protocol}); + + /// Sets whether announcements of other devices are answered with a + /// register request (the answer is what makes the announcing device enter + /// the store). On by default. + /// + /// Turned off while the HTTP server is not running: the answer would + /// advertise a port that nobody listens on. + Future setAnswerAnnouncements({required bool answer}); + + /// Stops the discovery, which also ends the [RsDiscovery::listen] stream. + /// Returns after all sockets are closed, so the port can be bound again. + Future stop(); +} + +/// A device that was confirmed over HTTP by the discovery: it answered a +/// register request, or its register request was accepted by our server and +/// was fed back via [RsDiscovery::add_device]. +/// +/// Emitted on [RsDiscovery::listen] for every confirmation, so a device +/// re-appears whenever it re-announces itself or is re-discovered. +class RsDiscoveredDevice { + final String alias; + + /// Protocol version (major.minor) implemented by the device. + final String version; + final String? deviceModel; + final DeviceType? deviceType; + + /// Fingerprint identifying the device; devices are deduplicated by it. + final String fingerprint; + + /// The host the device was confirmed on: an IP address, or the scoped + /// form `fe80::1%3` for link-local IPv6 (the Rust HTTP client accepts + /// both back as a host). + final String host; + + /// The port of the device's HTTP server. + final int port; + final ProtocolTypeV2 protocol; + + /// Whether the device's download API is active. + final bool download; + + const RsDiscoveredDevice({ + required this.alias, + required this.version, + this.deviceModel, + this.deviceType, + required this.fingerprint, + required this.host, + required this.port, + required this.protocol, + required this.download, + }); + + @override + int get hashCode => + alias.hashCode ^ + version.hashCode ^ + deviceModel.hashCode ^ + deviceType.hashCode ^ + fingerprint.hashCode ^ + host.hashCode ^ + port.hashCode ^ + protocol.hashCode ^ + download.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is RsDiscoveredDevice && + runtimeType == other.runtimeType && + alias == other.alias && + version == other.version && + deviceModel == other.deviceModel && + deviceType == other.deviceType && + fingerprint == other.fingerprint && + host == other.host && + port == other.port && + protocol == other.protocol && + download == other.download; +} diff --git a/packages/localsend_isolates/lib/rust/api/multicast.dart b/packages/localsend_isolates/lib/rust/api/multicast.dart deleted file mode 100644 index 719008b5..00000000 --- a/packages/localsend_isolates/lib/rust/api/multicast.dart +++ /dev/null @@ -1,141 +0,0 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. - -// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import - -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -import 'package:localsend_isolates/rust/api/model.dart'; -import 'package:localsend_isolates/rust/api/server.dart'; -import 'package:localsend_isolates/rust/frb_generated.dart'; - -/// Starts UDP multicast discovery: binds the multicast sockets on all usable -/// network interfaces and listens for announcements of other devices. -/// -/// Announcements are sent to the IPv4 [group] and, as a LocalSend extension, -/// to the (currently hardcoded) IPv6 group `ff12::fd3a:e420`. -/// -/// [port] is used both to bind the multicast sockets and as the HTTP server -/// port announced to other devices. -/// -/// Nothing is announced until [RsMulticast::announce] is called. -/// -/// Fails when [group] is not a valid IPv4 address or when no network -/// interface could be used at all. -Future startMulticast({ - required String group, - required int port, - List? networkWhitelist, - List? networkBlacklist, - required String alias, - required String version, - String? deviceModel, - DeviceType? deviceType, - required String fingerprint, - required ProtocolTypeV2 protocol, - required bool download, -}) => RustLib.instance.api.crateApiMulticastStartMulticast( - group: group, - port: port, - networkWhitelist: networkWhitelist, - networkBlacklist: networkBlacklist, - alias: alias, - version: version, - deviceModel: deviceModel, - deviceType: deviceType, - fingerprint: fingerprint, - protocol: protocol, - download: download, -); - -// Rust type: RustOpaqueMoi> -abstract class RsMulticast implements RustOpaqueInterface { - /// Announces this device to the network, which makes every other LocalSend - /// device on it register with this device over HTTP. - /// - /// Returns once the whole announcement burst has been sent, which takes a - /// few seconds, or immediately once discovery has been stopped. - Future announce(); - - /// Emits a [RsMulticastDiscovered] for every announcement received from - /// another device until discovery is stopped. - /// Can only be listened to once. - Stream listen(); - - /// Stops discovery, which also ends the [RsMulticast::listen] stream. - /// Returns after all sockets are closed, so the port can be bound again. - Future stop(); -} - -class MulticastMessageV2 { - final String alias; - final String version; - final String? deviceModel; - final DeviceType? deviceType; - final String fingerprint; - final int port; - final ProtocolTypeV2 protocol; - final bool download; - - const MulticastMessageV2({ - required this.alias, - required this.version, - this.deviceModel, - this.deviceType, - required this.fingerprint, - required this.port, - required this.protocol, - required this.download, - }); - - @override - int get hashCode => - alias.hashCode ^ - version.hashCode ^ - deviceModel.hashCode ^ - deviceType.hashCode ^ - fingerprint.hashCode ^ - port.hashCode ^ - protocol.hashCode ^ - download.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is MulticastMessageV2 && - runtimeType == other.runtimeType && - alias == other.alias && - version == other.version && - deviceModel == other.deviceModel && - deviceType == other.deviceType && - fingerprint == other.fingerprint && - port == other.port && - protocol == other.protocol && - download == other.download; -} - -/// Another device announced itself via UDP multicast. -/// -/// The peer expects to be answered with an HTTP register request. -class RsMulticastDiscovered { - /// The address the announcement was sent from. The peer's HTTP server is - /// reachable at this address on `message.port`. - /// - /// A link-local IPv6 source carries its interface scope as `fe80::1%3`, - /// which the Rust HTTP client accepts back as a host. - final String ip; - - /// The announcement as it was received. - final MulticastMessageV2 message; - - const RsMulticastDiscovered({ - required this.ip, - required this.message, - }); - - @override - int get hashCode => ip.hashCode ^ message.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || other is RsMulticastDiscovered && runtimeType == other.runtimeType && ip == other.ip && message == other.message; -} diff --git a/packages/localsend_isolates/lib/rust/frb_generated.dart b/packages/localsend_isolates/lib/rust/frb_generated.dart index c3b56afd..be5863ee 100644 --- a/packages/localsend_isolates/lib/rust/frb_generated.dart +++ b/packages/localsend_isolates/lib/rust/frb_generated.dart @@ -9,10 +9,10 @@ import 'dart:convert'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; import 'package:localsend_isolates/rust/api/cancel.dart'; import 'package:localsend_isolates/rust/api/crypto.dart'; +import 'package:localsend_isolates/rust/api/discovery.dart'; import 'package:localsend_isolates/rust/api/http.dart'; import 'package:localsend_isolates/rust/api/logging.dart'; import 'package:localsend_isolates/rust/api/model.dart'; -import 'package:localsend_isolates/rust/api/multicast.dart'; import 'package:localsend_isolates/rust/api/server.dart'; import 'package:localsend_isolates/rust/api/stream.dart'; import 'package:localsend_isolates/rust/api/webrtc.dart'; @@ -74,7 +74,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.12.0'; @override - int get rustContentHash => -286605518; + int get rustContentHash => -895476497; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( stem: 'rust_lib_localsend_app', @@ -112,6 +112,32 @@ abstract class RustLibApi extends BaseApi { void crateApiCancelRsCancellationTokenCancel({required RsCancellationToken that}); + Future crateApiDiscoveryRsDiscoveryAddDevice({required RsDiscovery that, required RsDiscoveredDevice device}); + + Future crateApiDiscoveryRsDiscoveryAnnounce({required RsDiscovery that}); + + Future crateApiDiscoveryRsDiscoveryDiscover({ + required RsDiscovery that, + required String host, + required int port, + required ProtocolTypeV2 protocol, + }); + + Stream crateApiDiscoveryRsDiscoveryListen({required RsDiscovery that}); + + Future crateApiDiscoveryRsDiscoveryMulticastError({required RsDiscovery that}); + + Future crateApiDiscoveryRsDiscoveryScanSubnet({ + required RsDiscovery that, + required String interfaceIp, + required int port, + required ProtocolTypeV2 protocol, + }); + + Future crateApiDiscoveryRsDiscoverySetAnswerAnnouncements({required RsDiscovery that, required bool answer}); + + Future crateApiDiscoveryRsDiscoveryStop({required RsDiscovery that}); + Future crateApiHttpRsHttpClientCancel({ required RsHttpClient that, required ProtocolType protocol, @@ -186,12 +212,6 @@ abstract class RustLibApi extends BaseApi { Future crateApiServerRsHttpServerStop({required RsHttpServer that}); - Future crateApiMulticastRsMulticastAnnounce({required RsMulticast that}); - - Stream crateApiMulticastRsMulticastListen({required RsMulticast that}); - - Future crateApiMulticastRsMulticastStop({required RsMulticast that}); - Future crateApiWebrtcRtcFileReceiverGetFileId({required RtcFileReceiver that}); Stream crateApiWebrtcRtcFileReceiverReceive({required RtcFileReceiver that}); @@ -251,7 +271,7 @@ abstract class RustLibApi extends BaseApi { Stream crateApiCryptoHashFile({String? path, int? fileDescriptor, Uint8List? bytes, required RsCancellationToken cancelToken}); - Future crateApiMulticastStartMulticast({ + Future crateApiDiscoveryStartDiscovery({ required String group, required int port, List? networkWhitelist, @@ -263,6 +283,9 @@ abstract class RustLibApi extends BaseApi { required String fingerprint, required ProtocolTypeV2 protocol, required bool download, + required String certPem, + required String privateKeyPem, + required BigInt timeoutMs, }); Future crateApiServerStartServer({ @@ -328,6 +351,12 @@ abstract class RustLibApi extends BaseApi { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsCancellationTokenPtr; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_RsDiscovery; + + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsDiscovery; + + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsDiscoveryPtr; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_RsHttpClient; RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsHttpClient; @@ -339,12 +368,6 @@ abstract class RustLibApi extends BaseApi { RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsHttpServer; CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsHttpServerPtr; - - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_RsMulticast; - - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsMulticast; - - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsMulticastPtr; } class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @@ -533,6 +556,229 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ['that'], ); + @override + Future crateApiDiscoveryRsDiscoveryAddDevice({required RsDiscovery that, required RsDiscoveredDevice device}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + sse_encode_box_autoadd_rs_discovered_device(device, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 7, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryAddDeviceConstMeta, + argValues: [that, device], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryAddDeviceConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_add_device', + argNames: ['that', 'device'], + ); + + @override + Future crateApiDiscoveryRsDiscoveryAnnounce({required RsDiscovery that}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryAnnounceConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryAnnounceConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_announce', + argNames: ['that'], + ); + + @override + Future crateApiDiscoveryRsDiscoveryDiscover({ + required RsDiscovery that, + required String host, + required int port, + required ProtocolTypeV2 protocol, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + sse_encode_String(host, serializer); + sse_encode_u_16(port, serializer); + sse_encode_protocol_type_v_2(protocol, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_box_autoadd_rs_discovered_device, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryDiscoverConstMeta, + argValues: [that, host, port, protocol], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryDiscoverConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_discover', + argNames: ['that', 'host', 'port', 'protocol'], + ); + + @override + Stream crateApiDiscoveryRsDiscoveryListen({required RsDiscovery that}) { + final sink = RustStreamSink(); + unawaited( + handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + sse_encode_StreamSink_rs_discovered_device_Sse(sink, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 10, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryListenConstMeta, + argValues: [that, sink], + apiImpl: this, + ), + ), + ); + return sink.stream; + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryListenConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_listen', + argNames: ['that', 'sink'], + ); + + @override + Future crateApiDiscoveryRsDiscoveryMulticastError({required RsDiscovery that}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_opt_String, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryMulticastErrorConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryMulticastErrorConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_multicast_error', + argNames: ['that'], + ); + + @override + Future crateApiDiscoveryRsDiscoveryScanSubnet({ + required RsDiscovery that, + required String interfaceIp, + required int port, + required ProtocolTypeV2 protocol, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + sse_encode_String(interfaceIp, serializer); + sse_encode_u_16(port, serializer); + sse_encode_protocol_type_v_2(protocol, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 12, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryScanSubnetConstMeta, + argValues: [that, interfaceIp, port, protocol], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryScanSubnetConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_scan_subnet', + argNames: ['that', 'interfaceIp', 'port', 'protocol'], + ); + + @override + Future crateApiDiscoveryRsDiscoverySetAnswerAnnouncements({required RsDiscovery that, required bool answer}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + sse_encode_bool(answer, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoverySetAnswerAnnouncementsConstMeta, + argValues: [that, answer], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoverySetAnswerAnnouncementsConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_set_answer_announcements', + argNames: ['that', 'answer'], + ); + + @override + Future crateApiDiscoveryRsDiscoveryStop({required RsDiscovery that}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(that, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: null, + ), + constMeta: kCrateApiDiscoveryRsDiscoveryStopConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiDiscoveryRsDiscoveryStopConstMeta => const TaskConstMeta( + debugName: 'RsDiscovery_stop', + argNames: ['that'], + ); + @override Future crateApiHttpRsHttpClientCancel({ required RsHttpClient that, @@ -550,7 +796,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ip, serializer); sse_encode_u_16(port, serializer); sse_encode_String(sessionId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 7, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -591,7 +837,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(publicKey, serializer); sse_encode_opt_String(pin, serializer); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(cancelToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_prepare_upload_result, @@ -626,7 +872,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(ip, serializer); sse_encode_u_16(port, serializer); sse_encode_box_autoadd_register_dto(payload, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_result_with_public_key_register_response_dto, @@ -683,7 +929,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); sse_encode_u_64(contentLength, serializer); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(cancelToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 10, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -726,7 +972,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 11, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -753,7 +999,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); sse_encode_String(fileId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 12, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -780,7 +1026,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); sse_encode_String(fileId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -808,7 +1054,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_StreamSink_rs_server_event_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 14, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -845,7 +1091,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(fileId, serializer); sse_encode_opt_String(path, serializer); sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 15, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -885,7 +1131,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(path, serializer); sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); sse_encode_u_64(fileSize, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 16, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -914,7 +1160,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_String(sessionId, serializer); sse_encode_bool(accept, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -940,7 +1186,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); sse_encode_opt_list_String(acceptedFileIds, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -965,7 +1211,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -983,86 +1229,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ['that'], ); - @override - Future crateApiMulticastRsMulticastAnnounce({required RsMulticast that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 20, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiMulticastRsMulticastAnnounceConstMeta, - argValues: [that], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMulticastRsMulticastAnnounceConstMeta => const TaskConstMeta( - debugName: 'RsMulticast_announce', - argNames: ['that'], - ); - - @override - Stream crateApiMulticastRsMulticastListen({required RsMulticast that}) { - final sink = RustStreamSink(); - unawaited( - handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(that, serializer); - sse_encode_StreamSink_rs_multicast_discovered_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiMulticastRsMulticastListenConstMeta, - argValues: [that, sink], - apiImpl: this, - ), - ), - ); - return sink.stream; - } - - TaskConstMeta get kCrateApiMulticastRsMulticastListenConstMeta => const TaskConstMeta( - debugName: 'RsMulticast_listen', - argNames: ['that', 'sink'], - ); - - @override - Future crateApiMulticastRsMulticastStop({required RsMulticast that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 22, port: port_); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_unit, - decodeErrorData: null, - ), - constMeta: kCrateApiMulticastRsMulticastStopConstMeta, - argValues: [that], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMulticastRsMulticastStopConstMeta => const TaskConstMeta( - debugName: 'RsMulticast_stop', - argNames: ['that'], - ); - @override Future crateApiWebrtcRtcFileReceiverGetFileId({required RtcFileReceiver that}) { return handler.executeNormal( @@ -1070,7 +1236,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileReceiver(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 23, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_String, @@ -1098,7 +1264,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileReceiver(that, serializer); sse_encode_StreamSink_list_prim_u_8_strict_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 24, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1126,7 +1292,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileSender(that, serializer); sse_encode_list_prim_u_8_loose(data, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1151,7 +1317,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1179,7 +1345,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_StreamSink_rtc_file_error_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1206,7 +1372,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_file_dto, @@ -1234,7 +1400,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_StreamSink_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileReceiver_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1264,7 +1430,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_StreamSink_rtc_status_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1292,7 +1458,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_box_autoadd_rtc_send_file_response(status, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1318,7 +1484,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_String(pin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 32, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1344,7 +1510,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCReceiveController(that, serializer); sse_encode_Set_String_None(selection, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 33, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1372,7 +1538,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_StreamSink_rtc_file_error_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 34, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1399,7 +1565,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 35, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Set_String_None, @@ -1427,7 +1593,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_StreamSink_rtc_status_Sse(sink, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 36, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1455,7 +1621,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_String(fileId, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 37, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCFileSender, @@ -1481,7 +1647,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRTCSendController(that, serializer); sse_encode_String(pin, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 38, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1520,7 +1686,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { onConnection, serializer, ); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 39, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1546,7 +1712,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { SyncTask( callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 40)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45)!; }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken, @@ -1581,7 +1747,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_ls_http_client_version(version, serializer); sse_encode_opt_String(expectedFingerprint, serializer); sse_encode_opt_box_autoadd_u_32(timeoutMs, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 41)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46)!; }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient, @@ -1605,7 +1771,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 42, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47, port: port_); }, codec: SseCodec( decodeSuccessData: @@ -1630,7 +1796,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 43, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1654,7 +1820,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 44, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_key_pair, @@ -1678,7 +1844,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 45, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 50, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_security_context, @@ -1709,7 +1875,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_box_autoadd_i_32(fileDescriptor, serializer); sse_encode_opt_list_prim_u_8_strict(bytes, serializer); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(cancelToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 46, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1730,7 +1896,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future crateApiMulticastStartMulticast({ + Future crateApiDiscoveryStartDiscovery({ required String group, required int port, List? networkWhitelist, @@ -1742,6 +1908,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required String fingerprint, required ProtocolTypeV2 protocol, required bool download, + required String certPem, + required String privateKeyPem, + required BigInt timeoutMs, }) { return handler.executeNormal( NormalTask( @@ -1758,21 +1927,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(fingerprint, serializer); sse_encode_protocol_type_v_2(protocol, serializer); sse_encode_bool(download, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 47, port: port_); + sse_encode_String(certPem, serializer); + sse_encode_String(privateKeyPem, serializer); + sse_encode_u_64(timeoutMs, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 52, port: port_); }, codec: SseCodec( - decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast, + decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery, decodeErrorData: sse_decode_AnyhowException, ), - constMeta: kCrateApiMulticastStartMulticastConstMeta, - argValues: [group, port, networkWhitelist, networkBlacklist, alias, version, deviceModel, deviceType, fingerprint, protocol, download], + constMeta: kCrateApiDiscoveryStartDiscoveryConstMeta, + argValues: [ + group, + port, + networkWhitelist, + networkBlacklist, + alias, + version, + deviceModel, + deviceType, + fingerprint, + protocol, + download, + certPem, + privateKeyPem, + timeoutMs, + ], apiImpl: this, ), ); } - TaskConstMeta get kCrateApiMulticastStartMulticastConstMeta => const TaskConstMeta( - debugName: 'start_multicast', + TaskConstMeta get kCrateApiDiscoveryStartDiscoveryConstMeta => const TaskConstMeta( + debugName: 'start_discovery', argNames: [ 'group', 'port', @@ -1785,6 +1972,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { 'fingerprint', 'protocol', 'download', + 'certPem', + 'privateKeyPem', + 'timeoutMs', ], ); @@ -1815,7 +2005,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_opt_String(pin, serializer); sse_encode_opt_box_autoadd_web_send_params(webSend, serializer); sse_encode_opt_String(showToken, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 48, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 53, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer, @@ -1841,7 +2031,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(cert, serializer); sse_encode_String(publicKey, serializer); - pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 49, port: port_); + pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1937,6 +2127,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsCancellationToken => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_RsDiscovery => + wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery; + + RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsDiscovery => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_RsHttpClient => wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient; @@ -1949,12 +2145,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsHttpServer => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer; - RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_RsMulticast => - wire.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast; - - RustArcDecrementStrongCountFnType get rust_arc_decrement_strong_count_RsMulticast => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast; - @protected AnyhowException dco_decode_AnyhowException(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2009,6 +2199,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsCancellationTokenImpl.frbInternalDcoDecode(raw as List); } + @protected + RsDiscovery dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return RsDiscoveryImpl.frbInternalDcoDecode(raw as List); + } + @protected RsHttpClient dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2021,12 +2217,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsHttpServerImpl.frbInternalDcoDecode(raw as List); } - @protected - RsMulticast dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return RsMulticastImpl.frbInternalDcoDecode(raw as List); - } - @protected Dart2RustStreamSink dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2075,6 +2265,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsCancellationTokenImpl.frbInternalDcoDecode(raw as List); } + @protected + RsDiscovery dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return RsDiscoveryImpl.frbInternalDcoDecode(raw as List); + } + @protected RsHttpClient dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2087,12 +2283,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsHttpServerImpl.frbInternalDcoDecode(raw as List); } - @protected - RsMulticast dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return RsMulticastImpl.frbInternalDcoDecode(raw as List); - } - @protected FutureOr Function(LsSignalingConnection) dco_decode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerLsSignalingConnection_Output_unit_AnyhowException( @@ -2168,6 +2358,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsCancellationTokenImpl.frbInternalDcoDecode(raw as List); } + @protected + RsDiscovery dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return RsDiscoveryImpl.frbInternalDcoDecode(raw as List); + } + @protected RsHttpClient dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2180,12 +2376,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsHttpServerImpl.frbInternalDcoDecode(raw as List); } - @protected - RsMulticast dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return RsMulticastImpl.frbInternalDcoDecode(raw as List); - } - @protected Set dco_decode_Set_String_None(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2213,13 +2403,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - RustStreamSink dco_decode_StreamSink_rs_hash_file_event_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_rs_discovered_device_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @protected - RustStreamSink dco_decode_StreamSink_rs_multicast_discovered_Sse(dynamic raw) { + RustStreamSink dco_decode_StreamSink_rs_hash_file_event_Sse(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs throw UnimplementedError(); } @@ -2352,6 +2542,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return dco_decode_register_dto_v_2(raw); } + @protected + RsDiscoveredDevice dco_decode_box_autoadd_rs_discovered_device(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dco_decode_rs_discovered_device(raw); + } + @protected RTCSendFileResponse dco_decode_box_autoadd_rtc_send_file_response(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2532,23 +2728,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return LsHttpClientVersion.values[raw as int]; } - @protected - MulticastMessageV2 dco_decode_multicast_message_v_2(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}'); - return MulticastMessageV2( - alias: dco_decode_String(arr[0]), - version: dco_decode_String(arr[1]), - deviceModel: dco_decode_opt_String(arr[2]), - deviceType: dco_decode_opt_box_autoadd_device_type(arr[3]), - fingerprint: dco_decode_String(arr[4]), - port: dco_decode_u_16(arr[5]), - protocol: dco_decode_protocol_type_v_2(arr[6]), - download: dco_decode_bool(arr[7]), - ); - } - @protected String? dco_decode_opt_String(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2600,6 +2779,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw == null ? null : dco_decode_box_autoadd_prepare_upload_response_dto(raw); } + @protected + RsDiscoveredDevice? dco_decode_opt_box_autoadd_rs_discovered_device(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_rs_discovered_device(raw); + } + @protected TlsConfig? dco_decode_opt_box_autoadd_tls_config(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2801,6 +2986,24 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + RsDiscoveredDevice dco_decode_rs_discovered_device(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 9) throw Exception('unexpected arr length: expect 9 but see ${arr.length}'); + return RsDiscoveredDevice( + alias: dco_decode_String(arr[0]), + version: dco_decode_String(arr[1]), + deviceModel: dco_decode_opt_String(arr[2]), + deviceType: dco_decode_opt_box_autoadd_device_type(arr[3]), + fingerprint: dco_decode_String(arr[4]), + host: dco_decode_String(arr[5]), + port: dco_decode_u_16(arr[6]), + protocol: dco_decode_protocol_type_v_2(arr[7]), + download: dco_decode_bool(arr[8]), + ); + } + @protected RsHashFileEvent dco_decode_rs_hash_file_event(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2848,17 +3051,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } - @protected - RsMulticastDiscovered dco_decode_rs_multicast_discovered(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - final arr = raw as List; - if (arr.length != 2) throw Exception('unexpected arr length: expect 2 but see ${arr.length}'); - return RsMulticastDiscovered( - ip: dco_decode_String(arr[0]), - message: dco_decode_multicast_message_v_2(arr[1]), - ); - } - @protected RsServerEvent dco_decode_rs_server_event(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3179,6 +3371,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsCancellationTokenImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } + @protected + RsDiscovery sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return RsDiscoveryImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected RsHttpClient sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3191,12 +3389,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsHttpServerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } - @protected - RsMulticast sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return RsMulticastImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); - } - @protected Dart2RustStreamSink sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink( SseDeserializer deserializer, @@ -3257,6 +3449,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsCancellationTokenImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } + @protected + RsDiscovery sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return RsDiscoveryImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected RsHttpClient sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3269,12 +3467,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsHttpServerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } - @protected - RsMulticast sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return RsMulticastImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); - } - @protected Object sse_decode_DartOpaque(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3346,6 +3538,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsCancellationTokenImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } + @protected + RsDiscovery sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return RsDiscoveryImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); + } + @protected RsHttpClient sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3358,12 +3556,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return RsHttpServerImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); } - @protected - RsMulticast sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return RsMulticastImpl.frbInternalSseDecode(sse_decode_usize(deserializer), sse_decode_i_32(deserializer)); - } - @protected Set sse_decode_Set_String_None(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3392,13 +3584,13 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - RustStreamSink sse_decode_StreamSink_rs_hash_file_event_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_rs_discovered_device_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @protected - RustStreamSink sse_decode_StreamSink_rs_multicast_discovered_Sse(SseDeserializer deserializer) { + RustStreamSink sse_decode_StreamSink_rs_hash_file_event_Sse(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs throw UnimplementedError('Unreachable ()'); } @@ -3533,6 +3725,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (sse_decode_register_dto_v_2(deserializer)); } + @protected + RsDiscoveredDevice sse_decode_box_autoadd_rs_discovered_device(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_rs_discovered_device(deserializer)); + } + @protected RTCSendFileResponse sse_decode_box_autoadd_rtc_send_file_response(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3737,29 +3935,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return LsHttpClientVersion.values[inner]; } - @protected - MulticastMessageV2 sse_decode_multicast_message_v_2(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var var_alias = sse_decode_String(deserializer); - var var_version = sse_decode_String(deserializer); - var var_deviceModel = sse_decode_opt_String(deserializer); - var var_deviceType = sse_decode_opt_box_autoadd_device_type(deserializer); - var var_fingerprint = sse_decode_String(deserializer); - var var_port = sse_decode_u_16(deserializer); - var var_protocol = sse_decode_protocol_type_v_2(deserializer); - var var_download = sse_decode_bool(deserializer); - return MulticastMessageV2( - alias: var_alias, - version: var_version, - deviceModel: var_deviceModel, - deviceType: var_deviceType, - fingerprint: var_fingerprint, - port: var_port, - protocol: var_protocol, - download: var_download, - ); - } - @protected String? sse_decode_opt_String(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -3851,6 +4026,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + RsDiscoveredDevice? sse_decode_opt_box_autoadd_rs_discovered_device(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_rs_discovered_device(deserializer)); + } else { + return null; + } + } + @protected TlsConfig? sse_decode_opt_box_autoadd_tls_config(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4062,6 +4248,31 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ResultWithPublicKeyRegisterResponseDto(publicKey: var_publicKey, body: var_body); } + @protected + RsDiscoveredDevice sse_decode_rs_discovered_device(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_alias = sse_decode_String(deserializer); + var var_version = sse_decode_String(deserializer); + var var_deviceModel = sse_decode_opt_String(deserializer); + var var_deviceType = sse_decode_opt_box_autoadd_device_type(deserializer); + var var_fingerprint = sse_decode_String(deserializer); + var var_host = sse_decode_String(deserializer); + var var_port = sse_decode_u_16(deserializer); + var var_protocol = sse_decode_protocol_type_v_2(deserializer); + var var_download = sse_decode_bool(deserializer); + return RsDiscoveredDevice( + alias: var_alias, + version: var_version, + deviceModel: var_deviceModel, + deviceType: var_deviceType, + fingerprint: var_fingerprint, + host: var_host, + port: var_port, + protocol: var_protocol, + download: var_download, + ); + } + @protected RsHashFileEvent sse_decode_rs_hash_file_event(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4106,14 +4317,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } - @protected - RsMulticastDiscovered sse_decode_rs_multicast_discovered(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var var_ip = sse_decode_String(deserializer); - var var_message = sse_decode_multicast_message_v_2(deserializer); - return RsMulticastDiscovered(ip: var_ip, message: var_message); - } - @protected RsServerEvent sse_decode_rs_server_event(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4428,6 +4631,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_usize((self as RsCancellationTokenImpl).frbInternalSseEncode(move: true), serializer); } + @protected + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize((self as RsDiscoveryImpl).frbInternalSseEncode(move: true), serializer); + } + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4440,12 +4649,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_usize((self as RsHttpServerImpl).frbInternalSseEncode(move: true), serializer); } - @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as RsMulticastImpl).frbInternalSseEncode(move: true), serializer); - } - @protected void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink( Dart2RustStreamSink self, @@ -4515,6 +4718,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_usize((self as RsCancellationTokenImpl).frbInternalSseEncode(move: false), serializer); } + @protected + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize((self as RsDiscoveryImpl).frbInternalSseEncode(move: false), serializer); + } + @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4527,12 +4736,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_usize((self as RsHttpServerImpl).frbInternalSseEncode(move: false), serializer); } - @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as RsMulticastImpl).frbInternalSseEncode(move: false), serializer); - } - @protected void sse_encode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerLsSignalingConnection_Output_unit_AnyhowException( @@ -4632,6 +4835,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_usize((self as RsCancellationTokenImpl).frbInternalSseEncode(move: null), serializer); } + @protected + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize((self as RsDiscoveryImpl).frbInternalSseEncode(move: null), serializer); + } + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4644,12 +4853,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_usize((self as RsHttpServerImpl).frbInternalSseEncode(move: null), serializer); } - @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize((self as RsMulticastImpl).frbInternalSseEncode(move: null), serializer); - } - @protected void sse_encode_Set_String_None(Set self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4702,12 +4905,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_rs_hash_file_event_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_rs_discovered_device_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( codec: SseCodec( - decodeSuccessData: sse_decode_rs_hash_file_event, + decodeSuccessData: sse_decode_rs_discovered_device, decodeErrorData: sse_decode_AnyhowException, ), ), @@ -4716,12 +4919,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } @protected - void sse_encode_StreamSink_rs_multicast_discovered_Sse(RustStreamSink self, SseSerializer serializer) { + void sse_encode_StreamSink_rs_hash_file_event_Sse(RustStreamSink self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs sse_encode_String( self.setupAndSerialize( codec: SseCodec( - decodeSuccessData: sse_decode_rs_multicast_discovered, + decodeSuccessData: sse_decode_rs_hash_file_event, decodeErrorData: sse_decode_AnyhowException, ), ), @@ -4890,6 +5093,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_register_dto_v_2(self, serializer); } + @protected + void sse_encode_box_autoadd_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_rs_discovered_device(self, serializer); + } + @protected void sse_encode_box_autoadd_rtc_send_file_response(RTCSendFileResponse self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5063,19 +5272,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_32(self.index, serializer); } - @protected - void sse_encode_multicast_message_v_2(MulticastMessageV2 self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.alias, serializer); - sse_encode_String(self.version, serializer); - sse_encode_opt_String(self.deviceModel, serializer); - sse_encode_opt_box_autoadd_device_type(self.deviceType, serializer); - sse_encode_String(self.fingerprint, serializer); - sse_encode_u_16(self.port, serializer); - sse_encode_protocol_type_v_2(self.protocol, serializer); - sse_encode_bool(self.download, serializer); - } - @protected void sse_encode_opt_String(String? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5159,6 +5355,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_box_autoadd_rs_discovered_device(RsDiscoveredDevice? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_rs_discovered_device(self, serializer); + } + } + @protected void sse_encode_opt_box_autoadd_tls_config(TlsConfig? self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5327,6 +5533,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_register_response_dto(self.body, serializer); } + @protected + void sse_encode_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.alias, serializer); + sse_encode_String(self.version, serializer); + sse_encode_opt_String(self.deviceModel, serializer); + sse_encode_opt_box_autoadd_device_type(self.deviceType, serializer); + sse_encode_String(self.fingerprint, serializer); + sse_encode_String(self.host, serializer); + sse_encode_u_16(self.port, serializer); + sse_encode_protocol_type_v_2(self.protocol, serializer); + sse_encode_bool(self.download, serializer); + } + @protected void sse_encode_rs_hash_file_event(RsHashFileEvent self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5363,13 +5583,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } - @protected - void sse_encode_rs_multicast_discovered(RsMulticastDiscovered self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.ip, serializer); - sse_encode_multicast_message_v_2(self.message, serializer); - } - @protected void sse_encode_rs_server_event(RsServerEvent self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5688,6 +5901,87 @@ class RsCancellationTokenImpl extends RustOpaque implements RsCancellationToken ); } +@sealed +class RsDiscoveryImpl extends RustOpaque implements RsDiscovery { + // Not to be used by end users + RsDiscoveryImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); + + // Not to be used by end users + RsDiscoveryImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + + static final _kStaticData = RustArcStaticData( + rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_RsDiscovery, + rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_RsDiscovery, + rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_RsDiscoveryPtr, + ); + + /// Puts a device confirmed outside of the discovery into the store, e.g. + /// one that answered an announcement by registering with this device's + /// HTTP server. The device is emitted on [RsDiscovery::listen]. + Future addDevice({required RsDiscoveredDevice device}) => + RustLib.instance.api.crateApiDiscoveryRsDiscoveryAddDevice(that: this, device: device); + + /// Announces this device to the network, which makes every other LocalSend + /// device on it register with this device over HTTP. + /// + /// Devices registering in response arrive at the application as server + /// events, not here: feed them back via [RsDiscovery::add_device]. + /// + /// Returns once the whole announcement burst has been sent, which takes a + /// few seconds, or immediately once the discovery has been stopped or + /// multicast is unavailable. + Future announce() => RustLib.instance.api.crateApiDiscoveryRsDiscoveryAnnounce( + that: this, + ); + + /// Discovers a device at a known address, e.g. a favorite or a peer that + /// multicast does not reach, by sending it a register request. + /// + /// The confirmed device is also emitted on [RsDiscovery::listen]. + /// Returns `None` when the device did not answer or answered with this + /// device's own fingerprint (i.e. the device discovered itself). + Future discover({required String host, required int port, required ProtocolTypeV2 protocol}) => + RustLib.instance.api.crateApiDiscoveryRsDiscoveryDiscover(that: this, host: host, port: port, protocol: protocol); + + /// Emits a [RsDiscoveredDevice] for every device confirmation until the + /// discovery is stopped. Can only be listened to once. + Stream listen() => RustLib.instance.api.crateApiDiscoveryRsDiscoveryListen( + that: this, + ); + + /// The reason the multicast sockets could not be bound, when they could + /// not. Discovery then neither hears nor sends announcements. + Future multicastError() => RustLib.instance.api.crateApiDiscoveryRsDiscoveryMulticastError( + that: this, + ); + + /// Scans the `/24` subnet of the local interface address [interface_ip] + /// by sending every other host a register request, for networks that do + /// not carry multicast. + /// + /// The found devices are emitted on [RsDiscovery::listen] as they answer; + /// this method returns once the whole scan has finished. At most one scan + /// runs per interface: a call for an address that is still being scanned + /// returns immediately. + Future scanSubnet({required String interfaceIp, required int port, required ProtocolTypeV2 protocol}) => + RustLib.instance.api.crateApiDiscoveryRsDiscoveryScanSubnet(that: this, interfaceIp: interfaceIp, port: port, protocol: protocol); + + /// Sets whether announcements of other devices are answered with a + /// register request (the answer is what makes the announcing device enter + /// the store). On by default. + /// + /// Turned off while the HTTP server is not running: the answer would + /// advertise a port that nobody listens on. + Future setAnswerAnnouncements({required bool answer}) => + RustLib.instance.api.crateApiDiscoveryRsDiscoverySetAnswerAnnouncements(that: this, answer: answer); + + /// Stops the discovery, which also ends the [RsDiscovery::listen] stream. + /// Returns after all sockets are closed, so the port can be bound again. + Future stop() => RustLib.instance.api.crateApiDiscoveryRsDiscoveryStop( + that: this, + ); +} + @sealed class RsHttpClientImpl extends RustOpaque implements RsHttpClient { // Not to be used by end users @@ -5858,43 +6152,6 @@ class RsHttpServerImpl extends RustOpaque implements RsHttpServer { ); } -@sealed -class RsMulticastImpl extends RustOpaque implements RsMulticast { - // Not to be used by end users - RsMulticastImpl.frbInternalDcoDecode(List wire) : super.frbInternalDcoDecode(wire, _kStaticData); - - // Not to be used by end users - RsMulticastImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); - - static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: RustLib.instance.api.rust_arc_increment_strong_count_RsMulticast, - rustArcDecrementStrongCount: RustLib.instance.api.rust_arc_decrement_strong_count_RsMulticast, - rustArcDecrementStrongCountPtr: RustLib.instance.api.rust_arc_decrement_strong_count_RsMulticastPtr, - ); - - /// Announces this device to the network, which makes every other LocalSend - /// device on it register with this device over HTTP. - /// - /// Returns once the whole announcement burst has been sent, which takes a - /// few seconds, or immediately once discovery has been stopped. - Future announce() => RustLib.instance.api.crateApiMulticastRsMulticastAnnounce( - that: this, - ); - - /// Emits a [RsMulticastDiscovered] for every announcement received from - /// another device until discovery is stopped. - /// Can only be listened to once. - Stream listen() => RustLib.instance.api.crateApiMulticastRsMulticastListen( - that: this, - ); - - /// Stops discovery, which also ends the [RsMulticast::listen] stream. - /// Returns after all sockets are closed, so the port can be bound again. - Future stop() => RustLib.instance.api.crateApiMulticastRsMulticastStop( - that: this, - ); -} - @sealed class RtcFileReceiverImpl extends RustOpaque implements RtcFileReceiver { // Not to be used by end users diff --git a/packages/localsend_isolates/lib/rust/frb_generated.io.dart b/packages/localsend_isolates/lib/rust/frb_generated.io.dart index 0aecf297..caa5e75c 100644 --- a/packages/localsend_isolates/lib/rust/frb_generated.io.dart +++ b/packages/localsend_isolates/lib/rust/frb_generated.io.dart @@ -10,10 +10,10 @@ import 'dart:ffi' as ffi; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; import 'package:localsend_isolates/rust/api/cancel.dart'; import 'package:localsend_isolates/rust/api/crypto.dart'; +import 'package:localsend_isolates/rust/api/discovery.dart'; import 'package:localsend_isolates/rust/api/http.dart'; import 'package:localsend_isolates/rust/api/logging.dart'; import 'package:localsend_isolates/rust/api/model.dart'; -import 'package:localsend_isolates/rust/api/multicast.dart'; import 'package:localsend_isolates/rust/api/server.dart'; import 'package:localsend_isolates/rust/api/stream.dart'; import 'package:localsend_isolates/rust/api/webrtc.dart'; @@ -52,15 +52,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsCancellationTokenPtr => wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationTokenPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsDiscoveryPtr => + wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscoveryPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsHttpClientPtr => wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClientPtr; CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsHttpServerPtr => wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServerPtr; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsMulticastPtr => - wire._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticastPtr; - @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @@ -88,15 +88,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(dynamic raw); + @protected + RsDiscovery dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw); + @protected RsHttpClient dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw); @protected RsHttpServer dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(dynamic raw); - @protected - RsMulticast dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw); - @protected Dart2RustStreamSink dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink(dynamic raw); @@ -121,15 +121,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(dynamic raw); + @protected + RsDiscovery dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw); + @protected RsHttpClient dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw); @protected RsHttpServer dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(dynamic raw); - @protected - RsMulticast dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw); - @protected FutureOr Function(LsSignalingConnection) dco_decode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerLsSignalingConnection_Output_unit_AnyhowException( @@ -169,15 +169,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(dynamic raw); + @protected + RsDiscovery dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw); + @protected RsHttpClient dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw); @protected RsHttpServer dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(dynamic raw); - @protected - RsMulticast dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw); - @protected Set dco_decode_Set_String_None(dynamic raw); @@ -193,10 +193,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_list_prim_u_8_strict_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_rs_hash_file_event_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_rs_discovered_device_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_rs_multicast_discovered_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_rs_hash_file_event_Sse(dynamic raw); @protected RustStreamSink dco_decode_StreamSink_rs_server_event_Sse(dynamic raw); @@ -263,6 +263,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RegisterDtoV2 dco_decode_box_autoadd_register_dto_v_2(dynamic raw); + @protected + RsDiscoveredDevice dco_decode_box_autoadd_rs_discovered_device(dynamic raw); + @protected RTCSendFileResponse dco_decode_box_autoadd_rtc_send_file_response(dynamic raw); @@ -332,9 +335,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected LsHttpClientVersion dco_decode_ls_http_client_version(dynamic raw); - @protected - MulticastMessageV2 dco_decode_multicast_message_v_2(dynamic raw); - @protected String? dco_decode_opt_String(dynamic raw); @@ -360,6 +360,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected PrepareUploadResponseDto? dco_decode_opt_box_autoadd_prepare_upload_response_dto(dynamic raw); + @protected + RsDiscoveredDevice? dco_decode_opt_box_autoadd_rs_discovered_device(dynamic raw); + @protected TlsConfig? dco_decode_opt_box_autoadd_tls_config(dynamic raw); @@ -420,15 +423,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ResultWithPublicKeyRegisterResponseDto dco_decode_result_with_public_key_register_response_dto(dynamic raw); + @protected + RsDiscoveredDevice dco_decode_rs_discovered_device(dynamic raw); + @protected RsHashFileEvent dco_decode_rs_hash_file_event(dynamic raw); @protected RsHttpClientError dco_decode_rs_http_client_error(dynamic raw); - @protected - RsMulticastDiscovered dco_decode_rs_multicast_discovered(dynamic raw); - @protected RsServerEvent dco_decode_rs_server_event(dynamic raw); @@ -519,15 +522,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + RsDiscovery sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer); + @protected RsHttpClient sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer); @protected RsHttpServer sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(SseDeserializer deserializer); - @protected - RsMulticast sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer); - @protected Dart2RustStreamSink sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink( SseDeserializer deserializer, @@ -562,15 +565,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + RsDiscovery sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer); + @protected RsHttpClient sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer); @protected RsHttpServer sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(SseDeserializer deserializer); - @protected - RsMulticast sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer); - @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @@ -606,15 +609,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(SseDeserializer deserializer); + @protected + RsDiscovery sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer); + @protected RsHttpClient sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer); @protected RsHttpServer sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(SseDeserializer deserializer); - @protected - RsMulticast sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer); - @protected Set sse_decode_Set_String_None(SseDeserializer deserializer); @@ -630,10 +633,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink sse_decode_StreamSink_list_prim_u_8_strict_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_rs_hash_file_event_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_rs_discovered_device_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_rs_multicast_discovered_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_rs_hash_file_event_Sse(SseDeserializer deserializer); @protected RustStreamSink sse_decode_StreamSink_rs_server_event_Sse(SseDeserializer deserializer); @@ -700,6 +703,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RegisterDtoV2 sse_decode_box_autoadd_register_dto_v_2(SseDeserializer deserializer); + @protected + RsDiscoveredDevice sse_decode_box_autoadd_rs_discovered_device(SseDeserializer deserializer); + @protected RTCSendFileResponse sse_decode_box_autoadd_rtc_send_file_response(SseDeserializer deserializer); @@ -769,9 +775,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected LsHttpClientVersion sse_decode_ls_http_client_version(SseDeserializer deserializer); - @protected - MulticastMessageV2 sse_decode_multicast_message_v_2(SseDeserializer deserializer); - @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -799,6 +802,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected PrepareUploadResponseDto? sse_decode_opt_box_autoadd_prepare_upload_response_dto(SseDeserializer deserializer); + @protected + RsDiscoveredDevice? sse_decode_opt_box_autoadd_rs_discovered_device(SseDeserializer deserializer); + @protected TlsConfig? sse_decode_opt_box_autoadd_tls_config(SseDeserializer deserializer); @@ -859,15 +865,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ResultWithPublicKeyRegisterResponseDto sse_decode_result_with_public_key_register_response_dto(SseDeserializer deserializer); + @protected + RsDiscoveredDevice sse_decode_rs_discovered_device(SseDeserializer deserializer); + @protected RsHashFileEvent sse_decode_rs_hash_file_event(SseDeserializer deserializer); @protected RsHttpClientError sse_decode_rs_http_client_error(SseDeserializer deserializer); - @protected - RsMulticastDiscovered sse_decode_rs_multicast_discovered(SseDeserializer deserializer); - @protected RsServerEvent sse_decode_rs_server_event(SseDeserializer deserializer); @@ -970,15 +976,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer); @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(RsHttpServer self, SseSerializer serializer); - @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer); - @protected void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink( Dart2RustStreamSink self, @@ -1024,15 +1030,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer); + @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer); @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(RsHttpServer self, SseSerializer serializer); - @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer); - @protected void sse_encode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerLsSignalingConnection_Output_unit_AnyhowException( @@ -1088,15 +1094,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer); @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(RsHttpServer self, SseSerializer serializer); - @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer); - @protected void sse_encode_Set_String_None(Set self, SseSerializer serializer); @@ -1113,10 +1119,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_StreamSink_list_prim_u_8_strict_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_rs_hash_file_event_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_rs_discovered_device_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_rs_multicast_discovered_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_rs_hash_file_event_Sse(RustStreamSink self, SseSerializer serializer); @protected void sse_encode_StreamSink_rs_server_event_Sse(RustStreamSink self, SseSerializer serializer); @@ -1184,6 +1190,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_box_autoadd_register_dto_v_2(RegisterDtoV2 self, SseSerializer serializer); + @protected + void sse_encode_box_autoadd_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer); + @protected void sse_encode_box_autoadd_rtc_send_file_response(RTCSendFileResponse self, SseSerializer serializer); @@ -1253,9 +1262,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_ls_http_client_version(LsHttpClientVersion self, SseSerializer serializer); - @protected - void sse_encode_multicast_message_v_2(MulticastMessageV2 self, SseSerializer serializer); - @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -1283,6 +1289,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_opt_box_autoadd_prepare_upload_response_dto(PrepareUploadResponseDto? self, SseSerializer serializer); + @protected + void sse_encode_opt_box_autoadd_rs_discovered_device(RsDiscoveredDevice? self, SseSerializer serializer); + @protected void sse_encode_opt_box_autoadd_tls_config(TlsConfig? self, SseSerializer serializer); @@ -1344,15 +1353,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_result_with_public_key_register_response_dto(ResultWithPublicKeyRegisterResponseDto self, SseSerializer serializer); + @protected + void sse_encode_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer); + @protected void sse_encode_rs_hash_file_event(RsHashFileEvent self, SseSerializer serializer); @protected void sse_encode_rs_http_client_error(RsHttpClientError self, SseSerializer serializer); - @protected - void sse_encode_rs_multicast_discovered(RsMulticastDiscovered self, SseSerializer serializer); - @protected void sse_encode_rs_server_event(RsServerEvent self, SseSerializer serializer); @@ -1672,6 +1681,38 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationTokenPtr .asFunction)>(); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ffi.Pointer ptr, + ) { + return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ptr, + ); + } + + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscoveryPtr = + _lookup)>>( + 'frbgen_localsend_isolates_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery', + ); + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery = + _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscoveryPtr + .asFunction)>(); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ffi.Pointer ptr, + ) { + return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ptr, + ); + } + + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscoveryPtr = + _lookup)>>( + 'frbgen_localsend_isolates_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery', + ); + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery = + _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscoveryPtr + .asFunction)>(); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient( ffi.Pointer ptr, ) { @@ -1735,36 +1776,4 @@ class RustLibWire implements BaseWire { late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer = _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServerPtr .asFunction)>(); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ffi.Pointer ptr, - ) { - return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ptr, - ); - } - - late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticastPtr = - _lookup)>>( - 'frbgen_localsend_isolates_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast', - ); - late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast = - _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticastPtr - .asFunction)>(); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ffi.Pointer ptr, - ) { - return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ptr, - ); - } - - late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticastPtr = - _lookup)>>( - 'frbgen_localsend_isolates_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast', - ); - late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast = - _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticastPtr - .asFunction)>(); } diff --git a/packages/localsend_isolates/lib/rust/frb_generated.web.dart b/packages/localsend_isolates/lib/rust/frb_generated.web.dart index 87feeebd..07f8e178 100644 --- a/packages/localsend_isolates/lib/rust/frb_generated.web.dart +++ b/packages/localsend_isolates/lib/rust/frb_generated.web.dart @@ -12,10 +12,10 @@ import 'dart:convert'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; import 'package:localsend_isolates/rust/api/cancel.dart'; import 'package:localsend_isolates/rust/api/crypto.dart'; +import 'package:localsend_isolates/rust/api/discovery.dart'; import 'package:localsend_isolates/rust/api/http.dart'; import 'package:localsend_isolates/rust/api/logging.dart'; import 'package:localsend_isolates/rust/api/model.dart'; -import 'package:localsend_isolates/rust/api/multicast.dart'; import 'package:localsend_isolates/rust/api/server.dart'; import 'package:localsend_isolates/rust/api/stream.dart'; import 'package:localsend_isolates/rust/api/webrtc.dart'; @@ -54,15 +54,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsCancellationTokenPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsDiscoveryPtr => + wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsHttpClientPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient; CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsHttpServerPtr => wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer; - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_RsMulticastPtr => - wire.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast; - @protected AnyhowException dco_decode_AnyhowException(dynamic raw); @@ -90,15 +90,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(dynamic raw); + @protected + RsDiscovery dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw); + @protected RsHttpClient dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw); @protected RsHttpServer dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(dynamic raw); - @protected - RsMulticast dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw); - @protected Dart2RustStreamSink dco_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink(dynamic raw); @@ -123,15 +123,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(dynamic raw); + @protected + RsDiscovery dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw); + @protected RsHttpClient dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw); @protected RsHttpServer dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(dynamic raw); - @protected - RsMulticast dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw); - @protected FutureOr Function(LsSignalingConnection) dco_decode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerLsSignalingConnection_Output_unit_AnyhowException( @@ -171,15 +171,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(dynamic raw); + @protected + RsDiscovery dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(dynamic raw); + @protected RsHttpClient dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(dynamic raw); @protected RsHttpServer dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(dynamic raw); - @protected - RsMulticast dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(dynamic raw); - @protected Set dco_decode_Set_String_None(dynamic raw); @@ -195,10 +195,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink dco_decode_StreamSink_list_prim_u_8_strict_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_rs_hash_file_event_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_rs_discovered_device_Sse(dynamic raw); @protected - RustStreamSink dco_decode_StreamSink_rs_multicast_discovered_Sse(dynamic raw); + RustStreamSink dco_decode_StreamSink_rs_hash_file_event_Sse(dynamic raw); @protected RustStreamSink dco_decode_StreamSink_rs_server_event_Sse(dynamic raw); @@ -265,6 +265,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RegisterDtoV2 dco_decode_box_autoadd_register_dto_v_2(dynamic raw); + @protected + RsDiscoveredDevice dco_decode_box_autoadd_rs_discovered_device(dynamic raw); + @protected RTCSendFileResponse dco_decode_box_autoadd_rtc_send_file_response(dynamic raw); @@ -334,9 +337,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected LsHttpClientVersion dco_decode_ls_http_client_version(dynamic raw); - @protected - MulticastMessageV2 dco_decode_multicast_message_v_2(dynamic raw); - @protected String? dco_decode_opt_String(dynamic raw); @@ -362,6 +362,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected PrepareUploadResponseDto? dco_decode_opt_box_autoadd_prepare_upload_response_dto(dynamic raw); + @protected + RsDiscoveredDevice? dco_decode_opt_box_autoadd_rs_discovered_device(dynamic raw); + @protected TlsConfig? dco_decode_opt_box_autoadd_tls_config(dynamic raw); @@ -422,15 +425,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ResultWithPublicKeyRegisterResponseDto dco_decode_result_with_public_key_register_response_dto(dynamic raw); + @protected + RsDiscoveredDevice dco_decode_rs_discovered_device(dynamic raw); + @protected RsHashFileEvent dco_decode_rs_hash_file_event(dynamic raw); @protected RsHttpClientError dco_decode_rs_http_client_error(dynamic raw); - @protected - RsMulticastDiscovered dco_decode_rs_multicast_discovered(dynamic raw); - @protected RsServerEvent dco_decode_rs_server_event(dynamic raw); @@ -521,15 +524,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + RsDiscovery sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer); + @protected RsHttpClient sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer); @protected RsHttpServer sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(SseDeserializer deserializer); - @protected - RsMulticast sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer); - @protected Dart2RustStreamSink sse_decode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink( SseDeserializer deserializer, @@ -564,15 +567,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + RsDiscovery sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer); + @protected RsHttpClient sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer); @protected RsHttpServer sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(SseDeserializer deserializer); - @protected - RsMulticast sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer); - @protected Object sse_decode_DartOpaque(SseDeserializer deserializer); @@ -608,15 +611,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RsCancellationToken sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(SseDeserializer deserializer); + @protected + RsDiscovery sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(SseDeserializer deserializer); + @protected RsHttpClient sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(SseDeserializer deserializer); @protected RsHttpServer sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(SseDeserializer deserializer); - @protected - RsMulticast sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(SseDeserializer deserializer); - @protected Set sse_decode_Set_String_None(SseDeserializer deserializer); @@ -632,10 +635,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { RustStreamSink sse_decode_StreamSink_list_prim_u_8_strict_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_rs_hash_file_event_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_rs_discovered_device_Sse(SseDeserializer deserializer); @protected - RustStreamSink sse_decode_StreamSink_rs_multicast_discovered_Sse(SseDeserializer deserializer); + RustStreamSink sse_decode_StreamSink_rs_hash_file_event_Sse(SseDeserializer deserializer); @protected RustStreamSink sse_decode_StreamSink_rs_server_event_Sse(SseDeserializer deserializer); @@ -702,6 +705,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected RegisterDtoV2 sse_decode_box_autoadd_register_dto_v_2(SseDeserializer deserializer); + @protected + RsDiscoveredDevice sse_decode_box_autoadd_rs_discovered_device(SseDeserializer deserializer); + @protected RTCSendFileResponse sse_decode_box_autoadd_rtc_send_file_response(SseDeserializer deserializer); @@ -771,9 +777,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected LsHttpClientVersion sse_decode_ls_http_client_version(SseDeserializer deserializer); - @protected - MulticastMessageV2 sse_decode_multicast_message_v_2(SseDeserializer deserializer); - @protected String? sse_decode_opt_String(SseDeserializer deserializer); @@ -801,6 +804,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected PrepareUploadResponseDto? sse_decode_opt_box_autoadd_prepare_upload_response_dto(SseDeserializer deserializer); + @protected + RsDiscoveredDevice? sse_decode_opt_box_autoadd_rs_discovered_device(SseDeserializer deserializer); + @protected TlsConfig? sse_decode_opt_box_autoadd_tls_config(SseDeserializer deserializer); @@ -861,15 +867,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ResultWithPublicKeyRegisterResponseDto sse_decode_result_with_public_key_register_response_dto(SseDeserializer deserializer); + @protected + RsDiscoveredDevice sse_decode_rs_discovered_device(SseDeserializer deserializer); + @protected RsHashFileEvent sse_decode_rs_hash_file_event(SseDeserializer deserializer); @protected RsHttpClientError sse_decode_rs_http_client_error(SseDeserializer deserializer); - @protected - RsMulticastDiscovered sse_decode_rs_multicast_discovered(SseDeserializer deserializer); - @protected RsServerEvent sse_decode_rs_server_event(SseDeserializer deserializer); @@ -972,15 +978,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer); @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(RsHttpServer self, SseSerializer serializer); - @protected - void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer); - @protected void sse_encode_Auto_RefMut_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDart2RustStreamSink( Dart2RustStreamSink self, @@ -1026,15 +1032,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer); + @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer); @protected void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(RsHttpServer self, SseSerializer serializer); - @protected - void sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer); - @protected void sse_encode_DartFn_Inputs_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerLsSignalingConnection_Output_unit_AnyhowException( @@ -1090,15 +1096,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(RsDiscovery self, SseSerializer serializer); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(RsHttpClient self, SseSerializer serializer); @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(RsHttpServer self, SseSerializer serializer); - @protected - void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(RsMulticast self, SseSerializer serializer); - @protected void sse_encode_Set_String_None(Set self, SseSerializer serializer); @@ -1115,10 +1121,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_StreamSink_list_prim_u_8_strict_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_rs_hash_file_event_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_rs_discovered_device_Sse(RustStreamSink self, SseSerializer serializer); @protected - void sse_encode_StreamSink_rs_multicast_discovered_Sse(RustStreamSink self, SseSerializer serializer); + void sse_encode_StreamSink_rs_hash_file_event_Sse(RustStreamSink self, SseSerializer serializer); @protected void sse_encode_StreamSink_rs_server_event_Sse(RustStreamSink self, SseSerializer serializer); @@ -1186,6 +1192,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_box_autoadd_register_dto_v_2(RegisterDtoV2 self, SseSerializer serializer); + @protected + void sse_encode_box_autoadd_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer); + @protected void sse_encode_box_autoadd_rtc_send_file_response(RTCSendFileResponse self, SseSerializer serializer); @@ -1255,9 +1264,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_ls_http_client_version(LsHttpClientVersion self, SseSerializer serializer); - @protected - void sse_encode_multicast_message_v_2(MulticastMessageV2 self, SseSerializer serializer); - @protected void sse_encode_opt_String(String? self, SseSerializer serializer); @@ -1285,6 +1291,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_opt_box_autoadd_prepare_upload_response_dto(PrepareUploadResponseDto? self, SseSerializer serializer); + @protected + void sse_encode_opt_box_autoadd_rs_discovered_device(RsDiscoveredDevice? self, SseSerializer serializer); + @protected void sse_encode_opt_box_autoadd_tls_config(TlsConfig? self, SseSerializer serializer); @@ -1346,15 +1355,15 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_result_with_public_key_register_response_dto(ResultWithPublicKeyRegisterResponseDto self, SseSerializer serializer); + @protected + void sse_encode_rs_discovered_device(RsDiscoveredDevice self, SseSerializer serializer); + @protected void sse_encode_rs_hash_file_event(RsHashFileEvent self, SseSerializer serializer); @protected void sse_encode_rs_http_client_error(RsHttpClientError self, SseSerializer serializer); - @protected - void sse_encode_rs_multicast_discovered(RsMulticastDiscovered self, SseSerializer serializer); - @protected void sse_encode_rs_server_event(RsServerEvent self, SseSerializer serializer); @@ -1460,6 +1469,12 @@ class RustLibWire implements BaseWire { void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(int ptr) => wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(int ptr) => + wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(ptr); + + void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(int ptr) => + wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(ptr); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(int ptr) => wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(ptr); @@ -1471,12 +1486,6 @@ class RustLibWire implements BaseWire { void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(int ptr) => wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(ptr); - - void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(int ptr) => - wasmModule.rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(ptr); - - void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(int ptr) => - wasmModule.rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(ptr); } @JS('wasm_bindgen') @@ -1517,6 +1526,10 @@ extension type RustLibWasmModule._(JSObject _) implements JSObject { external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsCancellationToken(int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(int ptr); + + external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery(int ptr); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(int ptr); external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient(int ptr); @@ -1524,8 +1537,4 @@ extension type RustLibWasmModule._(JSObject _) implements JSObject { external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(int ptr); external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpServer(int ptr); - - external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(int ptr); - - external void rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast(int ptr); } diff --git a/packages/localsend_isolates/lib/src/isolate/child/discovery_isolate.dart b/packages/localsend_isolates/lib/src/isolate/child/discovery_isolate.dart new file mode 100644 index 00000000..b4f4f0c9 --- /dev/null +++ b/packages/localsend_isolates/lib/src/isolate/child/discovery_isolate.dart @@ -0,0 +1,115 @@ +import 'package:localsend_isolates/model/device.dart'; +import 'package:localsend_isolates/src/isolate/child/main.dart'; +import 'package:localsend_isolates/src/isolate/dto/send_to_isolate_data.dart'; +import 'package:localsend_isolates/src/task/discovery/discovery.dart'; +import 'package:typed_isolates/typed_isolates.dart'; + +sealed class DiscoveryTask {} + +/// Starts the discovery and streams every confirmed device. +/// The stream never completes; it survives [DiscoveryRestartTask]s. +class DiscoveryListenTask implements DiscoveryTask {} + +/// Sends an announcement to all devices on all network interfaces. +/// They will respond by registering with this device's HTTP server. +class DiscoveryAnnouncementTask implements DiscoveryTask {} + +/// Restarts the discovery, e.g. after the port or the network settings changed. +class DiscoveryRestartTask implements DiscoveryTask {} + +/// Scans the subnet of one network interface over HTTP. +/// Completes (without events) when the scan is finished; the found devices +/// arrive on the [DiscoveryListenTask] stream. +class DiscoverySubnetScanTask implements DiscoveryTask { + final String networkInterface; + final int port; + final bool https; + + DiscoverySubnetScanTask({ + required this.networkInterface, + required this.port, + required this.https, + }); +} + +/// Probes the known addresses of the favorites over HTTP. +/// Completes (without events) when every favorite has been probed; the found +/// devices arrive on the [DiscoveryListenTask] stream. +class DiscoveryFavoriteScanTask implements DiscoveryTask { + final List<(String, int)> favorites; + final bool https; + + DiscoveryFavoriteScanTask({ + required this.favorites, + required this.https, + }); +} + +/// Feeds a device confirmed outside of the discovery into the store, e.g. one +/// that registered with this device's HTTP server. The device comes back on +/// the [DiscoveryListenTask] stream. +class DiscoveryAddDeviceTask implements DiscoveryTask { + final Device device; + + DiscoveryAddDeviceTask({ + required this.device, + }); +} + +Future setupDiscoveryIsolate( + Stream>> receiveFromMain, + void Function(IsolateTaskStreamResult) sendToMain, + InitialData initialData, +) async { + await setupChildIsolateHelper( + debugLabel: 'DiscoveryIsolate', + receiveFromMain: receiveFromMain, + sendToMain: sendToMain, + initialData: initialData, + handler: (ref, task) async { + switch (task.data) { + case DiscoveryListenTask(): + await for (final device in ref.read(discoveryProvider).startListener()) { + sendToMain( + IsolateTaskStreamResult.event( + id: task.id, + data: device, + ), + ); + } + return; + case DiscoveryAnnouncementTask(): + await ref.read(discoveryProvider).sendAnnouncement(); + break; + case DiscoveryRestartTask(): + ref.read(discoveryProvider).restartListener(); + break; + case DiscoverySubnetScanTask data: + await ref + .read(discoveryProvider) + .scanSubnet( + networkInterface: data.networkInterface, + port: data.port, + https: data.https, + ); + break; + case DiscoveryFavoriteScanTask data: + await ref + .read(discoveryProvider) + .discoverFavorites( + devices: data.favorites, + https: data.https, + ); + break; + case DiscoveryAddDeviceTask data: + await ref.read(discoveryProvider).addDevice(data.device); + break; + } + sendToMain( + IsolateTaskStreamResult.done( + id: task.id, + ), + ); + }, + ); +} diff --git a/packages/localsend_isolates/lib/src/isolate/child/http_provider.dart b/packages/localsend_isolates/lib/src/isolate/child/http_provider.dart index 6eeb88b9..825d93de 100644 --- a/packages/localsend_isolates/lib/src/isolate/child/http_provider.dart +++ b/packages/localsend_isolates/lib/src/isolate/child/http_provider.dart @@ -6,23 +6,9 @@ class HttpClientCollection { final String _privateKey; final String _certificate; - /// A client that accepts any valid peer certificate. - /// - /// Only for discovery, where the certificate of the peer is not known yet - /// and is learned from the response. Never use this to transfer files: - /// it cannot tell the discovered device apart from anyone else answering - /// on that address. - final RsHttpClient discovery; - - /// The request timeout of the [discovery] client. - /// Also apply it to short-lived pinned requests made during discovery. - final int discoveryTimeout; - HttpClientCollection({ required String privateKey, required String certificate, - required this.discovery, - required this.discoveryTimeout, }) : _privateKey = privateKey, _certificate = certificate; @@ -48,19 +34,9 @@ class HttpClientCollection { } final httpProvider = ViewProvider((ref) { - final (securityContext, discoveryTimeout) = ref.watch( - syncProvider.select((state) => (state.securityContext, state.discoveryTimeout)), - ); + final securityContext = ref.watch(syncProvider.select((state) => state.securityContext)); return HttpClientCollection( privateKey: securityContext.privateKey, certificate: securityContext.certificate, - discovery: createClient( - privateKey: securityContext.privateKey, - cert: securityContext.certificate, - version: LsHttpClientVersion.v2, - expectedFingerprint: null, - timeoutMs: discoveryTimeout, - ), - discoveryTimeout: discoveryTimeout, ); }); diff --git a/packages/localsend_isolates/lib/src/isolate/child/http_scan_discovery_isolate.dart b/packages/localsend_isolates/lib/src/isolate/child/http_scan_discovery_isolate.dart deleted file mode 100644 index d4824777..00000000 --- a/packages/localsend_isolates/lib/src/isolate/child/http_scan_discovery_isolate.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:localsend_isolates/model/device.dart'; -import 'package:localsend_isolates/src/isolate/child/main.dart'; -import 'package:localsend_isolates/src/isolate/dto/send_to_isolate_data.dart'; -import 'package:localsend_isolates/src/task/discovery/http_scan_discovery.dart'; -import 'package:typed_isolates/typed_isolates.dart'; - -sealed class HttpScanTask {} - -class HttpInterfaceScanTask implements HttpScanTask { - final String networkInterface; - final int port; - final bool https; - - HttpInterfaceScanTask({ - required this.networkInterface, - required this.port, - required this.https, - }); -} - -class HttpFavoriteScanTask implements HttpScanTask { - final List<(String, int)> favorites; - final bool https; - - HttpFavoriteScanTask({ - required this.favorites, - required this.https, - }); -} - -Future setupHttpScanDiscoveryIsolate( - Stream>> receiveFromMain, - void Function(IsolateTaskStreamResult) sendToMain, - InitialData initialData, -) async { - await setupChildIsolateHelper( - debugLabel: 'HttpScanDiscoveryIsolate', - receiveFromMain: receiveFromMain, - sendToMain: sendToMain, - initialData: initialData, - handler: (ref, task) async { - final stream = switch (task.data) { - HttpInterfaceScanTask data => - ref - .read(httpScanDiscoveryProvider) - .getStream( - networkInterface: data.networkInterface, - port: data.port, - https: data.https, - ), - HttpFavoriteScanTask data => - ref - .read(httpScanDiscoveryProvider) - .getFavoriteStream( - devices: data.favorites, - https: data.https, - ), - }; - await for (final device in stream) { - sendToMain( - IsolateTaskStreamResult.event( - id: task.id, - data: device, - ), - ); - } - sendToMain( - IsolateTaskStreamResult.done( - id: task.id, - ), - ); - }, - ); -} diff --git a/packages/localsend_isolates/lib/src/isolate/child/multicast_discovery_isolate.dart b/packages/localsend_isolates/lib/src/isolate/child/multicast_discovery_isolate.dart deleted file mode 100644 index 33502ef4..00000000 --- a/packages/localsend_isolates/lib/src/isolate/child/multicast_discovery_isolate.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:localsend_isolates/model/device.dart'; -import 'package:localsend_isolates/src/isolate/child/main.dart'; -import 'package:localsend_isolates/src/isolate/dto/send_to_isolate_data.dart'; -import 'package:localsend_isolates/src/task/discovery/multicast_discovery.dart'; - -sealed class MulticastTask {} - -/// Sends an announcement to all devices to all network interfaces. -/// They will respond with their device information. -/// -/// This is not wrapped in an [IsolateTask] because -/// - (1) it is not important if the device was found by this specific announcement or another one -/// - (2) it is not 100% accurate to know if a device was found by this announcement or another one -class MulticastAnnouncementTask implements MulticastTask { - static const instance = MulticastAnnouncementTask._(); - - const MulticastAnnouncementTask._(); -} - -/// Restarts the listener. -class MulticastRestartListenerTask implements MulticastTask { - static const instance = MulticastRestartListenerTask._(); - - const MulticastRestartListenerTask._(); -} - -Future setupMulticastDiscoveryIsolate( - Stream> receiveFromMain, - void Function(Device) sendToMain, - InitialData initialData, -) async { - await setupChildIsolateHelper( - debugLabel: 'MulticastDiscoveryIsolate', - receiveFromMain: receiveFromMain, - sendToMain: sendToMain, - initialData: initialData, - init: (ref) async { - ref.read(multicastDiscoveryProvider).startListener().listen((event) { - sendToMain(event); - }); - }, - handler: (ref, task) async { - switch (task) { - case MulticastAnnouncementTask(): - await ref.read(multicastDiscoveryProvider).sendAnnouncement(); - break; - case MulticastRestartListenerTask(): - ref.read(multicastDiscoveryProvider).restartListener(); - break; - } - }, - ); -} diff --git a/packages/localsend_isolates/lib/src/isolate/parent/actions.dart b/packages/localsend_isolates/lib/src/isolate/parent/actions.dart index 7d1d0f61..d45185d3 100644 --- a/packages/localsend_isolates/lib/src/isolate/parent/actions.dart +++ b/packages/localsend_isolates/lib/src/isolate/parent/actions.dart @@ -2,8 +2,7 @@ import 'dart:async'; import 'package:localsend_isolates/model/device.dart'; import 'package:localsend_isolates/rust/api/server.dart' show WebSendParams; -import 'package:localsend_isolates/src/isolate/child/http_scan_discovery_isolate.dart'; -import 'package:localsend_isolates/src/isolate/child/multicast_discovery_isolate.dart'; +import 'package:localsend_isolates/src/isolate/child/discovery_isolate.dart'; import 'package:localsend_isolates/src/isolate/child/server_isolate.dart'; import 'package:localsend_isolates/src/isolate/child/upload_isolate.dart'; import 'package:localsend_isolates/src/isolate/dto/send_to_isolate_data.dart'; @@ -12,12 +11,37 @@ import 'package:refena_flutter/refena_flutter.dart'; import 'package:typed_isolates/id.dart'; import 'package:typed_isolates/typed_isolates.dart'; -class IsolateInterfaceHttpDiscoveryAction extends ReduxActionWithResult> { +/// Starts the discovery and returns the stream of confirmed devices: +/// answered announcements, scan results and devices fed in via +/// [IsolateDiscoveryAddDeviceAction] all arrive on this one stream. +/// The stream never completes; it survives [IsolateDiscoveryRestartAction]s. +class IsolateDiscoveryListenAction extends ReduxActionWithResult> { + @override + (ParentIsolateState, Stream) reduce() { + final connection = state.discovery; + if (connection == null) { + throw StateError('discovery is not initialized'); + } + + return ( + state, + connection.sendWrappedTaskAndListenStream( + task: DiscoveryListenTask(), + ), + ); + } +} + +/// Scans the subnet of one network interface over HTTP, +/// for networks that do not carry multicast. +/// The returned stream completes (without events) when the scan is finished; +/// the found devices arrive on the [IsolateDiscoveryListenAction] stream. +class IsolateDiscoverySubnetScanAction extends ReduxActionWithResult> { final String networkInterface; final int port; final bool https; - IsolateInterfaceHttpDiscoveryAction({ + IsolateDiscoverySubnetScanAction({ required this.networkInterface, required this.port, required this.https, @@ -25,68 +49,71 @@ class IsolateInterfaceHttpDiscoveryAction extends ReduxActionWithResult) reduce() { - final connection = state.httpScanDiscovery; + final connection = state.discovery; if (connection == null) { - throw StateError('httpScanDiscovery is not initialized'); + throw StateError('discovery is not initialized'); } - final task = HttpInterfaceScanTask( - networkInterface: networkInterface, - port: port, - https: https, - ); - return ( state, connection.sendWrappedTaskAndListenStream( - task: task, + task: DiscoverySubnetScanTask( + networkInterface: networkInterface, + port: port, + https: https, + ), ), ); } } -class IsolateFavoriteHttpDiscoveryAction extends ReduxActionWithResult> { +/// Probes the known addresses of the favorites over HTTP. +/// The returned stream completes (without events) when every favorite has been +/// probed; the found devices arrive on the [IsolateDiscoveryListenAction] stream. +class IsolateDiscoveryFavoriteScanAction extends ReduxActionWithResult> { final List<(String, int)> favorites; final bool https; - IsolateFavoriteHttpDiscoveryAction({ + IsolateDiscoveryFavoriteScanAction({ required this.favorites, required this.https, }); @override (ParentIsolateState, Stream) reduce() { - final connection = state.httpScanDiscovery; + final connection = state.discovery; if (connection == null) { - throw StateError('httpScanDiscovery is not initialized'); + throw StateError('discovery is not initialized'); } - final task = HttpFavoriteScanTask( - favorites: favorites, - https: https, - ); - return ( state, connection.sendWrappedTaskAndListenStream( - task: task, + task: DiscoveryFavoriteScanTask( + favorites: favorites, + https: https, + ), ), ); } } -class IsolateSendMulticastAnnouncementAction extends ReduxAction { +/// Sends an announcement which makes every other LocalSend device on the +/// network register with this device's HTTP server. +class IsolateDiscoveryAnnouncementAction extends ReduxAction { @override ParentIsolateState reduce() { - final connection = state.multicastDiscovery; + final connection = state.discovery; if (connection == null) { - throw StateError('multicastDiscovery is not initialized'); + throw StateError('discovery is not initialized'); } connection.sendToIsolate( SendToIsolateData( syncState: null, - data: MulticastAnnouncementTask.instance, + data: IsolateTask( + data: DiscoveryAnnouncementTask(), + ), ), ); @@ -94,18 +121,53 @@ class IsolateSendMulticastAnnouncementAction extends ReduxAction { +/// Restarts the discovery, e.g. after the port or the network settings changed. +class IsolateDiscoveryRestartAction extends ReduxAction { @override ParentIsolateState reduce() { - final connection = state.multicastDiscovery; + final connection = state.discovery; if (connection == null) { - throw StateError('multicastDiscovery is not initialized'); + throw StateError('discovery is not initialized'); } connection.sendToIsolate( SendToIsolateData( syncState: null, - data: MulticastRestartListenerTask.instance, + data: IsolateTask( + data: DiscoveryRestartTask(), + ), + ), + ); + + return state; + } +} + +/// Feeds a device confirmed outside of the discovery into the discovery store, +/// e.g. one that registered with this device's HTTP server. The device comes +/// back on the [IsolateDiscoveryListenAction] stream. +class IsolateDiscoveryAddDeviceAction extends ReduxAction { + final Device device; + + IsolateDiscoveryAddDeviceAction({ + required this.device, + }); + + @override + ParentIsolateState reduce() { + final connection = state.discovery; + if (connection == null) { + throw StateError('discovery is not initialized'); + } + + connection.sendToIsolate( + SendToIsolateData( + syncState: null, + data: IsolateTask( + data: DiscoveryAddDeviceTask( + device: device, + ), + ), ), ); diff --git a/packages/localsend_isolates/lib/src/isolate/parent/actions_sync.dart b/packages/localsend_isolates/lib/src/isolate/parent/actions_sync.dart index 5ace0651..efdb57bb 100644 --- a/packages/localsend_isolates/lib/src/isolate/parent/actions_sync.dart +++ b/packages/localsend_isolates/lib/src/isolate/parent/actions_sync.dart @@ -119,13 +119,7 @@ class _PublishSyncStateAction extends ReduxAction, SendToIsolateData>>? httpScanDiscovery; - final IsolateConnector>? multicastDiscovery; + final IsolateConnector, SendToIsolateData>>? discovery; final IsolateConnector, SendToIsolateData>>? httpUpload; final IsolateConnector, SendToIsolateData>>? httpServer; ParentIsolateState({ required this.syncState, - required this.httpScanDiscovery, - required this.multicastDiscovery, + required this.discovery, required this.httpUpload, required this.httpServer, }); static ParentIsolateState initial(SyncState syncState) => ParentIsolateState( syncState: syncState, - httpScanDiscovery: null, - multicastDiscovery: null, + discovery: null, httpUpload: null, httpServer: null, ); @@ -66,17 +62,8 @@ class IsolateController extends ReduxNotifier { class IsolateSetupAction extends AsyncReduxAction { @override Future reduce() async { - final httpScanDiscovery = - await TypedIsolates.startIsolate, SendToIsolateData>, InitialData>( - task: setupHttpScanDiscoveryIsolate, - param: InitialData( - syncState: state.syncState, - logLevel: Logger.root.level, - ), - ); - - final multicastDiscovery = await TypedIsolates.startIsolate, InitialData>( - task: setupMulticastDiscoveryIsolate, + final discovery = await TypedIsolates.startIsolate, SendToIsolateData>, InitialData>( + task: setupDiscoveryIsolate, param: InitialData( syncState: state.syncState, logLevel: Logger.root.level, @@ -102,8 +89,7 @@ class IsolateSetupAction extends AsyncReduxAction { @override ParentIsolateState reduce() { - state.httpScanDiscovery?.isolate.kill(); - state.multicastDiscovery?.isolate.kill(); + state.discovery?.isolate.kill(); state.httpUpload?.isolate.kill(); state.httpServer?.isolate.kill(); return state; diff --git a/packages/localsend_isolates/lib/src/isolate/parent/parent_isolate_provider.mapper.dart b/packages/localsend_isolates/lib/src/isolate/parent/parent_isolate_provider.mapper.dart index e558ab66..50c13db7 100644 --- a/packages/localsend_isolates/lib/src/isolate/parent/parent_isolate_provider.mapper.dart +++ b/packages/localsend_isolates/lib/src/isolate/parent/parent_isolate_provider.mapper.dart @@ -31,24 +31,17 @@ class ParentIsolateStateMapper extends ClassMapperBase { ); static IsolateConnector< IsolateTaskStreamResult, - SendToIsolateData> + SendToIsolateData> >? - _$httpScanDiscovery(ParentIsolateState v) => v.httpScanDiscovery; + _$discovery(ParentIsolateState v) => v.discovery; static const Field< ParentIsolateState, IsolateConnector< IsolateTaskStreamResult, - SendToIsolateData> + SendToIsolateData> > > - _f$httpScanDiscovery = Field('httpScanDiscovery', _$httpScanDiscovery); - static IsolateConnector>? - _$multicastDiscovery(ParentIsolateState v) => v.multicastDiscovery; - static const Field< - ParentIsolateState, - IsolateConnector> - > - _f$multicastDiscovery = Field('multicastDiscovery', _$multicastDiscovery); + _f$discovery = Field('discovery', _$discovery); static IsolateConnector< IsolateTaskStreamResult, SendToIsolateData> @@ -79,8 +72,7 @@ class ParentIsolateStateMapper extends ClassMapperBase { @override final MappableFields fields = const { #syncState: _f$syncState, - #httpScanDiscovery: _f$httpScanDiscovery, - #multicastDiscovery: _f$multicastDiscovery, + #discovery: _f$discovery, #httpUpload: _f$httpUpload, #httpServer: _f$httpServer, }; @@ -88,8 +80,7 @@ class ParentIsolateStateMapper extends ClassMapperBase { static ParentIsolateState _instantiate(DecodingData data) { return ParentIsolateState( syncState: data.dec(_f$syncState), - httpScanDiscovery: data.dec(_f$httpScanDiscovery), - multicastDiscovery: data.dec(_f$multicastDiscovery), + discovery: data.dec(_f$discovery), httpUpload: data.dec(_f$httpUpload), httpServer: data.dec(_f$httpServer), ); @@ -171,11 +162,9 @@ abstract class ParentIsolateStateCopyWith< SyncState? syncState, IsolateConnector< IsolateTaskStreamResult, - SendToIsolateData> + SendToIsolateData> >? - httpScanDiscovery, - IsolateConnector>? - multicastDiscovery, + discovery, IsolateConnector< IsolateTaskStreamResult, SendToIsolateData> @@ -206,15 +195,13 @@ class _ParentIsolateStateCopyWithImpl<$R, $Out> @override $R call({ SyncState? syncState, - Object? httpScanDiscovery = $none, - Object? multicastDiscovery = $none, + Object? discovery = $none, Object? httpUpload = $none, Object? httpServer = $none, }) => $apply( FieldCopyWithData({ if (syncState != null) #syncState: syncState, - if (httpScanDiscovery != $none) #httpScanDiscovery: httpScanDiscovery, - if (multicastDiscovery != $none) #multicastDiscovery: multicastDiscovery, + if (discovery != $none) #discovery: discovery, if (httpUpload != $none) #httpUpload: httpUpload, if (httpServer != $none) #httpServer: httpServer, }), @@ -222,14 +209,7 @@ class _ParentIsolateStateCopyWithImpl<$R, $Out> @override ParentIsolateState $make(CopyWithData data) => ParentIsolateState( syncState: data.get(#syncState, or: $value.syncState), - httpScanDiscovery: data.get( - #httpScanDiscovery, - or: $value.httpScanDiscovery, - ), - multicastDiscovery: data.get( - #multicastDiscovery, - or: $value.multicastDiscovery, - ), + discovery: data.get(#discovery, or: $value.discovery), httpUpload: data.get(#httpUpload, or: $value.httpUpload), httpServer: data.get(#httpServer, or: $value.httpServer), ); diff --git a/packages/localsend_isolates/lib/src/task/discovery/discovery.dart b/packages/localsend_isolates/lib/src/task/discovery/discovery.dart new file mode 100644 index 00000000..6b02e33a --- /dev/null +++ b/packages/localsend_isolates/lib/src/task/discovery/discovery.dart @@ -0,0 +1,183 @@ +import 'dart:async'; + +import 'package:localsend_isolates/constants.dart'; +import 'package:localsend_isolates/model/device.dart'; +import 'package:localsend_isolates/model/dto/multicast_dto.dart'; +import 'package:localsend_isolates/rust/api/discovery.dart'; +import 'package:localsend_isolates/rust/api/server.dart' show ProtocolTypeV2; +import 'package:localsend_isolates/src/isolate/child/sync_provider.dart'; +import 'package:localsend_isolates/util/rust.dart'; +import 'package:logging/logging.dart'; +import 'package:refena_flutter/refena_flutter.dart'; + +final _logger = Logger('Discovery'); + +final discoveryProvider = Provider((ref) { + return DiscoveryService(ref); +}); + +/// Owns the Rust discovery (`core/discovery`): the multicast sockets, the +/// register requests answering announcements, the subnet scans and the store +/// of confirmed devices all live on the Rust side. This service configures it +/// from the [syncProvider] state and maps every confirmation to a [Device]. +class DiscoveryService { + DiscoveryService(this._ref); + + final Ref _ref; + RsDiscovery? _discovery; + Completer _retryCompleter = Completer(); + bool _listening = false; + + /// Starts the discovery and emits every device confirmation: + /// answered announcements, scan results and devices fed in + /// via [addDevice] all arrive on this one stream. + Stream startListener() { + if (_listening) { + _logger.info('Already listening to discovery'); + return const Stream.empty(); + } + + _listening = true; + + final devices = StreamController(); + unawaited(_runListener(devices)); + return devices.stream; + } + + Future _runListener(StreamController devices) async { + // Announcements are only answered while the server runs: the answer would + // advertise an HTTP port that nobody listens on otherwise. + _ref.stream(syncProvider).listen((event) { + if (event.prev.serverRunning != event.next.serverRunning) { + unawaited(_discovery?.setAnswerAnnouncements(answer: event.next.serverRunning)); + } + }); + + while (true) { + final syncState = _ref.read(syncProvider); + + final RsDiscovery discovery; + try { + discovery = await startDiscovery( + group: syncState.multicastGroup, + port: syncState.port, + networkWhitelist: syncState.networkWhitelist, + networkBlacklist: syncState.networkBlacklist, + alias: syncState.alias, + version: protocolVersion, + deviceModel: syncState.deviceInfo.deviceModel, + deviceType: syncState.deviceInfo.deviceType.toRust(), + fingerprint: syncState.securityContext.certificateHash, + protocol: syncState.protocol == ProtocolType.https ? ProtocolTypeV2.https : ProtocolTypeV2.http, + download: syncState.download, + certPem: syncState.securityContext.certificate, + privateKeyPem: syncState.securityContext.privateKey, + timeoutMs: BigInt.from(syncState.discoveryTimeout), + ); + } catch (e) { + _logger.warning('Could not start discovery (group: ${syncState.multicastGroup}, port: ${syncState.port})', e); + // Wait for the next restart request instead of hot-looping + _retryCompleter = Completer(); + await _retryCompleter.future; + continue; + } + + final multicastError = await discovery.multicastError(); + if (multicastError != null) { + _logger.warning('Discovery runs without multicast (group: ${syncState.multicastGroup}, port: ${syncState.port}): $multicastError'); + } + + if (!_ref.read(syncProvider).serverRunning) { + await discovery.setAnswerAnnouncements(answer: false); + } + + _discovery = discovery; + + // Tell everyone in the network that I am online. + unawaited(discovery.announce()); + + await for (final device in discovery.listen()) { + if (!devices.isClosed) { + devices.add(device.toDevice()); + } + } + + // The stream ended because [restartListener] stopped the discovery. + _discovery = null; + } + } + + /// Restarts the discovery, e.g. after the port or the network settings changed. + void restartListener() { + final discovery = _discovery; + if (discovery != null) { + // Ends the listen stream, which makes [startListener] rebind. + unawaited(discovery.stop()); + } else if (!_retryCompleter.isCompleted) { + // Starting failed previously; let [startListener] try again. + _retryCompleter.complete(); + } + } + + /// Sends an announcement which triggers a response on every LocalSend member of the network. + Future sendAnnouncement() async { + final discovery = _discovery; + if (discovery == null) { + _logger.info('Discovery is not running, skipping announcement'); + return; + } + + _logger.info('Announce via UDP'); + await discovery.announce(); + } + + /// Scans the subnet of [networkInterface] by probing every host over HTTP, + /// for networks that do not carry multicast. + /// Found devices arrive on the [startListener] stream; this method returns + /// once the whole scan has finished. + Future scanSubnet({required String networkInterface, required int port, required bool https}) async { + final discovery = _discovery; + if (discovery == null) { + _logger.info('Discovery is not running, skipping subnet scan'); + return; + } + + await discovery.scanSubnet( + interfaceIp: networkInterface, + port: port, + protocol: https ? ProtocolTypeV2.https : ProtocolTypeV2.http, + ); + } + + /// Probes the known addresses of the favorites. + /// Found devices arrive on the [startListener] stream; this method returns + /// once every favorite has been probed. + Future discoverFavorites({required List<(String, int)> devices, required bool https}) async { + final discovery = _discovery; + if (discovery == null) { + _logger.info('Discovery is not running, skipping favorite scan'); + return; + } + + final protocol = https ? ProtocolTypeV2.https : ProtocolTypeV2.http; + await Future.wait([ + for (final (host, port) in devices) discovery.discover(host: host, port: port, protocol: protocol), + ]); + } + + /// Feeds a device confirmed outside of the discovery into the store, e.g. + /// one that registered with this device's HTTP server. + /// The device comes back on the [startListener] stream. + Future addDevice(Device device) async { + final discovery = _discovery; + final ip = device.ip; + if (discovery == null || ip == null) { + // A device lost here re-appears on its next register request, which the + // announcement sent when the discovery (re)starts triggers by itself. + _logger.info('Discovery is not running, skipping device ${device.alias} ($ip)'); + return; + } + + await discovery.addDevice(device: device.toRsDiscoveredDevice(ip)); + } +} diff --git a/packages/localsend_isolates/lib/src/task/discovery/http_scan_discovery.dart b/packages/localsend_isolates/lib/src/task/discovery/http_scan_discovery.dart deleted file mode 100644 index 5cb85363..00000000 --- a/packages/localsend_isolates/lib/src/task/discovery/http_scan_discovery.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:localsend_isolates/model/device.dart'; -import 'package:localsend_isolates/src/task/discovery/http_target_discovery.dart'; -import 'package:logging/logging.dart'; -import 'package:pool/pool.dart'; -import 'package:refena_flutter/refena_flutter.dart'; - -final _logger = Logger('HttpScanDiscovery'); - -const _concurrency = 50; - -final httpScanDiscoveryProvider = ViewProvider((ref) { - return HttpScanDiscoveryService( - targetedDiscoveryService: ref.accessor(httpTargetDiscoveryProvider), - ); -}); - -class _CancelToken { - bool cancelled = false; -} - -/// The token of the currently running scan per network interface. -Map _cancelTokens = {}; - -class HttpScanDiscoveryService { - final StateAccessor _targetedDiscoveryService; - - HttpScanDiscoveryService({ - required StateAccessor targetedDiscoveryService, - }) : _targetedDiscoveryService = targetedDiscoveryService; - - Stream getStream({required String networkInterface, required int port, required bool https}) { - final ipList = List.generate(256, (i) => '${networkInterface.split('.').take(3).join('.')}.$i').where((ip) => ip != networkInterface).toList(); - - // Let the previous scan of this interface skip its remaining requests, so its stream ends. - _cancelTokens[networkInterface]?.cancelled = true; - final token = _cancelTokens[networkInterface] = _CancelToken(); - - final stream = Pool(_concurrency).forEach(ipList, (ip) async => token.cancelled ? null : _doRequest(ip, port, https)); - return stream.where((device) => device != null).cast(); - } - - Stream getFavoriteStream({required List<(String, int)> devices, required bool https}) { - final stream = Pool(_concurrency).forEach<(String, int), Device?>(devices, (device) => _doRequest(device.$1, device.$2, https)); - return stream.where((device) => device != null).cast(); - } - - Future _doRequest(String currentIp, int port, bool https) async { - _logger.fine('Requesting $currentIp'); - final device = await _targetedDiscoveryService.state.discover( - ip: currentIp, - port: port, - https: https, - onError: null, - ); - if (device != null) { - _logger.info('[DISCOVER/TCP] ${device.alias} (${device.ip}, model: ${device.deviceModel})'); - } - - return device; - } -} diff --git a/packages/localsend_isolates/lib/src/task/discovery/http_target_discovery.dart b/packages/localsend_isolates/lib/src/task/discovery/http_target_discovery.dart deleted file mode 100644 index d9b3f34e..00000000 --- a/packages/localsend_isolates/lib/src/task/discovery/http_target_discovery.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:localsend_isolates/api_route_builder.dart'; -import 'package:localsend_isolates/constants.dart'; -import 'package:localsend_isolates/model/device.dart'; -import 'package:localsend_isolates/rust/api/http.dart'; -import 'package:localsend_isolates/rust/api/model.dart' as rust_model; -import 'package:localsend_isolates/src/isolate/child/http_provider.dart'; -import 'package:localsend_isolates/src/isolate/child/sync_provider.dart'; -import 'package:localsend_isolates/util/rust.dart'; -import 'package:logging/logging.dart'; -import 'package:refena_flutter/refena_flutter.dart'; - -final _logger = Logger('TargetedDiscovery'); - -final httpTargetDiscoveryProvider = ViewProvider((ref) { - final client = ref.watch(httpProvider).discovery; - final syncState = ref.watch(syncProvider); - return HttpTargetDiscoveryService( - client, - syncState.toRegisterDto(), - syncState.securityContext.certificateHash, - ); -}); - -/// Try to discover a single device using the given IP and port. -class HttpTargetDiscoveryService { - final RsHttpClient _client; - final rust_model.RegisterDto _registerDto; - final String _fingerprint; - - HttpTargetDiscoveryService(this._client, this._registerDto, this._fingerprint); - - Future discover({ - required String ip, - required int port, - required bool https, - void Function(String url, Object? error)? onError = defaultErrorPrinter, - }) async { - final url = ApiRoute.register.targetRaw(ip, port, https, protocolVersion); - try { - final response = await _client.register( - protocol: https ? rust_model.ProtocolType.https : rust_model.ProtocolType.http, - ip: ip, - port: port, - payload: _registerDto, - ); - if (response.body.token == _fingerprint) { - // discovered itself - return null; - } - return response.body.toDevice(ip, port, https, HttpDiscovery(ip: ip)); - } catch (e) { - onError?.call(url, e); - return null; - } - } - - static void defaultErrorPrinter(String url, Object? error) { - _logger.warning('$url: $error'); - } -} diff --git a/packages/localsend_isolates/lib/src/task/discovery/multicast_discovery.dart b/packages/localsend_isolates/lib/src/task/discovery/multicast_discovery.dart deleted file mode 100644 index 9e625a0f..00000000 --- a/packages/localsend_isolates/lib/src/task/discovery/multicast_discovery.dart +++ /dev/null @@ -1,143 +0,0 @@ -import 'dart:async'; - -import 'package:localsend_isolates/constants.dart'; -import 'package:localsend_isolates/model/device.dart'; -import 'package:localsend_isolates/model/dto/multicast_dto.dart'; -import 'package:localsend_isolates/rust/api/multicast.dart'; -import 'package:localsend_isolates/rust/api/server.dart' show ProtocolTypeV2; -import 'package:localsend_isolates/src/isolate/child/http_provider.dart'; -import 'package:localsend_isolates/src/isolate/child/sync_provider.dart'; -import 'package:localsend_isolates/util/rust.dart'; -import 'package:logging/logging.dart'; -import 'package:refena_flutter/refena_flutter.dart'; - -final _logger = Logger('Multicast'); - -final multicastDiscoveryProvider = Provider((ref) { - return MulticastService(ref); -}); - -class MulticastService { - MulticastService(this._ref); - - final Ref _ref; - RsMulticast? _multicast; - Completer _retryCompleter = Completer(); - bool _listening = false; - - /// Binds the UDP sockets and listens to multicast announcements. - Stream startListener() { - if (_listening) { - _logger.info('Already listening to multicast'); - return const Stream.empty(); - } - - _listening = true; - - // Verified devices are pushed in as [_answerAnnouncement] resolves, which - // runs concurrently: one unreachable peer must not hold up the others. - final devices = StreamController(); - unawaited(_runListener(devices)); - return devices.stream; - } - - Future _runListener(StreamController devices) async { - while (true) { - final syncState = _ref.read(syncProvider); - - final RsMulticast multicast; - try { - multicast = await startMulticast( - group: syncState.multicastGroup, - port: syncState.port, - networkWhitelist: syncState.networkWhitelist, - networkBlacklist: syncState.networkBlacklist, - alias: syncState.alias, - version: protocolVersion, - deviceModel: syncState.deviceInfo.deviceModel, - deviceType: syncState.deviceInfo.deviceType.toRust(), - fingerprint: syncState.securityContext.certificateHash, - protocol: syncState.protocol == ProtocolType.https ? ProtocolTypeV2.https : ProtocolTypeV2.http, - download: syncState.download, - ); - } catch (e) { - _logger.warning('Could not start multicast discovery (group: ${syncState.multicastGroup}, port: ${syncState.port})', e); - // Wait for the next restart request instead of hot-looping - _retryCompleter = Completer(); - await _retryCompleter.future; - continue; - } - - _multicast = multicast; - - // Tell everyone in the network that I am online. - unawaited(multicast.announce()); - - await for (final event in multicast.listen()) { - if (!_ref.read(syncProvider).serverRunning) { - // only respond when server is running - continue; - } - - unawaited(() async { - final device = await _answerAnnouncement(event.message.toDevice(event.ip)); - if (device != null && !devices.isClosed) { - devices.add(device); - } - }()); - } - - // The stream ended because [restartListener] stopped the discovery. - _multicast = null; - } - } - - /// Restarts the listener, e.g. after the port or the network settings changed. - void restartListener() { - final multicast = _multicast; - if (multicast != null) { - // Ends the listen stream, which makes [startListener] rebind. - unawaited(multicast.stop()); - } else if (!_retryCompleter.isCompleted) { - // Starting failed previously; let [startListener] try again. - _retryCompleter.complete(); - } - } - - /// Sends an announcement which triggers a response on every LocalSend member of the network. - Future sendAnnouncement() async { - final multicast = _multicast; - if (multicast == null) { - _logger.info('Multicast discovery is not running, skipping announcement'); - return; - } - - _logger.info('Announce via UDP'); - await multicast.announce(); - } - - /// Responds to an announcement and returns the peer. - /// Data from the multicast announcement is ignored. - /// - /// Returns null if the peer could not be reached or could not be verified. - Future _answerAnnouncement(Device peer) async { - final clients = _ref.read(httpProvider); - try { - final response = await clients - .pinnedTo(peer.fingerprint, timeoutMs: clients.discoveryTimeout) - .register( - protocol: peer.getProtocolType(), - ip: peer.ip!, - port: peer.port, - payload: _ref.read(syncProvider).toRegisterDto(), - ); - - _logger.info('Respond to announcement of ${peer.alias} (${peer.ip}, model: ${peer.deviceModel}) via TCP'); - - return response.body.toDevice(peer.ip!, peer.port, peer.https, const MulticastDiscovery()); - } catch (e) { - _logger.warning('Could not respond to announcement of ${peer.alias} (${peer.ip})', e); - return null; - } - } -} diff --git a/packages/localsend_isolates/lib/util/rust.dart b/packages/localsend_isolates/lib/util/rust.dart index e395c1f8..e5f4c405 100644 --- a/packages/localsend_isolates/lib/util/rust.dart +++ b/packages/localsend_isolates/lib/util/rust.dart @@ -2,9 +2,9 @@ import 'package:localsend_isolates/constants.dart'; import 'package:localsend_isolates/model/device.dart'; import 'package:localsend_isolates/model/dto/file_dto.dart'; import 'package:localsend_isolates/model/dto/multicast_dto.dart'; +import 'package:localsend_isolates/rust/api/discovery.dart' as rust_discovery; import 'package:localsend_isolates/rust/api/http.dart' as rust_http; import 'package:localsend_isolates/rust/api/model.dart' as rust_model; -import 'package:localsend_isolates/rust/api/multicast.dart' as rust_multicast; import 'package:localsend_isolates/rust/api/server.dart' as rust_server; import 'package:localsend_isolates/src/isolate/child/sync_provider.dart'; import 'package:mime/mime.dart'; @@ -129,11 +129,11 @@ extension RustFileDtoExt on rust_model.FileDto { } } -extension MulticastMessageV2Ext on rust_multicast.MulticastMessageV2 { - Device toDevice(String ip) { +extension RsDiscoveredDeviceExt on rust_discovery.RsDiscoveredDevice { + Device toDevice() { return Device( signalingId: null, - ip: ip, + ip: host, version: version, port: port, https: protocol == rust_server.ProtocolTypeV2.https, @@ -142,7 +142,23 @@ extension MulticastMessageV2Ext on rust_multicast.MulticastMessageV2 { deviceModel: deviceModel, deviceType: deviceType?.toDart() ?? DeviceType.desktop, download: download, - discoveryMethods: {MulticastDiscovery()}, + discoveryMethods: {HttpDiscovery(ip: host)}, + ); + } +} + +extension DeviceToRsDiscoveredDeviceExt on Device { + rust_discovery.RsDiscoveredDevice toRsDiscoveredDevice(String ip) { + return rust_discovery.RsDiscoveredDevice( + alias: alias, + version: version, + deviceModel: deviceModel, + deviceType: deviceType.toRust(), + fingerprint: fingerprint, + host: ip, + port: port, + protocol: https ? rust_server.ProtocolTypeV2.https : rust_server.ProtocolTypeV2.http, + download: download, ); } } diff --git a/packages/localsend_isolates/rust/src/api/discovery.rs b/packages/localsend_isolates/rust/src/api/discovery.rs new file mode 100644 index 00000000..c7b0feae --- /dev/null +++ b/packages/localsend_isolates/rust/src/api/discovery.rs @@ -0,0 +1,264 @@ +use crate::frb_generated::StreamSink; +use localsend::discovery::{ + DeviceChannel, DeviceIdentity, DiscoveredDevice, DiscoveryConfig, DiscoveryEvent, + DiscoveryHandle, HttpChannel, +}; +use localsend::http::dto_v2::ProtocolTypeV2; +use localsend::model::discovery::DeviceType; +use localsend::multicast::{DEFAULT_MULTICAST_GROUP_V6, InterfaceFilter, MulticastDevice}; +use std::time::Duration; +use tokio::sync::{Mutex, mpsc, oneshot}; + +/// A device that was confirmed over HTTP by the discovery: it answered a +/// register request, or its register request was accepted by our server and +/// was fed back via [RsDiscovery::add_device]. +/// +/// Emitted on [RsDiscovery::listen] for every confirmation, so a device +/// re-appears whenever it re-announces itself or is re-discovered. +pub struct RsDiscoveredDevice { + pub alias: String, + + /// Protocol version (major.minor) implemented by the device. + pub version: String, + + pub device_model: Option, + + pub device_type: Option, + + /// Fingerprint identifying the device; devices are deduplicated by it. + pub fingerprint: String, + + /// The host the device was confirmed on: an IP address, or the scoped + /// form `fe80::1%3` for link-local IPv6 (the Rust HTTP client accepts + /// both back as a host). + pub host: String, + + /// The port of the device's HTTP server. + pub port: u16, + + pub protocol: ProtocolTypeV2, + + /// Whether the device's download API is active. + pub download: bool, +} + +pub struct RsDiscovery { + handle: DiscoveryHandle, + event_rx: Mutex>>, + stop_tx: Mutex>>, +} + +/// Starts the discovery: binds the UDP multicast sockets on all usable +/// network interfaces, answers announcements of other devices with an HTTP +/// register request, and keeps the store of confirmed devices. +/// +/// Announcements are received from the IPv4 [group] and, as a LocalSend +/// extension, from the (currently hardcoded) IPv6 group `ff12::fd3a:e420`. +/// +/// [port] is used both to bind the multicast sockets and as the HTTP server +/// port announced to other devices. [cert_pem] and [private_key_pem] are this +/// device's TLS identity, sent as client certificate with every register +/// request; [fingerprint] must be the certificate's SHA-256 fingerprint. +/// +/// Nothing is announced until [RsDiscovery::announce] is called. +/// +/// Cannot fail besides an invalid [group]: when no multicast socket could be +/// bound (e.g. the port is taken by another process), discovery still runs +/// without multicast — see [RsDiscovery::multicast_error] — and still learns +/// about devices through [RsDiscovery::discover], [RsDiscovery::scan_subnet] +/// and [RsDiscovery::add_device]. +pub async fn start_discovery( + group: String, + port: u16, + network_whitelist: Option>, + network_blacklist: Option>, + alias: String, + version: String, + device_model: Option, + device_type: Option, + fingerprint: String, + protocol: ProtocolTypeV2, + download: bool, + cert_pem: String, + private_key_pem: String, + timeout_ms: u64, +) -> anyhow::Result { + let group = group + .parse() + .map_err(|_| anyhow::anyhow!("Invalid multicast group: {group}"))?; + + let (event_tx, event_rx) = mpsc::channel::(16); + let (stop_tx, stop_rx) = oneshot::channel::<()>(); + + let handle = localsend::discovery::start( + DiscoveryConfig { + group, + // Hardcoded for now; becomes a parameter once the app exposes it. + group_v6: Some(DEFAULT_MULTICAST_GROUP_V6), + port, + interface_filter: InterfaceFilter { + whitelist: network_whitelist, + blacklist: network_blacklist, + }, + device: MulticastDevice { + alias, + version, + device_model, + device_type, + fingerprint, + port, + protocol, + download, + }, + identity: DeviceIdentity { + cert_pem, + private_key_pem, + }, + timeout: Duration::from_millis(timeout_ms), + event_tx: Some(event_tx), + }, + stop_rx, + ) + .await; + + Ok(RsDiscovery { + handle, + event_rx: Mutex::new(Some(event_rx)), + stop_tx: Mutex::new(Some(stop_tx)), + }) +} + +impl RsDiscovery { + /// Emits a [RsDiscoveredDevice] for every device confirmation until the + /// discovery is stopped. Can only be listened to once. + pub async fn listen(&self, sink: StreamSink) { + let Some(mut event_rx) = self.event_rx.lock().await.take() else { + let _ = sink.add_error(anyhow::anyhow!("Discovery events already listened to")); + return; + }; + + while let Some(event) = event_rx.recv().await { + let (DiscoveryEvent::Discovered { device } | DiscoveryEvent::Updated { device }) = + event; + let _ = sink.add(rs_device(device)); + } + } + + /// The reason the multicast sockets could not be bound, when they could + /// not. Discovery then neither hears nor sends announcements. + pub fn multicast_error(&self) -> Option { + self.handle.multicast_error().map(|err| format!("{err:#}")) + } + + /// Announces this device to the network, which makes every other LocalSend + /// device on it register with this device over HTTP. + /// + /// Devices registering in response arrive at the application as server + /// events, not here: feed them back via [RsDiscovery::add_device]. + /// + /// Returns once the whole announcement burst has been sent, which takes a + /// few seconds, or immediately once the discovery has been stopped or + /// multicast is unavailable. + pub async fn announce(&self) { + self.handle.announce().await; + } + + /// Sets whether announcements of other devices are answered with a + /// register request (the answer is what makes the announcing device enter + /// the store). On by default. + /// + /// Turned off while the HTTP server is not running: the answer would + /// advertise a port that nobody listens on. + pub fn set_answer_announcements(&self, answer: bool) { + self.handle.set_answer_announcements(answer); + } + + /// Discovers a device at a known address, e.g. a favorite or a peer that + /// multicast does not reach, by sending it a register request. + /// + /// The confirmed device is also emitted on [RsDiscovery::listen]. + /// Returns `None` when the device did not answer or answered with this + /// device's own fingerprint (i.e. the device discovered itself). + pub async fn discover( + &self, + host: String, + port: u16, + protocol: ProtocolTypeV2, + ) -> Option { + match self.handle.discover(&host, port, protocol).await { + Ok(found) => found.map(|found| rs_device(found.device)), + Err(err) => { + tracing::debug!("Could not discover {host}:{port}: {err:#}"); + None + } + } + } + + /// Scans the `/24` subnet of the local interface address [interface_ip] + /// by sending every other host a register request, for networks that do + /// not carry multicast. + /// + /// The found devices are emitted on [RsDiscovery::listen] as they answer; + /// this method returns once the whole scan has finished. At most one scan + /// runs per interface: a call for an address that is still being scanned + /// returns immediately. + pub async fn scan_subnet( + &self, + interface_ip: String, + port: u16, + protocol: ProtocolTypeV2, + ) -> anyhow::Result<()> { + let interface_ip = interface_ip + .parse() + .map_err(|_| anyhow::anyhow!("Invalid interface address: {interface_ip}"))?; + self.handle.scan_subnet(interface_ip, port, protocol).await?; + Ok(()) + } + + /// Puts a device confirmed outside of the discovery into the store, e.g. + /// one that answered an announcement by registering with this device's + /// HTTP server. The device is emitted on [RsDiscovery::listen]. + pub async fn add_device(&self, device: RsDiscoveredDevice) { + self.handle + .add_device(DiscoveredDevice { + alias: device.alias, + version: device.version, + device_model: device.device_model, + device_type: device.device_type, + fingerprint: device.fingerprint, + channel: DeviceChannel::Http(HttpChannel { + host: device.host, + port: device.port, + protocol: device.protocol, + }), + download: device.download, + }) + .await; + } + + /// Stops the discovery, which also ends the [RsDiscovery::listen] stream. + /// Returns after all sockets are closed, so the port can be bound again. + pub async fn stop(&self) { + if let Some(stop_tx) = self.stop_tx.lock().await.take() { + let _ = stop_tx.send(()); + self.handle.wait_stopped().await; + } + } +} + +/// The stored device flattened for the Dart side; only the channel of the +/// current confirmation is carried. +fn rs_device(device: DiscoveredDevice) -> RsDiscoveredDevice { + let DeviceChannel::Http(http) = device.channel; + RsDiscoveredDevice { + alias: device.alias, + version: device.version, + device_model: device.device_model, + device_type: device.device_type, + fingerprint: device.fingerprint, + host: http.host, + port: http.port, + protocol: http.protocol, + download: device.download, + } +} diff --git a/packages/localsend_isolates/rust/src/api/mod.rs b/packages/localsend_isolates/rust/src/api/mod.rs index e8d67c7a..97013188 100644 --- a/packages/localsend_isolates/rust/src/api/mod.rs +++ b/packages/localsend_isolates/rust/src/api/mod.rs @@ -1,9 +1,9 @@ pub mod cancel; pub mod crypto; +pub mod discovery; pub mod http; pub mod logging; pub mod model; -pub mod multicast; pub mod server; pub mod stream; pub mod webrtc; diff --git a/packages/localsend_isolates/rust/src/api/multicast.rs b/packages/localsend_isolates/rust/src/api/multicast.rs deleted file mode 100644 index 1d5b1c69..00000000 --- a/packages/localsend_isolates/rust/src/api/multicast.rs +++ /dev/null @@ -1,155 +0,0 @@ -use crate::frb_generated::StreamSink; -use flutter_rust_bridge::frb; -use localsend::model::discovery::DeviceType; -pub use localsend::model::discovery::{MulticastMessageV2, ProtocolTypeV2}; -use localsend::multicast::{ - DEFAULT_MULTICAST_GROUP_V6, InterfaceFilter, MulticastConfig, MulticastDevice, MulticastEvent, - MulticastHandle, -}; -use tokio::sync::{Mutex, mpsc, oneshot}; - -/// Another device announced itself via UDP multicast. -/// -/// The peer expects to be answered with an HTTP register request. -pub struct RsMulticastDiscovered { - /// The address the announcement was sent from. The peer's HTTP server is - /// reachable at this address on `message.port`. - /// - /// A link-local IPv6 source carries its interface scope as `fe80::1%3`, - /// which the Rust HTTP client accepts back as a host. - pub ip: String, - - /// The announcement as it was received. - pub message: MulticastMessageV2, -} - -pub struct RsMulticast { - handle: MulticastHandle, - event_rx: Mutex>>, - stop_tx: Mutex>>, -} - -/// Starts UDP multicast discovery: binds the multicast sockets on all usable -/// network interfaces and listens for announcements of other devices. -/// -/// Announcements are sent to the IPv4 [group] and, as a LocalSend extension, -/// to the (currently hardcoded) IPv6 group `ff12::fd3a:e420`. -/// -/// [port] is used both to bind the multicast sockets and as the HTTP server -/// port announced to other devices. -/// -/// Nothing is announced until [RsMulticast::announce] is called. -/// -/// Fails when [group] is not a valid IPv4 address or when no network -/// interface could be used at all. -pub async fn start_multicast( - group: String, - port: u16, - network_whitelist: Option>, - network_blacklist: Option>, - alias: String, - version: String, - device_model: Option, - device_type: Option, - fingerprint: String, - protocol: ProtocolTypeV2, - download: bool, -) -> anyhow::Result { - let group = group - .parse() - .map_err(|_| anyhow::anyhow!("Invalid multicast group: {group}"))?; - - let (event_tx, event_rx) = mpsc::channel::(16); - let (stop_tx, stop_rx) = oneshot::channel::<()>(); - - let handle = localsend::multicast::start( - MulticastConfig { - group, - // Hardcoded for now; becomes a parameter once the app exposes it. - group_v6: Some(DEFAULT_MULTICAST_GROUP_V6), - port, - interface_filter: InterfaceFilter { - whitelist: network_whitelist, - blacklist: network_blacklist, - }, - device: MulticastDevice { - alias, - version, - device_model, - device_type, - fingerprint, - port, - protocol, - download, - }, - event_tx, - }, - stop_rx, - ) - .await?; - - Ok(RsMulticast { - handle, - event_rx: Mutex::new(Some(event_rx)), - stop_tx: Mutex::new(Some(stop_tx)), - }) -} - -impl RsMulticast { - /// Emits a [RsMulticastDiscovered] for every announcement received from - /// another device until discovery is stopped. - /// Can only be listened to once. - pub async fn listen(&self, sink: StreamSink) { - let Some(mut event_rx) = self.event_rx.lock().await.take() else { - let _ = sink.add_error(anyhow::anyhow!("Multicast events already listened to")); - return; - }; - - while let Some(event) = event_rx.recv().await { - let MulticastEvent::Discovered { - ip, - scope_id, - message, - } = event; - - let _ = sink.add(RsMulticastDiscovered { - ip: match scope_id { - // A link-local source is unreachable without its scope. - Some(scope_id) => format!("{ip}%{scope_id}"), - None => ip.to_string(), - }, - message, - }); - } - } - - /// Announces this device to the network, which makes every other LocalSend - /// device on it register with this device over HTTP. - /// - /// Returns once the whole announcement burst has been sent, which takes a - /// few seconds, or immediately once discovery has been stopped. - pub async fn announce(&self) { - self.handle.announce().await; - } - - /// Stops discovery, which also ends the [RsMulticast::listen] stream. - /// Returns after all sockets are closed, so the port can be bound again. - pub async fn stop(&self) { - if let Some(stop_tx) = self.stop_tx.lock().await.take() { - let _ = stop_tx.send(()); - self.handle.wait_stopped().await; - } - } -} - -#[frb(mirror(MulticastMessageV2))] -pub struct _MulticastMessageV2 { - pub alias: String, - pub version: String, - pub device_model: Option, - pub device_type: Option, - pub fingerprint: String, - pub port: u16, - pub protocol: ProtocolTypeV2, - pub download: bool, -} diff --git a/packages/localsend_isolates/rust/src/frb_generated.rs b/packages/localsend_isolates/rust/src/frb_generated.rs index c9800711..aaa7bcba 100644 --- a/packages/localsend_isolates/rust/src/frb_generated.rs +++ b/packages/localsend_isolates/rust/src/frb_generated.rs @@ -27,8 +27,8 @@ // Section: imports use crate::api::cancel::*; +use crate::api::discovery::*; use crate::api::http::*; -use crate::api::multicast::*; use crate::api::server::*; use crate::api::stream::*; use crate::api::webrtc::*; @@ -44,7 +44,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -286605518; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -895476497; // Section: executor @@ -408,6 +408,481 @@ fn wire__crate__api__cancel__RsCancellationToken_cancel_impl( }, ) } +fn wire__crate__api__discovery__RsDiscovery_add_device_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_add_device", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_device = + ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, ()>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref().await) + } + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok({ + crate::api::discovery::RsDiscovery::add_device( + &*api_that_guard, + api_device, + ) + .await; + })?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__discovery__RsDiscovery_announce_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_announce", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, ()>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref().await) + } + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok({ + crate::api::discovery::RsDiscovery::announce(&*api_that_guard).await; + })?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__discovery__RsDiscovery_discover_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_discover", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_host = ::sse_decode(&mut deserializer); + let api_port = ::sse_decode(&mut deserializer); + let api_protocol = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, ()>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref().await) + } + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok( + crate::api::discovery::RsDiscovery::discover( + &*api_that_guard, + api_host, + api_port, + api_protocol, + ) + .await, + )?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__discovery__RsDiscovery_listen_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_listen", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_sink = >::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, ()>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref().await) + } + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok({ + crate::api::discovery::RsDiscovery::listen(&*api_that_guard, api_sink) + .await; + })?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__discovery__RsDiscovery_multicast_error_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_multicast_error", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok( + crate::api::discovery::RsDiscovery::multicast_error(&*api_that_guard), + )?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__discovery__RsDiscovery_scan_subnet_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_scan_subnet", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_interface_ip = ::sse_decode(&mut deserializer); + let api_port = ::sse_decode(&mut deserializer); + let api_protocol = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref().await) + } + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::discovery::RsDiscovery::scan_subnet( + &*api_that_guard, + api_interface_ip, + api_port, + api_protocol, + ) + .await?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} +fn wire__crate__api__discovery__RsDiscovery_set_answer_announcements_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_set_answer_announcements", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_answer = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok({ + crate::api::discovery::RsDiscovery::set_answer_announcements( + &*api_that_guard, + api_answer, + ); + })?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__discovery__RsDiscovery_stop_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "RsDiscovery_stop", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse::<_, ()>( + (move || async move { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => { + api_that_guard = + Some(api_that.lockable_decode_async_ref().await) + } + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok({ + crate::api::discovery::RsDiscovery::stop(&*api_that_guard).await; + })?; + Ok(output_ok) + })() + .await, + ) + } + }, + ) +} fn wire__crate__api__http__RsHttpClient_cancel_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -1300,182 +1775,6 @@ fn wire__crate__api__server__RsHttpServer_stop_impl( }, ) } -fn wire__crate__api__multicast__RsMulticast_announce_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "RsMulticast_announce", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_that = , - >>::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, ()>( - (move || async move { - let mut api_that_guard = None; - let decode_indices_ = - flutter_rust_bridge::for_generated::lockable_compute_decode_order( - vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, false, - )], - ); - for i in decode_indices_ { - match i { - 0 => { - api_that_guard = - Some(api_that.lockable_decode_async_ref().await) - } - _ => unreachable!(), - } - } - let api_that_guard = api_that_guard.unwrap(); - let output_ok = Result::<_, ()>::Ok({ - crate::api::multicast::RsMulticast::announce(&*api_that_guard).await; - })?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} -fn wire__crate__api__multicast__RsMulticast_listen_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "RsMulticast_listen", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_that = , - >>::sse_decode(&mut deserializer); - let api_sink = >::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, ()>( - (move || async move { - let mut api_that_guard = None; - let decode_indices_ = - flutter_rust_bridge::for_generated::lockable_compute_decode_order( - vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, false, - )], - ); - for i in decode_indices_ { - match i { - 0 => { - api_that_guard = - Some(api_that.lockable_decode_async_ref().await) - } - _ => unreachable!(), - } - } - let api_that_guard = api_that_guard.unwrap(); - let output_ok = Result::<_, ()>::Ok({ - crate::api::multicast::RsMulticast::listen(&*api_that_guard, api_sink) - .await; - })?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} -fn wire__crate__api__multicast__RsMulticast_stop_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "RsMulticast_stop", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_that = , - >>::sse_decode(&mut deserializer); - deserializer.end(); - move |context| async move { - transform_result_sse::<_, ()>( - (move || async move { - let mut api_that_guard = None; - let decode_indices_ = - flutter_rust_bridge::for_generated::lockable_compute_decode_order( - vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, false, - )], - ); - for i in decode_indices_ { - match i { - 0 => { - api_that_guard = - Some(api_that.lockable_decode_async_ref().await) - } - _ => unreachable!(), - } - } - let api_that_guard = api_that_guard.unwrap(); - let output_ok = Result::<_, ()>::Ok({ - crate::api::multicast::RsMulticast::stop(&*api_that_guard).await; - })?; - Ok(output_ok) - })() - .await, - ) - } - }, - ) -} fn wire__crate__api__webrtc__RtcFileReceiver_get_file_id_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -2743,7 +3042,7 @@ fn wire__crate__api__crypto__hash_file_impl( }, ) } -fn wire__crate__api__multicast__start_multicast_impl( +fn wire__crate__api__discovery__start_discovery_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, rust_vec_len_: i32, @@ -2751,7 +3050,7 @@ fn wire__crate__api__multicast__start_multicast_impl( ) { FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "start_multicast", + debug_name: "start_discovery", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, }, @@ -2777,11 +3076,14 @@ fn wire__crate__api__multicast__start_multicast_impl( let api_fingerprint = ::sse_decode(&mut deserializer); let api_protocol = ::sse_decode(&mut deserializer); let api_download = ::sse_decode(&mut deserializer); + let api_cert_pem = ::sse_decode(&mut deserializer); + let api_private_key_pem = ::sse_decode(&mut deserializer); + let api_timeout_ms = ::sse_decode(&mut deserializer); deserializer.end(); move |context| async move { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || async move { - let output_ok = crate::api::multicast::start_multicast( + let output_ok = crate::api::discovery::start_discovery( api_group, api_port, api_network_whitelist, @@ -2793,6 +3095,9 @@ fn wire__crate__api__multicast__start_multicast_impl( api_fingerprint, api_protocol, api_download, + api_cert_pem, + api_private_key_pem, + api_timeout_ms, ) .await?; Ok(output_ok) @@ -2935,17 +3240,6 @@ const _: fn() = || { let _: Option = FileMetadata.modified; let _: Option = FileMetadata.accessed; } - { - let MulticastMessageV2 = None::.unwrap(); - let _: String = MulticastMessageV2.alias; - let _: String = MulticastMessageV2.version; - let _: Option = MulticastMessageV2.device_model; - let _: Option = MulticastMessageV2.device_type; - let _: String = MulticastMessageV2.fingerprint; - let _: u16 = MulticastMessageV2.port; - let _: crate::api::server::ProtocolTypeV2 = MulticastMessageV2.protocol; - let _: bool = MulticastMessageV2.download; - } { let PinConfig = None::.unwrap(); let _: String = PinConfig.pin; @@ -3127,15 +3421,15 @@ flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); -flutter_rust_bridge::frb_generated_moi_arc_impl_value!( - flutter_rust_bridge::for_generated::RustAutoOpaqueInner -); // Section: dart2rust @@ -3227,6 +3521,16 @@ impl SseDecode for RsCancellationToken { } } +impl SseDecode for RsDiscovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); + } +} + impl SseDecode for RsHttpClient { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -3247,16 +3551,6 @@ impl SseDecode for RsHttpServer { } } -impl SseDecode for RsMulticast { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = , - >>::sse_decode(deserializer); - return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); - } -} - impl SseDecode for flutter_rust_bridge::DartOpaque { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -3365,6 +3659,16 @@ impl SseDecode } } +impl SseDecode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return decode_rust_opaque_moi(inner); + } +} + impl SseDecode for RustOpaqueMoi> { @@ -3385,16 +3689,6 @@ impl SseDecode } } -impl SseDecode - for RustOpaqueMoi> -{ - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ::sse_decode(deserializer); - return decode_rust_opaque_moi(inner); - } -} - impl SseDecode for std::collections::HashSet { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -3429,7 +3723,7 @@ impl SseDecode for StreamSink, flutter_rust_bridge::for_generated::SseCo impl SseDecode for StreamSink< - crate::api::crypto::RsHashFileEvent, + crate::api::discovery::RsDiscoveredDevice, flutter_rust_bridge::for_generated::SseCodec, > { @@ -3442,7 +3736,7 @@ impl SseDecode impl SseDecode for StreamSink< - crate::api::multicast::RsMulticastDiscovered, + crate::api::crypto::RsHashFileEvent, flutter_rust_bridge::for_generated::SseCodec, > { @@ -3737,30 +4031,6 @@ impl SseDecode for crate::api::http::LsHttpClientVersion { } } -impl SseDecode for crate::api::multicast::MulticastMessageV2 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_alias = ::sse_decode(deserializer); - let mut var_version = ::sse_decode(deserializer); - let mut var_deviceModel = >::sse_decode(deserializer); - let mut var_deviceType = >::sse_decode(deserializer); - let mut var_fingerprint = ::sse_decode(deserializer); - let mut var_port = ::sse_decode(deserializer); - let mut var_protocol = ::sse_decode(deserializer); - let mut var_download = ::sse_decode(deserializer); - return crate::api::multicast::MulticastMessageV2 { - alias: var_alias, - version: var_version, - device_model: var_deviceModel, - device_type: var_deviceType, - fingerprint: var_fingerprint, - port: var_port, - protocol: var_protocol, - download: var_download, - }; - } -} - impl SseDecode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -3853,6 +4123,19 @@ impl SseDecode for Option { } } +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode( + deserializer, + )); + } else { + return None; + } + } +} + impl SseDecode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -4109,6 +4392,32 @@ impl SseDecode for crate::api::http::ResultWithPublicKeyRegisterResponseDto { } } +impl SseDecode for crate::api::discovery::RsDiscoveredDevice { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_alias = ::sse_decode(deserializer); + let mut var_version = ::sse_decode(deserializer); + let mut var_deviceModel = >::sse_decode(deserializer); + let mut var_deviceType = >::sse_decode(deserializer); + let mut var_fingerprint = ::sse_decode(deserializer); + let mut var_host = ::sse_decode(deserializer); + let mut var_port = ::sse_decode(deserializer); + let mut var_protocol = ::sse_decode(deserializer); + let mut var_download = ::sse_decode(deserializer); + return crate::api::discovery::RsDiscoveredDevice { + alias: var_alias, + version: var_version, + device_model: var_deviceModel, + device_type: var_deviceType, + fingerprint: var_fingerprint, + host: var_host, + port: var_port, + protocol: var_protocol, + download: var_download, + }; + } +} + impl SseDecode for crate::api::crypto::RsHashFileEvent { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -4165,18 +4474,6 @@ impl SseDecode for crate::api::http::RsHttpClientError { } } -impl SseDecode for crate::api::multicast::RsMulticastDiscovered { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_ip = ::sse_decode(deserializer); - let mut var_message = ::sse_decode(deserializer); - return crate::api::multicast::RsMulticastDiscovered { - ip: var_ip, - message: var_message, - }; - } -} - impl SseDecode for crate::api::server::RsServerEvent { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -4550,176 +4847,206 @@ fn pde_ffi_dispatcher_primary_impl( rust_vec_len, data_len, ), - 7 => wire__crate__api__http__RsHttpClient_cancel_impl(port, ptr, rust_vec_len, data_len), - 8 => wire__crate__api__http__RsHttpClient_prepare_upload_impl( + 7 => wire__crate__api__discovery__RsDiscovery_add_device_impl( port, ptr, rust_vec_len, data_len, ), - 9 => wire__crate__api__http__RsHttpClient_register_impl(port, ptr, rust_vec_len, data_len), - 10 => wire__crate__api__http__RsHttpClient_upload_impl(port, ptr, rust_vec_len, data_len), - 11 => wire__crate__api__server__RsHttpServer_cancel_session_impl( + 8 => wire__crate__api__discovery__RsDiscovery_announce_impl( port, ptr, rust_vec_len, data_len, ), - 12 => wire__crate__api__server__RsHttpServer_fail_file_download_impl( + 9 => wire__crate__api__discovery__RsDiscovery_discover_impl( port, ptr, rust_vec_len, data_len, ), - 13 => wire__crate__api__server__RsHttpServer_fail_file_upload_impl( - port, - ptr, - rust_vec_len, - data_len, - ), - 14 => wire__crate__api__server__RsHttpServer_listen_impl(port, ptr, rust_vec_len, data_len), - 15 => wire__crate__api__server__RsHttpServer_respond_file_download_impl( - port, - ptr, - rust_vec_len, - data_len, - ), - 16 => wire__crate__api__server__RsHttpServer_respond_file_upload_impl( - port, - ptr, - rust_vec_len, - data_len, - ), - 17 => wire__crate__api__server__RsHttpServer_respond_prepare_download_impl( - port, - ptr, - rust_vec_len, - data_len, - ), - 18 => wire__crate__api__server__RsHttpServer_respond_prepare_upload_impl( - port, - ptr, - rust_vec_len, - data_len, - ), - 19 => wire__crate__api__server__RsHttpServer_stop_impl(port, ptr, rust_vec_len, data_len), - 20 => wire__crate__api__multicast__RsMulticast_announce_impl( - port, - ptr, - rust_vec_len, - data_len, - ), - 21 => { - wire__crate__api__multicast__RsMulticast_listen_impl(port, ptr, rust_vec_len, data_len) + 10 => { + wire__crate__api__discovery__RsDiscovery_listen_impl(port, ptr, rust_vec_len, data_len) } - 22 => wire__crate__api__multicast__RsMulticast_stop_impl(port, ptr, rust_vec_len, data_len), - 23 => wire__crate__api__webrtc__RtcFileReceiver_get_file_id_impl( + 11 => wire__crate__api__discovery__RsDiscovery_multicast_error_impl( port, ptr, rust_vec_len, data_len, ), - 24 => wire__crate__api__webrtc__RtcFileReceiver_receive_impl( + 12 => wire__crate__api__discovery__RsDiscovery_scan_subnet_impl( port, ptr, rust_vec_len, data_len, ), - 25 => wire__crate__api__webrtc__RtcFileSender_send_impl(port, ptr, rust_vec_len, data_len), - 26 => wire__crate__api__webrtc__RtcReceiveController_decline_impl( + 13 => wire__crate__api__discovery__RsDiscovery_set_answer_announcements_impl( port, ptr, rust_vec_len, data_len, ), - 27 => wire__crate__api__webrtc__RtcReceiveController_listen_error_impl( + 14 => wire__crate__api__discovery__RsDiscovery_stop_impl(port, ptr, rust_vec_len, data_len), + 15 => wire__crate__api__http__RsHttpClient_cancel_impl(port, ptr, rust_vec_len, data_len), + 16 => wire__crate__api__http__RsHttpClient_prepare_upload_impl( port, ptr, rust_vec_len, data_len, ), - 28 => wire__crate__api__webrtc__RtcReceiveController_listen_files_impl( + 17 => wire__crate__api__http__RsHttpClient_register_impl(port, ptr, rust_vec_len, data_len), + 18 => wire__crate__api__http__RsHttpClient_upload_impl(port, ptr, rust_vec_len, data_len), + 19 => wire__crate__api__server__RsHttpServer_cancel_session_impl( port, ptr, rust_vec_len, data_len, ), - 29 => wire__crate__api__webrtc__RtcReceiveController_listen_receiving_impl( + 20 => wire__crate__api__server__RsHttpServer_fail_file_download_impl( port, ptr, rust_vec_len, data_len, ), - 30 => wire__crate__api__webrtc__RtcReceiveController_listen_status_impl( + 21 => wire__crate__api__server__RsHttpServer_fail_file_upload_impl( port, ptr, rust_vec_len, data_len, ), - 31 => wire__crate__api__webrtc__RtcReceiveController_send_file_status_impl( + 22 => wire__crate__api__server__RsHttpServer_listen_impl(port, ptr, rust_vec_len, data_len), + 23 => wire__crate__api__server__RsHttpServer_respond_file_download_impl( port, ptr, rust_vec_len, data_len, ), - 32 => wire__crate__api__webrtc__RtcReceiveController_send_pin_impl( + 24 => wire__crate__api__server__RsHttpServer_respond_file_upload_impl( port, ptr, rust_vec_len, data_len, ), - 33 => wire__crate__api__webrtc__RtcReceiveController_send_selection_impl( + 25 => wire__crate__api__server__RsHttpServer_respond_prepare_download_impl( port, ptr, rust_vec_len, data_len, ), - 34 => wire__crate__api__webrtc__RtcSendController_listen_error_impl( + 26 => wire__crate__api__server__RsHttpServer_respond_prepare_upload_impl( port, ptr, rust_vec_len, data_len, ), - 35 => wire__crate__api__webrtc__RtcSendController_listen_selected_files_impl( + 27 => wire__crate__api__server__RsHttpServer_stop_impl(port, ptr, rust_vec_len, data_len), + 28 => wire__crate__api__webrtc__RtcFileReceiver_get_file_id_impl( port, ptr, rust_vec_len, data_len, ), - 36 => wire__crate__api__webrtc__RtcSendController_listen_status_impl( + 29 => wire__crate__api__webrtc__RtcFileReceiver_receive_impl( port, ptr, rust_vec_len, data_len, ), - 37 => wire__crate__api__webrtc__RtcSendController_send_file_impl( + 30 => wire__crate__api__webrtc__RtcFileSender_send_impl(port, ptr, rust_vec_len, data_len), + 31 => wire__crate__api__webrtc__RtcReceiveController_decline_impl( port, ptr, rust_vec_len, data_len, ), - 38 => wire__crate__api__webrtc__RtcSendController_send_pin_impl( + 32 => wire__crate__api__webrtc__RtcReceiveController_listen_error_impl( port, ptr, rust_vec_len, data_len, ), - 39 => wire__crate__api__webrtc__connect_impl(port, ptr, rust_vec_len, data_len), - 42 => wire__crate__api__stream__create_stream_impl(port, ptr, rust_vec_len, data_len), - 43 => { + 33 => wire__crate__api__webrtc__RtcReceiveController_listen_files_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 34 => wire__crate__api__webrtc__RtcReceiveController_listen_receiving_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 35 => wire__crate__api__webrtc__RtcReceiveController_listen_status_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 36 => wire__crate__api__webrtc__RtcReceiveController_send_file_status_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 37 => wire__crate__api__webrtc__RtcReceiveController_send_pin_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 38 => wire__crate__api__webrtc__RtcReceiveController_send_selection_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 39 => wire__crate__api__webrtc__RtcSendController_listen_error_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 40 => wire__crate__api__webrtc__RtcSendController_listen_selected_files_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 41 => wire__crate__api__webrtc__RtcSendController_listen_status_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 42 => wire__crate__api__webrtc__RtcSendController_send_file_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 43 => wire__crate__api__webrtc__RtcSendController_send_pin_impl( + port, + ptr, + rust_vec_len, + data_len, + ), + 44 => wire__crate__api__webrtc__connect_impl(port, ptr, rust_vec_len, data_len), + 47 => wire__crate__api__stream__create_stream_impl(port, ptr, rust_vec_len, data_len), + 48 => { wire__crate__api__logging__enable_debug_logging_impl(port, ptr, rust_vec_len, data_len) } - 44 => wire__crate__api__crypto__generate_key_pair_impl(port, ptr, rust_vec_len, data_len), - 45 => wire__crate__api__crypto__generate_security_context_impl( + 49 => wire__crate__api__crypto__generate_key_pair_impl(port, ptr, rust_vec_len, data_len), + 50 => wire__crate__api__crypto__generate_security_context_impl( port, ptr, rust_vec_len, data_len, ), - 46 => wire__crate__api__crypto__hash_file_impl(port, ptr, rust_vec_len, data_len), - 47 => wire__crate__api__multicast__start_multicast_impl(port, ptr, rust_vec_len, data_len), - 48 => wire__crate__api__server__start_server_impl(port, ptr, rust_vec_len, data_len), - 49 => wire__crate__api__crypto__verify_cert_impl(port, ptr, rust_vec_len, data_len), + 51 => wire__crate__api__crypto__hash_file_impl(port, ptr, rust_vec_len, data_len), + 52 => wire__crate__api__discovery__start_discovery_impl(port, ptr, rust_vec_len, data_len), + 53 => wire__crate__api__server__start_server_impl(port, ptr, rust_vec_len, data_len), + 54 => wire__crate__api__crypto__verify_cert_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -4734,8 +5061,8 @@ fn pde_ffi_dispatcher_sync_impl( match func_id { 2 => wire__crate__api__stream__Dart2RustStreamSink_close_impl(ptr, rust_vec_len, data_len), 6 => wire__crate__api__cancel__RsCancellationToken_cancel_impl(ptr, rust_vec_len, data_len), - 40 => wire__crate__api__cancel__create_cancellation_token_impl(ptr, rust_vec_len, data_len), - 41 => wire__crate__api__http__create_client_impl(ptr, rust_vec_len, data_len), + 45 => wire__crate__api__cancel__create_cancellation_token_impl(ptr, rust_vec_len, data_len), + 46 => wire__crate__api__http__create_client_impl(ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -4881,6 +5208,21 @@ impl flutter_rust_bridge::IntoIntoDart> for RsCa } } +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for RsDiscovery { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -4911,21 +5253,6 @@ impl flutter_rust_bridge::IntoIntoDart> for RsHttpServe } } -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for RsMulticast { - fn into_into_dart(self) -> FrbWrapper { - self.into() - } -} - // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -5107,33 +5434,6 @@ impl flutter_rust_bridge::IntoIntoDart { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.0.alias.into_into_dart().into_dart(), - self.0.version.into_into_dart().into_dart(), - self.0.device_model.into_into_dart().into_dart(), - self.0.device_type.into_into_dart().into_dart(), - self.0.fingerprint.into_into_dart().into_dart(), - self.0.port.into_into_dart().into_dart(), - self.0.protocol.into_into_dart().into_dart(), - self.0.download.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for FrbWrapper -{ -} -impl flutter_rust_bridge::IntoIntoDart> - for crate::api::multicast::MulticastMessageV2 -{ - fn into_into_dart(self) -> FrbWrapper { - self.into() - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ @@ -5383,6 +5683,34 @@ impl flutter_rust_bridge::IntoIntoDart flutter_rust_bridge::for_generated::DartAbi { + [ + self.alias.into_into_dart().into_dart(), + self.version.into_into_dart().into_dart(), + self.device_model.into_into_dart().into_dart(), + self.device_type.into_into_dart().into_dart(), + self.fingerprint.into_into_dart().into_dart(), + self.host.into_into_dart().into_dart(), + self.port.into_into_dart().into_dart(), + self.protocol.into_into_dart().into_dart(), + self.download.into_into_dart().into_dart(), + ] + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for crate::api::discovery::RsDiscoveredDevice +{ +} +impl flutter_rust_bridge::IntoIntoDart + for crate::api::discovery::RsDiscoveredDevice +{ + fn into_into_dart(self) -> crate::api::discovery::RsDiscoveredDevice { + self + } +} +// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::crypto::RsHashFileEvent { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { match self { @@ -5449,27 +5777,6 @@ impl flutter_rust_bridge::IntoIntoDart } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::multicast::RsMulticastDiscovered { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.ip.into_into_dart().into_dart(), - self.message.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::api::multicast::RsMulticastDiscovered -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::api::multicast::RsMulticastDiscovered -{ - fn into_into_dart(self) -> crate::api::multicast::RsMulticastDiscovered { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for crate::api::server::RsServerEvent { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { match self { @@ -5896,6 +6203,13 @@ impl SseEncode for RsCancellationToken { } } +impl SseEncode for RsDiscovery { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); + } +} + impl SseEncode for RsHttpClient { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -5910,13 +6224,6 @@ impl SseEncode for RsHttpServer { } } -impl SseEncode for RsMulticast { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); - } -} - impl SseEncode for flutter_rust_bridge::DartOpaque { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -6033,6 +6340,17 @@ impl SseEncode } } +impl SseEncode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + let (ptr, size) = self.sse_encode_raw(); + ::sse_encode(ptr, serializer); + ::sse_encode(size, serializer); + } +} + impl SseEncode for RustOpaqueMoi> { @@ -6055,17 +6373,6 @@ impl SseEncode } } -impl SseEncode - for RustOpaqueMoi> -{ - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - let (ptr, size) = self.sse_encode_raw(); - ::sse_encode(ptr, serializer); - ::sse_encode(size, serializer); - } -} - impl SseEncode for std::collections::HashSet { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -6096,7 +6403,7 @@ impl SseEncode for StreamSink, flutter_rust_bridge::for_generated::SseCo impl SseEncode for StreamSink< - crate::api::crypto::RsHashFileEvent, + crate::api::discovery::RsDiscoveredDevice, flutter_rust_bridge::for_generated::SseCodec, > { @@ -6108,7 +6415,7 @@ impl SseEncode impl SseEncode for StreamSink< - crate::api::multicast::RsMulticastDiscovered, + crate::api::crypto::RsHashFileEvent, flutter_rust_bridge::for_generated::SseCodec, > { @@ -6357,20 +6664,6 @@ impl SseEncode for crate::api::http::LsHttpClientVersion { } } -impl SseEncode for crate::api::multicast::MulticastMessageV2 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.alias, serializer); - ::sse_encode(self.version, serializer); - >::sse_encode(self.device_model, serializer); - >::sse_encode(self.device_type, serializer); - ::sse_encode(self.fingerprint, serializer); - ::sse_encode(self.port, serializer); - ::sse_encode(self.protocol, serializer); - ::sse_encode(self.download, serializer); - } -} - impl SseEncode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -6451,6 +6744,16 @@ impl SseEncode for Option { } } +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + impl SseEncode for Option { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -6652,6 +6955,21 @@ impl SseEncode for crate::api::http::ResultWithPublicKeyRegisterResponseDto { } } +impl SseEncode for crate::api::discovery::RsDiscoveredDevice { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.alias, serializer); + ::sse_encode(self.version, serializer); + >::sse_encode(self.device_model, serializer); + >::sse_encode(self.device_type, serializer); + ::sse_encode(self.fingerprint, serializer); + ::sse_encode(self.host, serializer); + ::sse_encode(self.port, serializer); + ::sse_encode(self.protocol, serializer); + ::sse_encode(self.download, serializer); + } +} + impl SseEncode for crate::api::crypto::RsHashFileEvent { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -6703,14 +7021,6 @@ impl SseEncode for crate::api::http::RsHttpClientError { } } -impl SseEncode for crate::api::multicast::RsMulticastDiscovered { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.ip, serializer); - ::sse_encode(self.message, serializer); - } -} - impl SseEncode for crate::api::server::RsServerEvent { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -7004,8 +7314,8 @@ mod io { use super::*; use crate::api::cancel::*; + use crate::api::discovery::*; use crate::api::http::*; - use crate::api::multicast::*; use crate::api::server::*; use crate::api::stream::*; use crate::api::webrtc::*; @@ -7131,6 +7441,20 @@ mod io { MoiArc::>::decrement_strong_count(ptr as _); } + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_localsend_isolates_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_localsend_isolates_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[unsafe(no_mangle)] pub extern "C" fn frbgen_localsend_isolates_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient( ptr: *const std::ffi::c_void, @@ -7158,20 +7482,6 @@ mod io { ) { MoiArc::>::decrement_strong_count(ptr as _); } - - #[unsafe(no_mangle)] - pub extern "C" fn frbgen_localsend_isolates_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::increment_strong_count(ptr as _); - } - - #[unsafe(no_mangle)] - pub extern "C" fn frbgen_localsend_isolates_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::decrement_strong_count(ptr as _); - } } #[cfg(not(target_family = "wasm"))] pub use io::*; @@ -7186,8 +7496,8 @@ mod web { use super::*; use crate::api::cancel::*; + use crate::api::discovery::*; use crate::api::http::*; - use crate::api::multicast::*; use crate::api::server::*; use crate::api::stream::*; use crate::api::webrtc::*; @@ -7315,6 +7625,20 @@ mod web { MoiArc::>::decrement_strong_count(ptr as _); } + #[wasm_bindgen] + pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[wasm_bindgen] + pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsDiscovery( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[wasm_bindgen] pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsHttpClient( ptr: *const std::ffi::c_void, @@ -7342,20 +7666,6 @@ mod web { ) { MoiArc::>::decrement_strong_count(ptr as _); } - - #[wasm_bindgen] - pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::increment_strong_count(ptr as _); - } - - #[wasm_bindgen] - pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRsMulticast( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::decrement_strong_count(ptr as _); - } } #[cfg(target_family = "wasm")] pub use web::*;