132 lines
3.4 KiB
JavaScript
132 lines
3.4 KiB
JavaScript
const { spawn } = require('child_process');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const config = require('../../config');
|
|
const paths = require('../../utils/paths');
|
|
const logger = require('../../utils/logger');
|
|
|
|
class FRPService {
|
|
constructor(options = {}) {
|
|
this.enabled = options.enabled !== false;
|
|
this.frpcPath = options.frpcPath || path.join(paths.getFRPPath(), 'frpc.exe');
|
|
this.configPath = options.configPath || path.join(paths.getFRPPath(), 'frpc.toml');
|
|
this.process = null;
|
|
this.isRunning = false;
|
|
}
|
|
|
|
_prepareConfig() {
|
|
const frpDir = paths.getFRPPath();
|
|
const logPath = path.join(paths.getBasePath(), 'logs', 'frpc.log');
|
|
const logsDir = path.dirname(logPath);
|
|
|
|
if (!fs.existsSync(logsDir)) {
|
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
}
|
|
|
|
if (fs.existsSync(this.configPath)) {
|
|
let content = fs.readFileSync(this.configPath, 'utf8');
|
|
content = content.replace(/log\.to\s*=\s*"[^"]*"/, `log.to = "${logPath.replace(/\\/g, '\\\\')}"`);
|
|
|
|
const tempConfigPath = path.join(frpDir, 'frpc-runtime.toml');
|
|
fs.writeFileSync(tempConfigPath, content);
|
|
return tempConfigPath;
|
|
}
|
|
|
|
return this.configPath;
|
|
}
|
|
|
|
start() {
|
|
if (!this.enabled) {
|
|
logger.info('FRP service is disabled');
|
|
return;
|
|
}
|
|
|
|
if (this.isRunning) {
|
|
logger.warn('FRP service is already running');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
if (!fs.existsSync(this.frpcPath)) {
|
|
logger.error('FRP client not found', { path: this.frpcPath });
|
|
return;
|
|
}
|
|
|
|
if (!fs.existsSync(this.configPath)) {
|
|
logger.error('FRP config not found', { path: this.configPath });
|
|
return;
|
|
}
|
|
|
|
const runtimeConfigPath = this._prepareConfig();
|
|
|
|
logger.info('Starting FRP client', {
|
|
frpcPath: this.frpcPath,
|
|
configPath: runtimeConfigPath
|
|
});
|
|
|
|
this.process = spawn(this.frpcPath, ['-c', runtimeConfigPath], {
|
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
windowsHide: true
|
|
});
|
|
|
|
this.isRunning = true;
|
|
|
|
this.process.stdout.on('data', (data) => {
|
|
const output = data.toString().trim();
|
|
if (output) {
|
|
logger.info(`[FRP] ${output}`);
|
|
}
|
|
});
|
|
|
|
this.process.stderr.on('data', (data) => {
|
|
const output = data.toString().trim();
|
|
if (output) {
|
|
logger.error(`[FRP] ${output}`);
|
|
}
|
|
});
|
|
|
|
this.process.on('error', (error) => {
|
|
logger.error('FRP process error', { error: error.message });
|
|
this.isRunning = false;
|
|
});
|
|
|
|
this.process.on('close', (code) => {
|
|
logger.info('FRP process closed', { code });
|
|
this.isRunning = false;
|
|
this.process = null;
|
|
});
|
|
|
|
logger.info('FRP service started successfully');
|
|
} catch (error) {
|
|
logger.error('Failed to start FRP service', { error: error.message });
|
|
this.isRunning = false;
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
if (!this.isRunning || !this.process) {
|
|
return;
|
|
}
|
|
|
|
logger.info('Stopping FRP service');
|
|
|
|
try {
|
|
this.process.kill();
|
|
this.process = null;
|
|
this.isRunning = false;
|
|
logger.info('FRP service stopped');
|
|
} catch (error) {
|
|
logger.error('Failed to stop FRP service', { error: error.message });
|
|
}
|
|
}
|
|
|
|
getStatus() {
|
|
return {
|
|
enabled: this.enabled,
|
|
running: this.isRunning
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = FRPService;
|