Initial commit
This commit is contained in:
131
remote/src/services/network/FRPService.js
Normal file
131
remote/src/services/network/FRPService.js
Normal file
@@ -0,0 +1,131 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user