Optimizations

Fix stream/time node matcher not working with YAML configuration.
Add PCRE2 JIT optimization for filtering nodes.
Add space after adding proxy type to node remarks.
Add displaying Subscription User Info when generating artifacts in generator mode.
Add support for another type of time node.
Optimize codes.
This commit is contained in:
Tindy X committed 2020-03-02 17:37:26 +08:00
1 parent 1b6e877724
commit 849483fd43
6 files changed
+192 -20

No files matched your search

+2
View File
@@ -22,10 +22,12 @@ userinfo:
- {match: "^剩余流量:(.*?) (.*)$", replace: "total=$1&left=$2"} - {match: "^剩余流量:(.*?) (.*)$", replace: "total=$1&left=$2"}
- {match: "^Bandwidth: (.*?)/(.*)$", replace: "used=$1&total=$2"} - {match: "^Bandwidth: (.*?)/(.*)$", replace: "used=$1&total=$2"}
- {match: "^.*剩余(.*?)(?:\\s*?)@(?:.*)$", replace: "total=$1"} - {match: "^.*剩余(.*?)(?:\\s*?)@(?:.*)$", replace: "total=$1"}
- {match: "^.*?流量:(.*?) 剩:(?:.*)$", replace: "total=$1"}
time_rule: time_rule:
- {match: "^过期时间:(\\d+)-(\\d+)-(\\d+) (\\d+):(\\d+):(\\d+)$", replace: "$1:$2:$3:$4:$5:$6"} - {match: "^过期时间:(\\d+)-(\\d+)-(\\d+) (\\d+):(\\d+):(\\d+)$", replace: "$1:$2:$3:$4:$5:$6"}
- {match: "^到期时间:(\\d+)-(\\d+)-(\\d+)$", replace: "$1:$2:$3:0:0:0"} - {match: "^到期时间:(\\d+)-(\\d+)-(\\d+)$", replace: "$1:$2:$3:0:0:0"}
- {match: "^Smart Access expire: (\\d+)/(\\d+)/(\\d+)$", replace: "$1:$2:$3:0:0:0"} - {match: "^Smart Access expire: (\\d+)/(\\d+)/(\\d+)$", replace: "$1:$2:$3:0:0:0"}
- {match: "^.*?流量:(?:.*?) 剩:(.*?)天$", replace: "left=$1d"}
node_pref: node_pref:
udp_flag: false udp_flag: false
+1
View File
@@ -63,6 +63,7 @@ stream_rule=^.*?流量:(.*?) 剩:(?:.*)$|total=$1
time_rule=^过期时间:(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$|$1:$2:$3:$4:$5:$6 time_rule=^过期时间:(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)$|$1:$2:$3:$4:$5:$6
time_rule=^到期时间:(\d+)-(\d+)-(\d+)$|$1:$2:$3:0:0:0 time_rule=^到期时间:(\d+)-(\d+)-(\d+)$|$1:$2:$3:0:0:0
time_rule=^Smart Access expire: (\d+)/(\d+)/(\d+)$|$1:$2:$3:0:0:0 time_rule=^Smart Access expire: (\d+)/(\d+)/(\d+)$|$1:$2:$3:0:0:0
time_rule=^.*?流量:(?:.*?) 剩:(.*)$|left=$1d
[node_pref] [node_pref]
udp_flag=false udp_flag=false
+75 -5
View File
@@ -418,13 +418,13 @@ void readYAMLConf(YAML::Node &node)
section = node["userinfo"]; section = node["userinfo"];
if(section["stream_rule"].IsSequence()) if(section["stream_rule"].IsSequence())
{ {
readRegexMatch(section["stream_rule"], "@", tempArray); readRegexMatch(section["stream_rule"], "|", tempArray);
safe_set_streams(tempArray); safe_set_streams(tempArray);
eraseElements(tempArray); eraseElements(tempArray);
} }
if(section["time_rule"].IsSequence()) if(section["time_rule"].IsSequence())
{ {
readRegexMatch(section["time_rule"], "@", tempArray); readRegexMatch(section["time_rule"], "|", tempArray);
safe_set_times(tempArray); safe_set_times(tempArray);
eraseElements(tempArray); eraseElements(tempArray);
} }
@@ -1697,6 +1697,67 @@ std::string getRewriteRemote(RESPONSE_CALLBACK_ARGS)
return output_content; return output_content;
} }
static inline std::string intToStream(unsigned long long stream)
{
char chrs[16] = {};
double streamval = stream;
int level = 0;
while(streamval > 1024.0)
{
if(level >= 5)
break;
level++;
streamval /= 1024.0;
}
switch(level)
{
case 3:
snprintf(chrs, 15, "%.2f GB", streamval);
break;
case 4:
snprintf(chrs, 15, "%.2f TB", streamval);
break;
case 5:
snprintf(chrs, 15, "%.2f PB", streamval);
break;
case 2:
snprintf(chrs, 15, "%.2f MB", streamval);
break;
case 1:
snprintf(chrs, 15, "%.2f KB", streamval);
break;
case 0:
snprintf(chrs, 15, "%.2f B", streamval);
break;
}
return std::string(chrs);
}
std::string subInfoToMessage(std::string subinfo)
{
typedef unsigned long long ull;
subinfo = replace_all_distinct(subinfo, "; ", "&");
std::string retdata, useddata = "N/A", totaldata = "N/A", expirydata = "N/A";
std::string upload = getUrlArg(subinfo, "upload"), download = getUrlArg(subinfo, "download"), total = getUrlArg(subinfo, "total"), expire = getUrlArg(subinfo, "expire");
ull used = to_number<ull>(upload, 0) + to_number<ull>(download, 0), tot = to_number<ull>(total, 0);
time_t expiry = to_number<time_t>(expire, 0);
if(used != 0)
useddata = intToStream(used);
if(tot != 0)
totaldata = intToStream(tot);
if(expiry != 0)
{
char buffer[30];
struct tm *dt = localtime(&expiry);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M", dt);
expirydata.assign(buffer);
}
if(useddata == "N/A" && totaldata == "N/A" && expirydata == "N/A")
retdata = "Not Available";
else
retdata += "Stream Used: " + useddata + " Stream Total: " + totaldata + " Expiry Time: " + expirydata;
return retdata;
}
int simpleGenerator() int simpleGenerator()
{ {
@@ -1740,7 +1801,7 @@ int simpleGenerator()
string_multimap allItems; string_multimap allItems;
std::string dummy_str; std::string dummy_str;
std::map<std::string, std::string> dummy_map; std::map<std::string, std::string> headers;
int ret_code = 200; int ret_code = 200;
for(std::string &x : sections) for(std::string &x : sections)
{ {
@@ -1758,7 +1819,7 @@ int simpleGenerator()
if(ini.ItemExist("profile")) if(ini.ItemExist("profile"))
{ {
profile = ini.Get("profile"); profile = ini.Get("profile");
content = getProfile("name=" + UrlEncode(profile) + "&token=" + access_token + "&expand=true", dummy_str, &ret_code, dummy_map); content = getProfile("name=" + UrlEncode(profile) + "&token=" + access_token + "&expand=true", dummy_str, &ret_code, headers);
} }
else else
{ {
@@ -1798,7 +1859,7 @@ int simpleGenerator()
arguments += y.first + "=" + UrlEncode(y.second) + "&"; arguments += y.first + "=" + UrlEncode(y.second) + "&";
} }
arguments.erase(arguments.size() - 1); arguments.erase(arguments.size() - 1);
content = subconverter(arguments, dummy_str, &ret_code, dummy_map); content = subconverter(arguments, dummy_str, &ret_code, headers);
} }
if(ret_code != 200) if(ret_code != 200)
{ {
@@ -1808,7 +1869,16 @@ int simpleGenerator()
continue; continue;
} }
fileWrite(path, content, true); fileWrite(path, content, true);
for(auto &y : headers)
{
if(regMatch(y.first, "(?i)Subscription-UserInfo"))
{
std::cerr<<"User Info for artifact '"<<x<<"': "<<subInfoToMessage(y.second)<<"\n";
break;
}
}
std::cerr<<"Artifact '"<<x<<"' generate SUCCESS!\n\n"; std::cerr<<"Artifact '"<<x<<"' generate SUCCESS!\n\n";
eraseElements(headers);
} }
std::cerr<<"All artifact generated. Exiting...\n"; std::cerr<<"All artifact generated. Exiting...\n";
return 0; return 0;
+1
View File
@@ -27,6 +27,7 @@ typedef jpcre2::select<char> jp;
#include "misc.h" #include "misc.h"
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
//#include <io.h> //#include <io.h>
#include <windows.h> #include <windows.h>
#include <winreg.h> #include <winreg.h>
+106 -9
View File
@@ -1,9 +1,10 @@
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <time.h> #include <time.h>
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#include <rapidjson/document.h> #include <rapidjson/document.h>
#include "misc.h" #include "misc.h"
@@ -1423,14 +1424,14 @@ bool chkIgnore(const nodeInfo &node, string_array &exclude_remarks, string_array
bool excluded = false, included = false; bool excluded = false, included = false;
//std::string remarks = UTF8ToACP(node.remarks); //std::string remarks = UTF8ToACP(node.remarks);
std::string remarks = node.remarks; std::string remarks = node.remarks;
writeLog(LOG_TYPE_INFO, "Comparing exclude remarks..."); //writeLog(LOG_TYPE_INFO, "Comparing exclude remarks...");
excluded = std::any_of(exclude_remarks.cbegin(), exclude_remarks.cend(), [&remarks](auto &x) excluded = std::any_of(exclude_remarks.cbegin(), exclude_remarks.cend(), [&remarks](auto &x)
{ {
return regFind(remarks, x); return regFind(remarks, x);
}); });
if(include_remarks.size() != 0) if(include_remarks.size() != 0)
{ {
writeLog(LOG_TYPE_INFO, "Comparing include remarks..."); //writeLog(LOG_TYPE_INFO, "Comparing include remarks...");
included = std::any_of(include_remarks.cbegin(), include_remarks.cend(), [&remarks](auto &x) included = std::any_of(include_remarks.cbegin(), include_remarks.cend(), [&remarks](auto &x)
{ {
return regFind(remarks, x); return regFind(remarks, x);
@@ -1582,8 +1583,9 @@ void explodeSub(std::string sub, bool sslibev, bool ssrlibev, std::string custom
void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks, int groupID) void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, string_array &include_remarks, int groupID)
{ {
int index = 0; int node_index = 0;
std::vector<nodeInfo>::iterator iter = nodes.begin(); std::vector<nodeInfo>::iterator iter = nodes.begin();
/*
while(iter != nodes.end()) while(iter != nodes.end())
{ {
if(chkIgnore(*iter, exclude_remarks, include_remarks)) if(chkIgnore(*iter, exclude_remarks, include_remarks))
@@ -1594,12 +1596,92 @@ void filterNodes(std::vector<nodeInfo> &nodes, string_array &exclude_remarks, st
else else
{ {
writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been added."); writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been added.");
iter->id = index; iter->id = node_index;
iter->groupID = groupID; iter->groupID = groupID;
++index; ++node_index;
++iter; ++iter;
} }
} }
*/
bool excluded = false, included = false;
std::vector<std::unique_ptr<pcre2_code, decltype(&pcre2_code_free)>> exclude_patterns, include_patterns;
std::vector<std::unique_ptr<pcre2_match_data, decltype(&pcre2_match_data_free)>> exclude_match_data, include_match_data;
unsigned int i = 0;
PCRE2_SIZE erroroffset;
int errornumber, rc;
for(i = 0; i < exclude_remarks.size(); i++)
{
std::unique_ptr<pcre2_code, decltype(&pcre2_code_free)> pattern(pcre2_compile(reinterpret_cast<const unsigned char*>(exclude_remarks[i].c_str()), PCRE2_ZERO_TERMINATED | PCRE2_MULTILINE, 0, &errornumber, &erroroffset, NULL), &pcre2_code_free);
if(!pattern)
return;
exclude_patterns.push_back(std::move(pattern));
pcre2_jit_compile(exclude_patterns[i].get(), 0);
std::unique_ptr<pcre2_match_data, decltype(&pcre2_match_data_free)> match_data(pcre2_match_data_create_from_pattern(exclude_patterns[i].get(), NULL), &pcre2_match_data_free);
exclude_match_data.push_back(std::move(match_data));
}
for(i = 0; i < include_remarks.size(); i++)
{
std::unique_ptr<pcre2_code, decltype(&pcre2_code_free)> pattern(pcre2_compile(reinterpret_cast<const unsigned char*>(include_remarks[i].c_str()), PCRE2_ZERO_TERMINATED | PCRE2_MULTILINE, 0, &errornumber, &erroroffset, NULL), &pcre2_code_free);
if(!pattern)
return;
include_patterns.push_back(std::move(pattern));
pcre2_jit_compile(include_patterns[i].get(), 0);
std::unique_ptr<pcre2_match_data, decltype(&pcre2_match_data_free)> match_data(pcre2_match_data_create_from_pattern(include_patterns[i].get(), NULL), &pcre2_match_data_free);
include_match_data.push_back(std::move(match_data));
}
writeLog(LOG_TYPE_INFO, "Filter started.");
while(iter != nodes.end())
{
excluded = false;
included = false;
for(i = 0; i < exclude_patterns.size(); i++)
{
rc = pcre2_match(exclude_patterns[i].get(), reinterpret_cast<const unsigned char*>(iter->remarks.c_str()), iter->remarks.size(), 0, 0, exclude_match_data[i].get(), NULL);
if (rc < 0)
{
switch(rc)
{
case PCRE2_ERROR_NOMATCH: break;
default: return;
}
}
else
excluded = true;
}
if(include_patterns.size() > 0)
for(i = 0; i < include_patterns.size(); i++)
{
rc = pcre2_match(include_patterns[i].get(), reinterpret_cast<const unsigned char*>(iter->remarks.c_str()), iter->remarks.size(), 0, 0, include_match_data[i].get(), NULL);
if (rc < 0)
{
switch(rc)
{
case PCRE2_ERROR_NOMATCH: break;
default: return;
}
}
else
included = true;
}
else
included = true;
if(excluded || !included)
{
writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been ignored and will not be added.");
nodes.erase(iter);
}
else
{
writeLog(LOG_TYPE_INFO, "Node " + iter->group + " - " + iter->remarks + " has been added.");
iter->id = node_index;
iter->groupID = groupID;
++node_index;
++iter;
}
}
writeLog(LOG_TYPE_INFO, "Filter done.");
} }
static inline unsigned long long streamToInt(std::string stream) static inline unsigned long long streamToInt(std::string stream)
@@ -1629,12 +1711,26 @@ static inline double percentToDouble(std::string percent)
time_t dateStringToTimestamp(std::string date) time_t dateStringToTimestamp(std::string date)
{ {
time_t rawtime;
time(&rawtime);
if(startsWith(date, "left="))
{
time_t seconds_left = 0;
date.erase(0, 5);
if(endsWith(date, "d"))
{
date.erase(date.size() - 1);
seconds_left = to_number<double>(date, 0.0) * 86400.0;
}
return rawtime + seconds_left;
}
else
{
struct tm *expire_time;
std::vector<std::string> date_array = split(date, ":"); std::vector<std::string> date_array = split(date, ":");
if(date_array.size() != 6) if(date_array.size() != 6)
return 0; return 0;
time_t rawtime;
struct tm *expire_time;
time(&rawtime);
expire_time = localtime(&rawtime); expire_time = localtime(&rawtime);
expire_time->tm_year = to_int(date_array[0], 1900) - 1900; expire_time->tm_year = to_int(date_array[0], 1900) - 1900;
expire_time->tm_mon = to_int(date_array[1], 1) - 1; expire_time->tm_mon = to_int(date_array[1], 1) - 1;
@@ -1643,6 +1739,7 @@ time_t dateStringToTimestamp(std::string date)
expire_time->tm_min = to_int(date_array[4]); expire_time->tm_min = to_int(date_array[4]);
expire_time->tm_sec = to_int(date_array[5]); expire_time->tm_sec = to_int(date_array[5]);
return mktime(expire_time); return mktime(expire_time);
}
} }
bool getSubInfoFromHeader(std::string &header, std::string &result) bool getSubInfoFromHeader(std::string &header, std::string &result)
+7 -6
View File
@@ -677,7 +677,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
type = GetMember(json, "Type"); type = GetMember(json, "Type");
if(ext.append_proxy_type) if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks; x.remarks = "[" + type + "] " + x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0) while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$"; x.remarks += "$";
@@ -928,6 +928,7 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
ini.store_any_line = true; ini.store_any_line = true;
// filter out sections that requires direct-save // filter out sections that requires direct-save
ini.AddDirectSaveSection("Rule"); ini.AddDirectSaveSection("Rule");
ini.AddDirectSaveSection("MITM");
ini.AddDirectSaveSection("Script"); ini.AddDirectSaveSection("Script");
ini.AddDirectSaveSection("URL Rewrite"); ini.AddDirectSaveSection("URL Rewrite");
ini.AddDirectSaveSection("Header Rewrite"); ini.AddDirectSaveSection("Header Rewrite");
@@ -962,7 +963,7 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
type = GetMember(json, "Type"); type = GetMember(json, "Type");
if(ext.append_proxy_type) if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks; x.remarks = "[" + type + "] " + x.remarks;
remark = x.remarks; remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0) while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
@@ -1466,7 +1467,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
type = GetMember(json, "Type"); type = GetMember(json, "Type");
if(ext.append_proxy_type) if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks; x.remarks = "[" + type + "] " + x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0) while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$"; x.remarks += "$";
@@ -1692,7 +1693,7 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
type = GetMember(json, "Type"); type = GetMember(json, "Type");
if(ext.append_proxy_type) if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks; x.remarks = "[" + type + "] " + x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0) while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)
x.remarks += "$"; x.remarks += "$";
@@ -2083,7 +2084,7 @@ void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rul
type = GetMember(json, "Type"); type = GetMember(json, "Type");
if(ext.append_proxy_type) if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks; x.remarks = "[" + type + "] " + x.remarks;
remark = x.remarks; remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0) while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
@@ -2254,7 +2255,7 @@ std::string netchToLoon(std::vector<nodeInfo> &nodes, std::string &base_conf, st
type = GetMember(json, "Type"); type = GetMember(json, "Type");
if(ext.append_proxy_type) if(ext.append_proxy_type)
x.remarks = "[" + type + "]" + x.remarks; x.remarks = "[" + type + "] " + x.remarks;
remark = x.remarks; remark = x.remarks;
while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0) while(std::count(remarks_list.begin(), remarks_list.end(), x.remarks) > 0)