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
|