IPBS_Station/ObjectVariable/Configuration.h
2025-09-05 08:44:30 +08:00

435 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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