2023-09-28 07:23:33 +02:00
|
|
|
const Rcon = require('rcon-srcds').default;
|
|
|
|
const { better_sqlite_client } = require('../db');
|
|
|
|
|
|
|
|
|
|
|
|
class RconManager {
|
|
|
|
constructor() {
|
|
|
|
this.rcons = {};
|
|
|
|
this.details = {};
|
|
|
|
this.init();
|
|
|
|
}
|
|
|
|
|
|
|
|
async init() {
|
|
|
|
try {
|
|
|
|
const servers_query = better_sqlite_client.prepare(`
|
|
|
|
SELECT * FROM servers
|
|
|
|
`);
|
|
|
|
const servers = servers_query.all();
|
|
|
|
console.log('All servers in DB:', servers);
|
|
|
|
for (const server of servers) {
|
|
|
|
const server_id = server.id.toString();
|
|
|
|
if (server_id in this.rcons) continue;
|
2023-10-04 09:29:23 +02:00
|
|
|
await this.connect(server_id, server);
|
2023-09-28 07:23:33 +02:00
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error connecting to MongoDB:', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 18:56:36 +02:00
|
|
|
async send_heartbeat(server_id, server) {
|
2023-10-04 09:29:23 +02:00
|
|
|
if (!this.rcons[server_id].connection.writable) {
|
|
|
|
console.log("Connection unwritable, reconnecting...")
|
|
|
|
await this.disconnect_rcon(server_id);
|
|
|
|
await this.connect(server_id, server);
|
|
|
|
}
|
2023-10-03 18:56:36 +02:00
|
|
|
try {
|
|
|
|
const status_promise = this.rcons[server_id].execute(`status`);
|
|
|
|
|
|
|
|
const timeout_promise = new Promise((resolve, reject) => {
|
|
|
|
setTimeout(() => {
|
|
|
|
reject(Error('Timeout - status command not received within 5 seconds'));
|
|
|
|
}, 5000); // 5 seconds timeout
|
|
|
|
});
|
|
|
|
let status = await Promise.race([status_promise, timeout_promise]);
|
2023-10-04 09:29:23 +02:00
|
|
|
console.log("HEARTBEAT SUCCESS", server_id)
|
2023-10-03 18:56:36 +02:00
|
|
|
} catch (error) {
|
2023-10-04 09:29:23 +02:00
|
|
|
console.log("Error in connecting to the server, reconnecting..... ERROR:", error);
|
2023-10-03 18:56:36 +02:00
|
|
|
await this.disconnect_rcon(server_id);
|
|
|
|
await this.connect(server_id, server);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-28 07:23:33 +02:00
|
|
|
async connect(server_id, server) {
|
2023-10-11 15:59:14 +02:00
|
|
|
try {
|
|
|
|
let rcon_connection = null;
|
|
|
|
rcon_connection = new Rcon({ host: server.serverIP, port: server.serverPort, timeout: 5000 });
|
|
|
|
console.log("CONNECTING RCON", server_id, server.serverIP, server.serverPort);
|
|
|
|
|
|
|
|
// Set a timeout for the authentication process
|
|
|
|
const authenticationTimeout = setTimeout(async () => {
|
|
|
|
console.error('RCON Authentication timed out', server_id);
|
|
|
|
try {
|
|
|
|
await this.disconnect_rcon(server_id); // Disconnect the RCON connection
|
|
|
|
console.log('Timed out, disconnected RCON', server_id);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error disconnecting RCON', server_id, error);
|
|
|
|
}
|
|
|
|
}, 10000);
|
|
|
|
|
2023-09-28 07:23:33 +02:00
|
|
|
try {
|
2023-10-11 15:59:14 +02:00
|
|
|
await rcon_connection.authenticate(server.rconPassword);
|
|
|
|
clearTimeout(authenticationTimeout);
|
|
|
|
console.log('RCON Authenticated', server_id, server.serverIP, server.serverPort);
|
2023-09-28 07:23:33 +02:00
|
|
|
} catch (error) {
|
2023-10-11 15:59:14 +02:00
|
|
|
clearTimeout(authenticationTimeout);
|
|
|
|
console.error('RCON Authentication failed', server_id, error);
|
2023-09-28 07:23:33 +02:00
|
|
|
}
|
2023-10-11 15:59:14 +02:00
|
|
|
|
|
|
|
this.rcons[server_id] = rcon_connection;
|
|
|
|
this.details[server_id] = {
|
|
|
|
host: server.serverIP,
|
|
|
|
port: server.serverPort,
|
|
|
|
rcon_password: server.rconPassword,
|
|
|
|
connected: rcon_connection.isConnected(),
|
|
|
|
authenticated: rcon_connection.isAuthenticated()
|
|
|
|
};
|
|
|
|
if (rcon_connection.isConnected() && rcon_connection.isAuthenticated()) {
|
|
|
|
this.details[server_id].heartbeat_interval = setInterval(async () => this.send_heartbeat(server_id, server), 5000);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} catch (error) {
|
|
|
|
console.error('[CONNECTION ERROR]', error);
|
2023-09-28 07:23:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async disconnect_rcon(server_id) {
|
|
|
|
console.log('starting disconnect', server_id)
|
2023-09-28 08:00:21 +02:00
|
|
|
if ( !(server_id in this.rcons) || (!this.rcons[server_id].connected)) {
|
2023-09-28 07:23:33 +02:00
|
|
|
return Promise.resolve();
|
|
|
|
}
|
2023-10-04 09:29:23 +02:00
|
|
|
clearInterval(this.details[server_id].heartbeat_interval)
|
2023-09-28 07:23:33 +02:00
|
|
|
this.rcons[server_id].authenticated = false;
|
|
|
|
this.rcons[server_id].connected = false;
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.rcons[server_id].connection.once('close', () => {
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
|
|
|
|
this.rcons[server_id].connection.once('error', (e) => {
|
|
|
|
console.error('Socket error during disconnect:', e);
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
|
|
|
|
this.rcons[server_id].connection.end(); // Close the socket gracefully
|
2023-10-04 09:29:23 +02:00
|
|
|
console.log("Disconnected", server_id)
|
2023-09-28 07:23:33 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = new RconManager();
|