#ifndef CONFIGURATION_H #define CONFIGURATION_H #include #include #include #include #include #include #include #include #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 #include #include #include // 包含 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 CSPortList; inline static std::vector CSIPList; inline static std::vector 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& 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(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 getAvailablePorts(int count, int startPort = 1024, int endPort = 65535) { std::vector 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