feat: rename product and runtime to Piik
Rename the active product, Go module, binaries, configuration, protocols and documentation to Piik while retaining the TV mascot and existing media/room behavior. Use one current private contract without old-name aliases. Preserve SQLite authority and copy compatible local settings once; other settings start fresh. Git-message cleanup and the infrastructure name cutover are coordinated with this phase, with original history and deployment data archived externally. Validated locally with Web and Go checks, Windows capture compilation, matched Client/Server builds, packaged Client control handshake and history-rewrite integrity checks. Skip duplicate hosted CI for this owner-authorized local release. [skip ci]
This commit is contained in:
1 parent
35f9251088
commit
1332473513
254 files changed
+1443
-1321
No files matched your search
@@ -35,8 +35,8 @@ import {
|
||||
const root = resolve(import.meta.dirname, "..");
|
||||
const nginxConfigPath = resolve(root, "deploy/nginx/share.bonfire.icu.conf.example");
|
||||
const serverExecutable = join(root, "build", "client-check",
|
||||
process.platform === "win32" ? "screener-server.exe" : "screener-server");
|
||||
// SCREENER_ENV=production refuses to start without STUN. Nothing listens on
|
||||
process.platform === "win32" ? "piik-server.exe" : "piik-server");
|
||||
// PIIK_ENV=production refuses to start without STUN. Nothing listens on
|
||||
// this address, so the gate still never leaves the loopback interface.
|
||||
const gateStunUrl = "stun:127.0.0.1:3478";
|
||||
const hostClientId = "privacy-gate-host";
|
||||
@@ -55,7 +55,7 @@ const fragmentProbe = `(() => {
|
||||
if (location.hash) { state.replaced = true; state.beforeDomContentLoaded = !domContentLoaded; }
|
||||
return replaceState.apply(this, args);
|
||||
};
|
||||
Object.defineProperty(globalThis, "__SCREENER_ACCESS_GATE__", { value: state });
|
||||
Object.defineProperty(globalThis, "__PIIK_ACCESS_GATE__", { value: state });
|
||||
})();`;
|
||||
interface GateReport {
|
||||
passed: boolean; serverReady: boolean; roomPrepared: boolean;
|
||||
@@ -96,13 +96,13 @@ async function reserveDistinctPorts(count: number): Promise<number[]> {
|
||||
return ports;
|
||||
}
|
||||
function buildServer(): void {
|
||||
const go = process.env.SCREENER_GO?.trim() || "go";
|
||||
const result = spawnSync(go, ["build", "-trimpath", "-o", serverExecutable, "./cmd/screener-server"], {
|
||||
const go = process.env.PIIK_GO?.trim() || "go";
|
||||
const result = spawnSync(go, ["build", "-trimpath", "-o", serverExecutable, "./cmd/piik-server"], {
|
||||
cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"],
|
||||
env: { ...process.env, CGO_ENABLED: "0" },
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
if (result.status !== 0) throw new Error("screener-server build failed");
|
||||
if (result.status !== 0) throw new Error("piik-server build failed");
|
||||
}
|
||||
function forwardedHeaders(headers: IncomingHttpHeaders): OutgoingHttpHeaders {
|
||||
return Object.fromEntries(
|
||||
@@ -244,7 +244,7 @@ async function main(): Promise<void> {
|
||||
try {
|
||||
await access(chromePath);
|
||||
[proxyPort, serverPort, debugPort] = await reserveDistinctPorts(3);
|
||||
profile = await mkdtemp(join(tmpdir(), "screener-access-privacy-"));
|
||||
profile = await mkdtemp(join(tmpdir(), "piik-access-privacy-"));
|
||||
const baseUrl = `http://127.0.0.1:${proxyPort}`;
|
||||
await mkdir(dirname(serverExecutable), { recursive: true });
|
||||
buildServer();
|
||||
@@ -260,7 +260,7 @@ async function main(): Promise<void> {
|
||||
env: {
|
||||
PATH: process.env.PATH,
|
||||
SystemRoot: process.env.SystemRoot,
|
||||
SCREENER_ENV: "production",
|
||||
PIIK_ENV: "production",
|
||||
ROOM_DATABASE_PATH: ":memory:",
|
||||
PORT: String(serverPort),
|
||||
LISTEN_HOST: "127.0.0.1",
|
||||
@@ -346,7 +346,7 @@ async function main(): Promise<void> {
|
||||
const expected = JSON.stringify({ roomId: room.roomId, grant });
|
||||
const audit = await evaluate<BrowserAudit>(cdp, page, `(() => {
|
||||
const expected = ${expected};
|
||||
const fragment = globalThis.__SCREENER_ACCESS_GATE__;
|
||||
const fragment = globalThis.__PIIK_ACCESS_GATE__;
|
||||
const entries = (storage) => Object.keys(storage).map((key) => [key, storage.getItem(key)]);
|
||||
const session = entries(sessionStorage); const local = entries(localStorage);
|
||||
return {
|
||||
@@ -355,8 +355,8 @@ async function main(): Promise<void> {
|
||||
fragmentClearedBeforeDomContentLoaded: fragment?.beforeDomContentLoaded === true,
|
||||
fragmentCleared: location.hash === "",
|
||||
canonicalRoomPath: location.pathname === "/r/" + expected.roomId && location.search === "",
|
||||
roomSessionGrantMatches: session.filter(([key, value]) => key === "screener:viewer-grant:" + expected.roomId && value === expected.grant).length,
|
||||
otherSessionGrantMatches: session.filter(([key, value]) => value?.includes(expected.grant) && key !== "screener:viewer-grant:" + expected.roomId).length,
|
||||
roomSessionGrantMatches: session.filter(([key, value]) => key === "piik:viewer-grant:" + expected.roomId && value === expected.grant).length,
|
||||
otherSessionGrantMatches: session.filter(([key, value]) => value?.includes(expected.grant) && key !== "piik:viewer-grant:" + expected.roomId).length,
|
||||
localGrantMatches: local.filter(([, value]) => value && value.includes(expected.grant)).length,
|
||||
resourceGrantMatches: performance.getEntriesByType("resource").filter((entry) => entry.name.includes(expected.grant)).length,
|
||||
};
|
||||
|
||||
@@ -132,7 +132,7 @@ function readDescriptor(path) {
|
||||
function assertOutputDirectory(repositoryRoot, outputRoot, target) {
|
||||
const path = relative(repositoryRoot, outputRoot);
|
||||
const candidateOutput = join(repositoryRoot, "build", "client-package", target.id,
|
||||
"candidate", `Screener-Client-${target.id}`);
|
||||
"candidate", `Piik-Client-${target.id}`);
|
||||
if (outputRoot !== candidateOutput &&
|
||||
(path === "" || (path.split(/[\\/]/)[0] !== ".." && !isAbsolute(path)))) {
|
||||
fail("Client output must be outside the repository or its exact candidate workspace");
|
||||
@@ -248,15 +248,15 @@ try {
|
||||
|
||||
const clientName = target.clientName;
|
||||
const clientPath = join(packageRoot, clientName);
|
||||
const goCommand = process.env.SCREENER_GO?.trim() || "go";
|
||||
const goCommand = process.env.PIIK_GO?.trim() || "go";
|
||||
run(goCommand, [
|
||||
"build",
|
||||
"-trimpath",
|
||||
"-ldflags",
|
||||
`-s -w -X github.com/TNTcraftHIM/Screener/internal/client/clientapp.BuildRevision=${revision}`,
|
||||
`-s -w -X github.com/TNTcraftHIM/Piik/internal/client/clientapp.BuildRevision=${revision}`,
|
||||
"-o",
|
||||
clientPath,
|
||||
"./cmd/screener-client",
|
||||
"./cmd/piik-client",
|
||||
], repositoryRoot, clientGoEnvironment(target));
|
||||
chmodSync(clientPath, 0o755);
|
||||
assertTargetExecutable(clientPath, target, "Client executable");
|
||||
@@ -266,7 +266,7 @@ try {
|
||||
packageRoot,
|
||||
target,
|
||||
revision,
|
||||
iconPath: join(repositoryRoot, "cmd", "screener-client", "screener.ico"),
|
||||
iconPath: join(repositoryRoot, "cmd", "piik-client", "piik.ico"),
|
||||
});
|
||||
writeFileSync(join(packageRoot, "REVISION"), `${revision}\n`, "ascii");
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ interface AsyncCloseable {
|
||||
}
|
||||
|
||||
// A gate's server is either an in-process page server it closes directly or a
|
||||
// spawned Screener server it stops like any other child.
|
||||
// spawned Piik server it stops like any other child.
|
||||
export type CleanupServer = AsyncCloseable | ChildProcessWithoutNullStreams;
|
||||
|
||||
export interface CleanupResources {
|
||||
@@ -495,11 +495,11 @@ function portClosed(port: number, deadline: number): Promise<boolean> {
|
||||
|
||||
export const profileCleanupScript = String.raw`
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$root = [IO.Path]::GetFullPath($env:SCREENER_GATE_PROFILE_TO_REMOVE)
|
||||
$root = [IO.Path]::GetFullPath($env:PIIK_GATE_PROFILE_TO_REMOVE)
|
||||
$temp = [IO.Path]::GetFullPath([IO.Path]::GetTempPath()).TrimEnd([IO.Path]::DirectorySeparatorChar)
|
||||
$parent = [IO.Path]::GetDirectoryName($root).TrimEnd([IO.Path]::DirectorySeparatorChar)
|
||||
$name = [IO.Path]::GetFileName($root)
|
||||
if ($parent -ine $temp -or $name -notmatch '^screener-(access-privacy|client-loopback|client-media)-[A-Za-z0-9_-]{6}$') { exit 31 }
|
||||
if ($parent -ine $temp -or $name -notmatch '^piik-(access-privacy|client-loopback|client-media)-[A-Za-z0-9_-]{6}$') { exit 31 }
|
||||
$rootEntries = @([IO.Directory]::EnumerateFileSystemEntries($parent, $name, [IO.SearchOption]::TopDirectoryOnly))
|
||||
if ($rootEntries.Count -eq 0) { exit 0 }
|
||||
if ($rootEntries.Count -ne 1) { exit 34 }
|
||||
@@ -534,7 +534,7 @@ export function isExactGateProfile(
|
||||
? dirname(candidate).toLowerCase() === temp.toLowerCase()
|
||||
: dirname(candidate) === temp;
|
||||
return same &&
|
||||
/^screener-(?:access-privacy|client-loopback|client-media)-[A-Za-z0-9_-]{6}$/.test(
|
||||
/^piik-(?:access-privacy|client-loopback|client-media)-[A-Za-z0-9_-]{6}$/.test(
|
||||
basename(candidate),
|
||||
);
|
||||
}
|
||||
@@ -564,7 +564,7 @@ async function removeGateProfile(profile: string): Promise<boolean> {
|
||||
"powershell.exe",
|
||||
["-NoProfile", "-NonInteractive", "-Command", profileCleanupScript],
|
||||
10_000,
|
||||
{ ...process.env, SCREENER_GATE_PROFILE_TO_REMOVE: profile },
|
||||
{ ...process.env, PIIK_GATE_PROFILE_TO_REMOVE: profile },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ const server = createServer((request, response) => {
|
||||
});
|
||||
await new Promise<void>(r => server.listen(0, '127.0.0.1', r));
|
||||
const port = (server.address() as { port: number }).port, debugPort = await reservePort();
|
||||
const profile = await mkdtemp(join(tmpdir(), 'screener-client-media-'));
|
||||
const profile = await mkdtemp(join(tmpdir(), 'piik-client-media-'));
|
||||
const chrome = launchChrome(process.env.CHROME_PATH || 'C:/Program Files/Google/Chrome/Application/chrome.exe', debugPort, profile,
|
||||
['--headless=new', '--no-first-run', '--autoplay-policy=no-user-gesture-required',
|
||||
...(background ? [] : ['--disable-background-timer-throttling', '--disable-renderer-backgrounding']),
|
||||
|
||||
@@ -52,9 +52,9 @@ function buildWebAssets() {
|
||||
|
||||
function checkCore() {
|
||||
buildWebAssets();
|
||||
const go = process.env.SCREENER_GO?.trim() || "go";
|
||||
const go = process.env.PIIK_GO?.trim() || "go";
|
||||
const goRoot = run(go, ["env", "GOROOT"], { capture: true });
|
||||
const gofmt = process.env.SCREENER_GOFMT?.trim() ||
|
||||
const gofmt = process.env.PIIK_GOFMT?.trim() ||
|
||||
join(goRoot, "bin", process.platform === "win32" ? "gofmt.exe" : "gofmt");
|
||||
const unformatted = run(gofmt, ["-l", "."], { capture: true });
|
||||
if (unformatted) {
|
||||
@@ -73,9 +73,9 @@ function checkCore() {
|
||||
return true;
|
||||
});
|
||||
const builds = buildTargets.flatMap((target) =>
|
||||
["screener-client", "screener-peer-gate"].map((command) => ({ target, command })),
|
||||
["piik-client", "piik-peer-gate"].map((command) => ({ target, command })),
|
||||
);
|
||||
builds.push({ target: SERVER_TARGET, command: "screener-server" });
|
||||
builds.push({ target: SERVER_TARGET, command: "piik-server" });
|
||||
for (const { target, command } of builds) {
|
||||
const outputName = target.goos === "windows"
|
||||
? `${command}.exe`
|
||||
@@ -132,7 +132,7 @@ function checkPlatformCapture() {
|
||||
"7",
|
||||
"pwsh.exe",
|
||||
);
|
||||
const powershell = process.env.SCREENER_POWERSHELL?.trim() ||
|
||||
const powershell = process.env.PIIK_POWERSHELL?.trim() ||
|
||||
(existsSync(modernPowerShell)
|
||||
? modernPowerShell
|
||||
: (existsSync(systemPowerShell) ? systemPowerShell : "pwsh"));
|
||||
@@ -146,13 +146,13 @@ function checkPlatformCapture() {
|
||||
buildRoot,
|
||||
"-Check",
|
||||
]);
|
||||
executable = join(buildRoot, "screener-client-capture.exe");
|
||||
executable = join(buildRoot, "piik-client-capture.exe");
|
||||
} else if (process.platform === "darwin") {
|
||||
run("sh", [join(captureRoot, "darwin", "build.sh"), buildRoot]);
|
||||
executable = join(buildRoot, "screener-client-capture");
|
||||
executable = join(buildRoot, "piik-client-capture");
|
||||
} else {
|
||||
run("sh", [join(captureRoot, "linux", "build.sh"), buildRoot]);
|
||||
executable = join(buildRoot, "screener-client-capture");
|
||||
executable = join(buildRoot, "piik-client-capture");
|
||||
}
|
||||
if (!existsSync(executable)) {
|
||||
throw new Error("Native capture build did not produce its executable");
|
||||
@@ -205,4 +205,4 @@ function checkPlatformCapture() {
|
||||
|
||||
if (mode !== "--capture-only") checkCore();
|
||||
if (mode !== "--core") checkPlatformCapture();
|
||||
process.stdout.write("Screener Client checks passed.\n");
|
||||
process.stdout.write("Piik Client checks passed.\n");
|
||||
@@ -2,7 +2,7 @@ $ErrorActionPreference = "Stop"
|
||||
|
||||
$repoRoot = (git rev-parse --show-toplevel).Trim()
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "This command must run inside the Screener Git repository."
|
||||
throw "This command must run inside the Piik Git repository."
|
||||
}
|
||||
Set-Location $repoRoot
|
||||
|
||||
@@ -19,8 +19,8 @@ if ($LASTEXITCODE -ne 0) { throw "Working-tree whitespace check failed." }
|
||||
git diff --cached --check
|
||||
if ($LASTEXITCODE -ne 0) { throw "Staged whitespace check failed." }
|
||||
|
||||
if ($env:SCREENER_BASE_SHA -and $env:SCREENER_BASE_SHA -notmatch '^0{40}$') {
|
||||
git diff --check "$env:SCREENER_BASE_SHA...HEAD"
|
||||
if ($env:PIIK_BASE_SHA -and $env:PIIK_BASE_SHA -notmatch '^0{40}$') {
|
||||
git diff --check "$env:PIIK_BASE_SHA...HEAD"
|
||||
if ($LASTEXITCODE -ne 0) { throw "Commit-range whitespace check failed." }
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ done < scripts/required-project-paths.txt
|
||||
git diff --check
|
||||
git diff --cached --check
|
||||
|
||||
if [ -n "${SCREENER_BASE_SHA:-}" ] && [ "$SCREENER_BASE_SHA" != "0000000000000000000000000000000000000000" ]; then
|
||||
git diff --check "$SCREENER_BASE_SHA"...HEAD
|
||||
if [ -n "${PIIK_BASE_SHA:-}" ] && [ "$PIIK_BASE_SHA" != "0000000000000000000000000000000000000000" ]; then
|
||||
git diff --check "$PIIK_BASE_SHA"...HEAD
|
||||
fi
|
||||
|
||||
node scripts/check-docs.mjs
|
||||
|
||||
@@ -15,10 +15,10 @@ const BUILD_ROOT = join(ROOT, "build/client-check");
|
||||
// Client does on a real network.
|
||||
const LAN_ADDRESS = "192.0.2.1";
|
||||
|
||||
const initialAudio = process.env.SCREENER_CLIENT_GATE_AUDIO !== "false";
|
||||
const initialAudio = process.env.PIIK_CLIENT_GATE_AUDIO !== "false";
|
||||
const probe = String.raw`(() => {
|
||||
localStorage.setItem('screener:ui-lang', 'en');
|
||||
localStorage.setItem('screener:ui-mode', 'text');
|
||||
localStorage.setItem('piik:ui-lang', 'en');
|
||||
localStorage.setItem('piik:ui-mode', 'text');
|
||||
const pcs = [], requests = [], sockets = [], errors = [];
|
||||
window.addEventListener('unhandledrejection', (e) => errors.push(String(e.reason)));
|
||||
const codecPreferences = RTCRtpTransceiver.prototype.setCodecPreferences;
|
||||
@@ -103,20 +103,20 @@ function build(command: string, args: string[]): void {
|
||||
}
|
||||
}
|
||||
|
||||
// startRoomServer builds and starts the Screener server the Browser pages and
|
||||
// both Clients share. SCREENER_ENV stays development because production
|
||||
// startRoomServer builds and starts the Piik server the Browser pages and
|
||||
// both Clients share. PIIK_ENV stays development because production
|
||||
// requires an https public origin, a site password and STUN; the Web assets are
|
||||
// embedded either way.
|
||||
async function startRoomServer(
|
||||
port: number,
|
||||
workingDirectory: string,
|
||||
): Promise<ChildProcessWithoutNullStreams> {
|
||||
const go = process.env.SCREENER_GO?.trim() || "go";
|
||||
const go = process.env.PIIK_GO?.trim() || "go";
|
||||
await mkdir(BUILD_ROOT, { recursive: true });
|
||||
// The server embeds the Vite output, so the Web build precedes the Go build.
|
||||
build(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", "npm run build:client"]);
|
||||
const binary = join(BUILD_ROOT, "screener-server.exe");
|
||||
build(go, ["build", "-trimpath", "-o", binary, "./cmd/screener-server"]);
|
||||
const binary = join(BUILD_ROOT, "piik-server.exe");
|
||||
build(go, ["build", "-trimpath", "-o", binary, "./cmd/piik-server"]);
|
||||
const origins = [`http://localhost:${port}`, `http://127.0.0.1:${port}`, `http://${LAN_ADDRESS}:${port}`];
|
||||
const child = spawn(binary, [], {
|
||||
// The gate profile has no .env, and the environment is explicit: the
|
||||
@@ -126,7 +126,7 @@ async function startRoomServer(
|
||||
env: {
|
||||
PATH: process.env.PATH,
|
||||
SystemRoot: process.env.SystemRoot,
|
||||
SCREENER_ENV: "development",
|
||||
PIIK_ENV: "development",
|
||||
ROOM_DATABASE_PATH: ":memory:",
|
||||
PORT: String(port),
|
||||
LISTEN_HOST: "127.0.0.1",
|
||||
@@ -145,10 +145,10 @@ async function startRoomServer(
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
if (process.env.SCREENER_CLIENT_BROWSER_FANOUT_GATE !== "true") throw new Error("Browser fanout gate was not enabled");
|
||||
if (process.env.PIIK_CLIENT_BROWSER_FANOUT_GATE !== "true") throw new Error("Browser fanout gate was not enabled");
|
||||
const chromePath = process.env.CHROME_PATH;
|
||||
if (!chromePath) throw new Error("CHROME_PATH is required");
|
||||
const profile = await mkdtemp(join(tmpdir(), "screener-client-media-"));
|
||||
const profile = await mkdtemp(join(tmpdir(), "piik-client-media-"));
|
||||
const appPort = await reservePort(), debugPort = await reservePort();
|
||||
const origin = `http://localhost:${appPort}`;
|
||||
let client: ChildProcessWithoutNullStreams | null = null;
|
||||
@@ -163,10 +163,10 @@ async function main(): Promise<void> {
|
||||
let stage = "startup", error: string | null = null;
|
||||
try {
|
||||
server = await startRoomServer(appPort, profile);
|
||||
client = spawn(process.env.SCREENER_CLIENT_EXE || join(BUILD_ROOT, "screener-client.exe"), [
|
||||
client = spawn(process.env.PIIK_CLIENT_EXE || join(BUILD_ROOT, "piik-client.exe"), [
|
||||
"--site", origin, "--config", join(profile, "client.json"),
|
||||
"--capture-process", join(BUILD_ROOT, "screener-client-capture.exe"),
|
||||
], { windowsHide: true, stdio: "pipe", env: { ...process.env, SCREENER_CLIENT_GATE_NO_BROWSER: "true" } });
|
||||
"--capture-process", join(BUILD_ROOT, "piik-client-capture.exe"),
|
||||
], { windowsHide: true, stdio: "pipe", env: { ...process.env, PIIK_CLIENT_GATE_NO_BROWSER: "true" } });
|
||||
client.stderr.resume();
|
||||
let output = "";
|
||||
client.stdout.on("data", (chunk: Buffer) => {
|
||||
@@ -185,7 +185,7 @@ async function main(): Promise<void> {
|
||||
checks.browser = version.Browser;
|
||||
cdp = await CdpConnection.connect(version.webSocketDebuggerUrl, Date.now() + 10000);
|
||||
await cdp.call("Browser.setPermission", { origin, permission: {name:"loopback-network"}, setting:"granted" }, undefined, Date.now()+5000);
|
||||
const host = await createPage(cdp, `${origin}/#screener-client=1`, probe);
|
||||
const host = await createPage(cdp, `${origin}/#piik-client=1`, probe);
|
||||
pages.push(host);
|
||||
const read = async (page: PageHandle) => {
|
||||
const sample = await evaluate<any>(cdp!, page, "fanoutGate.sample()", Date.now()+5000);
|
||||
@@ -211,10 +211,10 @@ async function main(): Promise<void> {
|
||||
let invite = await evaluate<string>(cdp, host, "document.querySelector('.lr-invite-url').value", Date.now()+5000);
|
||||
const url = new URL(invite); url.host = `localhost:${appPort}`; invite = url.toString();
|
||||
const relayOrigin = `http://127.0.0.1:${appPort}`;
|
||||
relayClient = spawn(process.env.SCREENER_CLIENT_EXE || join(BUILD_ROOT,"screener-client.exe"), [
|
||||
relayClient = spawn(process.env.PIIK_CLIENT_EXE || join(BUILD_ROOT,"piik-client.exe"), [
|
||||
"--site", relayOrigin, "--config", join(profile,"relay-client.json"),
|
||||
"--capture-process", join(BUILD_ROOT,"screener-client-capture.exe"),
|
||||
], { windowsHide:true, stdio:"pipe", env:{...process.env,SCREENER_CLIENT_GATE_NO_BROWSER:"true"} });
|
||||
"--capture-process", join(BUILD_ROOT,"piik-client-capture.exe"),
|
||||
], { windowsHide:true, stdio:"pipe", env:{...process.env,PIIK_CLIENT_GATE_NO_BROWSER:"true"} });
|
||||
relayClient.stderr.resume(); let relayOutput="";
|
||||
relayClient.stdout.on("data", (chunk:Buffer) => {
|
||||
relayOutput+=chunk.toString();
|
||||
@@ -226,7 +226,7 @@ async function main(): Promise<void> {
|
||||
stage = `viewer-${index+1}`;
|
||||
const context = await cdp.call<{browserContextId: string}>("Target.createBrowserContext", {}, undefined, Date.now()+5000);
|
||||
await cdp.call("Browser.setPermission", { origin:index===0?relayOrigin:origin, permission: {name:"loopback-network"}, setting:"granted", browserContextId: context.browserContextId }, undefined, Date.now()+5000);
|
||||
const viewerURL = index===0 ? invite.replace(origin,relayOrigin)+"&screener-client=1" : invite;
|
||||
const viewerURL = index===0 ? invite.replace(origin,relayOrigin)+"&piik-client=1" : invite;
|
||||
const viewer = await createPage(cdp, viewerURL, probe, true, context.browserContextId);
|
||||
viewers.push(viewer);
|
||||
pages.push(viewer);
|
||||
|
||||
+15
-15
@@ -92,19 +92,19 @@ function writeLinuxAssets(packageRoot, entries) {
|
||||
mkdirSync(iconDirectory, { recursive: true });
|
||||
mkdirSync(applicationDirectory, { recursive: true });
|
||||
writeFileSync(
|
||||
join(iconDirectory, "screener-client.png"),
|
||||
join(iconDirectory, "piik-client.png"),
|
||||
requireEntry(entries, 256),
|
||||
);
|
||||
writeFileSync(
|
||||
join(applicationDirectory, "screener-client.desktop"),
|
||||
join(applicationDirectory, "piik-client.desktop"),
|
||||
[
|
||||
"[Desktop Entry]",
|
||||
"Version=1.0",
|
||||
"Type=Application",
|
||||
"Name=Screener Client",
|
||||
"Exec=screener-client",
|
||||
"TryExec=screener-client",
|
||||
"Icon=screener-client",
|
||||
"Name=Piik Client",
|
||||
"Exec=piik-client",
|
||||
"TryExec=piik-client",
|
||||
"Icon=piik-client",
|
||||
"Terminal=false",
|
||||
"Categories=Network;Utility;",
|
||||
"StartupNotify=true",
|
||||
@@ -115,13 +115,13 @@ function writeLinuxAssets(packageRoot, entries) {
|
||||
}
|
||||
|
||||
function writeMacAssets(packageRoot, revision, entries) {
|
||||
const bundleRoot = join(packageRoot, "Screener Client.app");
|
||||
const bundleRoot = join(packageRoot, "Piik Client.app");
|
||||
const contents = join(bundleRoot, "Contents");
|
||||
const macos = join(contents, "MacOS");
|
||||
const resources = join(contents, "Resources");
|
||||
mkdirSync(macos, { recursive: true });
|
||||
mkdirSync(resources, { recursive: true });
|
||||
writeIcns(entries, join(resources, "screener.icns"));
|
||||
writeIcns(entries, join(resources, "piik.icns"));
|
||||
writeFileSync(
|
||||
join(contents, "Info.plist"),
|
||||
[
|
||||
@@ -129,12 +129,12 @@ function writeMacAssets(packageRoot, revision, entries) {
|
||||
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
||||
'<plist version="1.0"><dict>',
|
||||
"<key>CFBundleDevelopmentRegion</key><string>en</string>",
|
||||
"<key>CFBundleDisplayName</key><string>Screener Client</string>",
|
||||
"<key>CFBundleDisplayName</key><string>Piik Client</string>",
|
||||
"<key>CFBundleExecutable</key><string>Launcher</string>",
|
||||
"<key>CFBundleIconFile</key><string>screener.icns</string>",
|
||||
"<key>CFBundleIdentifier</key><string>icu.bonfire.screener.client</string>",
|
||||
"<key>CFBundleIconFile</key><string>piik.icns</string>",
|
||||
"<key>CFBundleIdentifier</key><string>tv.piik.client</string>",
|
||||
"<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>",
|
||||
"<key>CFBundleName</key><string>Screener Client</string>",
|
||||
"<key>CFBundleName</key><string>Piik Client</string>",
|
||||
"<key>CFBundlePackageType</key><string>APPL</string>",
|
||||
"<key>CFBundleShortVersionString</key><string>1.0</string>",
|
||||
"<key>NSScreenCaptureUsageDescription</key><string>Share a screen or application selected by you.</string>",
|
||||
@@ -152,7 +152,7 @@ function writeMacAssets(packageRoot, revision, entries) {
|
||||
"#!/bin/sh",
|
||||
"set -eu",
|
||||
'base=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)',
|
||||
'exec "$base/../../../screener-client" "$@"',
|
||||
'exec "$base/../../../piik-client" "$@"',
|
||||
"",
|
||||
].join("\n"),
|
||||
"utf8",
|
||||
@@ -170,8 +170,8 @@ export function writeClientPlatformAssets({
|
||||
if (target.goos === "linux") writeLinuxAssets(packageRoot, entries);
|
||||
if (target.goos === "darwin") writeMacAssets(packageRoot, revision, entries);
|
||||
return target.goos === "linux"
|
||||
? "share/applications/screener-client.desktop"
|
||||
? "share/applications/piik-client.desktop"
|
||||
: target.goos === "darwin"
|
||||
? "Screener Client.app"
|
||||
? "Piik Client.app"
|
||||
: null;
|
||||
}
|
||||
+15
-15
@@ -86,21 +86,21 @@ function remoteOptions(): {
|
||||
key: string;
|
||||
ssh: string;
|
||||
} {
|
||||
const host = process.env.SCREENER_REMOTE_HOST?.trim();
|
||||
const key = process.env.SCREENER_REMOTE_SSH_KEY?.trim();
|
||||
const host = process.env.PIIK_REMOTE_HOST?.trim();
|
||||
const key = process.env.PIIK_REMOTE_SSH_KEY?.trim();
|
||||
if (!host || !key) {
|
||||
throw new Error("SCREENER_REMOTE_HOST and SCREENER_REMOTE_SSH_KEY are required");
|
||||
throw new Error("PIIK_REMOTE_HOST and PIIK_REMOTE_SSH_KEY are required");
|
||||
}
|
||||
return {
|
||||
host,
|
||||
key,
|
||||
user: process.env.SCREENER_REMOTE_USER?.trim() || "root",
|
||||
ssh: process.env.SCREENER_SSH?.trim() || "ssh",
|
||||
user: process.env.PIIK_REMOTE_USER?.trim() || "root",
|
||||
ssh: process.env.PIIK_SSH?.trim() || "ssh",
|
||||
};
|
||||
}
|
||||
|
||||
function transportArgs(key: string): string[] {
|
||||
const bindAddress = process.env.SCREENER_REMOTE_BIND_ADDRESS?.trim();
|
||||
const bindAddress = process.env.PIIK_REMOTE_BIND_ADDRESS?.trim();
|
||||
return [
|
||||
"-o", "BatchMode=yes",
|
||||
"-o", "StrictHostKeyChecking=yes",
|
||||
@@ -196,21 +196,21 @@ async function waitUntilLinkCloses(origin: string): Promise<boolean> {
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
if (process.env.SCREENER_CLIENT_LINK_GATE !== "true") {
|
||||
throw new Error("SCREENER_CLIENT_LINK_GATE=true is required");
|
||||
if (process.env.PIIK_CLIENT_LINK_GATE !== "true") {
|
||||
throw new Error("PIIK_CLIENT_LINK_GATE=true is required");
|
||||
}
|
||||
const remote = remoteOptions();
|
||||
const transport = transportArgs(remote.key);
|
||||
const destination = `${remote.user}@${remote.host}`;
|
||||
const go = process.env.SCREENER_GO?.trim() || "go";
|
||||
const configuredClient = process.env.SCREENER_CLIENT_EXE?.trim();
|
||||
const tunnel = process.env.SCREENER_CLOUDFLARED?.trim() ||
|
||||
const go = process.env.PIIK_GO?.trim() || "go";
|
||||
const configuredClient = process.env.PIIK_CLIENT_EXE?.trim();
|
||||
const tunnel = process.env.PIIK_CLOUDFLARED?.trim() ||
|
||||
join(BUILD_ROOT, process.platform === "win32" ? "cloudflared.exe" : "cloudflared");
|
||||
const profile = await mkdtemp(join(tmpdir(), "screener-client-link-"));
|
||||
const profile = await mkdtemp(join(tmpdir(), "piik-client-link-"));
|
||||
const port = await reservePort();
|
||||
const clientBinary = configuredClient || join(
|
||||
BUILD_ROOT,
|
||||
process.platform === "win32" ? "screener-client.exe" : "screener-client",
|
||||
process.platform === "win32" ? "piik-client.exe" : "piik-client",
|
||||
);
|
||||
let client: ChildProcessWithoutNullStreams | null = null;
|
||||
let publicOrigin = "";
|
||||
@@ -236,7 +236,7 @@ async function main(): Promise<void> {
|
||||
} else {
|
||||
run("npm", ["run", "build:client"]);
|
||||
}
|
||||
run(go, ["build", "-trimpath", "-o", clientBinary, "./cmd/screener-client"],
|
||||
run(go, ["build", "-trimpath", "-o", clientBinary, "./cmd/piik-client"],
|
||||
ROOT);
|
||||
}
|
||||
result.stage = "client-start";
|
||||
@@ -248,7 +248,7 @@ async function main(): Promise<void> {
|
||||
"--tunnel-process", tunnel,
|
||||
], {
|
||||
cwd: ROOT,
|
||||
env: { ...process.env, SCREENER_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
env: { ...process.env, PIIK_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
stdio: "pipe",
|
||||
windowsHide: true,
|
||||
});
|
||||
|
||||
@@ -45,22 +45,22 @@ const LOCAL_PAGE_STATE = `fetch('/api/site-access')
|
||||
.then((response) => response.json())
|
||||
.catch(() => null)
|
||||
.then((access) => ({
|
||||
bootstrapPresent: ['client-access', 'screener-client']
|
||||
bootstrapPresent: ['client-access', 'piik-client']
|
||||
.some((key) => new URLSearchParams(location.hash.slice(1)).has(key)),
|
||||
access,
|
||||
hostReady: Boolean(document.querySelector('.lr-host-personal-controls')),
|
||||
}))`;
|
||||
|
||||
async function main(): Promise<void> {
|
||||
if (process.env.SCREENER_CLIENT_LOCAL_GATE !== "true") {
|
||||
if (process.env.PIIK_CLIENT_LOCAL_GATE !== "true") {
|
||||
throw new Error("Local Client gate was not explicitly enabled");
|
||||
}
|
||||
const browserPath = process.env.CHROME_PATH?.trim();
|
||||
const clientPath = process.env.SCREENER_CLIENT_EXE?.trim();
|
||||
const lanAddress = process.env.SCREENER_CLIENT_GATE_LAN_ADDRESS?.trim();
|
||||
const clientPath = process.env.PIIK_CLIENT_EXE?.trim();
|
||||
const lanAddress = process.env.PIIK_CLIENT_GATE_LAN_ADDRESS?.trim();
|
||||
if (!browserPath || !clientPath || !lanAddress) {
|
||||
throw new Error(
|
||||
"CHROME_PATH, SCREENER_CLIENT_EXE, and SCREENER_CLIENT_GATE_LAN_ADDRESS are required",
|
||||
"CHROME_PATH, PIIK_CLIENT_EXE, and PIIK_CLIENT_GATE_LAN_ADDRESS are required",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ async function main(): Promise<void> {
|
||||
};
|
||||
const appPort = await reservePort();
|
||||
const debugPort = await reservePort();
|
||||
const profile = await mkdtemp(join(tmpdir(), "screener-client-loopback-"));
|
||||
const profile = await mkdtemp(join(tmpdir(), "piik-client-loopback-"));
|
||||
const configPath = join(profile, "client.json");
|
||||
let client: ChildProcessWithoutNullStreams | null = null;
|
||||
let browser: ChildProcessWithoutNullStreams | null = null;
|
||||
@@ -97,7 +97,7 @@ async function main(): Promise<void> {
|
||||
], {
|
||||
stdio: "pipe",
|
||||
windowsHide: true,
|
||||
env: { ...process.env, SCREENER_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
env: { ...process.env, PIIK_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
});
|
||||
client.stderr.resume();
|
||||
const endpoint = await readClientEndpoint(client);
|
||||
@@ -121,12 +121,12 @@ async function main(): Promise<void> {
|
||||
const localAccessPassword = config.localAccessPassword;
|
||||
const bootstrap = new URLSearchParams({
|
||||
...(localAccessPassword ? { "client-access": localAccessPassword } : {}),
|
||||
"screener-client": "1",
|
||||
"piik-client": "1",
|
||||
}).toString();
|
||||
|
||||
browser = launchChrome(browserPath, debugPort, profile, [
|
||||
"--headless=new",
|
||||
...(process.env.SCREENER_CLIENT_GATE_NO_SANDBOX === "true"
|
||||
...(process.env.PIIK_CLIENT_GATE_NO_SANDBOX === "true"
|
||||
? ["--no-sandbox"]
|
||||
: []),
|
||||
"--no-first-run",
|
||||
|
||||
@@ -73,7 +73,7 @@ async function browserHandshake(
|
||||
});
|
||||
if (!response.ok) continue;
|
||||
const health = await response.json();
|
||||
if (health.protocol === ${NATIVE_PROTOCOL} && health.service === "screener-client" &&
|
||||
if (health.protocol === ${NATIVE_PROTOCOL} && health.service === "piik-client" &&
|
||||
health.port === port && typeof health.instanceToken === "string" &&
|
||||
typeof health.nativeMedia?.video === "boolean" &&
|
||||
typeof health.nativeMedia?.processAudio === "boolean" &&
|
||||
@@ -137,18 +137,18 @@ async function main(): Promise<void> {
|
||||
if (process.platform !== "win32" && process.platform !== "darwin" && process.platform !== "linux") {
|
||||
throw new Error("loopback gate requires a desktop platform");
|
||||
}
|
||||
if (process.env.SCREENER_CLIENT_LOOPBACK_GATE !== "true") {
|
||||
if (process.env.PIIK_CLIENT_LOOPBACK_GATE !== "true") {
|
||||
throw new Error("loopback gate was not explicitly enabled");
|
||||
}
|
||||
const browserPath = process.env.CHROME_PATH?.trim();
|
||||
const clientPath = process.env.SCREENER_CLIENT_EXE?.trim();
|
||||
const clientPath = process.env.PIIK_CLIENT_EXE?.trim();
|
||||
if (!browserPath || !clientPath) {
|
||||
throw new Error("CHROME_PATH and SCREENER_CLIENT_EXE are required");
|
||||
throw new Error("CHROME_PATH and PIIK_CLIENT_EXE are required");
|
||||
}
|
||||
const disposableNoSandbox =
|
||||
process.env.SCREENER_CLIENT_GATE_NO_SANDBOX === "true";
|
||||
process.env.PIIK_CLIENT_GATE_NO_SANDBOX === "true";
|
||||
const grantLoopback =
|
||||
process.env.SCREENER_CLIENT_GATE_GRANT_LOOPBACK === "true";
|
||||
process.env.PIIK_CLIENT_GATE_GRANT_LOOPBACK === "true";
|
||||
|
||||
const report: GateReport = {
|
||||
passed: false,
|
||||
@@ -173,14 +173,14 @@ async function main(): Promise<void> {
|
||||
let cdp: CdpConnection | null = null;
|
||||
let debugPort = 0;
|
||||
try {
|
||||
profile = await mkdtemp(join(tmpdir(), "screener-client-loopback-"));
|
||||
profile = await mkdtemp(join(tmpdir(), "piik-client-loopback-"));
|
||||
client = spawn(clientPath, [
|
||||
"--site", PAGE_URL,
|
||||
"--config", join(profile, "client.json"),
|
||||
], {
|
||||
stdio: "pipe",
|
||||
windowsHide: true,
|
||||
env: { ...process.env, SCREENER_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
env: { ...process.env, PIIK_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
});
|
||||
client.stderr.resume();
|
||||
const endpoint = await readClientEndpoint(client, { timeoutMs: 8_000 });
|
||||
|
||||
@@ -26,8 +26,8 @@ import {
|
||||
|
||||
const ROOT = resolve(import.meta.dirname, "..");
|
||||
const BUILD_ROOT = join(ROOT, "build", "client-check");
|
||||
const SOURCE_TITLE = "Screener Native Gate Source";
|
||||
const GATE_STUN_URLS = process.env.SCREENER_CLIENT_GATE_STUN_URLS?.trim();
|
||||
const SOURCE_TITLE = "Piik Native Gate Source";
|
||||
const GATE_STUN_URLS = process.env.PIIK_CLIENT_GATE_STUN_URLS?.trim();
|
||||
|
||||
interface Probe {
|
||||
protocol: number;
|
||||
@@ -97,7 +97,7 @@ function run(command: string, args: string[], cwd = ROOT): string {
|
||||
}
|
||||
|
||||
function powershell(): string {
|
||||
const configured = process.env.SCREENER_POWERSHELL?.trim();
|
||||
const configured = process.env.PIIK_POWERSHELL?.trim();
|
||||
if (configured) return configured;
|
||||
return join(
|
||||
process.env.SystemRoot || "C:\\Windows",
|
||||
@@ -301,7 +301,7 @@ async function browserMediaGate(input: {
|
||||
const health = await healthResponse.json();
|
||||
if (
|
||||
health.protocol !== input.protocol ||
|
||||
health.service !== "screener-client" ||
|
||||
health.service !== "piik-client" ||
|
||||
health.instanceToken !== input.endpoint.instanceToken ||
|
||||
health.nativeMedia?.video !== true ||
|
||||
health.nativeMedia?.hardwareH264 !== true
|
||||
@@ -657,16 +657,16 @@ async function main(): Promise<void> {
|
||||
if (process.platform !== "win32") {
|
||||
throw new Error("The native capture gate currently requires Windows");
|
||||
}
|
||||
if (process.env.SCREENER_CLIENT_MEDIA_GATE !== "true") {
|
||||
throw new Error("SCREENER_CLIENT_MEDIA_GATE=true is required");
|
||||
if (process.env.PIIK_CLIENT_MEDIA_GATE !== "true") {
|
||||
throw new Error("PIIK_CLIENT_MEDIA_GATE=true is required");
|
||||
}
|
||||
const chromePath = process.env.CHROME_PATH?.trim();
|
||||
if (!chromePath) throw new Error("CHROME_PATH is required");
|
||||
if (!GATE_STUN_URLS) {
|
||||
throw new Error("SCREENER_CLIENT_GATE_STUN_URLS is required");
|
||||
throw new Error("PIIK_CLIENT_GATE_STUN_URLS is required");
|
||||
}
|
||||
|
||||
const profile = await mkdtemp(join(tmpdir(), "screener-client-media-"));
|
||||
const profile = await mkdtemp(join(tmpdir(), "piik-client-media-"));
|
||||
// Keep network-capable binaries at a stable repository path. Windows
|
||||
// associates its firewall decision with the full executable path; the
|
||||
// disposable Browser profile remains in the system temp directory.
|
||||
@@ -734,7 +734,7 @@ async function main(): Promise<void> {
|
||||
"-OutputDirectory",
|
||||
buildRoot,
|
||||
]);
|
||||
const executable = join(buildRoot, "screener-client-capture.exe");
|
||||
const executable = join(buildRoot, "piik-client-capture.exe");
|
||||
const probe = JSON.parse(run(executable, ["--probe"])) as Probe;
|
||||
const adapter = probe.adapters.find((candidate) => candidate.hardwareH264.length > 0);
|
||||
const encoder = adapter?.hardwareH264[0];
|
||||
@@ -775,7 +775,7 @@ async function main(): Promise<void> {
|
||||
oscillator.frequency.value = 440;
|
||||
oscillator.connect(gain).connect(context.destination);
|
||||
oscillator.start();
|
||||
globalThis.__screenerAudioGate = { context, oscillator };
|
||||
globalThis.__piikAudioGate = { context, oscillator };
|
||||
return context.resume().then(() => context.state);
|
||||
})()`,
|
||||
Date.now() + 5_000,
|
||||
@@ -785,7 +785,7 @@ async function main(): Promise<void> {
|
||||
}
|
||||
const targets = JSON.parse(run(executable, ["--list"])) as WindowTarget[];
|
||||
const sourceKind: "window" | "display" =
|
||||
process.env.SCREENER_CLIENT_MEDIA_SOURCE === "display"
|
||||
process.env.PIIK_CLIENT_MEDIA_SOURCE === "display"
|
||||
? "display"
|
||||
: "window";
|
||||
const target = targets.find(
|
||||
@@ -859,17 +859,17 @@ async function main(): Promise<void> {
|
||||
await mkdir(nativeRoot, { recursive: true });
|
||||
await copyFile(
|
||||
executable,
|
||||
join(nativeRoot, "screener-client-capture.exe"),
|
||||
join(nativeRoot, "piik-client-capture.exe"),
|
||||
);
|
||||
const clientExecutable = join(packageRoot, "screener-client.exe");
|
||||
const go = process.env.SCREENER_GO?.trim() || "go";
|
||||
const clientExecutable = join(packageRoot, "piik-client.exe");
|
||||
const go = process.env.PIIK_GO?.trim() || "go";
|
||||
// The Client embeds the Vite output, so the Web build precedes the Go build.
|
||||
run(process.env.ComSpec || "cmd.exe", [
|
||||
"/d", "/s", "/c", "npm run build:client",
|
||||
], ROOT);
|
||||
run(
|
||||
go,
|
||||
["build", "-trimpath", "-o", clientExecutable, "./cmd/screener-client"],
|
||||
["build", "-trimpath", "-o", clientExecutable, "./cmd/piik-client"],
|
||||
ROOT,
|
||||
);
|
||||
client = spawn(clientExecutable, [
|
||||
@@ -880,7 +880,7 @@ async function main(): Promise<void> {
|
||||
], {
|
||||
stdio: "pipe",
|
||||
windowsHide: true,
|
||||
env: { ...process.env, SCREENER_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
env: { ...process.env, PIIK_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
});
|
||||
client.stderr.resume();
|
||||
const endpoint = await readClientEndpoint(client);
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
|
||||
const ROOT = resolve(import.meta.dirname, "..");
|
||||
const BUILD_ROOT = join(ROOT, "build", "client-check");
|
||||
export const SOURCE_TITLE = "Screener Native Gate Source";
|
||||
export const SOURCE_TITLE = "Piik Native Gate Source";
|
||||
|
||||
type GateMode = "local" | "cross-nat" | "one-link";
|
||||
type VideoCodec = "h264" | "vp8";
|
||||
@@ -40,7 +40,7 @@ const CODEC_PROBE = `(() => {
|
||||
window.WebSocket = class extends BrowserSocket {
|
||||
constructor(...args) { super(...args); sockets.push(this); }
|
||||
};
|
||||
window.__screenerGatePublicSignal = () => sockets.some((socket) => {
|
||||
window.__piikGatePublicSignal = () => sockets.some((socket) => {
|
||||
const url = new URL(socket.url);
|
||||
return socket.readyState === WebSocket.OPEN && url.protocol === 'wss:' &&
|
||||
url.host === location.host && url.pathname === '/signal';
|
||||
@@ -48,7 +48,7 @@ const CODEC_PROBE = `(() => {
|
||||
window.RTCPeerConnection = class extends BrowserPeer {
|
||||
constructor(...args) { super(...args); peers.push(this); }
|
||||
};
|
||||
window.__screenerGateVideoCodec = async () => {
|
||||
window.__piikGateVideoCodec = async () => {
|
||||
const trackId = document.querySelector('video')?.srcObject?.getVideoTracks()[0]?.id;
|
||||
if (!trackId) return null;
|
||||
for (const peer of peers) {
|
||||
@@ -240,7 +240,7 @@ async function clickHostControl(
|
||||
|
||||
async function readVideoCodec(cdp: CdpConnection, page: PageHandle): Promise<VideoCodec> {
|
||||
const codec = await waitForValue(
|
||||
(deadline) => evaluate<VideoCodec | null>(cdp, page, "window.__screenerGateVideoCodec()", deadline),
|
||||
(deadline) => evaluate<VideoCodec | null>(cdp, page, "window.__piikGateVideoCodec()", deadline),
|
||||
(value) => value === "vp8" || value === "h264",
|
||||
5_000,
|
||||
);
|
||||
@@ -254,14 +254,14 @@ async function assertVideoCodec(cdp: CdpConnection, page: PageHandle, expected:
|
||||
}
|
||||
|
||||
function remoteOptions(): RemoteGateOptions {
|
||||
const host = process.env.SCREENER_REMOTE_HOST?.trim();
|
||||
const user = process.env.SCREENER_REMOTE_USER?.trim() || "root";
|
||||
const key = process.env.SCREENER_REMOTE_SSH_KEY?.trim();
|
||||
const signalPortText = process.env.SCREENER_REMOTE_SIGNAL_PORT?.trim() || "49721";
|
||||
const host = process.env.PIIK_REMOTE_HOST?.trim();
|
||||
const user = process.env.PIIK_REMOTE_USER?.trim() || "root";
|
||||
const key = process.env.PIIK_REMOTE_SSH_KEY?.trim();
|
||||
const signalPortText = process.env.PIIK_REMOTE_SIGNAL_PORT?.trim() || "49721";
|
||||
const signalPort = Number(signalPortText);
|
||||
if (!host || !key || !Number.isInteger(signalPort) || signalPort < 1024 || signalPort > 65_535) {
|
||||
throw new Error(
|
||||
"SCREENER_REMOTE_HOST, SCREENER_REMOTE_SSH_KEY, and a valid SCREENER_REMOTE_SIGNAL_PORT are required",
|
||||
"PIIK_REMOTE_HOST, PIIK_REMOTE_SSH_KEY, and a valid PIIK_REMOTE_SIGNAL_PORT are required",
|
||||
);
|
||||
}
|
||||
return {
|
||||
@@ -269,7 +269,7 @@ function remoteOptions(): RemoteGateOptions {
|
||||
user,
|
||||
key,
|
||||
signalPort,
|
||||
bindAddress: process.env.SCREENER_REMOTE_BIND_ADDRESS?.trim() || null,
|
||||
bindAddress: process.env.PIIK_REMOTE_BIND_ADDRESS?.trim() || null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -293,10 +293,10 @@ async function runRemotePeerGate(
|
||||
viewerGrant: string,
|
||||
origin: string,
|
||||
): Promise<RemoteGateResult> {
|
||||
const ssh = process.env.SCREENER_SSH?.trim() || "ssh";
|
||||
const scp = process.env.SCREENER_SCP?.trim() || "scp";
|
||||
const ssh = process.env.PIIK_SSH?.trim() || "ssh";
|
||||
const scp = process.env.PIIK_SCP?.trim() || "scp";
|
||||
const destination = `${options.user}@${options.host}`;
|
||||
const remotePath = `/tmp/screener-peer-gate-${randomBytes(8).toString("hex")}`;
|
||||
const remotePath = `/tmp/piik-peer-gate-${randomBytes(8).toString("hex")}`;
|
||||
const transportOptions = remoteTransportOptions(options);
|
||||
try {
|
||||
run(scp, [...transportOptions, binary, `${destination}:${remotePath}`]);
|
||||
@@ -376,7 +376,7 @@ async function runRemotePeerGate(
|
||||
}
|
||||
|
||||
export function powershell(): string {
|
||||
return process.env.SCREENER_POWERSHELL?.trim() || join(
|
||||
return process.env.PIIK_POWERSHELL?.trim() || join(
|
||||
process.env.SystemRoot || "C:\\Windows",
|
||||
"System32",
|
||||
"WindowsPowerShell",
|
||||
@@ -550,44 +550,44 @@ async function main(): Promise<void> {
|
||||
if (process.platform !== "win32") {
|
||||
throw new Error("The native Host gate currently requires Windows");
|
||||
}
|
||||
if (process.env.SCREENER_CLIENT_NATIVE_HOST_GATE !== "true") {
|
||||
throw new Error("SCREENER_CLIENT_NATIVE_HOST_GATE=true is required");
|
||||
if (process.env.PIIK_CLIENT_NATIVE_HOST_GATE !== "true") {
|
||||
throw new Error("PIIK_CLIENT_NATIVE_HOST_GATE=true is required");
|
||||
}
|
||||
const crossNat = process.env.SCREENER_CLIENT_CROSS_NAT_GATE === "true";
|
||||
const linkMedia = process.env.SCREENER_CLIENT_LINK_MEDIA_GATE === "true";
|
||||
const crossNat = process.env.PIIK_CLIENT_CROSS_NAT_GATE === "true";
|
||||
const linkMedia = process.env.PIIK_CLIENT_LINK_MEDIA_GATE === "true";
|
||||
if (crossNat && linkMedia) {
|
||||
throw new Error("Cross-NAT and one-link gate modes are mutually exclusive");
|
||||
}
|
||||
const mode: GateMode = linkMedia ? "one-link" : crossNat ? "cross-nat" : "local";
|
||||
const gateStunUrls = process.env.SCREENER_CLIENT_GATE_STUN_URLS?.trim();
|
||||
const gateStunUrls = process.env.PIIK_CLIENT_GATE_STUN_URLS?.trim();
|
||||
if (mode === "cross-nat" && !gateStunUrls) {
|
||||
throw new Error("SCREENER_CLIENT_GATE_STUN_URLS is required for the cross-NAT gate");
|
||||
throw new Error("PIIK_CLIENT_GATE_STUN_URLS is required for the cross-NAT gate");
|
||||
}
|
||||
const crashGate =
|
||||
process.env.SCREENER_CLIENT_NATIVE_HOST_CRASH_GATE === "true";
|
||||
process.env.PIIK_CLIENT_NATIVE_HOST_CRASH_GATE === "true";
|
||||
if (crashGate && mode !== "local") {
|
||||
throw new Error("Client crash gate requires local mode");
|
||||
}
|
||||
const sourceKind: "window" | "display" =
|
||||
process.env.SCREENER_CLIENT_NATIVE_HOST_SOURCE === "display"
|
||||
process.env.PIIK_CLIENT_NATIVE_HOST_SOURCE === "display"
|
||||
? "display"
|
||||
: "window";
|
||||
const requestedCodec = process.env.SCREENER_CLIENT_NATIVE_HOST_CODEC?.trim() || "auto";
|
||||
const requestedCodec = process.env.PIIK_CLIENT_NATIVE_HOST_CODEC?.trim() || "auto";
|
||||
if (requestedCodec !== "auto" && requestedCodec !== "h264" && requestedCodec !== "vp8") {
|
||||
throw new Error("SCREENER_CLIENT_NATIVE_HOST_CODEC must be auto, h264, or vp8");
|
||||
throw new Error("PIIK_CLIENT_NATIVE_HOST_CODEC must be auto, h264, or vp8");
|
||||
}
|
||||
const remote = mode === "cross-nat" || mode === "one-link" &&
|
||||
Boolean(process.env.SCREENER_REMOTE_HOST?.trim() || process.env.SCREENER_REMOTE_SSH_KEY?.trim())
|
||||
Boolean(process.env.PIIK_REMOTE_HOST?.trim() || process.env.PIIK_REMOTE_SSH_KEY?.trim())
|
||||
? remoteOptions() : null;
|
||||
const chromePath = process.env.CHROME_PATH?.trim();
|
||||
if (!chromePath) throw new Error("CHROME_PATH is required");
|
||||
const go = process.env.SCREENER_GO?.trim() || "go";
|
||||
const tunnel = process.env.SCREENER_CLOUDFLARED?.trim() || join(
|
||||
const go = process.env.PIIK_GO?.trim() || "go";
|
||||
const tunnel = process.env.PIIK_CLOUDFLARED?.trim() || join(
|
||||
BUILD_ROOT,
|
||||
"cloudflared.exe",
|
||||
);
|
||||
const profile = await mkdtemp(join(tmpdir(), "screener-client-media-"));
|
||||
const sourceProfile = await mkdtemp(join(tmpdir(), "screener-client-media-"));
|
||||
const profile = await mkdtemp(join(tmpdir(), "piik-client-media-"));
|
||||
const sourceProfile = await mkdtemp(join(tmpdir(), "piik-client-media-"));
|
||||
await mkdir(BUILD_ROOT, { recursive: true });
|
||||
const diagnosticDirectory = await mkdtemp(join(BUILD_ROOT, "native-host-gate-"));
|
||||
const sourcePort = await reservePort();
|
||||
@@ -596,9 +596,9 @@ async function main(): Promise<void> {
|
||||
const sourceDebugPort = await reservePort();
|
||||
const clientConfig = join(profile, "client.json");
|
||||
const captureBuild = BUILD_ROOT;
|
||||
const clientBinary = join(BUILD_ROOT, "screener-client.exe");
|
||||
const captureBinary = join(captureBuild, "screener-client-capture.exe");
|
||||
const remoteBinary = join(BUILD_ROOT, "screener-peer-gate-linux");
|
||||
const clientBinary = join(BUILD_ROOT, "piik-client.exe");
|
||||
const captureBinary = join(captureBuild, "piik-client-capture.exe");
|
||||
const remoteBinary = join(BUILD_ROOT, "piik-peer-gate-linux");
|
||||
let source: { close(): Promise<void> } | null = null;
|
||||
let client: ChildProcessWithoutNullStreams | null = null;
|
||||
let sourceChrome: ChildProcessWithoutNullStreams | null = null;
|
||||
@@ -669,13 +669,13 @@ async function main(): Promise<void> {
|
||||
process.stderr.write(`${JSON.stringify({ stage, status: "finished", at: new Date().toISOString() })}\n`);
|
||||
stage = "client-build";
|
||||
run(go, [
|
||||
"build", "-p", "1", "-trimpath", "-o", clientBinary, "./cmd/screener-client",
|
||||
"build", "-p", "1", "-trimpath", "-o", clientBinary, "./cmd/piik-client",
|
||||
], ROOT, { ...process.env, GOMAXPROCS: "2" });
|
||||
if (remote) {
|
||||
stage = "remote-peer-build";
|
||||
run(
|
||||
go,
|
||||
["build", "-trimpath", "-o", remoteBinary, "./cmd/screener-peer-gate"],
|
||||
["build", "-trimpath", "-o", remoteBinary, "./cmd/piik-peer-gate"],
|
||||
ROOT,
|
||||
{ ...process.env, GOOS: "linux", GOARCH: "amd64", CGO_ENABLED: "0" },
|
||||
);
|
||||
@@ -703,8 +703,8 @@ async function main(): Promise<void> {
|
||||
windowsHide: true,
|
||||
env: {
|
||||
...process.env,
|
||||
SCREENER_DEBUG: "",
|
||||
SCREENER_CLIENT_GATE_NO_BROWSER: "true",
|
||||
PIIK_DEBUG: "",
|
||||
PIIK_CLIENT_GATE_NO_BROWSER: "true",
|
||||
// STUN_URLS reaches only the Client's own Pion edge: the in-process
|
||||
// room server never reads it, so the cross-NAT arm stays isolated.
|
||||
...(mode === "cross-nat" && gateStunUrls
|
||||
@@ -719,7 +719,7 @@ async function main(): Promise<void> {
|
||||
if (mode === "cross-nat" && remote) {
|
||||
stage = "signaling-tunnel";
|
||||
const tunnel = spawn(
|
||||
process.env.SCREENER_SSH?.trim() || "ssh",
|
||||
process.env.PIIK_SSH?.trim() || "ssh",
|
||||
[
|
||||
"-N", "-T",
|
||||
...remoteTransportOptions(remote),
|
||||
@@ -761,7 +761,7 @@ async function main(): Promise<void> {
|
||||
cdp = await CdpConnection.connect(version.webSocketDebuggerUrl, Date.now() + 10_000);
|
||||
const hostBootstrap = new URLSearchParams({
|
||||
...(clientInfo.password ? { "client-access": clientInfo.password } : {}),
|
||||
"screener-client": "1",
|
||||
"piik-client": "1",
|
||||
}).toString();
|
||||
stage = "host-page";
|
||||
const host = await createPage(
|
||||
@@ -942,7 +942,7 @@ async function main(): Promise<void> {
|
||||
`location.origin === ${JSON.stringify(clientInfo.publicOrigin)} && location.pathname === ${JSON.stringify(viewerURL.pathname)}`,
|
||||
Date.now() + 5_000);
|
||||
result.publicViewerSignal = await evaluate<boolean>(cdp, viewer,
|
||||
"window.__screenerGatePublicSignal()", Date.now() + 5_000);
|
||||
"window.__piikGatePublicSignal()", Date.now() + 5_000);
|
||||
} else {
|
||||
await evaluate<boolean>(
|
||||
cdp,
|
||||
@@ -950,8 +950,8 @@ async function main(): Promise<void> {
|
||||
`(() => {
|
||||
const video = document.querySelector('video');
|
||||
if (!video) return false;
|
||||
window.__screenerGateMedia = video.srcObject;
|
||||
return window.__screenerGateMedia !== null;
|
||||
window.__piikGateMedia = video.srcObject;
|
||||
return window.__piikGateMedia !== null;
|
||||
})()`,
|
||||
Date.now() + 5_000,
|
||||
);
|
||||
@@ -1151,7 +1151,7 @@ async function main(): Promise<void> {
|
||||
frames: video?.getVideoPlaybackQuality().totalVideoFrames ?? 0,
|
||||
width: video?.videoWidth ?? 0,
|
||||
height: video?.videoHeight ?? 0,
|
||||
sameMedia: Boolean(video && video.srcObject === window.__screenerGateMedia),
|
||||
sameMedia: Boolean(video && video.srcObject === window.__piikGateMedia),
|
||||
};
|
||||
})()`,
|
||||
deadline,
|
||||
@@ -1213,7 +1213,7 @@ async function main(): Promise<void> {
|
||||
await waitForValue((deadline) => evaluate<boolean>(cdp!, viewer,
|
||||
`(() => {
|
||||
const video = document.querySelector('video');
|
||||
return Boolean(video && video.srcObject === window.__screenerGateMedia &&
|
||||
return Boolean(video && video.srcObject === window.__piikGateMedia &&
|
||||
video.videoWidth === ${width} && video.videoHeight === ${height} &&
|
||||
video.getVideoPlaybackQuality().totalVideoFrames >= ${before + 10});
|
||||
})()`, deadline,
|
||||
@@ -1275,7 +1275,7 @@ async function main(): Promise<void> {
|
||||
`(() => {
|
||||
const video = document.querySelector('video');
|
||||
return Boolean(
|
||||
video && video.srcObject === window.__screenerGateMedia &&
|
||||
video && video.srcObject === window.__piikGateMedia &&
|
||||
video.videoWidth === 854 && video.videoHeight === 480 &&
|
||||
video.getVideoPlaybackQuality().totalVideoFrames >= ${framesBeforeSourceChange + 10}
|
||||
);
|
||||
@@ -1298,7 +1298,7 @@ async function main(): Promise<void> {
|
||||
return diagnostics.split(/\r?\n/).some((line) => {
|
||||
try {
|
||||
const record = JSON.parse(line);
|
||||
return record.msg === "screener-route" && record.event === "sender-quality-evidence" &&
|
||||
return record.msg === "piik-route" && record.event === "sender-quality-evidence" &&
|
||||
(record.state === "healthy" || record.state === "degraded");
|
||||
} catch {
|
||||
return false;
|
||||
@@ -1383,7 +1383,7 @@ async function main(): Promise<void> {
|
||||
`(() => {
|
||||
const video = document.querySelector('video');
|
||||
return Boolean(video && video.srcObject &&
|
||||
video.srcObject !== window.__screenerGateMedia &&
|
||||
video.srcObject !== window.__piikGateMedia &&
|
||||
video.videoWidth === 854 && video.videoHeight === 480);
|
||||
})()`,
|
||||
deadline,
|
||||
|
||||
@@ -8,9 +8,9 @@ export const CLIENT_PACKAGE_TARGETS = [
|
||||
goos: "windows",
|
||||
goarch: "amd64",
|
||||
cgo: false,
|
||||
clientName: "screener-client.exe",
|
||||
clientName: "piik-client.exe",
|
||||
tunnelName: "cloudflared.exe",
|
||||
captureName: "screener-client-capture.exe",
|
||||
captureName: "piik-client-capture.exe",
|
||||
tunnelAsset: "cloudflared-windows-amd64.exe",
|
||||
tunnelSha256: "83e726ed18ea78c5ad5213c4c3a3a27051393950d2bc8ed4de69bec12d14eaae",
|
||||
tunnelArchive: false,
|
||||
@@ -22,9 +22,9 @@ export const CLIENT_PACKAGE_TARGETS = [
|
||||
goos: "linux",
|
||||
goarch: "amd64",
|
||||
cgo: false,
|
||||
clientName: "screener-client",
|
||||
clientName: "piik-client",
|
||||
tunnelName: "cloudflared",
|
||||
captureName: "screener-client-capture",
|
||||
captureName: "piik-client-capture",
|
||||
tunnelAsset: "cloudflared-linux-amd64",
|
||||
tunnelSha256: "f29324fe934d1e100617484c78deef803c4dc2cd351d645bbde42e96b4fccc5e",
|
||||
tunnelArchive: false,
|
||||
@@ -36,9 +36,9 @@ export const CLIENT_PACKAGE_TARGETS = [
|
||||
goos: "darwin",
|
||||
goarch: "arm64",
|
||||
cgo: true,
|
||||
clientName: "screener-client",
|
||||
clientName: "piik-client",
|
||||
tunnelName: "cloudflared",
|
||||
captureName: "screener-client-capture",
|
||||
captureName: "piik-client-capture",
|
||||
tunnelAsset: "cloudflared-darwin-arm64.tgz",
|
||||
tunnelSha256: "40c9144d86df8937c5b43293a1f7d2d2107029aa74725023dd46b1b27154352f",
|
||||
tunnelArchive: true,
|
||||
|
||||
@@ -22,9 +22,9 @@ const AUDIO_PROBE = `(() => {
|
||||
window.RTCPeerConnection = class extends BrowserPeer {
|
||||
constructor(...args) { super(...args); peers.push(this); }
|
||||
};
|
||||
window.__screenerGateAudioEnergy = async () => {
|
||||
window.__piikGateAudioEnergy = async () => {
|
||||
const trackId = document.querySelector('video')?.srcObject?.getAudioTracks()[0]?.id;
|
||||
const diagnostic = window.__screenerGateAudioStats = { hasAudioTrack: !!trackId, peerCount: peers.length, inbound: [] };
|
||||
const diagnostic = window.__piikGateAudioStats = { hasAudioTrack: !!trackId, peerCount: peers.length, inbound: [] };
|
||||
if (!trackId) return 0;
|
||||
for (const peer of peers) {
|
||||
if (peer.connectionState !== 'connected') continue;
|
||||
@@ -54,26 +54,26 @@ async function udpPort(requested = 0): Promise<number> {
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
if (process.env.SCREENER_EMBEDDED_SFU_GATE !== "true") {
|
||||
throw new Error("SCREENER_EMBEDDED_SFU_GATE=true is required; this is an explicit local Browser media gate");
|
||||
if (process.env.PIIK_EMBEDDED_SFU_GATE !== "true") {
|
||||
throw new Error("PIIK_EMBEDDED_SFU_GATE=true is required; this is an explicit local Browser media gate");
|
||||
}
|
||||
const chromePath = process.env.CHROME_PATH?.trim();
|
||||
if (!chromePath) throw new Error("CHROME_PATH is required");
|
||||
const nativeArm = process.env.SCREENER_EMBEDDED_SFU_NATIVE === "true";
|
||||
const twoRooms = process.env.SCREENER_EMBEDDED_SFU_TWO_ROOMS === "true";
|
||||
const nativeArm = process.env.PIIK_EMBEDDED_SFU_NATIVE === "true";
|
||||
const twoRooms = process.env.PIIK_EMBEDDED_SFU_TWO_ROOMS === "true";
|
||||
if (twoRooms && !nativeArm) throw new Error("Two-room arm requires Native publication");
|
||||
const codec = process.env.SCREENER_EMBEDDED_SFU_CODEC?.trim() || "vp8";
|
||||
const codec = process.env.PIIK_EMBEDDED_SFU_CODEC?.trim() || "vp8";
|
||||
if (codec !== "vp8" && codec !== "h264") throw new Error("SFU gate codec must be vp8 or h264");
|
||||
const captureBinary = process.env.SCREENER_CAPTURE_PROCESS?.trim();
|
||||
const captureBinary = process.env.PIIK_CAPTURE_PROCESS?.trim();
|
||||
if (nativeArm && (process.platform !== "win32" || !captureBinary)) {
|
||||
throw new Error("Native arm requires Windows and SCREENER_CAPTURE_PROCESS");
|
||||
throw new Error("Native arm requires Windows and PIIK_CAPTURE_PROCESS");
|
||||
}
|
||||
await mkdir(BUILD_ROOT, { recursive: true });
|
||||
const binary = join(BUILD_ROOT, `screener-server${process.platform === "win32" ? ".exe" : ""}`);
|
||||
const clientBinary = join(BUILD_ROOT, "screener-client.exe");
|
||||
for (const command of nativeArm ? ["screener-server", "screener-client"] : ["screener-server"]) {
|
||||
const build = spawnSync(process.env.SCREENER_GO?.trim() || "go", [
|
||||
"build", "-p", "1", "-trimpath", "-o", command === "screener-server" ? binary : clientBinary, `./cmd/${command}`,
|
||||
const binary = join(BUILD_ROOT, `piik-server${process.platform === "win32" ? ".exe" : ""}`);
|
||||
const clientBinary = join(BUILD_ROOT, "piik-client.exe");
|
||||
for (const command of nativeArm ? ["piik-server", "piik-client"] : ["piik-server"]) {
|
||||
const build = spawnSync(process.env.PIIK_GO?.trim() || "go", [
|
||||
"build", "-p", "1", "-trimpath", "-o", command === "piik-server" ? binary : clientBinary, `./cmd/${command}`,
|
||||
], { cwd: ROOT, env: { ...process.env, GOMAXPROCS: "2" }, encoding: "utf8", windowsHide: true, timeout: 120_000 });
|
||||
if (build.error || build.status !== 0) throw build.error ?? new Error(build.stderr || `${command} build failed`);
|
||||
}
|
||||
@@ -82,8 +82,8 @@ async function main(): Promise<void> {
|
||||
]);
|
||||
const origin = `http://127.0.0.1:${vitePort}`;
|
||||
const backend = `http://127.0.0.1:${serverPort}`;
|
||||
const profile = await mkdtemp(join(tmpdir(), "screener-client-media-"));
|
||||
const sourceProfile = nativeArm ? await mkdtemp(join(tmpdir(), "screener-client-media-")) : null;
|
||||
const profile = await mkdtemp(join(tmpdir(), "piik-client-media-"));
|
||||
const sourceProfile = nativeArm ? await mkdtemp(join(tmpdir(), "piik-client-media-")) : null;
|
||||
const [sourcePort, sourceDebugPort] = nativeArm ? [await reservePort(), await reservePort()] : [0, 0];
|
||||
const result = { passed: false, arm: `${nativeArm ? "native" : "browser"}-${codec}-simulcast${twoRooms ? "-two-rooms" : ""}`, stage: "start",
|
||||
startedAt: new Date().toISOString(), finishedAt: "", processes: [] as Array<{ role: string; pid: number | null }>,
|
||||
@@ -132,7 +132,7 @@ async function main(): Promise<void> {
|
||||
try {
|
||||
server = spawn(binary, [], { cwd: ROOT, stdio: "pipe", windowsHide: true,
|
||||
env: { PATH: process.env.PATH, SystemRoot: process.env.SystemRoot,
|
||||
SCREENER_ENV: "development", LISTEN_HOST: "127.0.0.1", PORT: String(serverPort),
|
||||
PIIK_ENV: "development", LISTEN_HOST: "127.0.0.1", PORT: String(serverPort),
|
||||
PUBLIC_BASE_URL: origin, ALLOWED_ORIGINS: origin,
|
||||
SFU_LISTEN_HOST: "127.0.0.1", SFU_UDP_PORT: String(mediaPort), SFU_PUBLIC_IP: "127.0.0.1" },
|
||||
});
|
||||
@@ -157,7 +157,7 @@ async function main(): Promise<void> {
|
||||
result.stage = "native-client-start";
|
||||
client = spawn(clientBinary, ["--site", origin, "--capture-process", captureBinary!,
|
||||
"--config", join(profile, "client.json")], { cwd: ROOT, stdio: "pipe", windowsHide: true,
|
||||
env: { ...process.env, GOMAXPROCS: "2", SCREENER_CLIENT_GATE_NO_BROWSER: "true" } });
|
||||
env: { ...process.env, GOMAXPROCS: "2", PIIK_CLIENT_GATE_NO_BROWSER: "true" } });
|
||||
processStarted("client", client);
|
||||
client.stderr.resume();
|
||||
clientPort = (await readClientEndpoint(client, { timeoutMs: 15_000, ignoreNonEndpointLines: true })).port;
|
||||
@@ -266,7 +266,7 @@ async function main(): Promise<void> {
|
||||
} catch (error) {
|
||||
result.error = error instanceof Error ? error.message : String(error);
|
||||
if (viewer && cdp && result.stage === "decoded-audio-energy") result.audioDiagnostics = await evaluate(
|
||||
cdp, viewer, "window.__screenerGateAudioStats ?? null", Date.now() + 3_000).catch(() => null);
|
||||
cdp, viewer, "window.__piikGateAudioStats ?? null", Date.now() + 3_000).catch(() => null);
|
||||
if (server?.exitCode !== null && serverError) result.error += `; server: ${serverError}`;
|
||||
} finally {
|
||||
const pagesStopped = await Promise.all([host, viewer, secondHost, secondViewer].map((page) =>
|
||||
|
||||
@@ -249,7 +249,7 @@ export function snapshot() {
|
||||
}
|
||||
|
||||
export async function audioEnergy(): Promise<number> {
|
||||
const probe = (window as unknown as { __screenerGateAudioEnergy: () => Promise<number> }).__screenerGateAudioEnergy;
|
||||
const probe = (window as unknown as { __piikGateAudioEnergy: () => Promise<number> }).__piikGateAudioEnergy;
|
||||
return await probe();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import { readFile, writeFile } from "node:fs/promises";
|
||||
import { createServer } from "node:http";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
const customInput = process.env.SCREENER_ENCODED_OUTPUT;
|
||||
const codec = process.env.SCREENER_ENCODED_CODEC ?? "vp8";
|
||||
const customInput = process.env.PIIK_ENCODED_OUTPUT;
|
||||
const codec = process.env.PIIK_ENCODED_CODEC ?? "vp8";
|
||||
assert.ok(["vp8", "avc1.42c033"].includes(codec), "Expected VP8 or constrained-baseline H264");
|
||||
const inputPath = customInput ? resolve(customInput) : new URL("../build/embedded-media/encoded-group.received.json", import.meta.url);
|
||||
const input = await readFile(inputPath);
|
||||
|
||||
@@ -2,7 +2,7 @@ $ErrorActionPreference = "Stop"
|
||||
|
||||
$repoRoot = git rev-parse --show-toplevel
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "This command must run inside the Screener Git repository."
|
||||
throw "This command must run inside the Piik Git repository."
|
||||
}
|
||||
|
||||
git -C $repoRoot config core.hooksPath .githooks
|
||||
|
||||
@@ -26,7 +26,7 @@ import { resetBuildWorkspace } from "./build-workspace.mjs";
|
||||
// as the service user, so the release is always built for linux/amd64, and
|
||||
// CGO_ENABLED=0 keeps it self-contained.
|
||||
const SERVER_TARGET = { goos: "linux", goarch: "amd64" };
|
||||
const SERVER_NAME = "screener-server";
|
||||
const SERVER_NAME = "piik-server";
|
||||
|
||||
// Everything the archive may contain. deploy/release-app.sh enforces the same
|
||||
// four names in its entry allowlist and manifest pattern; both change together.
|
||||
@@ -198,7 +198,7 @@ const verifyRoot = join(temporaryRoot, "verify");
|
||||
try {
|
||||
mkdirSync(runtimeRoot, { recursive: true });
|
||||
copyFileSync(join(repositoryRoot, "LICENSE"), join(runtimeRoot, "LICENSE"));
|
||||
const goCommand = process.env.SCREENER_GO?.trim() || "go";
|
||||
const goCommand = process.env.PIIK_GO?.trim() || "go";
|
||||
const serverPath = join(runtimeRoot, SERVER_NAME);
|
||||
run(goCommand, [
|
||||
"build",
|
||||
@@ -207,7 +207,7 @@ try {
|
||||
`-s -w -X main.BuildRevision=${revision}`,
|
||||
"-o",
|
||||
serverPath,
|
||||
"./cmd/screener-server",
|
||||
"./cmd/piik-server",
|
||||
], repositoryRoot, {
|
||||
...process.env,
|
||||
GOOS: SERVER_TARGET.goos,
|
||||
@@ -225,9 +225,9 @@ try {
|
||||
writeFileSync(join(runtimeRoot, "REVISION"), `${revision}\n`, "ascii");
|
||||
|
||||
const records = recordsFor(runtimeRoot);
|
||||
const manifestName = `screener-${releaseId}.manifest.tsv`;
|
||||
const artifactName = `screener-${releaseId}-runtime.tar.gz`;
|
||||
const descriptorName = `screener-${releaseId}.release.json`;
|
||||
const manifestName = `piik-${releaseId}.manifest.tsv`;
|
||||
const artifactName = `piik-${releaseId}-runtime.tar.gz`;
|
||||
const descriptorName = `piik-${releaseId}.release.json`;
|
||||
mkdirSync(outputRoot, { recursive: false, mode: 0o700 });
|
||||
const manifestPath = join(outputRoot, manifestName);
|
||||
const artifactPath = join(outputRoot, artifactName);
|
||||
|
||||
@@ -155,7 +155,7 @@ async function verifyLocalPackage(root, target, temporaryRoot) {
|
||||
"--port", String(port),
|
||||
], {
|
||||
cwd: root,
|
||||
env: { ...process.env, SCREENER_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
env: { ...process.env, PIIK_CLIENT_GATE_NO_BROWSER: "true" },
|
||||
stdio: "pipe",
|
||||
windowsHide: true,
|
||||
});
|
||||
@@ -262,7 +262,7 @@ async function verifyPackage(root, target, revision, temporaryRoot) {
|
||||
|
||||
function verifyPlatformAssets(root, target) {
|
||||
if (target.goos === "linux") {
|
||||
const desktop = join(root, "share", "applications", "screener-client.desktop");
|
||||
const desktop = join(root, "share", "applications", "piik-client.desktop");
|
||||
const icon = join(
|
||||
root,
|
||||
"share",
|
||||
@@ -270,12 +270,12 @@ function verifyPlatformAssets(root, target) {
|
||||
"hicolor",
|
||||
"256x256",
|
||||
"apps",
|
||||
"screener-client.png",
|
||||
"piik-client.png",
|
||||
);
|
||||
if (!existsSync(desktop) || !existsSync(icon)) {
|
||||
fail("Linux Client icon assets are missing");
|
||||
}
|
||||
if (!readFileSync(desktop, "utf8").includes("Icon=screener-client\n")) {
|
||||
if (!readFileSync(desktop, "utf8").includes("Icon=piik-client\n")) {
|
||||
fail("Linux desktop entry does not name its icon");
|
||||
}
|
||||
if (!readFileSync(icon).subarray(0, 8).equals(Buffer.from([
|
||||
@@ -285,10 +285,10 @@ function verifyPlatformAssets(root, target) {
|
||||
}
|
||||
}
|
||||
if (target.goos === "darwin") {
|
||||
const bundle = join(root, "Screener Client.app");
|
||||
const bundle = join(root, "Piik Client.app");
|
||||
const launcher = join(bundle, "Contents", "MacOS", "Launcher");
|
||||
const plist = join(bundle, "Contents", "Info.plist");
|
||||
const icon = join(bundle, "Contents", "Resources", "screener.icns");
|
||||
const icon = join(bundle, "Contents", "Resources", "piik.icns");
|
||||
if (!existsSync(launcher) || !existsSync(plist) || !existsSync(icon)) {
|
||||
fail("macOS Client app icon assets are missing");
|
||||
}
|
||||
@@ -352,7 +352,7 @@ try {
|
||||
capture = join(repositoryRoot, "build", "client-check", target.captureName);
|
||||
}
|
||||
|
||||
const packageRoot = join(temporaryRoot, `Screener-Client-${target.id}`);
|
||||
const packageRoot = join(temporaryRoot, `Piik-Client-${target.id}`);
|
||||
const assembleArguments = [
|
||||
join(repositoryRoot, "scripts", "assemble-client.mjs"),
|
||||
applicationDescriptor(applicationRoot),
|
||||
@@ -368,7 +368,7 @@ try {
|
||||
|
||||
mkdirSync(outputRoot, { recursive: false, mode: 0o700 });
|
||||
const shortRevision = revision.slice(0, 7);
|
||||
const archiveName = `Screener-Client-${target.id}-${shortRevision}.tar.gz`;
|
||||
const archiveName = `Piik-Client-${target.id}-${shortRevision}.tar.gz`;
|
||||
const archive = join(outputRoot, archiveName);
|
||||
run(tarExecutable(), ["-czf", archive, "-C", packageRoot, "."], repositoryRoot);
|
||||
const digest = sha256(archive);
|
||||
|
||||
@@ -42,7 +42,7 @@ export function writeWebLicenseNotices(repositoryRoot, outputFile) {
|
||||
const visited = new Set();
|
||||
const entries = new Map();
|
||||
for (const [name, parent] of queue) {
|
||||
const paths = createRequire(parent).resolve.paths("screener-license-lookup");
|
||||
const paths = createRequire(parent).resolve.paths("piik-license-lookup");
|
||||
const directory = paths.map((path) => join(path, name))
|
||||
.find((path) => existsSync(join(path, "package.json")));
|
||||
if (!directory) throw new Error(`Missing installed runtime dependency ${name}`);
|
||||
@@ -64,7 +64,7 @@ export function writeWebLicenseNotices(repositoryRoot, outputFile) {
|
||||
}
|
||||
mkdirSync(dirname(outputFile), { recursive: true });
|
||||
writeFileSync(outputFile, "Third-party software notices\n" +
|
||||
"Screener's MIT license does not replace the following component licenses.\n" +
|
||||
"Piik's MIT license does not replace the following component licenses.\n" +
|
||||
[...entries].sort(([a], [b]) => a.localeCompare(b)).map(([, body]) => body).join(""));
|
||||
}
|
||||
|
||||
@@ -109,10 +109,10 @@ function moduleSections(modules) {
|
||||
}
|
||||
|
||||
// writeServerLicenseNotices produces the Hosted application release notice file,
|
||||
// which ships beside the single screener-server binary.
|
||||
// which ships beside the single piik-server binary.
|
||||
export function writeServerLicenseNotices(repositoryRoot, outputFile, goCommand, target) {
|
||||
const notices = goNotices(repositoryRoot, goCommand, target, "./cmd/screener-server");
|
||||
writeFileSync(outputFile, "Screener server third-party software notices\n" +
|
||||
const notices = goNotices(repositoryRoot, goCommand, target, "./cmd/piik-server");
|
||||
writeFileSync(outputFile, "Piik server third-party software notices\n" +
|
||||
WEB_NOTICE_LINE + notices.toolchain + moduleSections(notices.modules));
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ export function writeClientLicenseNotices(repositoryRoot, packageRoot, goCommand
|
||||
writeFileSync(join(packageRoot, "runtime", "tunnel", "THIRD-PARTY-NOTICES.txt"),
|
||||
pinnedNotice(`cloudflared@${tunnelVersion}`));
|
||||
}
|
||||
const notices = goNotices(repositoryRoot, goCommand, target, "./cmd/screener-client");
|
||||
const notices = goNotices(repositoryRoot, goCommand, target, "./cmd/piik-client");
|
||||
let text = "Native Client third-party software notices\n" +
|
||||
WEB_NOTICE_LINE +
|
||||
(tunnelVersion ? "Cloudflared: runtime/tunnel/THIRD-PARTY-NOTICES.txt\n" : "") +
|
||||
|
||||
@@ -1680,11 +1680,11 @@ function buildBenchmarkInitScript(options: {
|
||||
}): string {
|
||||
const serialized = JSON.stringify(options);
|
||||
return `(() => {
|
||||
if (globalThis.__SCREENER_BENCHMARK__) return;
|
||||
if (globalThis.__PIIK_BENCHMARK__) return;
|
||||
const options = ${serialized};
|
||||
const expectedRoleCap = options.expectedEndpointCap;
|
||||
if (options.clearHostRoom) {
|
||||
try { localStorage.removeItem("screener:host-room:v1"); } catch {}
|
||||
try { localStorage.removeItem("piik:host-room:v1"); } catch {}
|
||||
}
|
||||
const state = {
|
||||
label: options.label,
|
||||
@@ -2226,7 +2226,7 @@ function buildBenchmarkInitScript(options: {
|
||||
function markShareRequested() {
|
||||
state.shareRequestedAtEpochMs = Date.now();
|
||||
}
|
||||
Object.defineProperty(globalThis, "__SCREENER_BENCHMARK__", {
|
||||
Object.defineProperty(globalThis, "__PIIK_BENCHMARK__", {
|
||||
configurable: false,
|
||||
value: { sample, progress, snapshot, canarySnapshot, senderDegradationPreferences, sendViewerQualityEvidence, markShareRequested, requestRouteDiagnosticSnapshot, routeDiagnosticTimingSamples, stop: () => clearInterval(videoObserver) },
|
||||
});
|
||||
@@ -2262,23 +2262,23 @@ function buildStep(command: string, args: string[], failure: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
// buildServer compiles the Screener server this run starts. The Web assets are
|
||||
// buildServer compiles the Piik server this run starts. The Web assets are
|
||||
// embedded, so the Vite build precedes the Go build and the Browser reaches the
|
||||
// same bundle the binary serves.
|
||||
function buildServer(): string {
|
||||
const go = process.env.SCREENER_GO?.trim() || "go";
|
||||
const go = process.env.PIIK_GO?.trim() || "go";
|
||||
const buildRoot = join(REPO_ROOT, "build", "peer-benchmark");
|
||||
mkdirSync(buildRoot, { recursive: true });
|
||||
const output = join(buildRoot,
|
||||
process.platform === "win32" ? "screener-server.exe" : "screener-server");
|
||||
process.platform === "win32" ? "piik-server.exe" : "piik-server");
|
||||
if (process.platform === "win32") {
|
||||
buildStep(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", "npm run build:client"],
|
||||
"Browser client build failed");
|
||||
} else {
|
||||
buildStep("npm", ["run", "build:client"], "Browser client build failed");
|
||||
}
|
||||
buildStep(go, ["build", "-trimpath", "-o", output, "./cmd/screener-server"],
|
||||
"Screener server build failed");
|
||||
buildStep(go, ["build", "-trimpath", "-o", output, "./cmd/piik-server"],
|
||||
"Piik server build failed");
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -2431,7 +2431,7 @@ async function createPage(
|
||||
await waitForPage(
|
||||
cdp,
|
||||
page,
|
||||
"document.readyState === 'complete' && Boolean(globalThis.__SCREENER_BENCHMARK__)",
|
||||
"document.readyState === 'complete' && Boolean(globalThis.__PIIK_BENCHMARK__)",
|
||||
15_000,
|
||||
"page initialization",
|
||||
signal,
|
||||
@@ -2484,7 +2484,7 @@ async function quickSnapshot(
|
||||
return evaluate<PageObservation>(
|
||||
cdp,
|
||||
page,
|
||||
"globalThis.__SCREENER_BENCHMARK__.snapshot()",
|
||||
"globalThis.__PIIK_BENCHMARK__.snapshot()",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2495,7 +2495,7 @@ async function detailedSample(
|
||||
return evaluate<PageObservation>(
|
||||
cdp,
|
||||
page,
|
||||
"globalThis.__SCREENER_BENCHMARK__.sample()",
|
||||
"globalThis.__PIIK_BENCHMARK__.sample()",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2506,7 +2506,7 @@ async function progressSample(
|
||||
return evaluate<PageObservation>(
|
||||
cdp,
|
||||
page,
|
||||
"globalThis.__SCREENER_BENCHMARK__.progress()",
|
||||
"globalThis.__PIIK_BENCHMARK__.progress()",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2600,7 +2600,7 @@ async function startHost(
|
||||
profile.click();
|
||||
const start = document.querySelector('.lr-entry-actions button.lr-tv-big.is-action[aria-label]');
|
||||
if (!(start instanceof HTMLButtonElement)) throw new Error('Start button missing');
|
||||
globalThis.__SCREENER_BENCHMARK__.markShareRequested();
|
||||
globalThis.__PIIK_BENCHMARK__.markShareRequested();
|
||||
start.click();
|
||||
return true;
|
||||
})()`,
|
||||
@@ -2608,7 +2608,7 @@ async function startHost(
|
||||
await waitForPage(
|
||||
cdp,
|
||||
page,
|
||||
"globalThis.__SCREENER_BENCHMARK__.snapshot().peerId !== null",
|
||||
"globalThis.__PIIK_BENCHMARK__.snapshot().peerId !== null",
|
||||
timeoutMs,
|
||||
"host signaling authentication",
|
||||
signal,
|
||||
@@ -2655,7 +2655,7 @@ async function requestRouteTimingSummary(
|
||||
const requested = await evaluate<boolean>(
|
||||
cdp,
|
||||
hostPage,
|
||||
"globalThis.__SCREENER_BENCHMARK__.requestRouteDiagnosticSnapshot()",
|
||||
"globalThis.__PIIK_BENCHMARK__.requestRouteDiagnosticSnapshot()",
|
||||
);
|
||||
if (!requested) {
|
||||
throw new Error("Host route diagnostic request was unavailable");
|
||||
@@ -2663,7 +2663,7 @@ async function requestRouteTimingSummary(
|
||||
await waitForPage(
|
||||
cdp,
|
||||
hostPage,
|
||||
"globalThis.__SCREENER_BENCHMARK__.routeDiagnosticTimingSamples() !== null",
|
||||
"globalThis.__PIIK_BENCHMARK__.routeDiagnosticTimingSamples() !== null",
|
||||
timeoutMs,
|
||||
"Host route diagnostic snapshot",
|
||||
signal,
|
||||
@@ -2671,7 +2671,7 @@ async function requestRouteTimingSummary(
|
||||
const samples = await evaluate<BenchmarkRouteTimingSamples>(
|
||||
cdp,
|
||||
hostPage,
|
||||
"globalThis.__SCREENER_BENCHMARK__.routeDiagnosticTimingSamples()",
|
||||
"globalThis.__PIIK_BENCHMARK__.routeDiagnosticTimingSamples()",
|
||||
);
|
||||
return summarizeBenchmarkRouteTiming(samples);
|
||||
}
|
||||
@@ -2849,7 +2849,7 @@ async function runQualityControlSmoke(
|
||||
waitForPage(
|
||||
cdp,
|
||||
page,
|
||||
`JSON.stringify(globalThis.__SCREENER_BENCHMARK__.snapshot().qualitySettings) === ${serializedSettings}`,
|
||||
`JSON.stringify(globalThis.__PIIK_BENCHMARK__.snapshot().qualitySettings) === ${serializedSettings}`,
|
||||
10_000,
|
||||
`${settings.degradationPreference} quality propagation`,
|
||||
signal,
|
||||
@@ -2878,7 +2878,7 @@ async function runQualityControlSmoke(
|
||||
sendingPages.map(async (page) => {
|
||||
const expectedCount = activeSenderCounts.get(page.label) ?? 0;
|
||||
const predicate = `(() => {
|
||||
const values = globalThis.__SCREENER_BENCHMARK__.senderDegradationPreferences();
|
||||
const values = globalThis.__PIIK_BENCHMARK__.senderDegradationPreferences();
|
||||
return values.length === ${expectedCount} &&
|
||||
values.every((value) => value === ${JSON.stringify(preference)});
|
||||
})()`;
|
||||
@@ -3236,7 +3236,7 @@ async function runViewerMbbCanary(
|
||||
const oldFrames = old.receiveTotals?.framesTotal ?? 0;
|
||||
const revision = target.routeRevision;
|
||||
const send = (page: PageHandle, method: string, message: unknown) =>
|
||||
evaluate<boolean>(cdp, page, `globalThis.__SCREENER_BENCHMARK__.${method}(${JSON.stringify(message)})`);
|
||||
evaluate<boolean>(cdp, page, `globalThis.__PIIK_BENCHMARK__.${method}(${JSON.stringify(message)})`);
|
||||
let windows = 0;
|
||||
for (let sequence = 0; sequence < 3; sequence += 1) {
|
||||
const windowSent = await send(targetHandle, "sendViewerQualityEvidence", {
|
||||
@@ -3303,7 +3303,7 @@ async function canary(cdp: CdpConnection, page: PageHandle): Promise<{
|
||||
prepareUpdates: number; activeUpdates: number; routeFailed: number;
|
||||
maxActiveOutboundMediaEdges: number;
|
||||
}> {
|
||||
return evaluate(cdp, page, "globalThis.__SCREENER_BENCHMARK__.canarySnapshot()");
|
||||
return evaluate(cdp, page, "globalThis.__PIIK_BENCHMARK__.canarySnapshot()");
|
||||
}
|
||||
|
||||
function canaryChecks(result: ViewerMbbCanaryResult): RunCheck[] {
|
||||
@@ -3360,7 +3360,7 @@ async function runCase(
|
||||
cdp,
|
||||
hostPage,
|
||||
`(() => {
|
||||
const grant = sessionStorage.getItem('screener:viewer-grant:${roomId}');
|
||||
const grant = sessionStorage.getItem('piik:viewer-grant:${roomId}');
|
||||
return grant ? location.origin + '/r/${roomId}#v=' + grant : '';
|
||||
})()`,
|
||||
);
|
||||
@@ -3702,7 +3702,7 @@ async function main(): Promise<number> {
|
||||
const appPort = externalServer ? null : await reservePort();
|
||||
const debugPort = await reservePort();
|
||||
const baseUrl = externalServer?.origin ?? `http://127.0.0.1:${appPort}`;
|
||||
profileDirectory = await mkdtemp(join(tmpdir(), "screener-peer-benchmark-"));
|
||||
profileDirectory = await mkdtemp(join(tmpdir(), "piik-peer-benchmark-"));
|
||||
if (appPort !== null) {
|
||||
// An explicit environment and a profile working directory: the measured
|
||||
// configuration is exactly these values, never the repository's .env or
|
||||
@@ -3711,7 +3711,7 @@ async function main(): Promise<number> {
|
||||
server = startProcess(buildServer(), [], {
|
||||
PATH: process.env.PATH,
|
||||
SystemRoot: process.env.SystemRoot,
|
||||
SCREENER_ENV: "development",
|
||||
PIIK_ENV: "development",
|
||||
PORT: String(appPort),
|
||||
LISTEN_HOST: "127.0.0.1",
|
||||
PUBLIC_BASE_URL: baseUrl,
|
||||
|
||||
@@ -39,10 +39,10 @@ scripts/client-icons.mjs
|
||||
scripts/package-client-candidate.mjs
|
||||
scripts/check-client.mjs
|
||||
scripts/client-native-host-gate.ts
|
||||
cmd/screener-server/main.go
|
||||
cmd/screener-peer-gate/main.go
|
||||
cmd/screener-client/screener.ico
|
||||
cmd/screener-client/screener_windows_amd64.syso
|
||||
cmd/piik-server/main.go
|
||||
cmd/piik-peer-gate/main.go
|
||||
cmd/piik-client/piik.ico
|
||||
cmd/piik-client/piik_windows_amd64.syso
|
||||
internal/server/webassets/dist/.gitkeep
|
||||
deploy/release-app.sh
|
||||
deploy/check-release.sh
|
||||
|
||||
Reference in new issue
Block a user