diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..df6b737 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Electron: Main", + "cwd": "${workspaceFolder}", + "port": 9222, + "request": "attach", + "sourceMaps": true, + "type": "node", + "timeout": 1000000 + }, + { + "name": "Electron: Renderer", + "port": 9223, + "request": "attach", + "sourceMaps": true, + "type": "chrome", + "webRoot": "${workspaceFolder}" + }, + { + "name": "Electron: Worker", + "cwd": "${workspaceFolder}", + "port": 9224, + "request": "attach", + "sourceMaps": true, + "type": "node", + "timeout": 1000000 + } + ], + "compounds": [ + { + "name": "Electron: All", + "configurations": ["Electron: Main", "Electron: Renderer"] + } + ] +} \ No newline at end of file diff --git a/src/common/interfaces.ts b/src/common/interfaces.ts new file mode 100644 index 0000000..2a72c60 --- /dev/null +++ b/src/common/interfaces.ts @@ -0,0 +1,20 @@ +import { Socket } from 'net'; + +export interface ClientHost { + enabled: boolean; + host: string; + port: number; + clients?: Socket[]; +} + +export interface ClientMessage { + enabled: boolean; + format: 'hex' | 'ascii' | 'binary'; + message: string; + name: string; +} + +export interface ServerPort { + enabled: boolean; + port: number; +} diff --git a/src/main/libs/Sender.js b/src/main/libs/Sender.js deleted file mode 100644 index dd8c96c..0000000 --- a/src/main/libs/Sender.js +++ /dev/null @@ -1,408 +0,0 @@ -'use strict'; - -const net = require('net'); -const fs = require('fs'); - -class Sender { - /** - *Creates an instance of Sender. - * @param {*} process Processo dove inviare i log - * @memberof Sender - */ - constructor (process) { - this.process = process; - this.closeOnEcho = true; - this.persistentConnection = false; - this.nMsgs = 0; - this.tMin = 0; - this.tMax = 0; - this.nClients = 1; - this.trace = false; - this.alertReset = false; - this.hexMsg = false; - this.nConnected = 0; - this.nClosed = 0; - this.nTryConnect = 0; - this.nReceived = []; - this.nSent = 0; - this.timeStart = new Date(); - this.hosts = []; - this.messages = []; - this.nHostClients = []; - this.nHostBytes = []; - this.nHostMsgs = []; - this.storagePath = ''; - } - - /** - * Setta gli hosts - * - * @param {*} hosts - * @memberof Sender - */ - setHosts (hosts) { - this.hosts = hosts; - } - - /** - * Setta i parametri del messaggio - * - * @param {*} params - * @memberof Sender - */ - setParams (params) { - this.closeOnEcho = params.closeOnEcho; - this.persistentConnection = params.persistentConnection; - this.nMsgs = params.nMsgs; - this.tMin = params.tMin; - this.tMax = params.tMax; - this.nClients = params.nClients; - this.trace = params.trace; - this.alertReset = params.alertReset; - this.loop = params.loop; - } - - /** - * Setta il percorso della cartella storage - * - * @param {string} storagePath - * @memberof Sender - */ - setStoragePath (storagePath) { - this.storagePath = storagePath; - } - - /** - * Carica i messaggi in memoria - * - * @memberof Sender - */ - loadMessages () { - let self = this; - if (self.trace) this.sendLog('Lettura dei messaggi'); - let messages = fs.readFileSync(`${self.storagePath}/storage/clientMessages.json`); - messages = JSON.parse(messages); - this.messages = messages.filter((message) => { - return message.enabled === true; - }); - if (self.trace) this.sendLog(`Messaggi caricari: ${this.messages.length}`); - } - - /** - * Invia i log al render process - * - * @param {string} message Messaggio del log - * @param {string} [color=''] Colore del log (green, yellow, red) - * @memberof Sender - */ - sendLog (message, color = '') { - let log = { - event: 'log', - content: { message, color } - }; - this.process.send(log); - } - - /** Restituisce un messaggio casuale */ - randMsg () { - let self = this; - if (self.messages.length > 0) { - let index = Math.floor((Math.random() * (self.messages.length))); - let msg; - - switch (self.messages[index].format) { - case 'ascii': - msg = Buffer.from(self.messages[index].message, 'ascii'); - break; - case 'hex': - msg = Buffer.from(self.messages[index].message.replace(/\s|0x/g, ''), 'hex'); - break; - case 'binary': - msg = Buffer.from(self.messages[index].message.replace(/\s/g, ''), 'binary'); - break; - } - - return msg; - } - else return 'Nessun messaggio specificato'; - }; - - /** - * Istanzia i client e invia i messaggi - * - * @param {*} params Parametri dei client - * @memberof Sender - */ - startFullTest (callback) { - let self = this; - - /** Carica in memoria i messaggi */ - self.loadMessages(); - - /** Applica uno sleep */ - function delay () { - let wait = Math.floor((Math.random() * self.tMax) + self.tMin); - return new Promise(resolve => setTimeout(resolve, wait)); - } - - for (let x = 0; x < self.hosts.length; x++) { // hosts for - let params = self.hosts[x]; - self.hosts[x].clients = []; - self.nHostClients[x] = 0; - self.nHostMsgs[x] = self.nHostMsgs[x] === undefined ? 0 : self.nHostMsgs[x]; - self.nHostBytes[x] = self.nHostBytes[x] === undefined ? 0 : self.nHostBytes[x]; - self.nReceived[x] = self.nReceived[x] === undefined ? 0 : self.nReceived[x]; - - for (let i = 0; i < self.nClients; i++) { // clients for - self.hosts[x].clients[i] = new net.Socket(); - let client = self.hosts[x].clients[i]; - let clientId = i + 1; - - try { - client.connect(params, () => { - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} aperto`); - self.nHostClients[x]++; - - (async () => { - for (let i = 0; i < self.nMsgs; i++) { // msg for - await delay(); - - let msg = self.randMsg(); - - client.write(msg, err => { - if (err) - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\nErrore messaggio: ${err}`, 'red'); - else { - self.nSent++; - self.nHostMsgs[x]++; - self.nHostBytes[x] += msg.length; - } - }); - - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} messaggio #${i + 1}`); - if (i + 1 === self.nMsgs && !self.closeOnEcho && !self.persistentConnection) client.end(); - }// <- msg for - })(); - }); - } - catch (err) { - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); - } - - client.on('connect', err => { - self.nTryConnect++; - if (err) - self.sendLog(`Errore connessione #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); - else - self.nConnected++; - // if (self.nConnected === (self.nClients * self.hosts.length)) self.getReport(); - }); - - client.on('data', data => { - self.nReceived[x]++; - if (self.closeOnEcho) - client.end(); - - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} risposta: ${data}`); - }); - - client.on('close', () => { - self.nClosed++; - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} chiuso`); - - // Misura tempo esecuzione - if (self.nClosed === self.nTryConnect) { - if (!self.loop) self.getConsoleReports(); - callback(); - } - }); - - client.on('error', err => { - switch (err.code) { - case 'ECONNRESET': - if (self.alertReset) - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'yellow'); - - break; - default: - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); - } - }); - }// <- clients for - }// <- hosts for - } - - /** - * Connette i client per il test a step - * - * @param {*} callback - * @memberof Sender - */ - connectClients (callback) { - let self = this; - for (let x = 0; x < self.hosts.length; x++) { // hosts for - let params = self.hosts[x]; - self.hosts[x].clients = []; - self.nHostMsgs[x] = 0; - self.nHostBytes[x] = 0; - self.nHostClients[x] = 0; - self.nReceived[x] = 0; - - for (let i = 0; i < self.nClients; i++) { // clients for - self.hosts[x].clients[i] = new net.Socket(); - let client = self.hosts[x].clients[i]; - let clientId = i + 1; - - try { - client.connect(params, () => { - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} aperto`); - self.nHostClients[x]++; - }); - } - catch (err) { - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); - } - - client.on('connect', err => { - self.nTryConnect++; - if (err) - self.sendLog(`Errore connessione #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); - else - self.nConnected++; - // if (self.nConnected === (self.nClients * self.hosts.length)) self.getReport(); - - if ((self.nClients * self.hosts.length) === self.nTryConnect) callback(); - }); - - client.on('data', data => { - self.nReceived[x]++; - if (self.closeOnEcho) - client.end(); - - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} risposta: ${data}`); - }); - - client.on('close', () => { - self.nClosed++; - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} chiuso`); - }); - - client.on('error', err => { - switch (err.code) { - case 'ECONNRESET': - if (self.alertReset) - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'yellow'); - - break; - default: - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); - } - }); - }// <- clients for - }// <- hosts for - } - - /** - * Invia i messaggi nella modalità a step - * - * @param {*} callback - * @memberof Sender - */ - sendMessages (callback) { - let self = this; - - /** Carica in memoria i messaggi */ - self.loadMessages(); - - self.nSent = 0; - - /** Applica uno sleep */ - function delay () { - let wait = Math.floor((Math.random() * self.tMax) + self.tMin); - return new Promise(resolve => setTimeout(resolve, wait)); - } - - for (let x = 0; x < self.hosts.length; x++) { // hosts for - for (let i = 0; i < self.hosts[x].clients.length; i++) { // clients for - let client = self.hosts[x].clients[i]; - let params = self.hosts[x]; - let clientId = i + 1; - - (async () => { - for (let i = 0; i < self.nMsgs; i++) { // msg for - await delay(); - - let msg = self.randMsg(); - - client.write(msg, err => { - if (err) - self.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\nErrore messaggio: ${err}`, 'red'); - else { - self.nSent++; - self.nHostMsgs[x]++; - self.nHostBytes[x] += msg.length; - if ((self.nMsgs * self.hosts.length * self.nClients) === self.nSent) callback(); - } - }); - - if (self.trace) self.sendLog(`Socket #${clientId} su ${params.host}:${params.port} messaggio #${i + 1}`); - }// <- msg for - })(); - }// <- clients for - }// <- hosts for - } - - /** Genera il report su console */ - getConsoleReports () { - let self = this; - let end = new Date() - self.timeStart; - let report = `Durata del test: ${end}ms`; - - self.sendLog(report, 'green'); - } - - stopClients (callback) { - let self = this; - for (let x = 0; x < self.hosts.length; x++) { - for (let i = 0; i < self.hosts[x].clients.length; i++) - self.hosts[x].clients[i].end(); - } - - self.getConsoleReports(); - callback(); - } - - getReports () { - let self = this; - let reportList = []; - for (let i = 0; i < self.hosts.length; i++) { - let report = { - host: `${self.hosts[i].host}:${self.hosts[i].port}`, - sockets: self.nHostClients[i], - data: self.nHostBytes[i], - messages: self.nHostMsgs[i], - received: self.nReceived[i] - }; - reportList.push(report); - - if ((i + 1) === self.hosts.length) { - let rep = { - event: 'report', - content: reportList - }; - self.process.send(rep); - } - } - } - - resetReports () { - let self = this; - for (let i = 0; i < self.hosts.length; i++) { - self.nHostBytes[i] = 0; - self.nHostMsgs[i] = 0; - self.nHostClients[i] = 0; - self.nReceived[i] = 0; - } - } -} -module.exports = Sender; diff --git a/src/main/libs/Sender.ts b/src/main/libs/Sender.ts new file mode 100644 index 0000000..aac1e80 --- /dev/null +++ b/src/main/libs/Sender.ts @@ -0,0 +1,420 @@ +import * as net from 'net'; +import { ClientHost, ClientMessage } from 'common/interfaces'; +import * as ElectronStore from 'electron-store'; +const persistentStore = new ElectronStore({ name: 'client' }); + +class Sender { + process: NodeJS.Process; + closeOnEcho: boolean; + persistentConnection: boolean; + nMsgs: number; + tMin: number; + tMax: number; + nClients: number; + trace: boolean; + alertReset: boolean; + hexMsg: boolean; + nConnected: number; + nClosed: number; + nTryConnect: number; + nReceived: any[]; + nSent: number; + timeStart: Date; + hosts: ClientHost[]; + messages: ClientMessage[]; + nHostClients: any[]; + nHostBytes: any[]; + nHostMsgs: any[]; + storagePath: string; + loop: boolean; + + /** + *Creates an instance of Sender. + * @param {*} process Processo dove inviare i log + * @memberof Sender + */ + constructor (process: NodeJS.Process) { + this.process = process; + this.closeOnEcho = true; + this.persistentConnection = false; + this.nMsgs = 0; + this.tMin = 0; + this.tMax = 0; + this.nClients = 1; + this.trace = false; + this.alertReset = false; + this.hexMsg = false; + this.nConnected = 0; + this.nClosed = 0; + this.nTryConnect = 0; + this.nReceived = []; + this.nSent = 0; + this.timeStart = new Date(); + this.hosts = []; + this.messages = []; + this.nHostClients = []; + this.nHostBytes = []; + this.nHostMsgs = []; + this.storagePath = ''; + } + + /** + * Setta gli hosts + * + * @param {*} hosts + * @memberof Sender + */ + setHosts (hosts: ClientHost[]) { + this.hosts = hosts; + } + + /** + * Setta i parametri del messaggio + * + * @param {*} params + * @memberof Sender + */ + setParams (params: any) { + this.closeOnEcho = params.closeOnEcho; + this.persistentConnection = params.persistentConnection; + this.nMsgs = params.nMsgs; + this.tMin = params.tMin; + this.tMax = params.tMax; + this.nClients = params.nClients; + this.trace = params.trace; + this.alertReset = params.alertReset; + this.loop = params.loop; + } + + /** + * Setta il percorso della cartella storage + * + * @param {string} storagePath + * @memberof Sender + */ + setStoragePath (storagePath: string) { + this.storagePath = storagePath; + } + + /** + * Carica i messaggi in memoria + * + * @memberof Sender + */ + loadMessages () { + if (this.trace) this.sendLog('Lettura dei messaggi'); + const messages = persistentStore.get('messages', []) as ClientMessage[]; + this.messages = messages.filter((message) => { + return message.enabled === true; + }); + if (this.trace) this.sendLog(`Messaggi caricari: ${this.messages.length}`); + } + + /** + * Invia i log al render process + * + * @param {string} message Messaggio del log + * @param {string} [color=''] Colore del log (green, yellow, red) + * @memberof Sender + */ + sendLog (message: string, color = '') { + const log = { + event: 'log', + content: { message, color } + }; + this.process.send(log); + } + + /** Restituisce un messaggio casuale */ + randMsg () { + if (this.messages.length > 0) { + const index = Math.floor((Math.random() * (this.messages.length))); + let msg; + + switch (this.messages[index].format) { + case 'ascii': + msg = Buffer.from(this.messages[index].message, 'ascii'); + break; + case 'hex': + msg = Buffer.from(this.messages[index].message.replace(/\s|0x/g, ''), 'hex'); + break; + case 'binary': + msg = Buffer.from(this.messages[index].message.replace(/\s/g, ''), 'binary'); + break; + } + + return msg; + } + else return 'Nessun messaggio specificato'; + } + + /** + * Istanzia i client e invia i messaggi + * + * @param {*} params Parametri dei client + * @memberof Sender + */ + startFullTest (callback: () => void) { + /** Carica in memoria i messaggi */ + this.loadMessages(); + + /** Applica uno sleep */ + const delay = () => { + const wait = Math.floor((Math.random() * this.tMax) + this.tMin); + return new Promise(resolve => setTimeout(resolve, wait)); + }; + + for (let x = 0; x < this.hosts.length; x++) { // hosts for + const params = this.hosts[x]; + this.hosts[x].clients = []; + this.nHostClients[x] = 0; + this.nHostMsgs[x] = this.nHostMsgs[x] === undefined ? 0 : this.nHostMsgs[x]; + this.nHostBytes[x] = this.nHostBytes[x] === undefined ? 0 : this.nHostBytes[x]; + this.nReceived[x] = this.nReceived[x] === undefined ? 0 : this.nReceived[x]; + + for (let i = 0; i < this.nClients; i++) { // clients for + this.hosts[x].clients[i] = new net.Socket(); + const client = this.hosts[x].clients[i]; + const clientId = i + 1; + + try { + client.connect(params, () => { + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} aperto`); + this.nHostClients[x]++; + + (async () => { + for (let i = 0; i < this.nMsgs; i++) { // msg for + await delay(); + + const msg = this.randMsg(); + + client.write(msg, (err: any) => { + if (err) + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\nErrore messaggio: ${err}`, 'red'); + else { + this.nSent++; + this.nHostMsgs[x]++; + this.nHostBytes[x] += msg.length; + } + }); + + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} messaggio #${i + 1}`); + if (i + 1 === this.nMsgs && !this.closeOnEcho && !this.persistentConnection) client.end(); + }// <- msg for + })(); + }); + } + catch (err) { + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); + } + + client.on('connect', (err: any) => { + this.nTryConnect++; + if (err) + this.sendLog(`Errore connessione #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); + else + this.nConnected++; + // if (this.nConnected === (this.nClients * this.hosts.length)) this.getReport(); + }); + + client.on('data', (data: Buffer) => { + this.nReceived[x]++; + if (this.closeOnEcho) + client.end(); + + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} risposta: ${data}`); + }); + + client.on('close', () => { + this.nClosed++; + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} chiuso`); + + // Misura tempo esecuzione + if (this.nClosed === this.nTryConnect) { + if (!this.loop) this.getConsoleReports(); + callback(); + } + }); + + client.on('error', (err: any) => { + switch (err.code) { + case 'ECONNRESET': + if (this.alertReset) + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'yellow'); + + break; + default: + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); + } + }); + }// <- clients for + }// <- hosts for + } + + /** + * Connette i client per il test a step + * + * @param {*} callback + * @memberof Sender + */ + connectClients (callback: () => void) { + for (let x = 0; x < this.hosts.length; x++) { // hosts for + const params = this.hosts[x]; + this.hosts[x].clients = []; + this.nHostMsgs[x] = 0; + this.nHostBytes[x] = 0; + this.nHostClients[x] = 0; + this.nReceived[x] = 0; + + for (let i = 0; i < this.nClients; i++) { // clients for + this.hosts[x].clients[i] = new net.Socket(); + const client = this.hosts[x].clients[i]; + const clientId = i + 1; + + try { + client.connect(params, () => { + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} aperto`); + this.nHostClients[x]++; + }); + } + catch (err) { + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); + } + + client.on('connect', (err: any) => { + this.nTryConnect++; + if (err) + this.sendLog(`Errore connessione #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); + else + this.nConnected++; + // if (this.nConnected === (this.nClients * this.hosts.length)) this.getReport(); + + if ((this.nClients * this.hosts.length) === this.nTryConnect) callback(); + }); + + client.on('data', (data: Buffer) => { + this.nReceived[x]++; + if (this.closeOnEcho) + client.end(); + + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} risposta: ${data}`); + }); + + client.on('close', () => { + this.nClosed++; + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} chiuso`); + }); + + client.on('error', (err: any) => { + switch (err.code) { + case 'ECONNRESET': + if (this.alertReset) + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'yellow'); + + break; + default: + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red'); + } + }); + }// <- clients for + }// <- hosts for + } + + /** + * Invia i messaggi nella modalità a step + * + * @param {*} callback + * @memberof Sender + */ + sendMessages (callback: () => void) { + /** Carica in memoria i messaggi */ + this.loadMessages(); + + this.nSent = 0; + + /** Applica uno sleep */ + function delay () { + const wait = Math.floor((Math.random() * this.tMax) + this.tMin); + return new Promise(resolve => setTimeout(resolve, wait)); + } + + for (let x = 0; x < this.hosts.length; x++) { // hosts for + for (let i = 0; i < this.hosts[x].clients.length; i++) { // clients for + const client = this.hosts[x].clients[i]; + const params = this.hosts[x]; + const clientId = i + 1; + + (async () => { + for (let i = 0; i < this.nMsgs; i++) { // msg for + await delay(); + + const msg = this.randMsg(); + + client.write(msg, (err: any) => { + if (err) + this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\nErrore messaggio: ${err}`, 'red'); + else { + this.nSent++; + this.nHostMsgs[x]++; + this.nHostBytes[x] += msg.length; + if ((this.nMsgs * this.hosts.length * this.nClients) === this.nSent) callback(); + } + }); + + if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} messaggio #${i + 1}`); + }// <- msg for + })(); + }// <- clients for + }// <- hosts for + } + + /** Genera il report su console */ + getConsoleReports () { + const end = new Date().getMilliseconds() - this.timeStart.getMilliseconds(); + const report = `Durata del test: ${end}ms`; + + this.sendLog(report, 'green'); + } + + stopClients (callback: () => void) { + for (let x = 0; x < this.hosts.length; x++) { + for (let i = 0; i < this.hosts[x].clients.length; i++) + this.hosts[x].clients[i].end(); + } + + this.getConsoleReports(); + callback(); + } + + getReports () { + const reportList = []; + for (let i = 0; i < this.hosts.length; i++) { + const report = { + host: `${this.hosts[i].host}:${this.hosts[i].port}`, + sockets: this.nHostClients[i], + data: this.nHostBytes[i], + messages: this.nHostMsgs[i], + received: this.nReceived[i] + }; + reportList.push(report); + + if ((i + 1) === this.hosts.length) { + const rep = { + event: 'report', + content: reportList + }; + this.process.send(rep); + } + } + } + + resetReports () { + for (let i = 0; i < this.hosts.length; i++) { + this.nHostBytes[i] = 0; + this.nHostMsgs[i] = 0; + this.nHostClients[i] = 0; + this.nReceived[i] = 0; + } + } +} +export { Sender }; diff --git a/src/main/libs/Server.js b/src/main/libs/Server.js deleted file mode 100644 index b1d83cb..0000000 --- a/src/main/libs/Server.js +++ /dev/null @@ -1,143 +0,0 @@ -'use strict'; - -const net = require('net'); - -class Server { - constructor (process) { - this.process = process; - this.trace = false; - this.echo = false; - this.alertReset = false; - this.ports = []; - this.server = []; - this.nBytes = []; - this.nMsgs = []; - } - - /** - * Setta le porte - * - * @param {*} ports - * @memberof Server - */ - setPorts (ports) { - this.ports = ports; - } - - /** - * Invia i log al render process - * - * @param {string} message Messaggio del log - * @param {string} [color=''] Colore del log (green, yellow, red) - * @memberof Server - */ - sendLog (message, color = '') { - let log = { - event: 'log', - content: { message, color } - }; - this.process.send(log); - } - - startServer (params) { - let self = this; - - self.trace = params.trace; - self.echo = params.echo; - self.alertReset = params.alertReset; - - for (let i = 0; i < self.ports.length; i++) { - let port = self.ports[i].port; - - self.server[i] = net.createServer(); - self.nBytes[i] = 0; - self.nMsgs[i] = 0; - - self.server[i].on('connection', socket => { - if (self.trace) self.sendLog(`Client connesso su porta ${port}`); - - socket.on('data', msg => { - let msgString = msg.toString(); - if (self.echo) socket.write(msg); - self.nBytes[i] += msg.length; - self.nMsgs[i]++; - - if (self.trace) self.sendLog(`Messaggio ricevuto su porta ${port}: ${msgString}`); - });// <- socket data - - socket.on('end', () => { - if (self.trace) self.sendLog(`Client disconnesso su porta ${port}`); - }); - - socket.on('error', (err) => { - switch (err.code) { - case 'ECONNRESET': - if (self.alertReset) - self.sendLog(`Errore client su porta ${port}: \n${err}`, 'yellow'); - else - if (self.trace) self.sendLog(`Client disconnesso su porta ${port}`); - break; - default: - self.sendLog(`Errore client su porta ${port}: \n${err}`, 'red'); - } - }); - });// <- server - - self.server[i].on('error', err => { - self.sendLog(`Errore server su porta ${port}: \n${err}`, 'red'); - }); - - self.server[i].listen(port, () => { - self.sendLog(`In ascolto sulla porta ${port}`); - }); - } - } - - stopServer (callback) { - let self = this; - (async () => { - for (let i = 0; i < self.server.length; i++) { - await self.server[i].close(function () { - self.server[i].unref(); - }); - } - callback(); - })(); - } - - getReports () { - let self = this; - let reportList = []; - for (let i = 0; i < self.server.length; i++) { - let report = { - port: self.server[i].address().port, - sockets: null, - data: self.nBytes[i], - messages: self.nMsgs[i] - }; - - self.server[i].getConnections((err, nSockets) => { - if (err) self.sendLog(`Errore report: \n${err}`, 'red'); - report.sockets = nSockets; - reportList.push(report); - - if ((i + 1) === self.server.length) { - let rep = { - event: 'report', - content: reportList - }; - self.process.send(rep); - } - }); - } - } - - resetReports () { - let self = this; - for (let i = 0; i < self.server.length; i++) { - self.nBytes[i] = 0; - self.nMsgs[i] = 0; - } - } -} -module.exports = Server; diff --git a/src/main/libs/Server.ts b/src/main/libs/Server.ts new file mode 100644 index 0000000..bba2d3a --- /dev/null +++ b/src/main/libs/Server.ts @@ -0,0 +1,146 @@ +import { ServerPort } from 'common/interfaces'; +import * as net from 'net'; + +class Server { + process: NodeJS.Process; + trace: boolean; + echo: boolean; + alertReset: boolean; + ports: ServerPort[]; + server: any[]; + nBytes: any[]; + nMsgs: any[]; + + constructor (process: NodeJS.Process) { + this.process = process; + this.trace = false; + this.echo = false; + this.alertReset = false; + this.ports = []; + this.server = []; + this.nBytes = []; + this.nMsgs = []; + } + + /** + * Setta le porte + * + * @param {*} ports + * @memberof Server + */ + setPorts (ports: any) { + this.ports = ports; + } + + /** + * Invia i log al render process + * + * @param {string} message Messaggio del log + * @param {string} [color=''] Colore del log (green, yellow, red) + * @memberof Server + */ + sendLog (message: string, color = '') { + const log = { + event: 'log', + content: { message, color } + }; + this.process.send(log); + } + + startServer (params: any) { + this.trace = params.trace; + this.echo = params.echo; + this.alertReset = params.alertReset; + + for (let i = 0; i < this.ports.length; i++) { + const port = this.ports[i].port; + + this.server[i] = net.createServer(); + this.nBytes[i] = 0; + this.nMsgs[i] = 0; + + this.server[i].on('connection', (socket: any) => { + if (this.trace) this.sendLog(`Client connesso su porta ${port}`); + + socket.on('data', (msg: any) => { + const msgString = msg.toString(); + if (this.echo) socket.write(msg); + this.nBytes[i] += msg.length; + this.nMsgs[i]++; + + if (this.trace) this.sendLog(`Messaggio ricevuto su porta ${port}: ${msgString}`); + });// <- socket data + + socket.on('end', () => { + if (this.trace) this.sendLog(`Client disconnesso su porta ${port}`); + }); + + socket.on('error', (err: any) => { + switch (err.code) { + case 'ECONNRESET': + if (this.alertReset) + this.sendLog(`Errore client su porta ${port}: \n${err}`, 'yellow'); + else + if (this.trace) this.sendLog(`Client disconnesso su porta ${port}`); + break; + default: + this.sendLog(`Errore client su porta ${port}: \n${err}`, 'red'); + } + }); + });// <- server + + this.server[i].on('error', (err: any) => { + this.sendLog(`Errore server su porta ${port}: \n${err}`, 'red'); + }); + + this.server[i].listen(port, () => { + this.sendLog(`In ascolto sulla porta ${port}`); + }); + } + } + + stopServer (callback: () => void) { + (async () => { + for (let i = 0; i < this.server.length; i++) { + await this.server[i].close(function () { + this.server[i].unref(); + }); + } + callback(); + })(); + } + + getReports () { + const reportList: any[] = []; + for (let i = 0; i < this.server.length; i++) { + const report = { + port: this.server[i].address().port, + sockets: null as any, + data: this.nBytes[i], + messages: this.nMsgs[i] + }; + + this.server[i].getConnections((err: any, nSockets: any) => { + if (err) this.sendLog(`Errore report: \n${err}`, 'red'); + report.sockets = nSockets; + reportList.push(report); + + if ((i + 1) === this.server.length) { + const rep = { + event: 'report', + content: reportList + }; + this.process.send(rep); + } + }); + } + } + + resetReports () { + for (let i = 0; i < this.server.length; i++) { + this.nBytes[i] = 0; + this.nMsgs[i] = 0; + } + } +} +export { Server }; diff --git a/src/main/main.ts b/src/main/main.ts index 1e648ee..b005f6b 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -24,7 +24,7 @@ let mainWindow: BrowserWindow; let mainWindowState: windowStateKeeper.State; async function createMainWindow () { - const icon = require('../renderer/assets/icons/icon.png'); + // const icon = require('../renderer/assets/icons/icon.png'); const window = new BrowserWindow({ width: mainWindowState.width, height: mainWindowState.height, @@ -34,7 +34,7 @@ async function createMainWindow () { minHeight: 500, show: !isWindows, title: 'Mizar TCP Tester', - icon: nativeImage.createFromDataURL(icon.default), + // icon: nativeImage.createFromDataURL(icon.default), webPreferences: { nodeIntegration: true, contextIsolation: false, @@ -150,7 +150,9 @@ else { let clientProcess: ChildProcess; ipcMain.on('startTest', (event, { params, hosts }) => { event.sender.send('clientLog', { message: 'Test avviato', color: '' }); - // clientProcess = fork(`${appRoot}/src/forks/clientProcess.js`); + clientProcess = fork(isDevelopment ? './dist/clientProcess.js' : path.resolve(__dirname, './clientProcess.js'), [], { + execArgv: isDevelopment ? ['--inspect=9225'] : undefined + }); const startEvent = params.stepTest ? 'startStep' : 'start'; @@ -162,7 +164,7 @@ ipcMain.on('startTest', (event, { params, hosts }) => { }; clientProcess.send(testParams); - clientProcess.on('message', (message: any) => { + clientProcess.on('message', (message: {event: string; content: string}) => { if (!mainWindow) return; switch (message.event) { case 'log': diff --git a/src/main/workers/clientProcess.js b/src/main/workers/clientProcess.ts similarity index 70% rename from src/main/workers/clientProcess.js rename to src/main/workers/clientProcess.ts index 2592c5e..b72a08f 100644 --- a/src/main/workers/clientProcess.js +++ b/src/main/workers/clientProcess.ts @@ -1,8 +1,9 @@ -const Sender = require('../classes/Sender'); -Sends = new Sender(process); -let interval = null; +import { Sender } from '../libs/Sender'; -process.on('message', message => { +const Sends = new Sender(process); +let clientTimer: NodeJS.Timer; + +process.on('message', (message: any) => { switch (message.event) { case 'start': Sends.setHosts(message.hosts); @@ -10,19 +11,19 @@ process.on('message', message => { Sends.setStoragePath(message.storagePath); Sends.startFullTest(() => { - let response = { + const response = { event: 'finish', content: 'Test concluso' }; process.send(response); - if (interval !== null) clearInterval(interval); + if (clientTimer !== undefined) clearInterval(clientTimer); Sends.getReports(); }); Sends.getReports(); - if (interval === null) { - interval = setInterval(() => { + if (clientTimer === undefined) { + clientTimer = setInterval(() => { Sends.getReports(); }, 200); } @@ -33,7 +34,7 @@ process.on('message', message => { Sends.setStoragePath(message.storagePath); Sends.connectClients(() => { - let response = { + const response = { event: 'log', content: { message: 'Client connessi', color: '' } }; @@ -42,15 +43,15 @@ process.on('message', message => { Sends.getReports(); - if (interval === null) { - interval = setInterval(() => { + if (clientTimer === undefined) { + clientTimer = setInterval(() => { Sends.getReports(); }, 200); } break; case 'sendStep': Sends.sendMessages(() => { - let response = { + const response = { event: 'log', content: { message: 'Messaggi inviati', color: '' } }; @@ -59,7 +60,7 @@ process.on('message', message => { break; case 'stop': Sends.stopClients(() => { - if (interval !== null) clearInterval(interval); + if (clientTimer !== undefined) clearInterval(clientTimer); Sends.getReports(); process.exit(); }); diff --git a/src/main/workers/exporter.ts b/src/main/workers/exporter.ts deleted file mode 100644 index 9f03826..0000000 --- a/src/main/workers/exporter.ts +++ /dev/null @@ -1,69 +0,0 @@ -import * as antares from 'common/interfaces/antares'; -import * as fs from 'fs'; -import { MySQLClient } from '../libs/clients/MySQLClient'; -import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; -import { ClientsFactory } from '../libs/ClientsFactory'; -import MysqlExporter from '../libs/exporters/sql/MysqlExporter'; -import PostgreSQLExporter from '../libs/exporters/sql/PostgreSQLExporter'; -let exporter: antares.Exporter; - -process.on('message', async ({ type, client, tables, options }) => { - if (type === 'init') { - const connection = await ClientsFactory.getClient({ - client: client.name, - params: client.config, - poolSize: 5 - }) as MySQLClient | PostgreSQLClient; - await connection.connect(); - - switch (client.name) { - case 'mysql': - case 'maria': - exporter = new MysqlExporter(connection as MySQLClient, tables, options); - break; - case 'pg': - exporter = new PostgreSQLExporter(connection as PostgreSQLClient, tables, options); - break; - default: - process.send({ - type: 'error', - payload: `"${client.name}" exporter not aviable` - }); - return; - } - - exporter.once('error', err => { - console.error(err); - process.send({ - type: 'error', - payload: err.toString() - }); - }); - - exporter.once('end', () => { - process.send({ - type: 'end', - payload: { cancelled: exporter.isCancelled } - }); - connection.destroy(); - }); - - exporter.once('cancel', () => { - fs.unlinkSync(exporter.outputFile); - process.send({ type: 'cancel' }); - }); - - exporter.on('progress', state => { - process.send({ - type: 'export-progress', - payload: state - }); - }); - - exporter.run(); - } - else if (type === 'cancel') - exporter.cancel(); -}); - -process.on('beforeExit', console.log); diff --git a/src/main/workers/importer.ts b/src/main/workers/importer.ts deleted file mode 100644 index 47500af..0000000 --- a/src/main/workers/importer.ts +++ /dev/null @@ -1,111 +0,0 @@ -import * as antares from 'common/interfaces/antares'; -import * as pg from 'pg'; -import * as mysql from 'mysql2'; -import { MySQLClient } from '../libs/clients/MySQLClient'; -import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; -import { ClientsFactory } from '../libs/ClientsFactory'; -import MySQLImporter from '../libs/importers/sql/MySQLlImporter'; -import PostgreSQLImporter from '../libs/importers/sql/PostgreSQLImporter'; -import SSHConfig from 'ssh2-promise/lib/sshConfig'; -import { ImportOptions } from 'common/interfaces/importer'; -let importer: antares.Importer; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -process.on('message', async ({ type, dbConfig, options }: { - type: string; - dbConfig: mysql.ConnectionOptions & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean } - | pg.ClientConfig & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean } - | { databasePath: string; readonly: boolean }; - options: ImportOptions; -}) => { - if (type === 'init') { - try { - const connection = await ClientsFactory.getClient({ - client: options.type, - params: { - ...dbConfig, - schema: options.schema - }, - poolSize: 1 - }) as MySQLClient | PostgreSQLClient; - - const pool = await connection.getConnectionPool(); - - switch (options.type) { - case 'mysql': - case 'maria': - importer = new MySQLImporter(pool as unknown as mysql.Pool, options); - break; - case 'pg': - importer = new PostgreSQLImporter(pool as unknown as pg.PoolClient, options); - break; - default: - process.send({ - type: 'error', - payload: `"${options.type}" importer not aviable` - }); - return; - } - - importer.once('error', err => { - console.error(err); - process.send({ - type: 'error', - payload: err.toString() - }); - }); - - importer.once('end', () => { - process.send({ - type: 'end', - payload: { cancelled: importer.isCancelled } - }); - }); - - importer.once('cancel', () => { - process.send({ type: 'cancel' }); - }); - - importer.on('progress', state => { - process.send({ - type: 'import-progress', - payload: state - }); - }); - - importer.on('query-error', state => { - process.send({ - type: 'query-error', - payload: state - }); - }); - - importer.run(); - } - catch (err) { - console.error(err); - process.send({ - type: 'error', - payload: err.toString() - }); - } - } - else if (type === 'cancel') - importer.cancel(); -}); - -process.on('uncaughtException', (err) => { - console.error(err); - process.send({ - type: 'error', - payload: err.toString() - }); -}); - -process.on('unhandledRejection', (err) => { - console.error(err); - process.send({ - type: 'error', - payload: err.toString() - }); -}); diff --git a/src/main/workers/serverProcess.js b/src/main/workers/serverProcess.ts similarity index 54% rename from src/main/workers/serverProcess.js rename to src/main/workers/serverProcess.ts index 5f1faeb..206b1ae 100644 --- a/src/main/workers/serverProcess.js +++ b/src/main/workers/serverProcess.ts @@ -1,22 +1,23 @@ -const Server = require('../classes/Server'); -myServer = new Server(process); -let interval = null; +import { Server } from '../libs/Server'; -process.on('message', message => { +const myServer = new Server(process); +let serverTimer: NodeJS.Timer; + +process.on('message', (message: {event: string; ports: string; params: any}) => { switch (message.event) { case 'start': myServer.setPorts(message.ports); myServer.startServer(message.params); - if (interval === null) { - interval = setInterval(() => { + if (serverTimer === undefined) { + serverTimer = setInterval(() => { myServer.getReports(); }, 200); } break; case 'stop': myServer.stopServer(() => { - if (interval !== null) clearInterval(interval); + if (serverTimer !== undefined) clearInterval(serverTimer); process.exit(); }); break; diff --git a/src/renderer/components/ClientTab.vue b/src/renderer/components/ClientTab.vue index 0509769..1f94cf3 100644 --- a/src/renderer/components/ClientTab.vue +++ b/src/renderer/components/ClientTab.vue @@ -231,7 +231,9 @@ import EditMessage from './ModalEditMessage.vue'; // import LoadConfig from './ModalLoadConfig.vue'; import ClientTabReports from './ClientTabReports.vue'; import { ipcRenderer } from 'electron'; -import { ClientHost, ClientMessage, useClientStore } from '@/stores/client'; +import { useClientStore } from '@/stores/client'; +import { unproxify } from '../libs/unproxify'; +import { ClientHost, ClientMessage } from 'common/interfaces'; const emit = defineEmits(['clientStatus']); @@ -299,7 +301,7 @@ const startTest = () => { return host.enabled === true; }) }; - ipcRenderer.send('startTest', obj); + ipcRenderer.send('startTest', unproxify(obj)); }; const sendMessages = () => { diff --git a/src/renderer/components/ServerTab.vue b/src/renderer/components/ServerTab.vue index 5154832..ad56dea 100644 --- a/src/renderer/components/ServerTab.vue +++ b/src/renderer/components/ServerTab.vue @@ -89,7 +89,9 @@ import Ports from './ServerTabPorts.vue'; import NewPort from './ModalNewPort.vue'; import SerterTabReports from './SerterTabReports.vue'; import { ipcRenderer } from 'electron'; -import { ServerPort, useServerStore } from '@/stores/server'; +import { useServerStore } from '@/stores/server'; +import { unproxify } from '../libs/unproxify'; +import { ServerPort } from 'common/interfaces'; const emit = defineEmits(['serverStatus']); const serverStore = useServerStore(); @@ -129,7 +131,7 @@ const startServer = (e: MouseEvent) => { return port.enabled === true; }) }; - ipcRenderer.send('startServer', obj); + ipcRenderer.send('startServer', unproxify(obj)); }; const stopServer = (e: MouseEvent) => { diff --git a/src/renderer/libs/unproxify.ts b/src/renderer/libs/unproxify.ts new file mode 100644 index 0000000..538cbcb --- /dev/null +++ b/src/renderer/libs/unproxify.ts @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { toRaw } from 'vue'; + +/** + * @param {*} val + * @param {Boolean} json converts the value in JSON object (default true) + */ +export function unproxify (val: any, json = true): any { + if (json)// JSON conversion + return JSON.parse(JSON.stringify(val)); + else if (Array.isArray(val))// If array + return toRaw(val); + else if (typeof val === 'object') { // If object + const result: any = {}; + for (const key in val) + result[key] = toRaw(val[key]); + + return result; + } + else + return toRaw(val); +} diff --git a/src/renderer/stores/client.ts b/src/renderer/stores/client.ts index 777bbf9..ac24405 100644 --- a/src/renderer/stores/client.ts +++ b/src/renderer/stores/client.ts @@ -1,20 +1,8 @@ import { defineStore } from 'pinia'; -import * as Store from 'electron-store'; +import * as ElectronStore from 'electron-store'; +import { ClientHost, ClientMessage } from 'common/interfaces'; -export interface ClientHost { - enabled: boolean; - host: string; - port: number; -} - -export interface ClientMessage { - enabled: boolean; - format: 'hex' | 'ascii'; - message: string; - name: string; -} - -const persistentStore = new Store({ name: 'client' }); +const persistentStore = new ElectronStore({ name: 'client' }); export const useClientStore = defineStore('client', { state: () => ({ diff --git a/src/renderer/stores/server.ts b/src/renderer/stores/server.ts index fc2f72c..fc5121a 100644 --- a/src/renderer/stores/server.ts +++ b/src/renderer/stores/server.ts @@ -1,12 +1,8 @@ import { defineStore } from 'pinia'; -import * as Store from 'electron-store'; +import * as ElectronStore from 'electron-store'; +import { ServerPort } from 'common/interfaces'; -export interface ServerPort { - enabled: boolean; - port: number; -} - -const persistentStore = new Store({ name: 'server' }); +const persistentStore = new ElectronStore({ name: 'server' }); export const useServerStore = defineStore('server', { state: () => ({ diff --git a/tsconfig.json b/tsconfig.json index 6fafaa9..abc6476 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "include": [ "./tests/**/*", "./src/main/**/*", - "./src/renderer/**/*" + "./src/renderer/**/*", + "./src/common/**/*" ], "compilerOptions": { "baseUrl": "./", @@ -19,6 +20,7 @@ "resolveJsonModule": true, "removeComments": true, "paths": { + "common/*": ["./src/common/*"], "@/*": ["./src/renderer/*"], } } diff --git a/webpack.main.config.js b/webpack.main.config.js index 54546f4..48a15f0 100644 --- a/webpack.main.config.js +++ b/webpack.main.config.js @@ -31,11 +31,6 @@ module.exports = { // Main extensions: ['.js', '.json', '.ts'], alias: { src: path.join(__dirname, 'src/') - }, - fallback: { - 'pg-native': false, - 'cpu-features': false, - cardinal: false } }, plugins: [ diff --git a/webpack.workers.config.js b/webpack.workers.config.js index c410072..cfab49b 100644 --- a/webpack.workers.config.js +++ b/webpack.workers.config.js @@ -13,8 +13,8 @@ const config = { mode: process.env.NODE_ENV, devtool: isDevMode ? 'eval-source-map' : false, entry: { - exporter: path.join(__dirname, './src/main/workers/exporter.ts'), - importer: path.join(__dirname, './src/main/workers/importer.ts') + clientProcess: path.join(__dirname, './src/main/workers/clientProcess.ts'), + serverProcess: path.join(__dirname, './src/main/workers/serverProcess.ts') }, target: 'node', output: { @@ -51,11 +51,6 @@ const config = { alias: { src: path.join(__dirname, 'src/'), common: path.resolve(__dirname, 'src/common') - }, - fallback: { - 'pg-native': false, - 'cpu-features': false, - cardinal: false } }, plugins: [