IPBS_Station/ObjectVariable/Configuration.h

435 lines
15 KiB
C
Raw Normal View History

2025-09-05 08:44:30 +08:00
#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