435 lines
15 KiB
C++
435 lines
15 KiB
C++
#ifndef CONFIGURATION_H
|
||
#define CONFIGURATION_H
|
||
#include <CApplication.h>
|
||
#include <CCFile.h>
|
||
#include <CCHttpClient.h>
|
||
#include <CCString.h>
|
||
#include <QNetworkInterface>
|
||
#include <CCThread.h>
|
||
#include <QMessageBox>
|
||
#include <QProcess>
|
||
|
||
#include "Tools/CText.h"
|
||
#include "CCSocket.h"
|
||
#include "CCProcess.h"
|
||
|
||
#define SubControl_Jar "SubControl/WebSub/SpringWeb.jar"
|
||
#define SubControl_Back_Cfg "SubControl/src/main/resources/ServerSettings/ServerSettings.CText"
|
||
#define SubControl_Web_Cfg "SubControl/conf/nginx.conf"
|
||
#define Sub_Logo "SubControl/html/assets/logo-CuXNbvLG.png"
|
||
#define Sub_ImgBuffer "ImgBuffer/"
|
||
|
||
#ifdef _WIN32
|
||
#include <tchar.h>
|
||
#include <windows.h>
|
||
#include <tlhelp32.h>
|
||
#include <shlobj.h> // 包含 ShellLink 和 IPersistFile 接口
|
||
#define SubControl_Java "SubControl/WebSub/jreWin/bin/Sub_Server.exe"
|
||
#define SubControl_Web_Exe "SubControl/Sub_Web.exe"
|
||
#define IPBS_NSSM_Exe "IPBS_NSSM.exe"
|
||
#elif __linux__
|
||
#define SubControl_Java "SubControl/WebSub/jreWin/bin/Sub_Server"
|
||
#define SubControl_Web_Exe "SubControl/Sub_WebL"
|
||
#endif
|
||
|
||
class Configuration
|
||
{
|
||
private:
|
||
inline static std::mutex _mutex;
|
||
public:
|
||
Configuration() = default;
|
||
inline static CCString ExePath = CApplication::GetTheProgramDirectory() + "/";
|
||
inline static CCString jarPath = CCFile::GetnormalizePath(ExePath + SubControl_Jar);
|
||
inline static CCString JavaPath = CCFile::GetnormalizePath(ExePath + SubControl_Java);
|
||
inline static CCString CfgPath = ExePath + SubControl_Back_Cfg;
|
||
inline static CCString WebCfgPath = ExePath + SubControl_Web_Cfg;
|
||
inline static CCString WebPath = CCFile::GetnormalizePath(ExePath + SubControl_Web_Exe);
|
||
inline static CCString IPBS_NSSMPath = CCFile::GetnormalizePath(ExePath + IPBS_NSSM_Exe);
|
||
inline static CCString CS_IP = "";
|
||
inline static CCString CS_Port = "";
|
||
inline static CCString Web_IP = "";
|
||
inline static CCString Web_Port = "";
|
||
inline static CCString Sub_IP = CCSocket::GetLocalIP()[0];
|
||
inline static CCString Sub_Port = "";
|
||
inline static CCString Sub_Audio_Port = "";
|
||
inline static CCString Sub_Org = "";
|
||
inline static CCString Language = "";
|
||
inline static CCString State = "Close";
|
||
inline static int OpenSleep = 20;
|
||
inline static CCString CORSEn = "false";
|
||
inline static int FirstRun = 1;
|
||
inline static CCString Web_URL = "";
|
||
inline static std::vector<CCInt> CSPortList;
|
||
inline static std::vector<CCString> CSIPList;
|
||
inline static std::vector<CCString> SubIPList;
|
||
inline static CCProcess WebRun,SubRun;
|
||
inline static int PostMax = 5417;
|
||
public:
|
||
static int GetInt(char h1, char h2)
|
||
{
|
||
int lowUnsigned = h1 & 0xFF;
|
||
int highUnsigned = h2 & 0xFF;
|
||
return (highUnsigned << 8) | lowUnsigned;
|
||
}
|
||
static void ReadConfigInit(){
|
||
CCVar A = CText::ReadConfig(CfgPath.c_str());
|
||
if(!A.empty()){
|
||
CS_IP = A["C/S_IP"];
|
||
CS_Port = A["C/S_PORT"];
|
||
Web_IP = A["Sub_Control_IP"];
|
||
Web_Port = A["Sub_Web_PORT"];
|
||
Sub_IP = Web_IP;
|
||
Sub_Port = A["Sub_Control_PORT"];
|
||
Sub_Audio_Port = A["Sub_Control_Audio_PORT"];
|
||
Sub_Org = A["Origins"];
|
||
Language = A["Language"];
|
||
OpenSleep = A["OpenSleep"].to_int();
|
||
State = A["State"];
|
||
CORSEn = A["CORSEn"];
|
||
FirstRun = A["FirstRun"].to_int();
|
||
}
|
||
Configuration::Web_URL = "http://" + Web_IP + ":" + Web_Port;
|
||
}
|
||
static void ReadCSInfo(const std::function<void()>& fun = nullptr,QWidget *parent = nullptr){
|
||
CCUniqueLock lock(_mutex);
|
||
CSPortList.clear();
|
||
CSIPList.clear();
|
||
CCSocket UDP;
|
||
UDP.Socket(IPVX::IPV4,TORU::UDP,TYPE::DGRAM);
|
||
bool A = UDP.SetSockOpt(CCOpt::BROADCAST);
|
||
const CCString IP = Sub_IP;
|
||
if(bool F = UDP.Bind(IP.c_str(),0)){
|
||
constexpr char str[] = {0x55,static_cast<char>(0xAA),0x48,0x00,0x00,0x00,0x00,0x00};
|
||
sockaddr_in serverAddr{};
|
||
serverAddr.sin_family = AF_INET;
|
||
serverAddr.sin_port = htons(10060);
|
||
serverAddr.sin_addr.s_addr = INADDR_BROADCAST;
|
||
UDP.SendData(str,serverAddr);
|
||
int AS = 0;
|
||
while (true){
|
||
char buf[1024] = {0};
|
||
CCHostInfo info;
|
||
if(UDP.isDataAvailable()){
|
||
CCVar length = UDP.UDPRecvData(buf, 1024,&info);
|
||
if(length > 0){
|
||
if(buf[2] == 0x48){
|
||
int P = GetInt(buf[4],buf[5]);
|
||
CSIPList.emplace_back(info.IPAddress);
|
||
CSPortList.emplace_back(P);
|
||
}
|
||
}
|
||
else{
|
||
if(length == -1)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else{
|
||
AS++;
|
||
CCThread::Sleep(1000 * 10);
|
||
if(AS == 10){
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
UDP.Close();
|
||
if(fun){
|
||
fun();
|
||
}
|
||
}
|
||
else{
|
||
// const CCString IPA = "网络初始化失败 -> " + Sub_IP;
|
||
// QMessageBox::information(parent,"错误",IPA.c_str());
|
||
}
|
||
}
|
||
static void ReadSub_IP(){
|
||
SubIPList.clear();
|
||
foreach (QHostAddress ptr , QNetworkInterface::allAddresses()) {
|
||
// 获取ipv4地址
|
||
if (ptr.protocol() == QAbstractSocket::IPv4Protocol) {
|
||
// 过滤本地回环127.0.0.1
|
||
if (!ptr.isLoopback()) {
|
||
CCString A = ptr.toString().toStdString();
|
||
SubIPList.emplace_back(A);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
static void CfgInit(){
|
||
while (true){
|
||
CCThread::Sleep(1000 * 500);
|
||
ReadSub_IP();
|
||
if(!SubIPList.empty()){
|
||
Sub_IP = SubIPList[0];
|
||
break;
|
||
}
|
||
else{
|
||
QMessageBox::StandardButton reply = QMessageBox::question(nullptr, "提示",
|
||
"未检测到合法IPV4地址,请检查网络,是否继续检测?",
|
||
QMessageBox::Yes | QMessageBox::No);
|
||
if (reply == QMessageBox::Yes) {
|
||
continue;
|
||
} else {
|
||
Sub_IP = "";
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
while (true){
|
||
CCThread::Sleep(1000 * 500);
|
||
ReadCSInfo();
|
||
if(!CSIPList.empty()){
|
||
CS_IP = CSIPList[0];
|
||
CS_Port = CSPortList[0].to_String();
|
||
break;
|
||
}
|
||
else{
|
||
CS_IP = "";
|
||
CS_Port = "";
|
||
QMessageBox::StandardButton reply = QMessageBox::question(nullptr, "提示",
|
||
"在局域网未检测到可用的C/S服务器,请先启动C/S服务器,是否继续检测?",
|
||
QMessageBox::Yes | QMessageBox::No);
|
||
if (reply == QMessageBox::Yes) {
|
||
continue;
|
||
} else {
|
||
CS_IP = "";
|
||
CS_Port = "";
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if(PostMax == Sub_Port.to_int()){
|
||
PostMax = PostMax + 3;
|
||
}
|
||
CCVar Ports = getAvailablePorts(3,PostMax);
|
||
Sub_Port = Ports[0].to_String();
|
||
Sub_Audio_Port = Ports[1].to_String();
|
||
Web_Port = Ports[2].to_String();
|
||
Web_IP = Sub_IP;
|
||
Sub_Org = "['http://" + Web_IP + ":" + Web_Port + "']";
|
||
}
|
||
static bool isPortAvailable(int port,TORU ipvx = TCP)
|
||
{
|
||
bool F = false;
|
||
if(ipvx == TCP){
|
||
CCSocket sock;
|
||
sock.Socket(IPV4,TCP,TYPE::STREAM);
|
||
F = sock.Bind(Sub_IP.c_str(), port);
|
||
try{
|
||
sock.Close();
|
||
}
|
||
catch (CCException& e){}
|
||
}
|
||
else{
|
||
CCSocket sock;
|
||
sock.Socket(IPV4,UDP,TYPE::DGRAM);
|
||
F = sock.Bind(Sub_IP.c_str(), port);
|
||
try{
|
||
sock.Close();
|
||
}
|
||
catch (CCException& e){}
|
||
}
|
||
return F;
|
||
}
|
||
static std::vector<CCInt> getAvailablePorts(int count, int startPort = 1024, int endPort = 65535)
|
||
{
|
||
std::vector<CCInt> availablePorts;
|
||
for (int port = startPort; port <= endPort && availablePorts.size() < count; ++port) {
|
||
if(availablePorts.size() < count - 1){
|
||
if (isPortAvailable(port)) {
|
||
availablePorts.push_back(port);
|
||
}
|
||
}
|
||
else{
|
||
if(isPortAvailable(port)){
|
||
availablePorts.push_back(port);
|
||
}
|
||
}
|
||
}
|
||
return availablePorts;
|
||
}
|
||
static void OpenSub_Server(){
|
||
CCString cmd = "cd " + ExePath + "SubControl/" + " && ";
|
||
SubRun.AddCommand(cmd);
|
||
// cmd = "start "" " + JavaPath + " -jar " + jarPath;
|
||
cmd = JavaPath + " -jar " + jarPath;
|
||
SubRun.AddCommand(cmd);
|
||
SubRun.Start();
|
||
}
|
||
static void CloseSub_Server(){
|
||
// CCProcess Close;
|
||
// Close.AddCommand("taskkill /f /t /im Sub_Server.exe");
|
||
// Close.Start();
|
||
QProcess::startDetached("taskkill /f /t /im Sub_Server.exe");
|
||
}
|
||
static void OpenSub_Web(){
|
||
CCString cmd = "cd " + ExePath + "SubControl/" + " && ";
|
||
WebRun.AddCommand(cmd);
|
||
cmd = WebPath;
|
||
WebRun.AddCommand(cmd);
|
||
WebRun.Start();
|
||
Configuration::Web_URL = "http://" + Web_IP + ":" + Web_Port + "/";
|
||
}
|
||
static void CloseSub_Web(){
|
||
// CCProcess Close;
|
||
// Close.AddCommand("taskkill /f /t /im Sub_Web.exe");
|
||
// Close.Start();
|
||
QProcess::startDetached("taskkill /f /t /im Sub_Web.exe");
|
||
}
|
||
static bool GetSub_Status(){
|
||
bool F = false;
|
||
CCProcess P;
|
||
#ifdef _WIN32
|
||
P.AddCommand("tasklist | findstr Sub_Server.exe");
|
||
#elif __linux__
|
||
#endif
|
||
P.Start(true);
|
||
while (true){
|
||
CCString str = P.ReadLineBuffer();
|
||
if(str.empty()){
|
||
break;
|
||
}
|
||
else{
|
||
F = str.find("Sub_Server") != CCString::npos;
|
||
if(F){
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
P.Stop();
|
||
return F;
|
||
}
|
||
static bool GetSub_Web_Status(){
|
||
bool F = false;
|
||
CCProcess P;
|
||
#ifdef _WIN32
|
||
P.AddCommand("tasklist | findstr Sub_Web.exe");
|
||
#elif __linux__
|
||
#endif
|
||
P.Start(true);
|
||
while (true){
|
||
CCString str = P.ReadLineBuffer();
|
||
if(str.empty()){
|
||
break;
|
||
}
|
||
else{
|
||
F = str.find("Sub_Web") != CCString::npos;
|
||
if(F){
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
P.Stop();
|
||
return F;
|
||
}
|
||
static bool SaveJarCfg() {
|
||
CCString File = CCFile::GetnormalizePath(CfgPath);
|
||
FILE *fp = fopen(File.c_str(), "w");
|
||
if(fp == nullptr){
|
||
return false;
|
||
}
|
||
fprintf(fp, "C/S_IP:%s\n",CS_IP.c_str());
|
||
fprintf(fp, "C/S_PORT:%s\n",CS_Port.c_str());
|
||
fprintf(fp, "Sub_Control_IP:%s\n",Sub_IP.c_str());
|
||
fprintf(fp, "Sub_Control_PORT:%s\n",Sub_Port.c_str());
|
||
fprintf(fp, "Sub_Control_Audio_PORT:%s\n",Sub_Audio_Port.c_str());
|
||
fprintf(fp, "Sub_Web_PORT:%s\n",Web_Port.c_str());
|
||
fprintf(fp, "Origins:%s\n",Sub_Org.c_str());
|
||
fprintf(fp, "#中文简体,English\n");
|
||
fprintf(fp, "Language:%s\n",Language.c_str());
|
||
fprintf(fp, "OpenSleep:%d\n",OpenSleep);
|
||
fprintf(fp, "State:%s\n",Configuration::State.c_str());
|
||
fprintf(fp, "CORSEn:%s\n",Configuration::CORSEn.c_str());
|
||
fprintf(fp, "FirstRun:%d\n",0);
|
||
fclose(fp);
|
||
return true;
|
||
}
|
||
static bool SaveWebCfg(){
|
||
CCString File = CCFile::GetnormalizePath(WebCfgPath);
|
||
CCVar fp = fopen(File.c_str(), "w");
|
||
if (fp == nullptr) {
|
||
return false;
|
||
}
|
||
// 写入配置数据
|
||
fprintf(fp, "worker_processes 1;\n"
|
||
"events {\n"
|
||
" worker_connections 1024;\n"
|
||
"}\n"
|
||
"http {\n"
|
||
" include mime.types;\n"
|
||
" default_type application/octet-stream;\n"
|
||
" sendfile on;\n"
|
||
" keepalive_timeout 65;\n"
|
||
" client_max_body_size 500m;\n"
|
||
" server {\n"
|
||
" listen %s;\n"
|
||
" server_name %s;\n"
|
||
" location / {\n"
|
||
" root html;\n"
|
||
" index index.html index.htm;\n"
|
||
" try_files $uri $uri/ /index.html;\n"
|
||
" # try_files $uri $uri/ @router;\n"
|
||
" }\n"
|
||
" location /api/ {\n"
|
||
" #rewrite ^.+api/?(.*)$ /$1 break; \n"
|
||
" rewrite ^/api/(.*)$ /$1 break; \n"
|
||
" proxy_pass http://%s:%s/;\n"
|
||
" proxy_redirect off;\n"
|
||
" proxy_set_header Host $host;\n"
|
||
" proxy_set_header X-Real-IP $remote_addr;\n"
|
||
" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n"
|
||
" }\n"
|
||
" error_page 500 502 503 504 /50x.html;\n"
|
||
" location = /50x.html {\n"
|
||
" root html;\n"
|
||
" }\n"
|
||
" }\n"
|
||
"}",Web_Port.c_str(),Web_IP.c_str(),
|
||
Sub_IP.c_str(),Sub_Port.c_str());
|
||
fclose(fp);
|
||
return true;
|
||
}
|
||
static bool terminateProcessByName(const char *processName) {
|
||
#ifdef _WIN32
|
||
CCString str = processName;
|
||
str.append(".exe");
|
||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||
if (hSnapshot == INVALID_HANDLE_VALUE) {
|
||
return false;
|
||
}
|
||
PROCESSENTRY32 pe32;
|
||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||
if (Process32First(hSnapshot, &pe32)) {
|
||
do {
|
||
if (_tcscmp(pe32.szExeFile, str.c_str()) == 0) {
|
||
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID);
|
||
if (hProcess != NULL) {
|
||
TerminateProcess(hProcess, 0);
|
||
CloseHandle(hProcess);
|
||
}
|
||
}
|
||
} while (Process32Next(hSnapshot, &pe32));
|
||
}
|
||
CloseHandle(hSnapshot);
|
||
return true;
|
||
#elif __linux__
|
||
|
||
#endif
|
||
}
|
||
static void IPBS_NSSMF(bool F){
|
||
if(F){
|
||
const CCString str = CCString("./") + IPBS_NSSM_Exe;
|
||
QProcess::startDetached(str.c_str());
|
||
}
|
||
else{
|
||
#ifdef _WIN32
|
||
terminateProcessByName("IPBS_NSSM");
|
||
#elif __linux__
|
||
#endif
|
||
}
|
||
}
|
||
};
|
||
|
||
#endif
|