feat: migration Socket.IO natif — login, terminaux REST, health check (closes #3)
Remplace toute la couche SignalR par une connexion Socket.IO directe au serveur Python (port 8004). Auth au handshake, reconnexion native illimitée, terminaux via REST GET /terminals. - socketio-adapter.js : connect/logoff/disconnect, events login_ok/login_error - main.js : initializeSocketIO, health check net.request, terminaux REST - renderer.js : IPC signalr-status → server-status - config.json : clé socketio (plus signalR) - Version 2.0.0
This commit is contained in:
151
socketio-adapter.js
Normal file
151
socketio-adapter.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Adaptateur Socket.IO natif pour le serveur Python SimpleServer
|
||||
*
|
||||
* Connexion directe au port 8004, auth au handshake,
|
||||
* reconnexion native illimitee.
|
||||
*/
|
||||
|
||||
const io = require('socket.io-client');
|
||||
|
||||
class SocketIOAdapter {
|
||||
constructor(serverUrl) {
|
||||
this.serverUrl = serverUrl;
|
||||
this.socket = null;
|
||||
this._state = 'disconnected'; // disconnected, connecting, connected, error
|
||||
this._eventHandlers = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connexion avec auth au handshake.
|
||||
* Le serveur authentifie dans le handler connect et emet 'login_ok' avec le resultat.
|
||||
* @returns {Promise<object>} connResult (accessCode, firstName, lastName, connList)
|
||||
*/
|
||||
connect(accessCode, password, terminal) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._state = 'connecting';
|
||||
|
||||
this.socket = io(this.serverUrl, {
|
||||
auth: { access_code: accessCode, password, terminal },
|
||||
transports: ['websocket'],
|
||||
reconnection: true,
|
||||
reconnectionAttempts: Infinity,
|
||||
reconnectionDelay: 2000,
|
||||
reconnectionDelayMax: 10000,
|
||||
});
|
||||
|
||||
let settled = false;
|
||||
|
||||
// Le serveur emet 'login_ok' avec les donnees de session
|
||||
this.socket.once('login_ok', (data) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
this._state = 'connected';
|
||||
resolve(data);
|
||||
});
|
||||
|
||||
// Le serveur emet 'login_error' si auth echouee (avant return false)
|
||||
this.socket.once('login_error', (data) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
this._state = 'error';
|
||||
this.socket.disconnect();
|
||||
reject(new Error(data.message || 'Authentification refusee'));
|
||||
});
|
||||
|
||||
// Erreur de connexion (serveur injoignable ou return false du handler connect)
|
||||
this.socket.on('connect_error', (err) => {
|
||||
if (!settled) {
|
||||
settled = true;
|
||||
this._state = 'error';
|
||||
this.socket.disconnect();
|
||||
reject(new Error(err.message || 'Connexion refusee'));
|
||||
}
|
||||
// Apres login reussi : reconnexion auto geree par socket.io
|
||||
});
|
||||
|
||||
// Timeout de connexion initiale (15s)
|
||||
setTimeout(() => {
|
||||
if (!settled) {
|
||||
settled = true;
|
||||
this._state = 'error';
|
||||
this.socket.disconnect();
|
||||
reject(new Error('Timeout de connexion au serveur'));
|
||||
}
|
||||
}, 15000);
|
||||
|
||||
// Restaurer les handlers enregistres avant connect
|
||||
this._eventHandlers.forEach((handler, event) => {
|
||||
this.socket.on(event, handler);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deconnexion volontaire avec logoff IPBX.
|
||||
* Emet 'logout' et attend 'logout_ok' du serveur.
|
||||
*/
|
||||
logoff() {
|
||||
return new Promise((resolve) => {
|
||||
if (!this.socket || !this.socket.connected) {
|
||||
this._state = 'disconnected';
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
this.socket.once('logout_ok', () => {
|
||||
this._state = 'disconnected';
|
||||
resolve();
|
||||
});
|
||||
|
||||
this.socket.emit('logout');
|
||||
|
||||
// Timeout si le serveur ne repond pas
|
||||
setTimeout(() => {
|
||||
if (this.socket) {
|
||||
this.socket.disconnect();
|
||||
}
|
||||
this._state = 'disconnected';
|
||||
resolve();
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deconnexion brute (sans logoff IPBX).
|
||||
*/
|
||||
disconnect() {
|
||||
if (this.socket) {
|
||||
this.socket.disconnect();
|
||||
}
|
||||
this._state = 'disconnected';
|
||||
}
|
||||
|
||||
/**
|
||||
* Ecouter un evenement serveur.
|
||||
*/
|
||||
on(event, handler) {
|
||||
this._eventHandlers.set(event, handler);
|
||||
if (this.socket) {
|
||||
this.socket.on(event, handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retirer un handler d'evenement.
|
||||
*/
|
||||
off(event) {
|
||||
this._eventHandlers.delete(event);
|
||||
if (this.socket) {
|
||||
this.socket.off(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Etat de la connexion.
|
||||
*/
|
||||
get state() {
|
||||
return this._state;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SocketIOAdapter;
|
||||
Reference in New Issue
Block a user