Add native self-hosted instance connection to fluxer_desktop
Trimmed monorepo checkout (fluxer_desktop + packages/voice_engine_v2 + tools/ci) with a "Connect to a Different Server" menu item and popout that lets the desktop app switch to any self-hosted Fluxer instance, plus fixes for well-known discovery on single-domain self-hosted deployments and a false-positive ERR_ABORTED on same-origin client redirects during the switch. Defaults to chat.fluxr.chat and uses an isolated userData directory from the official build.
This commit is contained in:
+233
@@ -0,0 +1,233 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||
dependencies = [
|
||||
"derive_arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be"
|
||||
dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||
dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"const-oid",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "fluxer_desktop_native"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluxer_desktop_native_fuzz"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"fluxer_desktop_native",
|
||||
"libfuzzer-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hybrid-array"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
|
||||
[[package]]
|
||||
name = "libfuzzer-sys"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.3+wasi-0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.57.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||
@@ -0,0 +1,46 @@
|
||||
[package]
|
||||
name = "fluxer_desktop_native_fuzz"
|
||||
version = "0.0.0"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
|
||||
[package.metadata]
|
||||
cargo-fuzz = true
|
||||
|
||||
[dependencies]
|
||||
arbitrary = {version = "1.4", features = ["derive"]}
|
||||
fluxer_desktop_native = {path = ".."}
|
||||
libfuzzer-sys = "0.4"
|
||||
|
||||
[[bin]]
|
||||
name = "routing"
|
||||
path = "fuzz_targets/routing.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "pid_payload"
|
||||
path = "fuzz_targets/pid_payload.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "audio_converter"
|
||||
path = "fuzz_targets/audio_converter.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "evdev_event"
|
||||
path = "fuzz_targets/evdev_event.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "process_tree"
|
||||
path = "fuzz_targets/process_tree.rs"
|
||||
test = false
|
||||
doc = false
|
||||
@@ -0,0 +1,40 @@
|
||||
#![no_main]
|
||||
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use arbitrary::Arbitrary;
|
||||
use fluxer_desktop_native::mac_app_audio::audio_converter::{
|
||||
AudioBuffer, AudioBufferListN, build_input_asbd, convert_buffer_list_to_interleaved_f32,
|
||||
};
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
#[derive(Arbitrary, Debug)]
|
||||
struct Input {
|
||||
samples: Vec<f32>,
|
||||
sample_rate: f64,
|
||||
output_rate: f64,
|
||||
channels: u8,
|
||||
}
|
||||
|
||||
fuzz_target!(|input: Input| {
|
||||
let channels = u32::from(input.channels.clamp(1, 2));
|
||||
let sample_rate = if input.sample_rate.is_finite() && input.sample_rate > 0.0 {
|
||||
input.sample_rate.min(384_000.0)
|
||||
} else {
|
||||
48_000.0
|
||||
};
|
||||
let output_rate = if input.output_rate.is_finite() && input.output_rate > 0.0 {
|
||||
input.output_rate.min(384_000.0)
|
||||
} else {
|
||||
48_000.0
|
||||
};
|
||||
let frame_count = (input.samples.len() as u32 / channels).min(4096);
|
||||
let list = AudioBufferListN {
|
||||
m_number_buffers: 1,
|
||||
buffers: [AudioBuffer::from_slice(channels, &input.samples)],
|
||||
};
|
||||
let asbd = build_input_asbd(sample_rate, channels, false);
|
||||
let mut out = vec![0.0_f32; frame_count as usize * 4 + 16];
|
||||
let _ =
|
||||
convert_buffer_list_to_interleaved_f32(asbd, &list, frame_count, output_rate, 2, &mut out);
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
#![no_main]
|
||||
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use fluxer_desktop_native::linux_evdev::event::{
|
||||
InputEvent, parse_input_event, parse_input_events,
|
||||
};
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _ = parse_input_event(data);
|
||||
let mut count = 0_usize;
|
||||
for event in parse_input_events(data) {
|
||||
let _ = event.time_sec ^ event.time_usec;
|
||||
let _ = event.event_type ^ event.code;
|
||||
let _ = event.value;
|
||||
count += 1;
|
||||
}
|
||||
assert_eq!(data.len() / InputEvent::BYTE_LEN, count);
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
#![no_main]
|
||||
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use fluxer_desktop_native::linux_portals::pid_payload::parse_shell_eval_pid_payload;
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
if let Ok(payload) = std::str::from_utf8(data) {
|
||||
let _ = parse_shell_eval_pid_payload(payload);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
#![no_main]
|
||||
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use arbitrary::Arbitrary;
|
||||
use fluxer_desktop_native::mac_app_audio::process_tree::{
|
||||
Info, collect_related_pids_with_resolver, is_same_launch_tree_with_resolver,
|
||||
};
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
#[derive(Arbitrary, Debug)]
|
||||
struct RawInfo {
|
||||
pid: i32,
|
||||
parent_pid: i32,
|
||||
process_group_id: i32,
|
||||
}
|
||||
|
||||
#[derive(Arbitrary, Debug)]
|
||||
struct Input {
|
||||
target_pid: i32,
|
||||
max_count: u8,
|
||||
infos: Vec<RawInfo>,
|
||||
candidates: Vec<i32>,
|
||||
}
|
||||
|
||||
fuzz_target!(|input: Input| {
|
||||
let infos: Vec<Info> = input
|
||||
.infos
|
||||
.into_iter()
|
||||
.take(128)
|
||||
.map(|raw| Info {
|
||||
pid: raw.pid,
|
||||
parent_pid: raw.parent_pid,
|
||||
process_group_id: raw.process_group_id,
|
||||
})
|
||||
.collect();
|
||||
let candidates: Vec<i32> = input.candidates.into_iter().take(128).collect();
|
||||
let target_info = infos
|
||||
.iter()
|
||||
.copied()
|
||||
.find(|info| info.pid == input.target_pid);
|
||||
let resolver = |pid| infos.iter().copied().find(|info| info.pid == pid);
|
||||
let related = collect_related_pids_with_resolver(
|
||||
input.target_pid,
|
||||
target_info,
|
||||
&candidates,
|
||||
usize::from(input.max_count),
|
||||
resolver,
|
||||
);
|
||||
assert!(related.len() <= usize::from(input.max_count));
|
||||
if input.target_pid <= 0 || input.max_count == 0 {
|
||||
assert!(related.is_empty());
|
||||
} else {
|
||||
assert_eq!(Some(&input.target_pid), related.first());
|
||||
}
|
||||
|
||||
for candidate in candidates.into_iter().take(16) {
|
||||
let resolver = |pid| infos.iter().copied().find(|info| info.pid == pid);
|
||||
let _ =
|
||||
is_same_launch_tree_with_resolver(candidate, input.target_pid, target_info, resolver);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
#![no_main]
|
||||
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use arbitrary::Arbitrary;
|
||||
use fluxer_desktop_native::linux_audio::routing::{
|
||||
MEDIA_CLASS_PLAYBACK_STREAM, RoutingRule, SelfIdentity, should_route_node,
|
||||
};
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Arbitrary, Debug)]
|
||||
struct Input {
|
||||
id: u32,
|
||||
sink_id: u32,
|
||||
default_name: String,
|
||||
default_id: String,
|
||||
include_name: String,
|
||||
app_name: String,
|
||||
process_id: String,
|
||||
binary: String,
|
||||
has_device_id: bool,
|
||||
media_class_is_playback: bool,
|
||||
}
|
||||
|
||||
fuzz_target!(|input: Input| {
|
||||
let mut props = BTreeMap::new();
|
||||
props.insert(
|
||||
"media.class".to_owned(),
|
||||
if input.media_class_is_playback {
|
||||
MEDIA_CLASS_PLAYBACK_STREAM.to_owned()
|
||||
} else {
|
||||
"Audio/Source".to_owned()
|
||||
},
|
||||
);
|
||||
props.insert("application.name".to_owned(), input.app_name);
|
||||
props.insert("application.process.id".to_owned(), input.process_id);
|
||||
props.insert("application.process.binary".to_owned(), input.binary);
|
||||
props.insert("target.object".to_owned(), input.default_name.clone());
|
||||
if input.has_device_id {
|
||||
props.insert("device.id".to_owned(), "5".to_owned());
|
||||
}
|
||||
let mut include = BTreeMap::new();
|
||||
include.insert("application.name".to_owned(), input.include_name);
|
||||
let rule = RoutingRule {
|
||||
include_when: vec![include],
|
||||
skip_hardware_devices: true,
|
||||
..RoutingRule::default()
|
||||
};
|
||||
let self_identity = SelfIdentity::default();
|
||||
let _ = should_route_node(
|
||||
input.id,
|
||||
&props,
|
||||
&rule,
|
||||
&input.default_name,
|
||||
&input.default_id,
|
||||
input.sink_id,
|
||||
&self_identity,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user