mirror of
https://gitlab.com/futo-org/fcast.git
synced 2025-06-24 21:25:23 +00:00
Receivers: Moved connection monitor to main process
This commit is contained in:
parent
bb330d9718
commit
2791357ba3
4 changed files with 73 additions and 65 deletions
|
@ -1,57 +1,73 @@
|
|||
import { Opcode } from 'common/Packets';
|
||||
|
||||
const connectionPingTimeout = 2500;
|
||||
const heartbeatRetries = {};
|
||||
let connections = [];
|
||||
let uiUpdateCallbacks = {
|
||||
onConnect: null,
|
||||
onDisconnect: null,
|
||||
}
|
||||
const logger = window.targetAPI.logger;
|
||||
import { Logger, LoggerType } from 'common/Logger';
|
||||
|
||||
// Window might be re-created while devices are still connected
|
||||
export function setUiUpdateCallbacks(callbacks: any) {
|
||||
uiUpdateCallbacks = callbacks;
|
||||
const logger = window.targetAPI.logger;
|
||||
let frontendConnections = [];
|
||||
|
||||
window.targetAPI.onConnect((_event, value: any) => {
|
||||
frontendConnections.push(value.sessionId);
|
||||
callbacks.onConnect(frontendConnections);
|
||||
});
|
||||
window.targetAPI.onDisconnect((_event, value: any) => {
|
||||
const index = frontendConnections.indexOf(value.sessionId);
|
||||
if (index != -1) {
|
||||
frontendConnections.splice(index, 1);
|
||||
callbacks.onDisconnect(frontendConnections, value.sessionId);
|
||||
}
|
||||
});
|
||||
|
||||
window.targetAPI.getSessions().then((sessions: string[]) => {
|
||||
connections = sessions;
|
||||
if (connections.length > 0) {
|
||||
uiUpdateCallbacks.onConnect(connections, true);
|
||||
logger.info('Window created with current sessions:', sessions);
|
||||
frontendConnections = sessions;
|
||||
|
||||
if (frontendConnections.length > 0) {
|
||||
callbacks.onConnect(frontendConnections, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onPingPong(value: any) {
|
||||
heartbeatRetries[value.sessionId] = 0;
|
||||
}
|
||||
window.targetAPI.onPing((_event, value: any) => onPingPong(value));
|
||||
window.targetAPI.onPong((_event, value: any) => onPingPong(value));
|
||||
export class ConnectionMonitor {
|
||||
private static initialized = false;
|
||||
private static connectionPingTimeout = 2500;
|
||||
private static heartbeatRetries = new Map();
|
||||
private static backendConnections = new Map();
|
||||
private static logger;
|
||||
|
||||
window.targetAPI.onConnect((_event, value: any) => {
|
||||
logger.info(`Device connected: ${JSON.stringify(value)}`);
|
||||
connections.push(value.sessionId);
|
||||
uiUpdateCallbacks.onConnect(connections);
|
||||
});
|
||||
window.targetAPI.onDisconnect((_event, value: any) => {
|
||||
logger.info(`Device disconnected: ${JSON.stringify(value)}`);
|
||||
const index = connections.indexOf(value.sessionId);
|
||||
if (index != -1) {
|
||||
connections.splice(index, 1);
|
||||
uiUpdateCallbacks.onDisconnect(connections, value.sessionId);
|
||||
}
|
||||
});
|
||||
constructor() {
|
||||
if (!ConnectionMonitor.initialized) {
|
||||
ConnectionMonitor.logger = new Logger('ConnectionMonitor', LoggerType.BACKEND);
|
||||
|
||||
setInterval(() => {
|
||||
if (connections.length > 0) {
|
||||
window.targetAPI.sendSessionMessage(Opcode.Ping, null);
|
||||
setInterval(() => {
|
||||
if (ConnectionMonitor.backendConnections.size > 0) {
|
||||
for (const sessionId in ConnectionMonitor.backendConnections) {
|
||||
if (ConnectionMonitor.heartbeatRetries.get(sessionId) > 3) {
|
||||
ConnectionMonitor.logger.warn(`Could not ping device with connection id ${sessionId}. Disconnecting...`);
|
||||
ConnectionMonitor.backendConnections.get(sessionId).disconnect(sessionId);
|
||||
}
|
||||
|
||||
for (const sessionId of connections) {
|
||||
if (heartbeatRetries[sessionId] > 3) {
|
||||
logger.warn(`Could not ping device with connection id ${sessionId}. Disconnecting...`);
|
||||
window.targetAPI.disconnectDevice(sessionId);
|
||||
}
|
||||
ConnectionMonitor.backendConnections.get(sessionId).send(Opcode.Ping, null);
|
||||
ConnectionMonitor.heartbeatRetries.set(sessionId, ConnectionMonitor.heartbeatRetries.get(sessionId) === undefined ? 1 : ConnectionMonitor.heartbeatRetries.get(sessionId) + 1);
|
||||
}
|
||||
}
|
||||
}, ConnectionMonitor.connectionPingTimeout);
|
||||
|
||||
heartbeatRetries[sessionId] = heartbeatRetries[sessionId] === undefined ? 1 : heartbeatRetries[sessionId] + 1;
|
||||
ConnectionMonitor.initialized = true;
|
||||
}
|
||||
}
|
||||
}, connectionPingTimeout);
|
||||
|
||||
public static onPingPong(value: any) {
|
||||
ConnectionMonitor.heartbeatRetries[value.sessionId] = 0;
|
||||
}
|
||||
|
||||
public static onConnect(listener: any, value: any) {
|
||||
ConnectionMonitor.logger.info(`Device connected: ${JSON.stringify(value)}`);
|
||||
ConnectionMonitor.backendConnections.set(value.sessionId, listener);
|
||||
}
|
||||
|
||||
public static onDisconnect(listener: any, value: any) {
|
||||
ConnectionMonitor.logger.info(`Device disconnected: ${JSON.stringify(value)}`);
|
||||
ConnectionMonitor.backendConnections.delete(value.sessionId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,12 +38,8 @@ if (TARGET === 'electron') {
|
|||
onDeviceInfo: (callback: any) => electronAPI.ipcRenderer.on('device-info', callback),
|
||||
getDeviceInfo: () => preloadData.deviceInfo,
|
||||
getSessions: () => electronAPI.ipcRenderer.invoke('get-sessions'),
|
||||
sendSessionMessage: (opcode: Opcode, message: any) => electronAPI.ipcRenderer.send('send-session-message', { opcode: opcode, message: message }),
|
||||
disconnectDevice: (session: string) => electronAPI.ipcRenderer.send('disconnect-device', session),
|
||||
onConnect: (callback: any) => electronAPI.ipcRenderer.on('connect', callback),
|
||||
onDisconnect: (callback: any) => electronAPI.ipcRenderer.on('disconnect', callback),
|
||||
onPing: (callback: any) => electronAPI.ipcRenderer.on('ping', callback),
|
||||
onPong: (callback: any) => electronAPI.ipcRenderer.on('pong', callback),
|
||||
logger: loggerInterface,
|
||||
});
|
||||
|
||||
|
@ -51,17 +47,17 @@ if (TARGET === 'electron') {
|
|||
} else if (TARGET === 'webOS' || TARGET === 'tizenOS') {
|
||||
preloadData = {
|
||||
onDeviceInfoCb: () => { logger.error('Main: Callback not set while fetching device info'); },
|
||||
getSessionsCb: () => { logger.error('Main: Callback not set while calling getSessions'); },
|
||||
onConnectCb: (_, value: any) => { logger.error('Main: Callback not set while calling onConnect'); },
|
||||
onDisconnectCb: (_, value: any) => { logger.error('Main: Callback not set while calling onDisconnect'); },
|
||||
onPingCb: (_, value: any) => { logger.error('Main: Callback not set while calling onPing'); },
|
||||
};
|
||||
|
||||
window.targetAPI = {
|
||||
onDeviceInfo: (callback: () => void) => preloadData.onDeviceInfoCb = callback,
|
||||
getDeviceInfo: () => preloadData.deviceInfo,
|
||||
getSessions: (callback: () => void) => preloadData.getSessionsCb = callback,
|
||||
onConnect: (callback: (_, value: any) => void) => preloadData.onConnectCb = callback,
|
||||
onDisconnect: (callback: (_, value: any) => void) => preloadData.onDisconnectCb = callback,
|
||||
onPing: (callback: (_, value: any) => void) => preloadData.onPingCb = callback,
|
||||
getDeviceInfo: () => preloadData.deviceInfo,
|
||||
logger: loggerInterface,
|
||||
};
|
||||
} else {
|
||||
|
|
|
@ -42,12 +42,8 @@ if (TARGET === 'electron') {
|
|||
onSetVolume: (callback: any) => electronAPI.ipcRenderer.on("setvolume", callback),
|
||||
onSetSpeed: (callback: any) => electronAPI.ipcRenderer.on("setspeed", callback),
|
||||
getSessions: () => electronAPI.ipcRenderer.invoke('get-sessions'),
|
||||
sendSessionMessage: (opcode: Opcode, message: any) => electronAPI.ipcRenderer.send('send-session-message', { opcode: opcode, message: message }),
|
||||
disconnectDevice: (session: string) => electronAPI.ipcRenderer.send('disconnect-device', session),
|
||||
onConnect: (callback: any) => electronAPI.ipcRenderer.on('connect', callback),
|
||||
onDisconnect: (callback: any) => electronAPI.ipcRenderer.on('disconnect', callback),
|
||||
onPing: (callback: any) => electronAPI.ipcRenderer.on('ping', callback),
|
||||
onPong: (callback: any) => electronAPI.ipcRenderer.on('pong', callback),
|
||||
logger: loggerInterface,
|
||||
});
|
||||
|
||||
|
@ -64,6 +60,9 @@ if (TARGET === 'electron') {
|
|||
onSeekCb: () => { logger.error('Player: Callback "onseek" not set'); },
|
||||
onSetVolumeCb: () => { logger.error('Player: Callback "setvolume" not set'); },
|
||||
onSetSpeedCb: () => { logger.error('Player: Callback "setspeed" not set'); },
|
||||
getSessionsCb: () => { logger.error('Player: Callback "getSessions" not set'); },
|
||||
onConnectCb: () => { logger.error('Player: Callback "onConnect" not set'); },
|
||||
onDisconnectCb: () => { logger.error('Player: Callback "onDisconnect" not set'); },
|
||||
};
|
||||
|
||||
window.targetAPI = {
|
||||
|
@ -76,6 +75,9 @@ if (TARGET === 'electron') {
|
|||
onSeek: (callback: any) => { preloadData.onSeekCb = callback; },
|
||||
onSetVolume: (callback: any) => { preloadData.onSetVolumeCb = callback; },
|
||||
onSetSpeed: (callback: any) => { preloadData.onSetSpeedCb = callback; },
|
||||
getSessions: (callback: any) => { preloadData.getSessionsCb = callback; },
|
||||
onConnect: (callback: any) => { preloadData.onConnectCb = callback; },
|
||||
onDisconnect: (callback: any) => { preloadData.onDisconnectCb = callback; },
|
||||
logger: loggerInterface,
|
||||
};
|
||||
} else {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { DiscoveryService } from 'common/DiscoveryService';
|
|||
import { TcpListenerService } from 'common/TcpListenerService';
|
||||
import { WebSocketListenerService } from 'common/WebSocketListenerService';
|
||||
import { NetworkService } from 'common/NetworkService';
|
||||
import { ConnectionMonitor } from 'common/ConnectionMonitor';
|
||||
import { Logger, LoggerType } from 'common/Logger';
|
||||
import { Updater } from './Updater';
|
||||
import * as os from 'os';
|
||||
|
@ -22,6 +23,7 @@ export class Main {
|
|||
static tcpListenerService: TcpListenerService;
|
||||
static webSocketListenerService: WebSocketListenerService;
|
||||
static discoveryService: DiscoveryService;
|
||||
static connectionMonitor: ConnectionMonitor;
|
||||
static tray: Tray;
|
||||
|
||||
private static cachedInterfaces = null;
|
||||
|
@ -143,6 +145,7 @@ export class Main {
|
|||
private static onReady() {
|
||||
Main.createTray();
|
||||
|
||||
Main.connectionMonitor = new ConnectionMonitor();
|
||||
Main.discoveryService = new DiscoveryService();
|
||||
Main.discoveryService.start();
|
||||
|
||||
|
@ -190,20 +193,20 @@ export class Main {
|
|||
l.emitter.on("setspeed", (message) => Main.playerWindow?.webContents?.send("setspeed", message));
|
||||
|
||||
l.emitter.on('connect', (message) => {
|
||||
ConnectionMonitor.onConnect(l, message);
|
||||
Main.mainWindow?.webContents?.send('connect', message);
|
||||
Main.playerWindow?.webContents?.send('connect', message);
|
||||
});
|
||||
l.emitter.on('disconnect', (message) => {
|
||||
ConnectionMonitor.onDisconnect(l, message);
|
||||
Main.mainWindow?.webContents?.send('disconnect', message);
|
||||
Main.playerWindow?.webContents?.send('disconnect', message);
|
||||
});
|
||||
l.emitter.on('ping', (message) => {
|
||||
Main.mainWindow?.webContents?.send('ping', message);
|
||||
Main.playerWindow?.webContents?.send('ping', message);
|
||||
ConnectionMonitor.onPingPong(message);
|
||||
});
|
||||
l.emitter.on('pong', (message) => {
|
||||
Main.mainWindow?.webContents?.send('pong', message);
|
||||
Main.playerWindow?.webContents?.send('pong', message);
|
||||
ConnectionMonitor.onPingPong(message);
|
||||
});
|
||||
l.start();
|
||||
|
||||
|
@ -218,15 +221,6 @@ export class Main {
|
|||
ipcMain.on('send-volume-update', (event: IpcMainEvent, value: VolumeUpdateMessage) => {
|
||||
l.send(Opcode.VolumeUpdate, value);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
ipcMain.on('send-session-message', (event: IpcMainEvent, value: any) => {
|
||||
l.send(value.opcode, value.message);
|
||||
});
|
||||
|
||||
ipcMain.on('disconnect-device', (event: IpcMainEvent, value: string) => {
|
||||
l.disconnect(value);
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('send-download-request', async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue