import yargs from 'yargs/yargs' import { hideBin } from 'yargs/helpers' import mysql from 'mysql2/promise' import { WebSocketServer } from 'ws' import fs from 'fs' import {RedisConnexion} from './redisConnexion.js' import {wssServer} from './wssServer.js' import {configHelper} from './configHelper.js' import express from 'express' import session from 'express-session' import connectMySQL from 'express-mysql-session' const argv = yargs(hideBin(process.argv)).command('wssGateway', 'Redis <=> Websocket message bus gateway', {}) .options({ 'argv.debug': { description: 'shows debug info', alias: 'd', type: 'boolean' }, }).help().version('1.1').argv const debug = Boolean(process.env.DEBUG) || argv.debug const MySQLStore = connectMySQL(session) const app = express(); app.set('trust proxy', 1) // trust first proxy (nginx), so we serve http to nginx, but we still behave as if we're in https app.use(express.json()) const mysqlCreds = { // host: '127.0.0.1', // port: 3306, socketPath: '/var/run/mysqld/mysqld.sock', user: 'p42', password: 'C3h=V9!r>Mvc>skxPf9?W2P3duJTk', database: 'p42', waitForConnections: true, connectionLimit: 10, queueLimit: 0 } const db = await mysql.createConnection(mysqlCreds) const sessionStore = new MySQLStore({ createDatabaseTable: false, clearExpired: true, schema: { tableName: 'p42_sessions', columnNames: { session_id: 'session_id', expires: 'expires', data: 'data' } } }, db) const sessionParser = session({ name: 'p42.api.sid', secret: 'qNhy555Y9vyxj?!3yaYA=aKfgk+Wy5eymNtP*?4i', store: sessionStore, resave: false, saveUninitialized: false, cookie: { maxAge: 1000 * 60 * 60 * 4, secure: true, //See trust proxy above sameSite: 'lax', }, } ) app.use(sessionParser) const cfgh = new configHelper({ localfile: './wssGatewayConfig.json', }) async function startRedis(wssGatewayConfig) { let REDIScnx = new RedisConnexion({ debug: debug, config: wssGatewayConfig, }); if(debug) console.log('Starting REDIS...'); await REDIScnx.redisLogin(); if(debug) console.log('REDIS Login OK'); await REDIScnx.redisChansStart(); if(debug) console.log('REDIS ChansStart OK'); return (REDIScnx); } cfgh.fetchConfig().then( async wssGatewayConfig => { if((!wssGatewayConfig) || (Object.keys(wssGatewayConfig).length<4)) { console.error('Cannot get a valid configuration ! Aaarrghhh...') process.exit() } let httpLib if(wssGatewayConfig.server.unsecure) httpLib = await import('http') else httpLib = await import('https') /////////////////////// Create & Start servers \\\\\\\\\\\\\\\\\\\\\\ console.log(`Debug mode : ${debug ? 'ON' : 'OFF'}`) let options if(!wssGatewayConfig.server.unsecure) { options = { key: fs.readFileSync(wssGatewayConfig.server.certKeyFile), cert: fs.readFileSync(wssGatewayConfig.server.certFile), }; } else options = {} const HTTPserver = httpLib.createServer(app) const wssServerOptions = { // server: HTTPserver, // path: wssGatewayConfig.server.listenPath, noServer: true } if(!wssGatewayConfig.server.unsecure) { wssServerOptions['key'] = fs.readFileSync(wssGatewayConfig.server.certKeyFile) wssServerOptions['cert'] = fs.readFileSync(wssGatewayConfig.server.certFile) } const WSSServer = new WebSocketServer(wssServerOptions); HTTPserver.on('upgrade', (req, socket, head) => { sessionParser(req, {}, () => { if (!req.session) { console.warn('No session, bye bye!') socket.destroy() return } WSSServer.handleUpgrade(req, socket, head, (ws) => { ws.session = req.session // direct access to Express session WSSServer.emit('connection', ws, req) }) }) }) // WSSServer.on('connection', (ws, req) => { // console.log('WS connected with session:', ws.session, ws.session.authenticated, ws.session.userInfos) // // modify session if you want // ws.session.views = (ws.session.views || 0) + 1 // ws.session.save() // ws.send(`You visited ${ws.session.views} times`) // }) HTTPserver.listen(wssGatewayConfig.server.listenPort, () => { console.log(`WS${wssGatewayConfig.server.unsecure ? '': 'S'} server created for ${wssGatewayConfig.server.listenHost}:${wssGatewayConfig.server.listenPort}`) }) startRedis(wssGatewayConfig).then((rediscnx) => { if(debug) console.log('Redis started & logged in !'); const wssSrv = new wssServer(cfgh, WSSServer, rediscnx, debug); }); })