mirror of
https://gitlab.com/futo-org/fcast.git
synced 2025-06-24 21:25:23 +00:00
Removal of encryption.,
This commit is contained in:
parent
9599c1931e
commit
a991b353a6
16 changed files with 24 additions and 980 deletions
15
receivers/electron/package-lock.json
generated
15
receivers/electron/package-lock.json
generated
|
@ -11,9 +11,7 @@
|
|||
"dependencies": {
|
||||
"bufferutil": "^4.0.8",
|
||||
"https": "^1.0.0",
|
||||
"node-forge": "^1.3.1",
|
||||
"qrcode": "^1.5.3",
|
||||
"tls": "^0.0.1",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -4309,14 +4307,6 @@
|
|||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.7.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.1.tgz",
|
||||
|
@ -5158,11 +5148,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tls": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tls/-/tls-0.0.1.tgz",
|
||||
"integrity": "sha512-GzHpG+hwupY8VMR6rYsnAhTHqT/97zT45PG8WD5eTT1lq+dFE0nN+1PYpsoBcHJgSmTz5ceK2Cv88IkPmIPOtQ=="
|
||||
},
|
||||
"node_modules/tmpl": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||
|
|
|
@ -28,9 +28,7 @@
|
|||
"dependencies": {
|
||||
"bufferutil": "^4.0.8",
|
||||
"https": "^1.0.0",
|
||||
"node-forge": "^1.3.1",
|
||||
"qrcode": "^1.5.3",
|
||||
"tls": "^0.0.1",
|
||||
"ws": "^8.14.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,7 @@ const os = require('os');
|
|||
|
||||
export class DiscoveryService {
|
||||
private serviceTcp: any;
|
||||
private serviceTls: any;
|
||||
private serviceWs: any;
|
||||
private serviceWss: any;
|
||||
|
||||
private static getComputerName() {
|
||||
switch (process.platform) {
|
||||
|
@ -23,7 +21,7 @@ export class DiscoveryService {
|
|||
}
|
||||
|
||||
start() {
|
||||
if (this.serviceTcp || this.serviceTls || this.serviceWs || this.serviceWss) {
|
||||
if (this.serviceTcp || this.serviceWs) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -32,12 +30,8 @@ export class DiscoveryService {
|
|||
|
||||
this.serviceTcp = mdns.createAdvertisement(mdns.tcp('_fcast'), 46899, { name: name });
|
||||
this.serviceTcp.start();
|
||||
this.serviceTls = mdns.createAdvertisement(mdns.tcp('_fcast-tls'), 46897, { name: name });
|
||||
this.serviceTls.start();
|
||||
this.serviceWs = mdns.createAdvertisement(mdns.tcp('_fcast-ws'), 46898, { name: name });
|
||||
this.serviceWs.start();
|
||||
this.serviceWss = mdns.createAdvertisement(mdns.tcp('_fcast-wss'), 46896, { name: name });
|
||||
this.serviceWss.start();
|
||||
}
|
||||
|
||||
stop() {
|
||||
|
@ -46,19 +40,9 @@ export class DiscoveryService {
|
|||
this.serviceTcp = null;
|
||||
}
|
||||
|
||||
if (this.serviceTls) {
|
||||
this.serviceTls.stop();
|
||||
this.serviceTls = null;
|
||||
}
|
||||
|
||||
if (this.serviceWs) {
|
||||
this.serviceWs.stop();
|
||||
this.serviceWs = null;
|
||||
}
|
||||
|
||||
if (this.serviceWss) {
|
||||
this.serviceWss.stop();
|
||||
this.serviceWss = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,10 +7,6 @@ import { Updater } from './Updater';
|
|||
import { WebSocketListenerService } from './WebSocketListenerService';
|
||||
import * as os from 'os';
|
||||
import { Opcode } from './FCastSession';
|
||||
import fs = require('fs');
|
||||
import forge = require('node-forge');
|
||||
import { TlsListenerService } from './TlsTcpListenerService';
|
||||
import { WebSocketSecureListenerService } from './WebSocketSecureListenerService';
|
||||
|
||||
export default class Main {
|
||||
static shouldOpenMainWindow = true;
|
||||
|
@ -19,8 +15,6 @@ export default class Main {
|
|||
static application: Electron.App;
|
||||
static tcpListenerService: TcpListenerService;
|
||||
static webSocketListenerService: WebSocketListenerService;
|
||||
static tlsListenerService: TlsListenerService;
|
||||
static webSocketSecureListenerService: WebSocketSecureListenerService;
|
||||
static discoveryService: DiscoveryService;
|
||||
static tray: Tray;
|
||||
static key: string = null;
|
||||
|
@ -108,10 +102,8 @@ export default class Main {
|
|||
|
||||
Main.tcpListenerService = new TcpListenerService();
|
||||
Main.webSocketListenerService = new WebSocketListenerService();
|
||||
Main.tlsListenerService = new TlsListenerService(Main.key, Main.cert);
|
||||
Main.webSocketSecureListenerService = new WebSocketSecureListenerService(Main.key, Main.cert);
|
||||
|
||||
const listeners = [Main.tcpListenerService, Main.webSocketListenerService, Main.tlsListenerService, Main.webSocketSecureListenerService];
|
||||
const listeners = [Main.tcpListenerService, Main.webSocketListenerService];
|
||||
listeners.forEach(l => {
|
||||
l.emitter.on("play", (message) => {
|
||||
if (Main.playerWindow == null) {
|
||||
|
@ -234,50 +226,6 @@ export default class Main {
|
|||
}
|
||||
|
||||
static main(app: Electron.App) {
|
||||
if (!fs.existsSync('./cert.pem') || !fs.existsSync('./key.pem')) {
|
||||
try {
|
||||
const keys = forge.pki.rsa.generateKeyPair(2048);
|
||||
|
||||
const cert = forge.pki.createCertificate();
|
||||
cert.publicKey = keys.publicKey;
|
||||
cert.validity.notBefore = new Date();
|
||||
cert.validity.notAfter = new Date(9999, 11, 31);
|
||||
cert.sign(keys.privateKey);
|
||||
|
||||
const pemCert = forge.pki.certificateToPem(cert);
|
||||
const pemKey = forge.pki.privateKeyToPem(keys.privateKey);
|
||||
fs.writeFileSync('./cert.pem', pemCert);
|
||||
fs.writeFileSync('./key.pem', pemKey);
|
||||
} catch {
|
||||
console.error("Failed to generate key pair.");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Main.key = fs.readFileSync('./key.pem', 'utf8');
|
||||
Main.cert = fs.readFileSync('./cert.pem', 'utf8');
|
||||
} catch (e) {
|
||||
console.error("Failed to load key pair.", e);
|
||||
|
||||
dialog.showMessageBox({
|
||||
type: 'error',
|
||||
title: 'Failed to initialize crypto',
|
||||
message: `The application failed to start properly '${JSON.stringify(e)}'.`,
|
||||
buttons: ['Restart', 'Close'],
|
||||
defaultId: 0,
|
||||
cancelId: 1
|
||||
}).then((p) => {
|
||||
if (p.response === 0) {
|
||||
app.relaunch();
|
||||
app.exit(0);
|
||||
} else {
|
||||
app.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Main.application = app;
|
||||
const argv = process.argv;
|
||||
if (argv.includes('--no-main-window')) {
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
import tls = require('tls');
|
||||
import { FCastSession, Opcode } from './FCastSession';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { dialog } from 'electron';
|
||||
import Main from './Main';
|
||||
|
||||
export class TlsListenerService {
|
||||
public static PORT = 46897;
|
||||
|
||||
emitter = new EventEmitter();
|
||||
|
||||
private server: tls.Server;
|
||||
private sessions: FCastSession[] = [];
|
||||
|
||||
constructor(private key: string, private cert: string) {}
|
||||
|
||||
start() {
|
||||
if (this.server != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options: tls.TlsOptions = {key: this.key, cert: this.cert};
|
||||
this.server = tls.createServer(options).listen(TlsListenerService.PORT)
|
||||
.on("secureConnection", this.handleConnection.bind(this))
|
||||
.on("error", this.handleServerError.bind(this));
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.server == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const server = this.server;
|
||||
this.server = null;
|
||||
|
||||
server.close();
|
||||
}
|
||||
|
||||
send(opcode: number, message = null) {
|
||||
this.sessions.forEach(session => {
|
||||
try {
|
||||
session.send(opcode, message);
|
||||
} catch (e) {
|
||||
console.warn("Failed to send error.", e);
|
||||
session.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async handleServerError(err: NodeJS.ErrnoException) {
|
||||
console.error("Server error:", err);
|
||||
|
||||
const restartPrompt = await dialog.showMessageBox({
|
||||
type: 'error',
|
||||
title: 'Failed to start',
|
||||
message: 'The application failed to start properly.',
|
||||
buttons: ['Restart', 'Close'],
|
||||
defaultId: 0,
|
||||
cancelId: 1
|
||||
});
|
||||
|
||||
if (restartPrompt.response === 0) {
|
||||
Main.application.relaunch();
|
||||
Main.application.exit(0);
|
||||
} else {
|
||||
Main.application.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
private handleConnection(socket: tls.TLSSocket) {
|
||||
console.log(`new secure connection from ${socket.remoteAddress}:${socket.remotePort}`);
|
||||
|
||||
const session = new FCastSession(socket, (data) => socket.write(data));
|
||||
session.bindEvents(this.emitter);
|
||||
this.sessions.push(session);
|
||||
|
||||
socket.on("error", (err) => {
|
||||
console.warn(`Error from ${socket.remoteAddress}:${socket.remotePort}.`, err);
|
||||
socket.destroy();
|
||||
});
|
||||
|
||||
socket.on("data", buffer => {
|
||||
try {
|
||||
session.processBytes(buffer);
|
||||
} catch (e) {
|
||||
console.warn(`Error while handling packet from ${socket.remoteAddress}:${socket.remotePort}.`, e);
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("close", () => {
|
||||
const index = this.sessions.indexOf(session);
|
||||
if (index != -1) {
|
||||
this.sessions.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
console.log('Sending version');
|
||||
session.send(Opcode.Version, {version: 2});
|
||||
} catch (e) {
|
||||
console.log('Failed to send version');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
import { FCastSession, Opcode } from './FCastSession';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { dialog } from 'electron';
|
||||
import Main from './Main';
|
||||
import { WebSocket, WebSocketServer } from 'ws';
|
||||
import * as https from 'https';
|
||||
|
||||
export class WebSocketSecureListenerService {
|
||||
public static PORT = 46896;
|
||||
|
||||
emitter = new EventEmitter();
|
||||
|
||||
private server: WebSocketServer;
|
||||
private sessions: FCastSession[] = [];
|
||||
private httpsServer: https.Server;
|
||||
|
||||
constructor(private key: string, private cert: string) {}
|
||||
|
||||
start() {
|
||||
if (this.server != null || this.httpsServer != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.httpsServer = https.createServer({key: this.key, cert: this.cert});
|
||||
this.httpsServer.listen(WebSocketSecureListenerService.PORT);
|
||||
|
||||
this.server = new WebSocketServer({server: this.httpsServer})
|
||||
.on("connection", this.handleConnection.bind(this))
|
||||
.on("error", this.handleServerError.bind(this));
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.server != null) {
|
||||
const server = this.server;
|
||||
this.server = null;
|
||||
server.close();
|
||||
}
|
||||
|
||||
if (this.httpsServer != null) {
|
||||
const httpsServer = this.httpsServer;
|
||||
this.httpsServer = null;
|
||||
httpsServer.close();
|
||||
}
|
||||
}
|
||||
|
||||
send(opcode: number, message = null) {
|
||||
this.sessions.forEach(session => {
|
||||
try {
|
||||
session.send(opcode, message);
|
||||
} catch (e) {
|
||||
console.warn("Failed to send error.", e);
|
||||
session.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async handleServerError(err: NodeJS.ErrnoException) {
|
||||
console.error("Server error:", err);
|
||||
|
||||
const restartPrompt = await dialog.showMessageBox({
|
||||
type: 'error',
|
||||
title: 'Failed to start',
|
||||
message: 'The application failed to start properly.',
|
||||
buttons: ['Restart', 'Close'],
|
||||
defaultId: 0,
|
||||
cancelId: 1
|
||||
});
|
||||
|
||||
if (restartPrompt.response === 0) {
|
||||
Main.application.relaunch();
|
||||
Main.application.exit(0);
|
||||
} else {
|
||||
Main.application.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
private handleConnection(socket: WebSocket) {
|
||||
console.log('New WebSocketSecure connection');
|
||||
|
||||
const session = new FCastSession(socket, (data) => socket.send(data));
|
||||
session.bindEvents(this.emitter);
|
||||
this.sessions.push(session);
|
||||
|
||||
socket.on("error", (err) => {
|
||||
console.warn(`Error.`, err);
|
||||
session.close();
|
||||
});
|
||||
|
||||
socket.on('message', data => {
|
||||
try {
|
||||
if (data instanceof Buffer) {
|
||||
session.processBytes(data);
|
||||
} else {
|
||||
console.warn("Received unhandled string message", data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(`Error while handling packet.`, e);
|
||||
session.close();
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("close", () => {
|
||||
console.log('WebSocketSecure connection closed');
|
||||
|
||||
const index = this.sessions.indexOf(session);
|
||||
if (index != -1) {
|
||||
this.sessions.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
console.log('Sending version');
|
||||
session.send(Opcode.Version, {version: 2});
|
||||
} catch (e) {
|
||||
console.log('Failed to send version');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
<div id="manual-connection-info">Manual connection information</div>
|
||||
<div>
|
||||
<div id="ips">IPs</div><br />
|
||||
<div>Port<br>46899 (TCP), 46898 (WS), 46897 (TLS), 46896 (WSS)</div>
|
||||
<div>Port<br>46899 (TCP), 46898 (WS)</div>
|
||||
</div>
|
||||
<div id="automatic-discovery">Automatic discovery is available via mDNS</div>
|
||||
<div id="qr-code"></div>
|
||||
|
|
|
@ -24,8 +24,6 @@ window.electronAPI.onDeviceInfo((_event, value) => {
|
|||
services: [
|
||||
{ port: 46899, type: 0 }, //TCP
|
||||
{ port: 46898, type: 1 }, //WS
|
||||
{ port: 46897, type: 2 }, //TCP-TLS
|
||||
{ port: 46896, type: 3 } //WSS
|
||||
]
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue