Enhancements

Fix potential segmentation fault error due to some incorrect copy assignments.
Fix potential crash due to incorrect usage of cURL library.
Fix potential memory leak causing memory usage to be too high.
Add /qx-rewrite and /qx-script interface to add device ID to scripts for some version of Quantumult X.
Add policy-path parsing support for /surge2clash interface.
Add interval/strict options support for managed config.
Add filename option for setting file name when downloading exported subscriptions.
Optimize codes.
This commit is contained in:
Tindy X 2020-02-20 21:19:03 +08:00
parent 452c9299f1
commit c6920fbbc3
No known key found for this signature in database
GPG Key ID: C6AD413169968D58
10 changed files with 254 additions and 59 deletions

View File

@ -39,6 +39,9 @@ node_pref:
managed_config: managed_config:
write_managed_config: true write_managed_config: true
managed_config_prefix: "http://127.0.0.1:25500" managed_config_prefix: "http://127.0.0.1:25500"
config_update_interval: 86400
config_update_strict: false
quanx_device_id: ""
surge_external_proxy: surge_external_proxy:
surge_ssr_path: "" # /usr/bin/ssr-local surge_ssr_path: "" # /usr/bin/ssr-local

View File

@ -83,6 +83,15 @@ write_managed_config=true
;This address will also be used for generating /getruleset addresses. ;This address will also be used for generating /getruleset addresses.
managed_config_prefix=http://127.0.0.1:25500 managed_config_prefix=http://127.0.0.1:25500
;Managed config update interval, determine how long the config will be updated.
config_update_interval=86400
;If config_update_struct is true, Surge will require a force update after the interval.
config_update_struct=false
;Device ID to be written to rewrite scripts for some version of Quantumult X
quanx_device_id=
[surge_external_proxy] [surge_external_proxy]
;surge_ssr_path=/usr/bin/ssr-local ;surge_ssr_path=/usr/bin/ssr-local

View File

@ -34,13 +34,14 @@ std::mutex on_configuring;
//preferences //preferences
string_array renames, emojis; string_array renames, emojis;
bool add_emoji = false, remove_old_emoji = false, append_proxy_type = false, filter_deprecated = true; bool add_emoji = false, remove_old_emoji = false, append_proxy_type = false, filter_deprecated = true;
bool udp_flag = false, tfo_flag = false, scv_flag = false, do_sort = false; bool udp_flag = false, tfo_flag = false, scv_flag = false, do_sort = false, config_update_strict = false;
std::string proxy_config, proxy_ruleset, proxy_subscription; std::string proxy_config, proxy_ruleset, proxy_subscription;
int config_update_interval = 0;
std::string clash_rule_base; std::string clash_rule_base;
string_array clash_extra_group; string_array clash_extra_group;
std::string surge_rule_base, surfboard_rule_base, mellow_rule_base, quan_rule_base, quanx_rule_base; std::string surge_rule_base, surfboard_rule_base, mellow_rule_base, quan_rule_base, quanx_rule_base;
std::string surge_ssr_path; std::string surge_ssr_path, quanx_script_id;
//pre-compiled rule bases //pre-compiled rule bases
YAML::Node clash_base; YAML::Node clash_base;
@ -448,6 +449,9 @@ void readYAMLConf(YAML::Node &node)
section = node["managed_config"]; section = node["managed_config"];
section["write_managed_config"] >> write_managed_config; section["write_managed_config"] >> write_managed_config;
section["managed_config_prefix"] >> managed_config_prefix; section["managed_config_prefix"] >> managed_config_prefix;
section["config_update_interval"] >> config_update_interval;
section["config_update_strict"] >> config_update_strict;
section["quanx_device_id"] >> quanx_script_id;
} }
if(node["surge_external_proxy"].IsDefined()) if(node["surge_external_proxy"].IsDefined())
@ -634,6 +638,12 @@ void readConf()
write_managed_config = ini.GetBool("write_managed_config"); write_managed_config = ini.GetBool("write_managed_config");
if(ini.ItemExist("managed_config_prefix")) if(ini.ItemExist("managed_config_prefix"))
managed_config_prefix = ini.Get("managed_config_prefix"); managed_config_prefix = ini.Get("managed_config_prefix");
if(ini.ItemExist("config_update_interval"))
config_update_interval = ini.GetInt("config_update_interval");
if(ini.ItemExist("config_update_strict"))
config_update_strict = ini.GetBool("config_update_strict");
if(ini.ItemExist("quanx_device_id"))
quanx_script_id = ini.Get("quanx_device_id");
ini.EnterSection("emojis"); ini.EnterSection("emojis");
if(ini.ItemExist("add_emoji")) if(ini.ItemExist("add_emoji"))
@ -878,13 +888,15 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
std::string append_type = getUrlArg(argument, "append_type"), tfo = getUrlArg(argument, "tfo"), udp = getUrlArg(argument, "udp"), nodelist = getUrlArg(argument, "list"); std::string append_type = getUrlArg(argument, "append_type"), tfo = getUrlArg(argument, "tfo"), udp = getUrlArg(argument, "udp"), nodelist = getUrlArg(argument, "list");
std::string include = UrlDecode(getUrlArg(argument, "include")), exclude = UrlDecode(getUrlArg(argument, "exclude")), sort_flag = getUrlArg(argument, "sort"); std::string include = UrlDecode(getUrlArg(argument, "include")), exclude = UrlDecode(getUrlArg(argument, "exclude")), sort_flag = getUrlArg(argument, "sort");
std::string scv = getUrlArg(argument, "scv"), fdn = getUrlArg(argument, "fdn"), expand = getUrlArg(argument, "expand"), append_sub_userinfo = getUrlArg(argument, "append_info"); std::string scv = getUrlArg(argument, "scv"), fdn = getUrlArg(argument, "fdn"), expand = getUrlArg(argument, "expand"), append_sub_userinfo = getUrlArg(argument, "append_info");
std::string dev_id = getUrlArg(argument, "dev_id"), filename = UrlDecode(getUrlArg(argument, "filename")), interval_str = getUrlArg(argument, "interval"), strict_str = getUrlArg(argument, "strict");
std::string base_content, output_content; std::string base_content, output_content;
string_array extra_group, extra_ruleset, include_remarks, exclude_remarks; string_array extra_group, extra_ruleset, include_remarks, exclude_remarks;
std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), config = UrlDecode(getUrlArg(argument, "config")); std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), config = UrlDecode(getUrlArg(argument, "config"));
std::vector<ruleset_content> rca; std::vector<ruleset_content> rca;
extra_settings ext; extra_settings ext;
std::string subInfo, dummy; std::string subInfo, dummy;
bool ruleset_updated = false, authorized = getUrlArg(argument, "token") == access_token; int interval = interval_str.size() ? to_int(interval_str, config_update_interval) : config_update_interval;
bool ruleset_updated = false, authorized = getUrlArg(argument, "token") == access_token, strict = strict_str.size() ? strict_str == "true" : config_update_strict;
if(std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), include) != regex_blacklist.cend() || std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), exclude) != regex_blacklist.cend()) if(std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), include) != regex_blacklist.cend() || std::find(regex_blacklist.cbegin(), regex_blacklist.cend(), exclude) != regex_blacklist.cend())
return "Invalid request!"; return "Invalid request!";
@ -944,6 +956,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
ext.nodelist = nodelist == "true"; ext.nodelist = nodelist == "true";
ext.surge_ssr_path = surge_ssr_path; ext.surge_ssr_path = surge_ssr_path;
ext.quanx_dev_id = dev_id.size() ? dev_id : quanx_script_id;
ext.enable_rule_generator = enable_rule_generator; ext.enable_rule_generator = enable_rule_generator;
if(expand != "true") if(expand != "true")
ext.managed_config_prefix = managed_config_prefix; ext.managed_config_prefix = managed_config_prefix;
@ -1135,7 +1148,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
uploadGist("surge" + version, upload_path, output_content, true); uploadGist("surge" + version, upload_path, output_content, true);
if(write_managed_config && managed_config_prefix.size()) if(write_managed_config && managed_config_prefix.size())
output_content = "#!MANAGED-CONFIG " + managed_config_prefix + "/sub?" + argument + "\n\n" + output_content; output_content = "#!MANAGED-CONFIG " + managed_config_prefix + "/sub?" + argument + (interval ? " interval=" + std::to_string(interval) : "") \
+ " strict=" + std::string(strict ? "true" : "false") + "\n\n" + output_content;
} }
} }
else if(target == "surfboard") else if(target == "surfboard")
@ -1151,7 +1165,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
uploadGist("surfboard", upload_path, output_content, true); uploadGist("surfboard", upload_path, output_content, true);
if(write_managed_config && managed_config_prefix.size()) if(write_managed_config && managed_config_prefix.size())
output_content = "#!MANAGED-CONFIG " + managed_config_prefix + "/sub?" + argument + "\n\n" + output_content; output_content = "#!MANAGED-CONFIG " + managed_config_prefix + "/sub?" + argument + (interval ? " interval=" + std::to_string(interval) : "") \
+ " strict=" + std::string(strict ? "true" : "false") + "\n\n" + output_content;
} }
else if(target == "mellow") else if(target == "mellow")
{ {
@ -1247,14 +1262,18 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else else
{ {
std::cerr<<"Unspecified"<<std::endl; std::cerr<<"Unspecified"<<std::endl;
*status_code = 500;
return "Unrecognized target";
} }
if(filename.size())
extra_headers.emplace("Content-Disposition", "attachment; filename=\"" + filename + "\"");
return output_content; return output_content;
} }
std::string simpleToClashR(RESPONSE_CALLBACK_ARGS) std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
{ {
std::string url = argument.size() <= 8 ? "" : argument.substr(8); std::string url = argument.size() <= 8 ? "" : argument.substr(8);
std::string base_content, output_content; std::string base_content;
std::vector<nodeInfo> nodes; std::vector<nodeInfo> nodes;
string_array extra_group, extra_ruleset, include_remarks, exclude_remarks; string_array extra_group, extra_ruleset, include_remarks, exclude_remarks;
std::vector<ruleset_content> rca; std::vector<ruleset_content> rca;
@ -1283,7 +1302,7 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
refreshRulesets(rulesets, ruleset_content_array); refreshRulesets(rulesets, ruleset_content_array);
rca = ruleset_content_array; rca = ruleset_content_array;
extra_settings ext = {true, overwrite_original_rules, safe_get_renames(), safe_get_emojis(), add_emoji, remove_old_emoji, append_proxy_type, udp_flag, tfo_flag, false, do_sort, scv_flag, filter_deprecated, "", ""}; extra_settings ext = {true, overwrite_original_rules, safe_get_renames(), safe_get_emojis(), add_emoji, remove_old_emoji, append_proxy_type, udp_flag, tfo_flag, false, do_sort, scv_flag, filter_deprecated, "", "", ""};
std::string proxy; std::string proxy;
if(proxy_subscription == "SYSTEM") if(proxy_subscription == "SYSTEM")
@ -1382,28 +1401,12 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
else else
proxy = proxy_subscription; proxy = proxy_subscription;
std::string subInfo; //scan groups first, get potential policy-path
std::cerr<<"Fetching node data from url '"<<url<<"'."<<std::endl;
if(addNodes(url, nodes, 0, proxy, dummy_str_array, dummy_str_array, dummy_str_array, dummy_str_array, subInfo, false) == -1)
{
*status_code = 400;
return std::string("The following link doesn't contain any valid node info: " + url);
}
//exit if found nothing
if(!nodes.size())
{
*status_code = 400;
return "No nodes were found!";
}
extra_settings ext = {true, true, dummy_str_array, dummy_str_array, false, false, false, udp_flag, tfo_flag, false, do_sort, scv_flag, filter_deprecated, "", ""};
netchToClash(nodes, clash, dummy_str_array, false, ext);
string_multimap section; string_multimap section;
ini.GetItems("Proxy Group", section); ini.GetItems("Proxy Group", section);
std::string name, type, content; std::string name, type, content;
string_array links;
links.emplace_back(url);
YAML::Node singlegroup; YAML::Node singlegroup;
for(auto &x : section) for(auto &x : section)
{ {
@ -1424,11 +1427,36 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
singlegroup["url"] = trim(dummy_str_array[i].substr(dummy_str_array[i].find("=") + 1)); singlegroup["url"] = trim(dummy_str_array[i].substr(dummy_str_array[i].find("=") + 1));
else if(dummy_str_array[i].find("interval") == 0) else if(dummy_str_array[i].find("interval") == 0)
singlegroup["interval"] = trim(dummy_str_array[i].substr(dummy_str_array[i].find("=") + 1)); singlegroup["interval"] = trim(dummy_str_array[i].substr(dummy_str_array[i].find("=") + 1));
else if(dummy_str_array[i].find("policy-path") == 0)
links.emplace_back(trim(dummy_str_array[i].substr(dummy_str_array[i].find("=") + 1)));
else else
singlegroup["proxies"].push_back(trim(dummy_str_array[i])); singlegroup["proxies"].push_back(trim(dummy_str_array[i]));
} }
clash["Proxy Group"].push_back(singlegroup); clash["Proxy Group"].push_back(singlegroup);
} }
std::string subInfo;
for(std::string &x : links)
{
std::cerr<<"Fetching node data from url '"<<x<<"'."<<std::endl;
if(addNodes(x, nodes, 0, proxy, dummy_str_array, dummy_str_array, dummy_str_array, dummy_str_array, subInfo, false) == -1)
{
*status_code = 400;
return std::string("The following link doesn't contain any valid node info: " + x);
}
}
//exit if found nothing
if(!nodes.size())
{
*status_code = 400;
return "No nodes were found!";
}
extra_settings ext = {true, true, dummy_str_array, dummy_str_array, false, false, false, udp_flag, tfo_flag, false, do_sort, scv_flag, filter_deprecated, "", "", ""};
netchToClash(nodes, clash, dummy_str_array, false, ext);
section.clear(); section.clear();
ini.GetItems("Proxy", section); ini.GetItems("Proxy", section);
for(auto &x : section) for(auto &x : section)
@ -1509,7 +1537,7 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
std::string getProfile(RESPONSE_CALLBACK_ARGS) std::string getProfile(RESPONSE_CALLBACK_ARGS)
{ {
std::string name = UrlDecode(getUrlArg(argument, "name")), token = getUrlArg(argument, "token"); std::string name = UrlDecode(getUrlArg(argument, "name")), token = UrlDecode(getUrlArg(argument, "token"));
if(token != access_token) if(token != access_token)
{ {
*status_code = 403; *status_code = 403;
@ -1546,3 +1574,86 @@ std::string getProfile(RESPONSE_CALLBACK_ARGS)
query.erase(query.size() - 1); query.erase(query.size() - 1);
return subconverter(query, postdata, status_code, extra_headers); return subconverter(query, postdata, status_code, extra_headers);
} }
std::string getScript(RESPONSE_CALLBACK_ARGS)
{
std::string url = urlsafe_base64_decode(getUrlArg(argument, "url")), dev_id = getUrlArg(argument, "id");
std::string output_content, dummy;
std::string proxy;
if(proxy_config == "SYSTEM")
proxy = getSystemProxy();
else if(proxy_config == "NONE")
proxy = "";
else
proxy = proxy_config;
if(fileExist(url))
output_content = fileGet(url, true, true);
else
output_content = webGet(url, proxy, dummy, cache_config);
if(!dev_id.size())
dev_id = quanx_script_id;
const std::string pattern = "(\\/\\*[\\s\\S]*?)^(.*?@supported )(.*?\\s?)$([\\s\\S]*\\*\\/\\s?";
if(dev_id.size())
{
if(regFind(output_content, pattern))
output_content = regReplace(output_content, pattern, "$1$2" + dev_id + "$4");
else
output_content = "/**\n * @supported " + dev_id + "\n * THIS COMMENT IS GENERATED BY SUBCONVERTER\n */\n\n" + output_content;
}
return output_content;
}
std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS)
{
std::string url = urlsafe_base64_decode(getUrlArg(argument, "url")), dev_id = getUrlArg(argument, "id");
std::string output_content, dummy;
std::string proxy;
if(proxy_config == "SYSTEM")
proxy = getSystemProxy();
else if(proxy_config == "NONE")
proxy = "";
else
proxy = proxy_config;
if(fileExist(url))
output_content = fileGet(url, true, true);
else
output_content = webGet(url, proxy, dummy, cache_config);
if(!dev_id.size())
dev_id = quanx_script_id;
if(dev_id.size())
{
std::stringstream ss;
std::string strLine;
const std::string pattern = "^(.*? url script-.*? )(.*?)$";
string_size lineSize;
char delimiter = count(output_content.begin(), output_content.end(), '\n') < 1 ? '\r' : '\n';
ss << output_content;
output_content.clear();
while(getline(ss, strLine, delimiter))
{
lineSize = strLine.size();
if(lineSize && strLine[lineSize - 1] == '\r') //remove line break
{
strLine.erase(lineSize - 1);
lineSize--;
}
if(!strLine.empty() && regMatch(strLine, pattern))
{
url = managed_config_prefix + "/qx-script?id=" + dev_id + "&url=" + urlsafe_base64_encode(regReplace(strLine, pattern, "$2"));
strLine = regReplace(strLine, pattern, "$1") + url;
}
output_content.append(strLine + "\n");
}
}
return output_content;
}

View File

@ -10,8 +10,12 @@
void refreshRulesets(string_array &ruleset_list, std::vector<ruleset_content> &rca); void refreshRulesets(string_array &ruleset_list, std::vector<ruleset_content> &rca);
void readConf(); void readConf();
void generateBase(); void generateBase();
std::string getScript(RESPONSE_CALLBACK_ARGS);
std::string getProfile(RESPONSE_CALLBACK_ARGS); std::string getProfile(RESPONSE_CALLBACK_ARGS);
std::string getRuleset(RESPONSE_CALLBACK_ARGS); std::string getRuleset(RESPONSE_CALLBACK_ARGS);
std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS);
std::string subconverter(RESPONSE_CALLBACK_ARGS); std::string subconverter(RESPONSE_CALLBACK_ARGS);
std::string simpleToClashR(RESPONSE_CALLBACK_ARGS); std::string simpleToClashR(RESPONSE_CALLBACK_ARGS);
std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS); std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS);

View File

@ -185,6 +185,10 @@ int main(int argc, char *argv[])
append_response("GET", "/getprofile", "text/plain;charset=utf-8", getProfile); append_response("GET", "/getprofile", "text/plain;charset=utf-8", getProfile);
append_response("GET", "/qx-script", "text/plain;charset=utf-8", getScript);
append_response("GET", "/qx-rewrite", "text/plain;charset=utf-8", getRewriteRemote);
append_response("GET", "/clash", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string append_response("GET", "/clash", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string
{ {
return subconverter(argument + "&target=clash", postdata, status_code, extra_headers); return subconverter(argument + "&target=clash", postdata, status_code, extra_headers);

View File

@ -35,7 +35,7 @@ string_array safe_get_times()
YAML::Node safe_get_clash_base() YAML::Node safe_get_clash_base()
{ {
guarded_mutex guard(clash_base_mutex); guarded_mutex guard(clash_base_mutex);
return clash_base; return YAML::Clone(clash_base);
} }
INIReader safe_get_mellow_base() INIReader safe_get_mellow_base()

View File

@ -1758,6 +1758,63 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
if(ext.enable_rule_generator) if(ext.enable_rule_generator)
rulesetToSurge(ini, ruleset_content_array, -1, ext.overwrite_original_rules, ext.managed_config_prefix); rulesetToSurge(ini, ruleset_content_array, -1, ext.overwrite_original_rules, ext.managed_config_prefix);
//process scripts
string_multimap scripts;
std::string content, title, url;
const std::string pattern = "^(.*? url script-.*? )(.*?)$";
if(ini.SectionExist("rewrite_local") && ext.quanx_dev_id.size())
{
ini.GetItems("rewrite_local", scripts);
ini.EraseSection("rewrite_local");
ini.SetCurrentSection("rewrite_local");
for(auto &x : scripts)
{
title = x.first;
if(title != "{NONAME}")
content = title + "=" + x.second;
else
content = x.second;
if(regMatch(content, pattern))
{
url = regReplace(content, pattern, "$2");
if(startsWith(url, "https://") || startsWith(url, "http://"))
{
url = ext.managed_config_prefix + "/qx-script?id=" + ext.quanx_dev_id + "&url=" + urlsafe_base64_encode(url);
content = regReplace(content, pattern, "$1") + url;
}
}
ini.Set("{NONAME}", content);
}
}
eraseElements(scripts);
string_size pos;
if(ini.SectionExist("rewrite_remote") && ext.quanx_dev_id.size())
{
ini.GetItems("rewrite_remote", scripts);
ini.EraseSection("rewrite_remote");
ini.SetCurrentSection("rewrite_remote");
for(auto &x : scripts)
{
title = x.first;
if(title != "{NONAME}")
content = title + "=" + x.second;
else
content = x.second;
if(startsWith(content, "https://") || startsWith(content, "http://"))
{
pos = content.find(",");
url = ext.managed_config_prefix + "/qx-rewrite?id=" + ext.quanx_dev_id + "&url=" + urlsafe_base64_encode(content.substr(0, pos));
if(pos != content.npos)
content = url + content.substr(content.find(","));
else
content = url;
}
ini.Set("{NONAME}", content);
}
}
} }
std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, std::string &userinfo, extra_settings &ext) std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, std::string &userinfo, extra_settings &ext)

View File

@ -32,6 +32,7 @@ struct extra_settings
bool filter_deprecated = false; bool filter_deprecated = false;
std::string surge_ssr_path; std::string surge_ssr_path;
std::string managed_config_prefix; std::string managed_config_prefix;
std::string quanx_dev_id;
}; };
void rulesetToClash(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset_content_array, bool overwrite_original_rules); void rulesetToClash(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset_content_array, bool overwrite_original_rules);

View File

@ -18,6 +18,16 @@ extern bool print_debug_info;
//std::string user_agent_str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"; //std::string user_agent_str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36";
std::string user_agent_str = "subconverter/" + std::string(VERSION) + " cURL/" + std::string(LIBCURL_VERSION); std::string user_agent_str = "subconverter/" + std::string(VERSION) + " cURL/" + std::string(LIBCURL_VERSION);
static inline void curl_init()
{
static bool init = false;
if(!init)
{
curl_global_init(CURL_GLOBAL_ALL);
init = true;
}
}
static int writer(char *data, size_t size, size_t nmemb, std::string *writerData) static int writer(char *data, size_t size, size_t nmemb, std::string *writerData)
{ {
if(writerData == NULL) if(writerData == NULL)
@ -28,22 +38,28 @@ static int writer(char *data, size_t size, size_t nmemb, std::string *writerData
return size * nmemb; return size * nmemb;
} }
static std::string curlGet(std::string url, std::string proxy, std::string &response_headers, CURLcode &return_code) static inline void curl_set_common_options(CURL *curl_handle, const char *url)
{ {
CURL *curl_handle; curl_easy_setopt(curl_handle, CURLOPT_URL, url);
std::string data;
curl_global_init(CURL_GLOBAL_ALL);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, url.data());
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, print_debug_info ? 1L : 0L); curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, print_debug_info ? 1L : 0L);
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L); curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent_str.data()); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent_str.data());
}
static std::string curlGet(std::string url, std::string proxy, std::string &response_headers, CURLcode &return_code)
{
CURL *curl_handle;
std::string data;
curl_init();
curl_handle = curl_easy_init();
curl_set_common_options(curl_handle, url.data());
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data);
curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, writer); curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, writer);
@ -132,27 +148,20 @@ std::string webGet(std::string url, std::string proxy)
int curlPost(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData) int curlPost(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData)
{ {
CURL *curl_handle; CURL *curl_handle;
CURLcode res;
struct curl_slist *list = NULL; struct curl_slist *list = NULL;
int retVal = 0; int retVal = 0;
CURLcode res; curl_init();
curl_global_init(CURL_GLOBAL_ALL);
curl_handle = curl_easy_init(); curl_handle = curl_easy_init();
list = curl_slist_append(list, "Content-Type: application/json;charset='utf-8'"); list = curl_slist_append(list, "Content-Type: application/json;charset='utf-8'");
if(auth_token.size()) if(auth_token.size())
list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data()); list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data());
curl_easy_setopt(curl_handle, CURLOPT_URL, url.data()); curl_set_common_options(curl_handle, url.data());
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, print_debug_info ? 1L : 0L);
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl_handle, CURLOPT_POST, 1L); curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data()); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data());
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, data.size()); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, data.size());
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L);
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, retData); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, retData);
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list);
@ -169,17 +178,18 @@ int curlPost(std::string url, std::string data, std::string proxy, std::string a
} }
curl_easy_cleanup(curl_handle); curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return retVal; return retVal;
} }
int curlPatch(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData) int curlPatch(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData)
{ {
CURL *curl_handle; CURL *curl_handle;
CURLcode res;
int retVal = 0; int retVal = 0;
struct curl_slist *list = NULL; struct curl_slist *list = NULL;
CURLcode res = curl_global_init(CURL_GLOBAL_ALL); curl_init();
curl_handle = curl_easy_init(); curl_handle = curl_easy_init();
@ -187,16 +197,10 @@ int curlPatch(std::string url, std::string data, std::string proxy, std::string
if(auth_token.size()) if(auth_token.size())
list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data()); list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data());
curl_easy_setopt(curl_handle, CURLOPT_URL, url.data()); curl_set_common_options(curl_handle, url.data());
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, print_debug_info ? 1L : 0L);
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "PATCH"); curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data()); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data());
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, data.size()); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, data.size());
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L);
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, retData); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, retData);
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, list);
@ -212,6 +216,6 @@ int curlPatch(std::string url, std::string data, std::string proxy, std::string
} }
curl_easy_cleanup(curl_handle); curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return retVal; return retVal;
} }

View File

@ -32,7 +32,7 @@ std::vector<responseRoute> responses;
static inline void buffer_cleanup(struct evbuffer *eb) static inline void buffer_cleanup(struct evbuffer *eb)
{ {
evbuffer_free(eb); //evbuffer_free(eb);
#ifdef MALLOC_TRIM #ifdef MALLOC_TRIM
malloc_trim(0); malloc_trim(0);
#endif // MALLOC_TRIM #endif // MALLOC_TRIM
@ -102,8 +102,8 @@ void OnReq(evhttp_request *req, void *args)
std::map<std::string, std::string> extra_headers; std::map<std::string, std::string> extra_headers;
retVal = process_request(req_method, uri, postdata, content_type, return_data, &status_code, extra_headers); retVal = process_request(req_method, uri, postdata, content_type, return_data, &status_code, extra_headers);
//auto *OutBuf = evhttp_request_get_output_buffer(req); auto *OutBuf = evhttp_request_get_output_buffer(req);
struct evbuffer *OutBuf = evbuffer_new(); //struct evbuffer *OutBuf = evbuffer_new();
if (!OutBuf) if (!OutBuf)
return; return;
@ -168,6 +168,7 @@ int start_web_server(void *argv)
evhttp_set_allowed_methods(Server.get(), EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS); evhttp_set_allowed_methods(Server.get(), EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS);
evhttp_set_gencb(Server.get(), OnReq, nullptr); evhttp_set_gencb(Server.get(), OnReq, nullptr);
evhttp_set_timeout(Server.get(), 30);
if (event_dispatch() == -1) if (event_dispatch() == -1)
{ {
std::cerr << "Failed to run message loop." << std::endl; std::cerr << "Failed to run message loop." << std::endl;
@ -253,6 +254,7 @@ int start_web_server_multi(void *argv)
evhttp_set_allowed_methods(httpd, EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS); evhttp_set_allowed_methods(httpd, EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_OPTIONS);
evhttp_set_gencb(httpd, OnReq, nullptr); evhttp_set_gencb(httpd, OnReq, nullptr);
evhttp_set_timeout(httpd, 30);
ret = pthread_create(&ths[i], NULL, httpserver_dispatch, base[i]); ret = pthread_create(&ths[i], NULL, httpserver_dispatch, base[i]);
if (ret != 0) if (ret != 0)
return -1; return -1;