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:
write_managed_config: true
managed_config_prefix: "http://127.0.0.1:25500"
config_update_interval: 86400
config_update_strict: false
quanx_device_id: ""
surge_external_proxy:
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.
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_ssr_path=/usr/bin/ssr-local

View File

@ -34,13 +34,14 @@ std::mutex on_configuring;
//preferences
string_array renames, emojis;
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;
int config_update_interval = 0;
std::string clash_rule_base;
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_ssr_path;
std::string surge_ssr_path, quanx_script_id;
//pre-compiled rule bases
YAML::Node clash_base;
@ -448,6 +449,9 @@ void readYAMLConf(YAML::Node &node)
section = node["managed_config"];
section["write_managed_config"] >> write_managed_config;
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())
@ -634,6 +638,12 @@ void readConf()
write_managed_config = ini.GetBool("write_managed_config");
if(ini.ItemExist("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");
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 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 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;
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::vector<ruleset_content> rca;
extra_settings ext;
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())
return "Invalid request!";
@ -944,6 +956,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
ext.nodelist = nodelist == "true";
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;
if(expand != "true")
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);
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")
@ -1151,7 +1165,8 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
uploadGist("surfboard", upload_path, output_content, true);
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")
{
@ -1247,14 +1262,18 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
{
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;
}
std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
{
std::string url = argument.size() <= 8 ? "" : argument.substr(8);
std::string base_content, output_content;
std::string base_content;
std::vector<nodeInfo> nodes;
string_array extra_group, extra_ruleset, include_remarks, exclude_remarks;
std::vector<ruleset_content> rca;
@ -1283,7 +1302,7 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
refreshRulesets(rulesets, 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;
if(proxy_subscription == "SYSTEM")
@ -1382,28 +1401,12 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS)
else
proxy = proxy_subscription;
std::string subInfo;
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);
//scan groups first, get potential policy-path
string_multimap section;
ini.GetItems("Proxy Group", section);
std::string name, type, content;
string_array links;
links.emplace_back(url);
YAML::Node singlegroup;
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));
else if(dummy_str_array[i].find("interval") == 0)
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
singlegroup["proxies"].push_back(trim(dummy_str_array[i]));
}
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();
ini.GetItems("Proxy", section);
for(auto &x : section)
@ -1509,7 +1537,7 @@ std::string surgeConfToClash(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)
{
*status_code = 403;
@ -1546,3 +1574,86 @@ std::string getProfile(RESPONSE_CALLBACK_ARGS)
query.erase(query.size() - 1);
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 readConf();
void generateBase();
std::string getScript(RESPONSE_CALLBACK_ARGS);
std::string getProfile(RESPONSE_CALLBACK_ARGS);
std::string getRuleset(RESPONSE_CALLBACK_ARGS);
std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS);
std::string subconverter(RESPONSE_CALLBACK_ARGS);
std::string simpleToClashR(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", "/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
{
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()
{
guarded_mutex guard(clash_base_mutex);
return clash_base;
return YAML::Clone(clash_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)
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)

View File

@ -32,6 +32,7 @@ struct extra_settings
bool filter_deprecated = false;
std::string surge_ssr_path;
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);

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 = "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)
{
if(writerData == NULL)
@ -28,22 +38,28 @@ static int writer(char *data, size_t size, size_t nmemb, std::string *writerData
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;
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_URL, url);
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_NOSIGNAL, 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_VERIFYHOST, 0L);
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 15L);
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_WRITEDATA, &data);
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)
{
CURL *curl_handle;
CURLcode res;
struct curl_slist *list = NULL;
int retVal = 0;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl_init();
curl_handle = curl_easy_init();
list = curl_slist_append(list, "Content-Type: application/json;charset='utf-8'");
if(auth_token.size())
list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data());
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_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L);
curl_set_common_options(curl_handle, url.data());
curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data());
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_WRITEDATA, retData);
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_global_cleanup();
return retVal;
}
int curlPatch(std::string url, std::string data, std::string proxy, std::string auth_token, std::string *retData)
{
CURL *curl_handle;
CURLcode res;
int retVal = 0;
struct curl_slist *list = NULL;
CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
curl_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())
list = curl_slist_append(list, std::string("Authorization: token " + auth_token).data());
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_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L);
curl_set_common_options(curl_handle, url.data());
curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data.data());
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_WRITEDATA, retData);
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_global_cleanup();
return retVal;
}

View File

@ -32,7 +32,7 @@ std::vector<responseRoute> responses;
static inline void buffer_cleanup(struct evbuffer *eb)
{
evbuffer_free(eb);
//evbuffer_free(eb);
#ifdef MALLOC_TRIM
malloc_trim(0);
#endif // MALLOC_TRIM
@ -102,8 +102,8 @@ void OnReq(evhttp_request *req, void *args)
std::map<std::string, std::string> 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);
struct evbuffer *OutBuf = evbuffer_new();
auto *OutBuf = evhttp_request_get_output_buffer(req);
//struct evbuffer *OutBuf = evbuffer_new();
if (!OutBuf)
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_gencb(Server.get(), OnReq, nullptr);
evhttp_set_timeout(Server.get(), 30);
if (event_dispatch() == -1)
{
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_gencb(httpd, OnReq, nullptr);
evhttp_set_timeout(httpd, 30);
ret = pthread_create(&ths[i], NULL, httpserver_dispatch, base[i]);
if (ret != 0)
return -1;