mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-10 09:35:39 +00:00
e855f5786d
Add a new betterdesk-server Go codebase (server, api, auth, db, relay, signal, metrics, audit, ratelimit, proto, tools, tests) and related deployment/migration scripts. Add a comprehensive SECURITY_AUDIT_2026-03-01 report and .gitattributes; update copilot-instructions (ALL-IN-ONE v2.4.0), README, VERSION, Dockerfiles, scripts, docker-compose and entrypoint. Large updates to web-nodejs (translations, routes, services, frontend assets and middleware) and numerous new utilities; remove legacy Flask web files and archive hbbs-patch-v2 artifacts. Prepares repository for PostgreSQL support, DB migration tooling and the new Go server as the production backend.
129 lines
3.6 KiB
JavaScript
129 lines
3.6 KiB
JavaScript
/**
|
|
* BetterDesk Console - LAN Discovery Service
|
|
*
|
|
* UDP broadcast responder on port 21119.
|
|
* Clients send a JSON probe; the server replies with its identity
|
|
* (name, version, public key, console URL, API port).
|
|
*
|
|
* Protocol:
|
|
* Client → broadcast 255.255.255.255:21119
|
|
* { "type": "betterdesk-discover", "version": 1 }
|
|
*
|
|
* Server → unicast reply to client
|
|
* { "type": "betterdesk-announce", "version": 1, "server": { ... } }
|
|
*
|
|
* @module services/lanDiscovery
|
|
*/
|
|
|
|
const dgram = require('dgram');
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const config = require('../config/config');
|
|
|
|
const DISCOVERY_PORT = parseInt(process.env.DISCOVERY_PORT, 10) || 21119;
|
|
const PROTOCOL_VERSION = 1;
|
|
|
|
let udpServer = null;
|
|
|
|
/**
|
|
* Build the server announcement payload.
|
|
* @returns {object} Server info for discovery response
|
|
*/
|
|
function buildAnnouncement() {
|
|
// Read public key (base64) if available
|
|
let publicKey = '';
|
|
try {
|
|
if (fs.existsSync(config.pubKeyPath)) {
|
|
publicKey = fs.readFileSync(config.pubKeyPath, 'utf8').trim();
|
|
}
|
|
} catch (_) { /* ignore */ }
|
|
|
|
// Gather local IP addresses
|
|
const addresses = [];
|
|
const ifaces = os.networkInterfaces();
|
|
for (const name of Object.keys(ifaces)) {
|
|
for (const iface of ifaces[name]) {
|
|
if (iface.family === 'IPv4' && !iface.internal) {
|
|
addresses.push(iface.address);
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
type: 'betterdesk-announce',
|
|
version: PROTOCOL_VERSION,
|
|
server: {
|
|
name: os.hostname(),
|
|
version: config.appVersion,
|
|
port: config.port,
|
|
apiPort: config.apiPort,
|
|
protocol: config.httpsEnabled ? 'https' : 'http',
|
|
publicKey,
|
|
addresses,
|
|
discoveryPort: DISCOVERY_PORT,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Start the UDP discovery responder.
|
|
* @returns {{ server: dgram.Socket, port: number }} Handle for the running service
|
|
*/
|
|
function startDiscoveryService() {
|
|
if (udpServer) {
|
|
return { server: udpServer, port: DISCOVERY_PORT };
|
|
}
|
|
|
|
udpServer = dgram.createSocket({ type: 'udp4', reuseAddr: true });
|
|
|
|
udpServer.on('message', (msg, rinfo) => {
|
|
try {
|
|
const data = JSON.parse(msg.toString('utf8'));
|
|
if (data.type !== 'betterdesk-discover') return;
|
|
|
|
const announcement = buildAnnouncement();
|
|
const reply = Buffer.from(JSON.stringify(announcement), 'utf8');
|
|
|
|
udpServer.send(reply, 0, reply.length, rinfo.port, rinfo.address, (err) => {
|
|
if (err) {
|
|
console.warn('LAN Discovery: failed to send reply:', err.message);
|
|
}
|
|
});
|
|
} catch (_) {
|
|
// Ignore non-JSON or malformed packets silently
|
|
}
|
|
});
|
|
|
|
udpServer.on('error', (err) => {
|
|
if (err.code === 'EADDRINUSE') {
|
|
console.warn(`LAN Discovery: port ${DISCOVERY_PORT} already in use, service disabled`);
|
|
} else {
|
|
console.error('LAN Discovery error:', err.message);
|
|
}
|
|
udpServer = null;
|
|
});
|
|
|
|
udpServer.bind(DISCOVERY_PORT, '0.0.0.0', () => {
|
|
console.log(` LAN Discovery active on UDP port ${DISCOVERY_PORT}`);
|
|
});
|
|
|
|
return { server: udpServer, port: DISCOVERY_PORT };
|
|
}
|
|
|
|
/**
|
|
* Stop the UDP discovery service.
|
|
*/
|
|
function stopDiscoveryService() {
|
|
if (udpServer) {
|
|
udpServer.close();
|
|
udpServer = null;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
DISCOVERY_PORT,
|
|
startDiscoveryService,
|
|
stopDiscoveryService,
|
|
buildAnnouncement,
|
|
};
|