123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- //
- // Created by xcbosa on 2023/1/31.
- //
- #pragma once
- #include <string>
- #include "utils/utils.h"
- #include "webuiconf.h"
- #include "fs.hpp"
- #include <signal.h>
- #include <strstream>
- using namespace std;
- using namespace xc;
- using namespace xc::utils;
- namespace frp {
- set<int> profileUsingPorts(string profile) {
- set<int> usingPorts;
- INIFile ini(conf::getFrpcDir() + "/" + profile);
- string value = ini.getMust("common")->get("webui_allowServerPorts");
- auto v = split(value, ",");
- int low(0), len(0);
- if (v.size() == 2) {
- try {
- low = stoi(v[0]);
- len = stoi(v[1]);
- } catch (...) { }
- }
- for (int i = low; i < low + len; i++) {
- usingPorts.insert(i);
- }
- return usingPorts;
- }
- set<int> serverUsingPorts(string serverIp) {
- set<int> usingPorts;
- for (string file : fs::contentsOfDirectory(conf::getFrpcDir())) {
- INIFile ini(conf::getFrpcDir() + "/" + file);
- if (ini.getMust("common")->get("server_addr") == serverIp) {
- auto profilePorts = profileUsingPorts(file);
- for (auto port : profilePorts) {
- usingPorts.insert(port);
- }
- }
- }
- return usingPorts;
- }
- void addProfile(string name, string ip, string port, string token) {
- INI ini;
- auto frpCommon = ini.getMust("common");
- frpCommon->set("server_addr", ip);
- frpCommon->set("server_port", port);
- frpCommon->set("token", token);
- frpCommon->set("tls_enable", "true");
- auto alreadyUsingPorts = serverUsingPorts(ip);
- int low = 0, len = conf::allowPortCountPerProfile;
- for (int i = 10000; i < 60000; i += len) {
- bool badPage = false;
- for (int j = i; j < i + len; j++) {
- if (alreadyUsingPorts.count(j)) {
- badPage = true;
- break;
- }
- }
- if (!badPage) {
- low = i;
- break;
- }
- }
- if (low == 0) {
- len = 0;
- }
- ostringstream oss;
- oss << low;
- oss << ",";
- oss << len;
- frpCommon->set("webui_allowServerPorts", oss.str());
- saveTextFile(conf::getFrpcDir() + "/" + name, ini.getINIString());
- }
- class FrpProcessWrapper {
- public:
- FrpProcessWrapper(string fileName, string filePath) {
- this->fileName = fileName;
- this->filePath = filePath;
- this->updated = false;
- }
- void startAndKeepRunning() {
- cout << "[FrpProcessWrapper] [" << fileName << "] Start" << endl;
- this->doKill();
- this->doStart();
- }
- void update() {
- if (getRunningPid() == 0) {
- cout << "[FrpProcessWrapper] [" << fileName << "] Exit unexpectedly, restarting..." << endl;
- this->doStart();
- }
- }
- int getRunningPid() {
- ::FILE *psStdoutFd = popen("ps -ef", "r");
- ostringstream oss;
- while (true) {
- int ch = ::fgetc(psStdoutFd);
- if (ch == -1) break;
- oss << (char) ch;
- }
- ::pclose(psStdoutFd);
- string str = oss.str();
- auto lines = split(str, "\n");
- for (auto line : lines) {
- if (line.find("frpc -c") != line.npos && line.find(this->filePath) != line.npos) {
- strstream ss;
- ss << line;
- string owner;
- int pid;
- ss >> owner;
- ss >> pid;
- return pid;
- }
- }
- return 0;
- }
- void stop() {
- cout << "[FrpProcessWrapper] [" << fileName << "] Stop" << endl;
- this->doKill();
- }
- void reloadConfig() {
- this->stop();
- this->startAndKeepRunning();
- }
- bool updated;
- string fileName;
- string filePath;
- private:
- void doStart() {
- ostringstream oss;
- oss << "frpc -c " << this->filePath << " &";
- string launchCmd = oss.str();
- ::system(launchCmd.c_str());
- }
- void doKill() {
- int pid = getRunningPid();
- if (pid > 0) {
- kill(pid, SIGKILL);
- }
- }
- };
- set<string> reloadConfigForFilePathRequests;
- mutex reloadConfigForFilePathRequestsLocker;
- void reloadProfileFilePath(string filePath) {
- reloadConfigForFilePathRequestsLocker.lock();
- reloadConfigForFilePathRequests.insert(filePath);
- reloadConfigForFilePathRequestsLocker.unlock();
- }
- void frpDaemon() {
- char readBuff[1024];
- vector<FrpProcessWrapper *> frpProcesses;
- while (true) {
- for (auto it : frpProcesses) {
- it->updated = false;
- }
- for (string file : fs::contentsOfDirectory(conf::getFrpcDir())) {
- string filePath = conf::getFrpcDir() + "/" + file;
- bool updated = false;
- for (auto process : frpProcesses) {
- if (process->filePath == filePath) {
- process->update();
- process->updated = true;
- updated = true;
- break;
- }
- }
- if (!updated) {
- auto newProcess = new FrpProcessWrapper(file, filePath);
- newProcess->startAndKeepRunning();
- newProcess->updated = true;
- frpProcesses.push_back(newProcess);
- }
- }
- for (auto it = frpProcesses.begin(); it != frpProcesses.end(); ) {
- FrpProcessWrapper *proc = *it;
- if (!proc->updated) {
- proc->stop();
- delete proc;
- it = frpProcesses.erase(it);
- } else {
- reloadConfigForFilePathRequestsLocker.lock();
- if (reloadConfigForFilePathRequests.count(proc->filePath)) {
- reloadConfigForFilePathRequests.erase(proc->filePath);
- reloadConfigForFilePathRequestsLocker.unlock();
- proc->reloadConfig();
- } else {
- reloadConfigForFilePathRequestsLocker.unlock();
- }
- it++;
- }
- }
- usleep(1000 * 1000);
- }
- }
- }
|