instead of restarting the whole container we now just restart css, much faster
This commit is contained in:
parent
435cd7f4ae
commit
cf4c95fe2c
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
cd ~/webclient_css_ze/streaming-agent
|
||||
CF_APP_ID= CF_APP_TOKEN= NAME_SALT= node signaling-server.js &> ../signaling.log &
|
||||
CF_APP_ID= CF_APP_TOKEN= NAME_SALT= CONTAINER_NAME=css-test node signaling-server.js &> ../signaling.log &
|
||||
echo "Signaling server started (PID $!), logs at webclient_css_ze/signaling.log"
|
||||
|
||||
#pkill -f signaling-server.js
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
* Signaling Server
|
||||
*
|
||||
* Handles two tracks: video and game audio.
|
||||
* Also manages controller queue and container restart for name changes.
|
||||
* Also manages controller queue and CSS process restart for name changes.
|
||||
* All Cloudflare API calls happen server-side.
|
||||
*
|
||||
* Run: CF_APP_ID=xxx CF_APP_TOKEN=xxx node signaling-server.js
|
||||
* Run: CF_APP_ID=xxx CF_APP_TOKEN=xxx NAME_SALT=xxx CONTAINER_NAME=css-test node signaling-server.js
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@ -23,6 +23,10 @@ const CF_APP_TOKEN = process.env.CF_APP_TOKEN || '';
|
||||
const CF_BASE = `https://rtc.live.cloudflare.com/v1/apps/${CF_APP_ID}`;
|
||||
const CONTAINER = process.env.CONTAINER_NAME || 'css-test';
|
||||
const IDLE_TIMEOUT = 10000; // 10 seconds
|
||||
const NAME_SALT = process.env.NAME_SALT || 'change-this-secret';
|
||||
|
||||
// How long to wait after relaunching CSS before granting control
|
||||
const CSS_LAUNCH_WAIT = 15000;
|
||||
|
||||
if (!CF_APP_ID || !CF_APP_TOKEN) {
|
||||
console.error('[sig] CF_APP_ID and CF_APP_TOKEN must be set');
|
||||
@ -98,11 +102,11 @@ async function applyController(entry) {
|
||||
containerRestarting = true;
|
||||
broadcastQueueState();
|
||||
|
||||
if (entry.visitorName === lastControllerName) {
|
||||
// Same person returning — no restart needed
|
||||
if (entry.visitorName === lastControllerName) {
|
||||
console.log(`[sig] same controller returning, skipping restart`);
|
||||
containerRestarting = false;
|
||||
currentController = entry;
|
||||
lastControllerName = entry.visitorName;
|
||||
resetIdleTimer(entry);
|
||||
broadcastQueueState();
|
||||
if (entry.ws.readyState === WebSocket.OPEN) {
|
||||
@ -111,9 +115,11 @@ async function applyController(entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Different person — update rev.ini and restart
|
||||
// Different person — update rev.ini and relaunch CSS only
|
||||
lastControllerName = entry.visitorName;
|
||||
console.log(`[sig] applying controller: ${entry.visitorName}`);
|
||||
|
||||
// Update rev.ini
|
||||
try {
|
||||
const safeName = entry.visitorName.replace(/'/g, "'\\''");
|
||||
execSync(`docker exec ${CONTAINER} sed -i "s/PlayerName=.*/PlayerName=${safeName}/" "/home/ubuntu/Counter-Strike Source/rev.ini"`);
|
||||
@ -122,23 +128,30 @@ async function applyController(entry) {
|
||||
console.error('[sig] failed to update rev.ini:', e.message);
|
||||
}
|
||||
|
||||
// Kill CSS and revLoader (leave Xvfb, PulseAudio, gst_agent running)
|
||||
try {
|
||||
execSync(`docker restart ${CONTAINER}`);
|
||||
console.log('[sig] container restarted');
|
||||
execSync(`docker exec ${CONTAINER} pkill -f "cstrike_win64.exe" || true`);
|
||||
execSync(`docker exec ${CONTAINER} pkill -f "revLoader.exe" || true`);
|
||||
execSync(`docker exec ${CONTAINER} pkill -f "wineserver" || true`);
|
||||
execSync(`docker exec ${CONTAINER} pkill -f "winedevice.exe" || true`);
|
||||
console.log('[sig] CSS processes killed');
|
||||
} catch (e) {
|
||||
console.error('[sig] failed to kill CSS:', e.message);
|
||||
}
|
||||
|
||||
// Wait for Wine to clean up
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
|
||||
// Relaunch CSS
|
||||
try {
|
||||
execSync(`docker exec -d ${CONTAINER} bash -c "DISPLAY=:99 wine '/home/ubuntu/Counter-Strike Source/revLoader.exe'"`);
|
||||
console.log('[sig] CSS relaunched');
|
||||
} catch (e) {
|
||||
console.error('[sig] failed to restart container:', e.message);
|
||||
console.error('[sig] failed to relaunch CSS:', e.message);
|
||||
}
|
||||
|
||||
// Wait for agent to re-register (up to 30 seconds)
|
||||
await new Promise(resolve => {
|
||||
const start = Date.now();
|
||||
const check = setInterval(() => {
|
||||
if (agentSessions.size > 0 || Date.now() - start > 30000) {
|
||||
clearInterval(check);
|
||||
resolve();
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
// Wait for CSS to launch and connect to server
|
||||
await new Promise(r => setTimeout(r, CSS_LAUNCH_WAIT));
|
||||
|
||||
containerRestarting = false;
|
||||
currentController = entry;
|
||||
@ -178,6 +191,28 @@ function removeFromQueue(ws) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── IP → Name (server side, salt never exposed to browser) ───────────────────
|
||||
function hashString(str) {
|
||||
let hash = 5381;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = ((hash << 5) + hash) + str.charCodeAt(i);
|
||||
hash = hash & 0x7fffffff;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
function ipToName(ip) {
|
||||
const adjectives = ['Fast','Slow','Red','Blue','Green','Dark','Bright','Wild',
|
||||
'Cool','Hot','Big','Small','Sharp','Brave','Swift','Bold'];
|
||||
const nouns = ['Wolf','Eagle','Tiger','Bear','Fox','Lion','Hawk','Shark',
|
||||
'Snake','Raven','Storm','Rock','Fire','Ice','Wind','Steel'];
|
||||
const salted = ip + NAME_SALT;
|
||||
const h1 = hashString(salted);
|
||||
const h2 = hashString(salted + '1');
|
||||
const h3 = hashString(salted + '2');
|
||||
return `${adjectives[h1 % adjectives.length]} ${nouns[h2 % nouns.length]} ${h3 % 9999}`;
|
||||
}
|
||||
|
||||
// ── pacat for mic audio ───────────────────────────────────────────────────────
|
||||
const PACAT_ARGS = [
|
||||
'--playback',
|
||||
@ -204,29 +239,6 @@ function stopPacat(browserSessId) {
|
||||
if (pacat) { pacat.kill(); pacatProcesses.delete(browserSessId); }
|
||||
}
|
||||
|
||||
const NAME_SALT = process.env.NAME_SALT || 'change-this-secret';
|
||||
|
||||
function hashString(str) {
|
||||
let hash = 5381;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = ((hash << 5) + hash) + str.charCodeAt(i);
|
||||
hash = hash & 0x7fffffff;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
function ipToName(ip) {
|
||||
const adjectives = ['Fast','Slow','Red','Blue','Green','Dark','Bright','Wild',
|
||||
'Cool','Hot','Big','Small','Sharp','Brave','Swift','Bold'];
|
||||
const nouns = ['Wolf','Eagle','Tiger','Bear','Fox','Lion','Hawk','Shark',
|
||||
'Snake','Raven','Storm','Rock','Fire','Ice','Wind','Steel'];
|
||||
const salted = ip + NAME_SALT;
|
||||
const h1 = hashString(salted);
|
||||
const h2 = hashString(salted + '1');
|
||||
const h3 = hashString(salted + '2');
|
||||
return `${adjectives[h1 % adjectives.length]} ${nouns[h2 % nouns.length]} ${h3 % 9999}`;
|
||||
}
|
||||
|
||||
// ── WebSocket handler ─────────────────────────────────────────────────────────
|
||||
wss.on('connection', ws => {
|
||||
let role = null;
|
||||
@ -262,16 +274,13 @@ wss.on('connection', ws => {
|
||||
else if (msg.type === 'request_control') {
|
||||
visitorName = msg.visitorName;
|
||||
|
||||
// Reject during restart
|
||||
if (containerRestarting) return;
|
||||
|
||||
// Already controlling — just reset idle timer
|
||||
if (currentController && currentController.ws === ws) {
|
||||
resetIdleTimer(currentController);
|
||||
return;
|
||||
}
|
||||
|
||||
// Already in queue
|
||||
if (controlQueue.find(e => e.ws === ws)) return;
|
||||
|
||||
const entry = { ws, visitorName, browserSessId };
|
||||
@ -295,6 +304,12 @@ wss.on('connection', ws => {
|
||||
if (browserSessId) stopPacat(browserSessId);
|
||||
}
|
||||
|
||||
else if (msg.type === 'get_ip') {
|
||||
const ip = ws._socket.remoteAddress.replace('::ffff:', '');
|
||||
const name = ipToName(ip);
|
||||
ws.send(JSON.stringify({ type: 'your_ip', ip: name }));
|
||||
}
|
||||
|
||||
else if (msg.type === 'browser_connect') {
|
||||
role = 'browser';
|
||||
const entry = [...agentSessions.values()][0];
|
||||
@ -358,11 +373,6 @@ wss.on('connection', ws => {
|
||||
entry.agentWs.send(JSON.stringify(msg.event));
|
||||
}
|
||||
}
|
||||
else if (msg.type === 'get_ip') {
|
||||
const ip = ws._socket.remoteAddress.replace('::ffff:', '');
|
||||
const name = ipToName(ip);
|
||||
ws.send(JSON.stringify({ type: 'your_ip', ip: name }));
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user