Bug fixes

Add custom proxy groups and rulesets with URI arguments.
Fix when running Linux version, if a request URI is too long, the program will crash.
Optimize codes.
Update LAN ruleset.
This commit is contained in:
Tindy X
2019-12-03 20:54:40 +08:00
parent db0a8e52cf
commit 7804cc4a05
8 changed files with 161 additions and 58 deletions

View File

@@ -7,6 +7,7 @@
typedef std::map<std::string, std::multimap<std::string, std::string>> ini_data_struct;
typedef std::multimap<std::string, std::string> string_multimap;
typedef std::vector<std::string> string_array;
class INIReader
{
@@ -31,13 +32,9 @@ private:
bool chkIgnore(std::string section)
{
bool excluded = false, included = false;
if(count(exclude_sections.begin(), exclude_sections.end(), section) > 0)
excluded = true;
if(include_sections.size() != 0)
{
if(count(include_sections.begin(), include_sections.end(), section) > 0)
included = true;
}
excluded = std::find(exclude_sections.cbegin(), exclude_sections.cend(), section) != exclude_sections.cend();
if(include_sections.size())
included = std::find(include_sections.cbegin(), include_sections.cend(), section) != include_sections.cend();
else
included = true;

View File

@@ -17,6 +17,7 @@
#include "multithread.h"
//common settings
std::string pref_path = "pref.ini";
string_array def_exclude_remarks, def_include_remarks, rulesets;
std::vector<ruleset_content> ruleset_content_array;
std::string listen_address = "127.0.0.1", default_url, managed_config_prefix;
@@ -61,10 +62,9 @@ void setcd(char *argv[])
}
std::string refreshRulesets()
std::string refreshRulesets(string_array &ruleset_list, std::vector<ruleset_content> &rca)
{
guarded_mutex guard(on_configuring);
eraseElements(ruleset_content_array);
eraseElements(rca);
std::string rule_group, rule_url;
ruleset_content rc;
@@ -76,7 +76,7 @@ std::string refreshRulesets()
else
proxy = proxy_ruleset;
for(std::string &x : rulesets)
for(std::string &x : ruleset_list)
{
/*
vArray = split(x, ",");
@@ -93,7 +93,7 @@ std::string refreshRulesets()
{
std::cerr<<"Adding rule '"<<rule_url.substr(2)<<","<<rule_group<<"'."<<std::endl;
rc = {rule_group, "", rule_url};
ruleset_content_array.emplace_back(rc);
rca.emplace_back(rc);
continue;
}
else
@@ -103,13 +103,15 @@ std::string refreshRulesets()
{
rc = {rule_group, rule_url, fileGet(rule_url, false)};
}
else
else if(rule_url.find("http://") == 0 || rule_url.find("https://") == 0)
{
rc = {rule_group, rule_url, webGet(rule_url, proxy)};
}
else
continue;
}
if(rc.rule_content.size())
ruleset_content_array.emplace_back(rc);
rca.emplace_back(rc);
else
std::cerr<<"Warning: No data was fetched from this link. Skipping..."<<std::endl;
}
@@ -127,8 +129,9 @@ void readConf()
eraseElements(rulesets);
string_array emojis_temp, renames_temp;
INIReader ini;
ini.allow_dup_section_titles = true;
//ini.do_utf8_to_gbk = true;
ini.ParseFile("pref.ini");
ini.ParseFile(pref_path);
ini.EnterSection("common");
if(ini.ItemExist("api_mode"))
@@ -227,9 +230,46 @@ 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"));
std::string base_content, output_content;
string_array extra_group, include_remarks, exclude_remarks;
std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups"));
extra_group = split(groups, "`");
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"));
std::vector<ruleset_content> rca;
if(!url.size())
url = default_url;
if(!url.size() || !target.size())
return "Invalid request!";
if(!api_mode || cfw_child_process)
readConf();
if(groups.size())
{
extra_group = split(groups, "@");
if(!extra_group.size())
extra_group = clash_extra_group;
}
else
extra_group = clash_extra_group;
if(ruleset.size())
{
extra_ruleset = split(ruleset, "@");
if(!extra_ruleset.size())
{
if(update_ruleset_on_request || cfw_child_process)
refreshRulesets(rulesets, ruleset_content_array);
rca = ruleset_content_array;
}
else
{
refreshRulesets(extra_ruleset, rca);
}
}
else
{
if(update_ruleset_on_request || cfw_child_process)
refreshRulesets(rulesets, ruleset_content_array);
rca = ruleset_content_array;
}
extra_settings ext;
if(emoji == "true")
@@ -259,13 +299,6 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
ext.nodelist = nodelist == "true";
ext.surge_ssr_path = surge_ssr_path;
if(!url.size())
url = default_url;
if(!url.size() || !target.size())
return "Invalid request!";
if(!api_mode || cfw_child_process)
readConf();
string_array urls = split(url, "|");
std::vector<nodeInfo> nodes;
int groupID = 0;
@@ -290,8 +323,6 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
}
if(!nodes.size())
return "No nodes were found!";
if(update_ruleset_on_request || cfw_child_process)
refreshRulesets();
std::cerr<<"Generate target: ";
if(target == "clash" || target == "clashr")
@@ -302,21 +333,22 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
base_content = webGet(clash_rule_base, getSystemProxy());
output_content = netchToClash(nodes, base_content, ruleset_content_array, clash_extra_group, target == "clashr", ext);
output_content = netchToClash(nodes, base_content, rca, extra_group, target == "clashr", ext);
if(upload == "true")
uploadGist("clash", upload_path, output_content, false);
return output_content;
}
else if(target == "surge")
{
std::cerr<<"Surge "<<version<<std::endl;
int surge_ver = version.size() ? stoi(version) : 3;
int surge_ver = version.size() ? to_int(version, 3) : 3;
std::cerr<<"Surge "<<surge_ver<<std::endl;
if(fileExist(surge_rule_base))
base_content = fileGet(surge_rule_base, false);
else
base_content = webGet(surge_rule_base, getSystemProxy());
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, surge_ver, ext);
output_content = netchToSurge(nodes, base_content, rca, extra_group, surge_ver, ext);
if(upload == "true")
uploadGist("surge" + version, upload_path, output_content, true);
@@ -332,7 +364,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
base_content = webGet(surfboard_rule_base, getSystemProxy());
output_content = netchToSurge(nodes, base_content, ruleset_content_array, clash_extra_group, 2, ext);
output_content = netchToSurge(nodes, base_content, rca, extra_group, 2, ext);
if(upload == "true")
uploadGist("surfboard", upload_path, output_content, true);
@@ -348,7 +380,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
base_content = webGet(mellow_rule_base, getSystemProxy());
output_content = netchToMellow(nodes, base_content, ruleset_content_array, clash_extra_group, ext);
output_content = netchToMellow(nodes, base_content, rca, extra_group, ext);
if(upload == "true")
uploadGist("mellow", upload_path, output_content, true);
@@ -415,6 +447,8 @@ void chkArg(int argc, char *argv[])
{
if(strcmp(argv[i], "-cfw") == 0)
cfw_child_process = true;
else if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--file") == 0)
pref_path.assign(argv[++i]);
}
}
@@ -433,13 +467,14 @@ int main(int argc, char *argv[])
#ifndef _DEBUG
setcd(argv);
#endif // _DEBUG
chkArg(argc, argv);
readConf();
if(!update_ruleset_on_request)
refreshRulesets();
refreshRulesets(rulesets, ruleset_content_array);
append_response("GET", "/refreshrules", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
{
return refreshRulesets();
return refreshRulesets(rulesets, ruleset_content_array);
});
append_response("GET", "/readconf", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string

View File

@@ -402,6 +402,7 @@ std::string trim(const std::string& str)
std::string getUrlArg(std::string url, std::string request)
{
std::smatch result;
/*
if (regex_search(url.cbegin(), url.cend(), result, std::regex(request + "=(.*?)&")))
{
return result[1];
@@ -414,6 +415,15 @@ std::string getUrlArg(std::string url, std::string request)
{
return std::string();
}
*/
string_array vArray, arglist = split(url, "&");
for(std::string &x : arglist)
{
if(regex_search(x.cbegin(), x.cend(), result, std::regex("^" + request + "=(.*)$")))
return result[1];
}
return std::string();
}
std::string replace_all_distinct(std::string str, std::string old_value, std::string new_value)
@@ -429,24 +439,45 @@ std::string replace_all_distinct(std::string str, std::string old_value, std::st
}
bool regFind(std::string src, std::string target)
{
try
{
std::regex reg(target);
return regex_search(src, reg);
}
catch (std::regex_error &e)
{
return false;
}
}
std::string regReplace(std::string src, std::string match, std::string rep)
{
std::string result = "";
try
{
std::regex reg(match);
regex_replace(back_inserter(result), src.begin(), src.end(), reg, rep);
}
catch (std::regex_error &e)
{
result = src;
}
return result;
}
bool regMatch(std::string src, std::string match)
{
try
{
std::regex reg(match);
return regex_match(src, reg);
}
catch (std::regex_error &e)
{
return false;
}
}
std::string speedCalc(double speed)
{
@@ -735,6 +766,19 @@ std::string to_string(const YAML::Node &node)
return ss.str();
}
int to_int(std::string &s, int def_vaule)
{
int retval = 0;
char c;
std::stringstream ss(s);
if(!(ss >> retval))
return def_vaule;
else if(ss >> c)
return def_vaule;
else
return retval;
}
std::string getFormData(const std::string &raw_data)
{
std::stringstream strstrm;

1
misc.h
View File

@@ -52,6 +52,7 @@ void removeUTF8BOM(std::string &data);
int shortAssemble(unsigned short num_a, unsigned short num_b);
void shortDisassemble(int source, unsigned short &num_a, unsigned short &num_b);
std::string to_string(const YAML::Node &node);
int to_int(std::string &s, int def_vaule = 0);
std::string fileGet(std::string path, bool binary = true);
int fileWrite(std::string path, std::string content, bool overwrite);

View File

@@ -4,7 +4,7 @@ IP-CIDR,10.0.0.0/8
IP-CIDR,172.16.0.0/12
IP-CIDR,127.0.0.0/8
IP-CIDR,100.64.0.0/10
IP-CIDR,::1/128
IP-CIDR,fc00::/7
IP-CIDR,fe80::/10
IP-CIDR,fd00::/8
IP-CIDR6,::1/128
IP-CIDR6,fc00::/7
IP-CIDR6,fe80::/10
IP-CIDR6,fd00::/8

View File

@@ -610,7 +610,7 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
ini.SetCurrentSection("Proxy");
ini.EraseSection();
ini.Set("DIRECT", "direct");
ini.Set("{NONAME}", "DIRECT = direct");
for(nodeInfo &x : nodes)
{
json.Parse(x.proxyStr.data());

View File

@@ -10,6 +10,7 @@
#include "webserver.h"
typedef std::vector<std::string> string_array;
int def_timeout = 5;
struct responseRoute
{
@@ -21,7 +22,7 @@ struct responseRoute
std::vector<responseRoute> responses;
//for use of multi-thread socket test
//for use of multi-thread
typedef std::lock_guard<std::mutex> guarded_mutex;
int working_thread = 0, max_send_failure = 10;
bool SERVER_EXIT_FLAG = false;
@@ -206,6 +207,21 @@ void send_file(std::string arguments, int sock)
sendall(sock, "0\r\n\r\n");
}
int setTimeout(SOCKET s, int timeout)
{
int ret = -1;
#ifdef _WIN32
ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(int));
ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(int));
#else
struct timeval timeo = {0, timeout * 1000};
ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeo, sizeof(timeo));
ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeo, sizeof(timeo));
#endif
def_timeout = timeout;
return ret;
}
void handle_req(std::string request, int client_sock)
{
working_acc();
@@ -220,8 +236,7 @@ void handle_req(std::string request, int client_sock)
goto end;
}
printf("handle_cmd: %s\n", command);
printf("handle_path: %s\n", arguments);
std::cerr<<"handle_cmd: "<<command<<"\n"<<"handle_path: "<<arguments<<"\n";
vArray = split(arguments, "?");
@@ -277,7 +292,7 @@ void append_response(std::string type, std::string request, std::string content_
responses.push_back(rr);
}
void* start_web_server(void *argv)
int start_web_server_multi(void *argv)
{
//log startup
struct listener_args *args = (listener_args*)argv;
@@ -295,7 +310,7 @@ void* start_web_server(void *argv)
{
//log socket error
std::cerr<<"socket build error!"<<std::endl;
return NULL;
return 0;
}
ZeroMemory(&server_addr, sizeof(server_addr));
@@ -307,14 +322,14 @@ void* start_web_server(void *argv)
//log bind error
std::cerr<<"socket bind error!"<<std::endl;
closesocket(server_socket);
return NULL;
return 0;
}
if (listen(server_socket, max_conn) == -1 )
{
//log listen error
std::cerr<<"socket listen error!"<<std::endl;
closesocket(server_socket);
return NULL;
return 0;
}
setTimeout(server_socket, 500);

View File

@@ -2,6 +2,7 @@
#include <cstdint>
#include <iostream>
#include <evhttp.h>
#include <malloc.h>
#include <string>
#include <vector>
@@ -22,10 +23,18 @@ struct responseRoute
std::vector<responseRoute> responses;
static inline void buffer_cleanup(struct evbuffer *eb)
{
evbuffer_free(eb);
#ifdef MALLOC_TRIM
malloc_trim(0);
#endif // MALLOC_TRIM
}
static inline int process_request(const char *method_str, std::string uri, std::string &postdata, std::string &content_type, std::string &return_data)
{
std::string path, arguments;
//std::cerr << "handle_cmd: " << method_str << std::endl << "handle_uri: " << uri << std::endl;
std::cerr << "handle_cmd: " << method_str << std::endl << "handle_uri: " << uri << std::endl;
if(strFind(uri, "?"))
{
@@ -56,7 +65,7 @@ static inline int process_request(const char *method_str, std::string uri, std::
void OnReq(evhttp_request *req, void *args)
{
const char *req_content_type = evhttp_find_header(req->input_headers, "Content-Type"), *req_ac_method = evhttp_find_header(req->input_headers, "Access-Control-Request-Method");
const char *req_method = req_ac_method == NULL ? EVBUFFER_LENGTH(req->input_buffer) == 0 ? "GET" : "POST" : "OPTIONS", *uri = evhttp_request_get_uri(req);
const char *req_method = req_ac_method == NULL ? EVBUFFER_LENGTH(req->input_buffer) == 0 ? "GET" : "POST" : "OPTIONS", *uri = req->uri;
int retVal;
std::string postdata, content_type, return_data;
@@ -73,7 +82,8 @@ void OnReq(evhttp_request *req, void *args)
retVal = process_request(req_method, uri, postdata, content_type, return_data);
auto *OutBuf = evhttp_request_get_output_buffer(req);
//auto *OutBuf = evhttp_request_get_output_buffer(req);
struct evbuffer *OutBuf = evbuffer_new();
if (!OutBuf)
return;
@@ -83,7 +93,6 @@ void OnReq(evhttp_request *req, void *args)
evhttp_add_header(req->output_headers, "Access-Control-Allow-Origin", "*");
evhttp_add_header(req->output_headers, "Access-Control-Allow-Headers", "*");
evhttp_send_reply(req, HTTP_OK, "", NULL);
return;
break;
case 0: //found normal
if(content_type.size())
@@ -92,6 +101,7 @@ void OnReq(evhttp_request *req, void *args)
{
evhttp_add_header(req->output_headers, "Location", return_data.c_str());
evhttp_send_reply(req, HTTP_MOVETEMP, "", NULL);
buffer_cleanup(OutBuf);
return;
}
else
@@ -108,6 +118,7 @@ void OnReq(evhttp_request *req, void *args)
default: //undefined behavior
evhttp_send_error(req, HTTP_INTERNAL, "");
}
buffer_cleanup(OutBuf);
}
int start_web_server(void *argv)