From 7d04cf93bd9f1422e968d1aa49fef9f8459203fd Mon Sep 17 00:00:00 2001 From: Tindy X <49061470+tindy2013@users.noreply.github.com> Date: Tue, 5 Nov 2019 16:42:24 +0800 Subject: [PATCH] Improve performance for API mode --- ini_reader.h | 38 +++++++++++++++++++++++++++++++------- main.cpp | 31 +++++++++++++++++++++++++++---- misc.cpp | 8 ++++---- webserver_libevent.cpp | 2 ++ 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/ini_reader.h b/ini_reader.h index d050b8b..334cd50 100644 --- a/ini_reader.h +++ b/ini_reader.h @@ -17,6 +17,9 @@ class INIReader * to store sections and items, allowing access in logarithmic time. */ private: + /** + * @brief Internal parsed flag. + */ bool parsed = false; std::string current_section; ini_data_struct ini_content; @@ -127,8 +130,8 @@ public: std::string strLine, thisSection, curSection, itemName, itemVal; string_multimap itemGroup, existItemGroup; std::stringstream strStrm; - unsigned int lineSize = 0, epos = 0; - char delimiter = count(content.begin(), content.end(), '\n') <= 1 ? '\r' : '\n'; + unsigned int lineSize = 0; + //char delimiter = count(content.begin(), content.end(), '\n') <= 1 ? '\r' : '\n'; EraseAll(); //first erase all data if(do_utf8_to_gbk && is_str_utf8(content)) @@ -137,7 +140,8 @@ public: if(store_isolated_line) curSection = isolated_items_section; //items before any section define will be store in this section strStrm< MAX_LINE_LENGTH || strLine[0] == ';' || strLine[0] == '#') //empty lines, lines longer than MAX_LINE_LENGTH and comments are ignored @@ -147,15 +151,14 @@ public: strLine.replace(lineSize - 1, 0, ""); lineSize--; } - epos = strLine.find("="); - if(epos != strLine.npos) //is an item + if(strLine.find("=") != strLine.npos) //is an item { if(inExcludedSection) //this section is excluded continue; if(!curSection.size()) //not in any section return -1; - itemName = trim(strLine.substr(0, epos)); - itemVal = trim(strLine.substr(epos + 1)); + itemName = trim(strLine.substr(0, strLine.find("="))); + itemVal = trim(strLine.substr(strLine.find("=") + 1)); itemGroup.emplace(itemName, itemVal); //insert to current section } else if(strLine[0] == '[' && strLine[lineSize - 1] == ']') //is a section title @@ -674,6 +677,27 @@ public: return current_section.size() ? EraseFirst(current_section, itemName) : -1; } + /** + * @brief Erase all items in the given section. + */ + void EraseSection(std::string section) + { + if(ini_content.find(section) == ini_content.end()) + return; + eraseElements(ini_content.at(section)); + if(cached_section == section) + eraseElements(cached_section_content); + } + + /** + * @brief Erase all items in current section. + */ + void EraseSection() + { + if(current_section.size()) + EraseSection(current_section); + } + /** * @brief Export the whole INI data structure into a string. */ diff --git a/main.cpp b/main.cpp index 1cff684..3556cf3 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include @@ -21,16 +22,24 @@ int listen_port = 25500, max_pending_connections = 10, max_concurrent_threads = bool api_mode = true, update_ruleset_on_request = false, overwrite_original_rules = true; extern std::string custom_group; +//safety lock for multi-thread +typedef std::lock_guard guarded_mutex; +std::mutex on_configuring; + //preferences string_array renames, emojis; bool add_emoji = false, remove_old_emoji = false; //clash custom -std::string clash_rule_base, clash_base_content; +std::string clash_rule_base; string_array clash_extra_group; +//surge custom +std::string surge_rule_base; + std::string refreshRulesets() { + guarded_mutex guard(on_configuring); eraseElements(ruleset_content_array); string_array vArray; std::string rule_group, rule_url, proxy = getSystemProxy(); @@ -70,6 +79,7 @@ std::string refreshRulesets() void readConf() { + guarded_mutex guard(on_configuring); eraseElements(def_exclude_remarks); eraseElements(def_include_remarks); eraseElements(clash_extra_group); @@ -91,6 +101,8 @@ void readConf() ini.GetAll("include_remarks", def_exclude_remarks); if(ini.ItemExist("clash_rule_base")) clash_rule_base = ini.Get("clash_rule_base"); + if(ini.ItemExist("surge_rule_base")) + surge_rule_base = ini.Get("surge_rule_base"); if(ini.ItemPrefixExist("rename_node")) ini.GetAll("rename_node", renames); @@ -138,6 +150,7 @@ void readConf() } std::string netchToClash(std::vector &nodes, std::string &baseConf, std::vector &ruleset_content_array, string_array &extra_proxy_group, bool clashR); +std::string netchToSurge(std::vector &nodes, std::string &base_conf, std::vector &ruleset_content_array, string_array &extra_proxy_group, int surge_ver); int main() { @@ -160,9 +173,17 @@ int main() return refreshRulesets(); }); - append_response("GET", "/clash", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string + append_response("GET", "/readconf", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { readConf(); + return "done"; + }); + + append_response("GET", "/clash", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string + { + if(!api_mode) + readConf(); + std::string clash_base_content; std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex")), group = UrlDecode(getUrlArg(argument, "group")); if(!url.size()) url = default_url; string_array urls = split(url, "|"); @@ -190,7 +211,9 @@ int main() append_response("GET", "/clashr", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { - readConf(); + if(!api_mode) + readConf(); + std::string clash_base_content; std::string url = UrlDecode(getUrlArg(argument, "url")), include = UrlDecode(getUrlArg(argument, "regex")), group = UrlDecode(getUrlArg(argument, "group")); if(!url.size()) url = default_url; string_array urls = split(url, "|"); @@ -232,7 +255,7 @@ int main() listener_args args = {listen_address, listen_port, 10240, 4}; std::cout<<"Serving HTTP @ http://"< #include #include -#include +//#include #include #include @@ -485,9 +485,9 @@ std::string fileGet(std::string path, bool binary) bool fileExist(std::string path) { - //using c++17 standard - return std::filesystem::exists(path); - //return _access(path.data(), 4) != -1; + //using c++17 standard, but may cause problem on clang + //return std::filesystem::exists(path); + return _access(path.data(), 4) != -1; } bool fileCopy(std::string source, std::string dest) diff --git a/webserver_libevent.cpp b/webserver_libevent.cpp index b43822e..9c4844a 100644 --- a/webserver_libevent.cpp +++ b/webserver_libevent.cpp @@ -206,6 +206,8 @@ int start_web_server_multi(void *argv) if (ret != 0) return -1; } + while(true) + sleep(10000); //block forever return 0; }