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:
2026-07-01 18:22:43 -04:00
commit 682afacd30
1763 changed files with 613720 additions and 0 deletions
@@ -0,0 +1,848 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
import {describe, test} from 'node:test';
const require = createRequire(import.meta.url);
const webrtcSender = require('./index.js');
describe('webrtc-sender loader wrapper', () => {
test('resolves the native addon filename for every desktop OS/arch target', () => {
const cases = [
['win32', 'x64', 'webrtc-sender.win32-x64-msvc.node'],
['win32', 'arm64', 'webrtc-sender.win32-arm64-msvc.node'],
['darwin', 'x64', 'webrtc-sender.darwin-x64.node'],
['darwin', 'arm64', 'webrtc-sender.darwin-arm64.node'],
['linux', 'x64', 'webrtc-sender.linux-x64-gnu.node'],
['linux', 'arm64', 'webrtc-sender.linux-arm64-gnu.node'],
];
for (const [platform, arch, expected] of cases) {
assert.equal(webrtcSender.__nativeFileNameForTests(platform, arch), expected);
}
});
test('rejects unsupported platform/architecture pairs explicitly', () => {
assert.throws(() => webrtcSender.__nativeFileNameForTests('linux', 'ia32'), /not supported/);
assert.throws(() => webrtcSender.__nativeFileNameForTests('freebsd', 'x64'), /not supported/);
});
test('returns a native hardware encoder capability when the binding exports one', () => {
const expected = {
available: true,
backend: 'nvenc',
compiled: true,
runtime: true,
codecs: ['h264', 'h265'],
zeroCopy: true,
nativeInputs: ['dmabuf'],
};
webrtcSender.__setBindingForTests({
getHardwareEncoderCapability() {
return expected;
},
});
assert.deepEqual(webrtcSender.getHardwareEncoderCapability(), expected);
assert.deepEqual(webrtcSender.getHardwareEncoderCapabilities(), expected);
});
test('delegates dropped video callback metrics through the VoiceEngine wrapper', () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {
inboundAudioFrames() {
return 2;
}
inboundVideoFrames() {
return 3;
}
droppedVideoFrameCallbacks() {
return 5;
}
},
});
const engine = new webrtcSender.VoiceEngine();
assert.equal(engine.inboundAudioFrames(), 2);
assert.equal(engine.inboundVideoFrames(), 3);
assert.equal(engine.droppedVideoFrameCallbacks(), 5);
});
test('reports VoiceEngine feature capabilities from the wrapped native prototype', () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishDeviceMicrophone() {}
publishMicrophone() {}
publishCamera() {}
listCameraDevices() {}
publishScreenShare() {}
updateScreenShareEncoding() {}
unpublishScreenShare() {}
publishScreenShareAudio() {}
pushScreenSharePcm() {}
pushScreenShareFloat() {}
unpublishScreenShareAudio() {}
listAudioInputDevices() {}
listAudioOutputDevices() {}
setAudioOutputDevice() {}
setParticipantVolume() {}
setRemoteTrackSubscription() {}
publishData() {}
getConnectionStats() {}
setVideoFrameCallback() {}
},
});
assert.deepEqual(webrtcSender.getCapabilities(), {
microphoneCapture: true,
syntheticMicrophonePcm: true,
cameraCapture: true,
nativeCameraBackgrounds: false,
screenShare: true,
screenShareEncodingUpdate: true,
screenShareAudio: true,
deviceLists: true,
outputDeviceSelection: true,
participantVolume: true,
remoteTrackSubscription: true,
dataChannel: true,
connectionStats: true,
nativeVideoFrames: true,
hardwareEncoderCapabilities: true,
});
});
test('does not report screen-share audio capability without the float push method', () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishScreenShareAudio() {}
pushScreenSharePcm() {}
unpublishScreenShareAudio() {}
},
});
assert.equal(webrtcSender.getCapabilities().screenShareAudio, false);
});
test('reports native camera background support only from the explicit native probe', () => {
webrtcSender.__setBindingForTests({
hasNativeCameraBackgrounds() {
return true;
},
VoiceEngine: class {
publishCamera() {}
listCameraDevices() {}
},
});
assert.equal(webrtcSender.hasNativeCameraBackgrounds(), true);
assert.equal(webrtcSender.getCapabilities().nativeCameraBackgrounds, true);
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishCamera() {}
listCameraDevices() {}
},
});
assert.equal(webrtcSender.hasNativeCameraBackgrounds(), false);
assert.equal(webrtcSender.getCapabilities().nativeCameraBackgrounds, false);
});
test('delegates video-frame callback clearing to the native binding when exported', () => {
let clearCalls = 0;
const setCalls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
setVideoFrameCallback(callback) {
setCalls.push(callback);
}
clearVideoFrameCallback() {
clearCalls += 1;
}
},
});
const engine = new webrtcSender.VoiceEngine();
engine.clearVideoFrameCallback();
assert.equal(clearCalls, 1);
assert.deepEqual(setCalls, []);
});
test('delegates screen-share float audio through the VoiceEngine wrapper', async () => {
const calls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
pushScreenShareFloat(buffer, sampleRate, numChannels) {
calls.push([buffer, sampleRate, numChannels]);
return Promise.resolve(true);
}
},
});
const engine = new webrtcSender.VoiceEngine();
const buffer = Buffer.from(new Float32Array([0.25, -0.25]).buffer);
const accepted = await engine.pushScreenShareFloat(buffer, 48000, 2);
assert.equal(accepted, true);
assert.deepEqual(calls, [[buffer, 48000, 2]]);
});
test('falls back to a no-op video-frame callback for older native bindings', () => {
const setCalls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
setVideoFrameCallback(callback) {
setCalls.push(callback);
}
},
});
const engine = new webrtcSender.VoiceEngine();
engine.clearVideoFrameCallback();
assert.equal(setCalls.length, 1);
assert.equal(typeof setCalls[0], 'function');
assert.equal(setCalls[0]('{}', Buffer.alloc(0)), undefined);
});
test('treats video-frame callback clearing as a no-op when the binding exports neither method', () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {},
});
const engine = new webrtcSender.VoiceEngine();
assert.equal(engine.clearVideoFrameCallback(), undefined);
});
test('delegates engine bridge version reads and assertions to the native binding', () => {
const assertedVersions = [];
webrtcSender.__setBindingForTests({
getEngineBridgeVersion() {
return 9;
},
assertEngineBridgeVersion(version) {
assertedVersions.push(version);
if (version !== 9) {
throw new Error(`voice engine bridge version mismatch: host sent ${version}, native addon expects 9`);
}
},
});
assert.equal(webrtcSender.getEngineBridgeVersion(), 9);
webrtcSender.assertEngineBridgeVersion(9);
assert.throws(() => webrtcSender.assertEngineBridgeVersion(8), /bridge version mismatch/);
assert.deepEqual(assertedVersions, [9, 8]);
});
test('reports a null engine bridge version and throws on assertion when the binding lacks the exports', () => {
webrtcSender.__setBindingForTests({});
assert.equal(webrtcSender.getEngineBridgeVersion(), null);
assert.throws(() => webrtcSender.assertEngineBridgeVersion(9), /does not export assertEngineBridgeVersion/);
});
test('delegates native voice engine prewarm when the binding exports it', () => {
let prewarmCalls = 0;
webrtcSender.__setBindingForTests({
prewarmVoiceEngine() {
prewarmCalls += 1;
},
});
webrtcSender.prewarmVoiceEngine();
assert.equal(prewarmCalls, 1);
});
test('delegates device microphone publish through the VoiceEngine wrapper', async () => {
const calls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishDeviceMicrophone(opts) {
calls.push(opts);
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
await engine.publishDeviceMicrophone({
deviceId: 'mic-guid',
echoCancellation: false,
noiseSuppression: true,
autoGainControl: false,
});
await engine.publishDeviceMicrophone({
deviceId: 'mic-guid',
echoCancellation: false,
noiseSuppression: true,
autoGainControl: false,
maxBitrateBps: 96_000,
});
assert.deepEqual(calls, [
{
deviceId: 'mic-guid',
echoCancellation: false,
noiseSuppression: true,
autoGainControl: false,
maxBitrateBps: undefined,
},
{
deviceId: 'mic-guid',
echoCancellation: false,
noiseSuppression: true,
autoGainControl: false,
maxBitrateBps: 96_000,
},
]);
});
test('delegates native camera devices and publish options through the VoiceEngine wrapper', async () => {
const publishCalls = [];
const processedPublishCalls = [];
const processedFrameCalls = [];
const nativeSinkPublishCalls = [];
const nativeSinkHandle = {};
const devices = [
{
deviceId: 'native-camera-id',
label: 'Studio Display Camera',
description: 'Apple Studio Display Camera',
index: 0,
deviceIdAliases: ['native-camera-id', '0'],
},
];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
listCameraDevices() {
return devices;
}
publishCamera(opts) {
publishCalls.push(opts);
return Promise.resolve();
}
publishProcessedCamera(opts) {
processedPublishCalls.push(opts);
return Promise.resolve({trackSid: 'TR_processed_camera'});
}
publishNativeCameraSink(opts) {
nativeSinkPublishCalls.push(opts);
return Promise.resolve({trackSid: 'TR_native_camera'});
}
createCameraFrameSinkHandle() {
return nativeSinkHandle;
}
pushProcessedCameraFrame(frame) {
processedFrameCalls.push(frame);
return Promise.resolve(true);
}
},
});
const engine = new webrtcSender.VoiceEngine();
assert.equal(engine.listCameraDevices(), devices);
await engine.publishCamera({
deviceId: 'native-camera-id',
width: 1280,
height: 720,
frameRate: 30,
mirror: true,
codec: 'h265',
maxBitrateBps: 6_000_000,
maxFramerate: 30,
});
const processedPublishResult = await engine.publishProcessedCamera({
width: 1280,
height: 720,
frameRate: 30,
ignored: true,
});
const nativeSinkPublishResult = await engine.publishNativeCameraSink({
deviceId: 'native-camera-id',
width: 1280,
height: 720,
frameRate: 30,
backgroundMode: 'custom',
backgroundCustomMediaPath: '/tmp/bg.webp',
backgroundCustomMediaKind: 'animated',
codec: 'h264',
});
const cameraFrameSinkHandle = engine.createCameraFrameSinkHandle();
const frame = {
format: 'i420',
width: 4,
height: 2,
timestampUs: 12_345,
data: Buffer.alloc(12),
ignored: true,
};
const processedFrameResult = await engine.pushProcessedCameraFrame(frame);
assert.deepEqual(publishCalls, [
{
deviceId: 'native-camera-id',
width: 1280,
height: 720,
frameRate: 30,
mirror: true,
backgroundMode: undefined,
backgroundCustomMediaPath: undefined,
backgroundCustomMediaKind: undefined,
backgroundBlurStrength: undefined,
codec: 'h265',
maxBitrateBps: 6_000_000,
maxFramerate: 30,
},
]);
assert.deepEqual(processedPublishResult, {trackSid: 'TR_processed_camera'});
assert.deepEqual(processedPublishCalls, [
{
width: 1280,
height: 720,
frameRate: 30,
},
]);
assert.deepEqual(nativeSinkPublishResult, {trackSid: 'TR_native_camera'});
assert.deepEqual(nativeSinkPublishCalls, [
{
deviceId: 'native-camera-id',
width: 1280,
height: 720,
frameRate: 30,
mirror: undefined,
backgroundMode: 'custom',
backgroundCustomMediaPath: '/tmp/bg.webp',
backgroundCustomMediaKind: 'animated',
backgroundBlurStrength: undefined,
codec: 'h264',
maxBitrateBps: undefined,
maxFramerate: undefined,
},
]);
assert.equal(cameraFrameSinkHandle, nativeSinkHandle);
assert.equal(processedFrameResult, true);
assert.deepEqual(processedFrameCalls, [
{
format: 'i420',
width: 4,
height: 2,
timestampUs: 12_345,
data: frame.data,
},
]);
});
test('reports processed camera publishing as unavailable for older native bindings', async () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {},
});
const engine = new webrtcSender.VoiceEngine();
assert.throws(
() => engine.publishProcessedCamera({width: 1280, height: 720, frameRate: 30}),
/native binding does not export publishProcessedCamera/,
);
assert.throws(
() => engine.publishNativeCameraSink({width: 1280, height: 720, frameRate: 30}),
/native binding does not export publishNativeCameraSink/,
);
assert.equal(engine.createCameraFrameSinkHandle(), null);
assert.throws(
() =>
engine.pushProcessedCameraFrame({
format: 'i420',
width: 4,
height: 2,
timestampUs: 12_345,
data: Buffer.alloc(12),
}),
/native binding does not export pushProcessedCameraFrame/,
);
});
test('delegates device screen-share publish through the VoiceEngine wrapper', async () => {
const publishCalls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishDeviceScreenShare(opts) {
publishCalls.push(opts);
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
await engine.publishDeviceScreenShare({
deviceId: 'studio-display-camera',
width: 1920,
height: 1080,
frameRate: 60,
codec: 'h264',
maxBitrateBps: 8_000_000,
maxFramerate: 60,
});
assert.deepEqual(publishCalls, [
{
deviceId: 'studio-display-camera',
width: 1920,
height: 1080,
frameRate: 60,
mirror: undefined,
backgroundMode: undefined,
backgroundCustomMediaPath: undefined,
backgroundCustomMediaKind: undefined,
backgroundBlurStrength: undefined,
codec: 'h264',
maxBitrateBps: 8_000_000,
maxFramerate: 60,
},
]);
});
test('delegates camera capture updates with effect strengths through the VoiceEngine wrapper', async () => {
const updateCalls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
updateCameraCapture(opts) {
updateCalls.push(opts);
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
await engine.updateCameraCapture({
deviceId: 'native-camera-id',
width: 1280,
height: 720,
frameRate: 30,
mirror: false,
backgroundMode: 'blur',
backgroundBlurStrength: 90,
ignored: true,
});
assert.deepEqual(updateCalls, [
{
deviceId: 'native-camera-id',
width: 1280,
height: 720,
frameRate: 30,
mirror: false,
backgroundMode: 'blur',
backgroundCustomMediaPath: undefined,
backgroundCustomMediaKind: undefined,
backgroundBlurStrength: 90,
codec: undefined,
maxBitrateBps: undefined,
maxFramerate: undefined,
},
]);
});
test('reports camera capture updates as unavailable for older native bindings', () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {},
});
const engine = new webrtcSender.VoiceEngine();
assert.throws(
() => engine.updateCameraCapture({deviceId: 'native-camera-id'}),
/native binding does not export updateCameraCapture/,
);
});
test('reports device screen-share publish as unavailable for older native bindings', async () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {},
});
const engine = new webrtcSender.VoiceEngine();
assert.throws(
() => engine.publishDeviceScreenShare({deviceId: 'studio-display-camera'}),
/native binding does not export publishDeviceScreenShare/,
);
});
test('delegates screen-share simulcast selection through the VoiceEngine wrapper', async () => {
const calls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishScreenShare(width, height, codec, maxBitrateBps, maxFramerate, simulcast, options) {
calls.push({width, height, codec, maxBitrateBps, maxFramerate, simulcast, options});
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
await engine.publishScreenShare(3840, 2160, 'h265', 50_000_000, 60, false, {
adaptiveSend: true,
minVideoFps: 15,
minResolutionScale: 0.5,
maxAudioBufferMs: 750,
captureId: 'screen-harness-primary',
});
assert.deepEqual(calls, [
{
width: 3840,
height: 2160,
codec: 'h265',
maxBitrateBps: 50_000_000,
maxFramerate: 60,
simulcast: false,
options: {
adaptiveSend: true,
minVideoFps: 15,
minResolutionScale: 0.5,
maxAudioBufferMs: 750,
captureId: 'screen-harness-primary',
},
},
]);
});
test('rejects screen-share publish and encoding update without capture IDs', async () => {
const calls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishScreenShare(...args) {
calls.push(['publish', args]);
return Promise.resolve();
}
updateScreenShareEncoding(...args) {
calls.push(['update', args]);
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
assert.throws(
() => engine.publishScreenShare(1280, 720, 'h264', undefined, 30, false, undefined),
/screen-share publish requires a non-empty captureId/,
);
assert.throws(
() => engine.publishScreenShare(1280, 720, 'h264', undefined, 30, false, {captureId: ''}),
/screen-share publish requires a non-empty captureId/,
);
assert.throws(
() => engine.updateScreenShareEncoding(1280, 720, undefined, 30, undefined),
/screen-share encoding update requires a non-empty captureId/,
);
assert.throws(
() => engine.updateScreenShareEncoding(1280, 720, undefined, 30, {captureId: ''}),
/screen-share encoding update requires a non-empty captureId/,
);
assert.deepEqual(calls, []);
});
test('delegates connect options through the VoiceEngine wrapper', async () => {
const calls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
connect(url, token, e2eeKey, options) {
calls.push({url, token, e2eeKey, options});
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
const key = Buffer.from('secret');
await engine.connect('ws://localhost:7880', 'token', key, {
autoSubscribe: false,
adaptiveStream: true,
dynacast: true,
});
assert.deepEqual(calls, [
{
url: 'ws://localhost:7880',
token: 'token',
e2eeKey: key,
options: {
autoSubscribe: false,
adaptiveStream: true,
dynacast: true,
},
},
]);
});
test('delegates native screen frame sink handle creation through the VoiceEngine wrapper', () => {
const calls = [];
const handle = {native: true};
webrtcSender.__setBindingForTests({
VoiceEngine: class {
createScreenFrameSinkHandle(captureId) {
calls.push(captureId);
return handle;
}
},
});
const engine = new webrtcSender.VoiceEngine();
assert.equal(engine.createScreenFrameSinkHandle('capture-1'), handle);
assert.deepEqual(calls, ['capture-1']);
});
test('treats native screen frame sink handles as unavailable for older voice bindings', () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {},
});
const engine = new webrtcSender.VoiceEngine();
assert.equal(engine.createScreenFrameSinkHandle('capture-1'), null);
});
test('defaults dropped video callback metrics to zero for older native bindings', () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {
inboundAudioFrames() {
return 2;
}
inboundVideoFrames() {
return 3;
}
},
});
const engine = new webrtcSender.VoiceEngine();
assert.equal(engine.droppedVideoFrameCallbacks(), 0);
});
test('delegates remote track subscription updates through the VoiceEngine wrapper', async () => {
const calls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
setRemoteTrackSubscription(participantIdentity, source, subscribed, enabled, quality) {
calls.push({participantIdentity, source, subscribed, enabled, quality});
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
await engine.setRemoteTrackSubscription({
participantIdentity: 'user_1_conn',
source: 'screen_share',
subscribed: true,
enabled: false,
quality: 'high',
});
assert.deepEqual(calls, [
{
participantIdentity: 'user_1_conn',
source: 'screen_share',
subscribed: true,
enabled: false,
quality: 'high',
},
]);
});
test('ignores remote track subscription updates for older native bindings', async () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {},
});
const engine = new webrtcSender.VoiceEngine();
await engine.setRemoteTrackSubscription({
participantIdentity: 'user_1_conn',
source: 'camera',
subscribed: true,
});
});
test('delegates data packets through the VoiceEngine wrapper', async () => {
const calls = [];
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishData(payload, reliable, topic, destinationIdentities) {
calls.push({payload, reliable, topic, destinationIdentities});
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
await engine.publishData(new Uint8Array([1, 2, 3]), {
reliable: true,
topic: 'screen-share-codec',
destinationIdentities: ['user_1_conn'],
});
assert.equal(Buffer.isBuffer(calls[0].payload), true);
assert.deepEqual([...calls[0].payload], [1, 2, 3]);
assert.deepEqual(calls, [
{
payload: calls[0].payload,
reliable: true,
topic: 'screen-share-codec',
destinationIdentities: ['user_1_conn'],
},
]);
});
test('rejects invalid data packet payloads in the wrapper', async () => {
webrtcSender.__setBindingForTests({
VoiceEngine: class {
publishData() {
return Promise.resolve();
}
},
});
const engine = new webrtcSender.VoiceEngine();
await assert.rejects(() => engine.publishData('not-bytes'), /payload must be/);
});
test('returns an unavailable hardware encoder capability without a binding', () => {
webrtcSender.__setBindingForTests(null);
assert.deepEqual(webrtcSender.getHardwareEncoderCapability(), {
available: false,
backend: 'none',
compiled: false,
runtime: false,
codecs: [],
zeroCopy: false,
nativeInputs: [],
reason: 'native_binding_unavailable',
detail: '@fluxer/webrtc-sender binding unavailable',
});
});
test('exposes every VoiceEngine method declared in index.d.ts on the wrapper', async () => {
const {readFileSync} = await import('node:fs');
const dts = readFileSync(new URL('./index.d.ts', import.meta.url), 'utf8');
const classStart = dts.indexOf('export declare class VoiceEngine {');
assert.ok(classStart >= 0);
const classEnd = dts.indexOf('\n}', classStart);
assert.ok(classEnd > classStart);
const classBody = dts.slice(classStart, classEnd);
const declaredMethods = [...classBody.matchAll(/^\t([A-Za-z0-9_]+)\(/gm)]
.map((match) => match[1])
.filter((name) => name !== 'constructor');
assert.ok(declaredMethods.length >= 30);
const wrapperMethods = new Set(Object.getOwnPropertyNames(webrtcSender.VoiceEngine.prototype));
const missing = declaredMethods.filter((name) => !wrapperMethods.has(name));
assert.deepEqual(missing, []);
});
});