Files
localsend/packages/localsend_isolates/lib/rust/api/discovery.dart
T
Tien Do Nam 73ff2fe6e2
CI / format (push) Has been cancelled
CI / test (push) Has been cancelled
CI / packaging (push) Has been cancelled
feat: add web receive
2026-08-03 04:33:21 +02:00

271 lines
10 KiB
Dart

// 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/frb_generated.dart';
// These functions are ignored because they are not marked as `pub`: `rs_stored_device`, `stop`
// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DiscoveryInstance`
/// 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<RsDiscovery> startDiscovery({
required String group,
required int port,
List<String>? networkWhitelist,
List<String>? networkBlacklist,
required String alias,
required String version,
String? deviceModel,
DeviceType? deviceType,
required String fingerprint,
required ProtocolType 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<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<RsDiscovery>>
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<void> 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<void> 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<RsStoredDevice?> discover({required String host, required int port, required ProtocolType protocol});
/// Emits a [RsStoredDevice] for every device confirmation until the
/// discovery is stopped. Can only be listened to once.
///
/// Also returns when the Dart side of the stream is gone (e.g. after a
/// hot restart), so this call does not keep the discovery alive forever.
Stream<RsStoredDevice> listen();
/// The reason the multicast sockets could not be bound, when they could
/// not. Discovery then neither hears nor sends announcements.
Future<String?> 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<void> scanSubnet({required String interfaceIp, required int port, required ProtocolType 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<void> 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<void> stop();
}
/// An address a stored device was confirmed on and is dialed at.
class RsDeviceChannel {
/// The host to dial: 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 at this address.
final int port;
final ProtocolType protocol;
const RsDeviceChannel({
required this.host,
required this.port,
required this.protocol,
});
@override
int get hashCode => host.hashCode ^ port.hashCode ^ protocol.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is RsDeviceChannel && runtimeType == other.runtimeType && host == other.host && port == other.port && protocol == other.protocol;
}
/// A single device confirmation over HTTP, fed into the store via
/// [RsDiscovery::add_device]: the device's register request was accepted by
/// our server, so it is known to be reachable at [RsDiscoveredDevice::host].
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 ProtocolType 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;
}
/// The merged stored state of a discovered device: one entry per fingerprint,
/// carrying every address the device was confirmed on. A multi-homed device
/// that is reachable over several network interfaces is still one
/// [RsStoredDevice].
///
/// Emitted on [RsDiscovery::listen] for every confirmation (answered
/// announcements, scan results and devices fed in via
/// [RsDiscovery::add_device]), so a device re-appears — with its channels
/// accumulated so far — whenever it re-announces itself or is re-discovered.
class RsStoredDevice {
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;
/// Whether the device's download API is active.
final bool download;
/// Every address the device was confirmed on, best first (available
/// before not-reachable, IPv6 before IPv4, most recently confirmed
/// first). Never empty: a device only enters the store through a
/// confirmation.
final List<RsDeviceChannel> channels;
const RsStoredDevice({
required this.alias,
required this.version,
this.deviceModel,
this.deviceType,
required this.fingerprint,
required this.download,
required this.channels,
});
@override
int get hashCode =>
alias.hashCode ^ version.hashCode ^ deviceModel.hashCode ^ deviceType.hashCode ^ fingerprint.hashCode ^ download.hashCode ^ channels.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is RsStoredDevice &&
runtimeType == other.runtimeType &&
alias == other.alias &&
version == other.version &&
deviceModel == other.deviceModel &&
deviceType == other.deviceType &&
fingerprint == other.fingerprint &&
download == other.download &&
channels == other.channels;
}