Enhancements

Add Edge header support for Surge/Quantumult/Clash.
Fix configuration file not found when start up via right-click menu on some platform.
Optimize codes.
Clean up unused files.
This commit is contained in:
Tindy X 2020-02-17 15:00:48 +08:00
parent b0b2546d93
commit e2aacf853c
No known key found for this signature in database
GPG Key ID: C6AD413169968D58
17 changed files with 110 additions and 120 deletions

View File

@ -1,7 +0,0 @@
# > AbemaTV
USER-AGENT,AbemaTV*
DOMAIN-SUFFIX,abema.io
DOMAIN-SUFFIX,abema.tv
DOMAIN-SUFFIX,akamaized.net
DOMAIN-SUFFIX,ameba.jp
DOMAIN-SUFFIX,hayabusa.io

View File

@ -1,12 +0,0 @@
# > Apple News and Apple Map TOMTOM Version
DOMAIN,gspe1-ssl.ls.apple.com
PROCESS-NAME,News
USER-AGENT,AppleNews*
USER-AGENT,com.apple.news*
#USER-AGENT,News*
#DOMAIN,gateway.icloud.com
#DOMAIN,news-events.apple.com
#DOMAIN,apple.comscoreresearch.com
#DOMAIN-SUFFIX,apple.news
#DOMAIN,news-client.apple.com
#DOMAIN,news-edge.apple.com

View File

@ -1,6 +0,0 @@
# > BBC iPlayer
USER-AGENT,BBCiPlayer*
DOMAIN-SUFFIX,bbc.co.uk
DOMAIN-SUFFIX,bbci.co.uk
DOMAIN-KEYWORD,bbcfmt
DOMAIN-KEYWORD,uk-live

View File

@ -1,5 +0,0 @@
# > Fox Now
USER-AGENT,FOX%20NOW*
DOMAIN-SUFFIX,fox.com
DOMAIN-SUFFIX,foxdcg.com
DOMAIN-SUFFIX,uplynk.com

View File

@ -1,3 +0,0 @@
# > Hulu(フールー)
DOMAIN-SUFFIX,happyon.jp
DOMAIN-SUFFIX,hulu.jp

View File

@ -1,4 +0,0 @@
# > Line TV
USER-AGENT,LINE*
DOMAIN-SUFFIX,d3c7rimkq79yfu.cloudfront.net
DOMAIN-SUFFIX,linetv.tw

View File

@ -1,5 +0,0 @@
# > NeteaseMusic
USER-AGENT,%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90
USER-AGENT,NeteaseMusic*
DOMAIN-SUFFIX,music.126.net
DOMAIN-SUFFIX,music.163.com

View File

@ -1,3 +0,0 @@
# > Youtube_Music
USER-AGENT,*YouTubeMusic*
USER-AGENT,*com.google.ios.youtubemusic*

View File

@ -1,4 +0,0 @@
# > myTV_SUPER
USER-AGENT,mytv*
DOMAIN-SUFFIX,mytvsuper.com
DOMAIN-SUFFIX,tvb.com

View File

@ -61,6 +61,21 @@ void chkArg(int argc, char *argv[])
}
}
void signal_handler(int sig)
{
std::cerr<<"Interrupt signal "<<sig<<" received. Exiting gracefully...\n";
switch(sig)
{
#ifndef _WIN32
case SIGHUP:
case SIGQUIT:
#endif // _WIN32
case SIGTERM:
case SIGINT:
stop_web_server();
break;
}
}
int main(int argc, char *argv[])
{
#ifdef _WIN32
@ -74,13 +89,21 @@ int main(int argc, char *argv[])
#else
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
signal(SIGHUP, signal_handler);
signal(SIGQUIT, signal_handler);
#endif // _WIN32
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
SetConsoleTitle("subconverter " VERSION);
#ifndef _DEBUG
std::string prgpath = argv[0];
setcd(prgpath); //first switch to program directory
#endif // _DEBUG
if(fileExist("pref.yml"))
pref_path = "pref.yml";
chkArg(argc, argv);
setcd(pref_path);
setcd(pref_path); //then switch to pref directory
readConf();
if(!update_ruleset_on_request)
refreshRulesets(rulesets, ruleset_content_array);

View File

@ -94,7 +94,7 @@ void explodeVmess(std::string vmess, std::string custom_port, int local_port, no
node.remarks = ps;
node.server = add;
node.port = to_int(port, 0);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, "auto", path, host, tls, local_port);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, "auto", path, host, "", tls, local_port);
}
void explodeVmessConf(std::string content, std::string custom_port, int local_port, bool libev, std::vector<nodeInfo> &nodes)
@ -181,7 +181,7 @@ void explodeVmessConf(std::string content, std::string custom_port, int local_po
json["vmess"][i]["security"] >> cipher;
group = V2RAY_DEFAULT_GROUP;
node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS;
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, tls, local_port);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, "", tls, local_port);
break;
case 3: //ss config
json["vmess"][i]["id"] >> id;
@ -579,7 +579,7 @@ void explodeSocks(std::string link, std::string custom_port, nodeInfo &node)
void explodeQuan(std::string quan, std::string custom_port, int local_port, nodeInfo &node)
{
std::string strTemp, itemName, itemVal;
std::string group = V2RAY_DEFAULT_GROUP, ps, add, port, cipher = "auto", type = "none", id, aid = "0", net = "tcp", path, host, tls;
std::string group = V2RAY_DEFAULT_GROUP, ps, add, port, cipher = "auto", type = "none", id, aid = "0", net = "tcp", path, host, edge, tls;
std::vector<std::string> configs, vArray;
strTemp = regReplace(quan, "(.*?) = (.*)", "$1,$2");
configs = split(strTemp, ",");
@ -614,6 +614,8 @@ void explodeQuan(std::string quan, std::string custom_port, int local_port, node
{
if(strFind(headers[j], "Host: "))
host = headers[j].substr(6);
else if(strFind(headers[j], "Edge: "))
edge = headers[j].substr(6);
}
}
else if(itemName == "obfs" && itemVal == "ws")
@ -627,14 +629,14 @@ void explodeQuan(std::string quan, std::string custom_port, int local_port, node
node.remarks = ps;
node.server = add;
node.port = to_int(port, 0);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, tls, local_port);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, edge, tls, local_port);
}
}
void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, std::string custom_port, int local_port, nodeInfo &node)
{
Document json;
std::string type, remark, address, port, username, password, method, plugin, pluginopts, protocol, protoparam, obfs, obfsparam, id, aid, transprot, faketype, host, path, tls;
std::string type, remark, address, port, username, password, method, plugin, pluginopts, protocol, protoparam, obfs, obfsparam, id, aid, transprot, faketype, host, edge, path, tls;
netch = urlsafe_base64_decode(netch.substr(8));
json.Parse(netch.data());
@ -685,10 +687,11 @@ void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, std::string
faketype = GetMember(json, "FakeType");
host = GetMember(json, "Host");
path = GetMember(json, "Path");
edge = GetMember(json, "Edge");
tls = GetMember(json, "TLSSecure") == "true" ? "tls" : "";
node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS;
node.group = V2RAY_DEFAULT_GROUP;
node.proxyStr = vmessConstruct(address, port, faketype, id, aid, transprot, method, path, host, tls, local_port);
node.proxyStr = vmessConstruct(address, port, faketype, id, aid, transprot, method, path, host, edge, tls, local_port);
}
else if(type == "Socks5")
{
@ -711,7 +714,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
Node singleproxy;
unsigned int index = nodes.size();
std::string proxytype, ps, server, port, cipher, group, password; //common
std::string type = "none", id, aid = "0", net = "tcp", path, host, tls; //vmess
std::string type = "none", id, aid = "0", net = "tcp", path, host, edge, tls; //vmess
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, pluginopts_mux; //ss
std::string protocol, protoparam, obfs, obfsparam; //ssr
std::string user; //socks
@ -736,13 +739,16 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
else
tls.clear();
if(singleproxy["ws-headers"].IsDefined())
{
singleproxy["ws-headers"]["Host"] >> host;
singleproxy["ws-headers"]["Edge"] >> edge;
}
else
host.clear();
node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS;
node.proxyStr = vmessConstruct(server, port, type, id, aid, net, cipher, path, host, tls, local_port);
node.proxyStr = vmessConstruct(server, port, type, id, aid, net, cipher, path, host, edge, tls, local_port);
}
else if(proxytype == "ss")
{
@ -940,7 +946,7 @@ void explodeShadowrocket(std::string rocket, std::string custom_port, int local_
node.remarks = remarks;
node.server = add;
node.port = to_int(port, 0);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, tls, local_port);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, "", tls, local_port);
}
void explodeKitsunebi(std::string kit, std::string custom_port, int local_port, nodeInfo &node)
@ -985,14 +991,14 @@ void explodeKitsunebi(std::string kit, std::string custom_port, int local_port,
node.remarks = remarks;
node.server = add;
node.port = to_int(port, 0);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, tls, local_port);
node.proxyStr = vmessConstruct(add, port, type, id, aid, net, cipher, path, host, "", tls, local_port);
}
bool explodeSurge(std::string surge, std::string custom_port, int local_port, std::vector<nodeInfo> &nodes, bool libev)
{
std::string remarks, server, port, method, username, password; //common
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host = "cloudfront.net", mod_url, mod_md5; //ss
std::string id, net, tls, host, path; //v2
std::string id, net, tls, host, edge, path; //v2
std::string protocol, protoparam; //ssr
std::string itemName, itemVal;
std::vector<std::string> configs, vArray, headers, header;
@ -1157,6 +1163,8 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
header = split(trim(y), ":");
if(header[0] == "Host")
host = header[1];
else if(header[0] == "Edge")
edge = header[1];
}
}
}
@ -1165,7 +1173,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS;
node.group = V2RAY_DEFAULT_GROUP;
node.proxyStr = vmessConstruct(server, port, "", id, "0", net, method, path, host, tls, local_port);
node.proxyStr = vmessConstruct(server, port, "", id, "0", net, method, path, host, edge, tls, local_port);
}
else if(configs[0] == "http") //http proxy
{
@ -1274,7 +1282,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS;
node.group = V2RAY_DEFAULT_GROUP;
node.proxyStr = vmessConstruct(server, port, "", id, "0", net, method, path, host, tls, local_port);
node.proxyStr = vmessConstruct(server, port, "", id, "0", net, method, path, host, "", tls, local_port);
}
else
continue;

View File

@ -7,7 +7,7 @@
#include "misc.h"
#include "nodeinfo.h"
std::string vmessConstruct(std::string add, std::string port, std::string type, std::string id, std::string aid, std::string net, std::string cipher, std::string path, std::string host, std::string tls, int local_port);
std::string vmessConstruct(std::string add, std::string port, std::string type, std::string id, std::string aid, std::string net, std::string cipher, std::string path, std::string host, std::string edge, std::string tls, int local_port);
std::string ssrConstruct(std::string group, std::string remarks, std::string remarks_base64, std::string server, std::string port, std::string protocol, std::string method, std::string obfs, std::string password, std::string obfsparam, std::string protoparam, int local_port, bool libev);
std::string ssConstruct(std::string server, std::string port, std::string password, std::string method, std::string plugin, std::string pluginopts, std::string remarks, int local_port, bool libev);
std::string socksConstruct(std::string remarks, std::string server, std::string port, std::string username, std::string password);

View File

@ -58,7 +58,7 @@ std::string hostnameToIPAddr(std::string host)
}
*/
std::string vmessConstruct(std::string add, std::string port, std::string type, std::string id, std::string aid, std::string net, std::string cipher, std::string path, std::string host, std::string tls, int local_port)
std::string vmessConstruct(std::string add, std::string port, std::string type, std::string id, std::string aid, std::string net, std::string cipher, std::string path, std::string host, std::string edge, std::string tls, int local_port)
{
if(!path.size())
path = "/";
@ -90,6 +90,8 @@ std::string vmessConstruct(std::string add, std::string port, std::string type,
writer.String(net.data());
writer.Key("Host");
writer.String(host.data());
writer.Key("Edge");
writer.String(edge.data());
if(net == "ws")
{
writer.Key("Path");
@ -557,7 +559,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
std::string type, remark, hostname, port, username, password, method;
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
std::string id, aid, transproto, faketype, host, path, quicsecure, quicsecret;
std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret;
std::vector<nodeInfo> nodelist;
bool tlssecure, replace_flag;
string_array vArray, remarks_list, filtered_nodelist;
@ -637,6 +639,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
aid = GetMember(json, "AlterID");
transproto = GetMember(json, "TransferProtocol");
host = GetMember(json, "Host");
edge = GetMember(json, "Edge");
path = GetMember(json, "Path");
tlssecure = GetMember(json, "TLSSecure") == "true";
singleproxy["type"] = "vmess";
@ -651,6 +654,12 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
singleproxy["network"] = transproto;
singleproxy["ws-path"] = path;
singleproxy["ws-headers"]["Host"] = host;
singleproxy["headers"]["Host"] = host;
if(edge.size())
{
singleproxy["ws-headers"]["Edge"] = edge;
singleproxy["headers"]["Edge"] = edge;
}
}
else if(transproto == "kcp" || transproto == "h2" || transproto == "quic")
continue;
@ -662,7 +671,7 @@ void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_arr
obfs = GetMember(json, "OBFS");
if(ext.filter_deprecated)
{
if(method == "chacha20")
if(method == "chacha20" && !clashR) //the mainline core no longer supports chacha20, but clashR core still does
continue;
if(std::find(clashr_protocols.cbegin(), clashr_protocols.cend(), protocol) == clashr_protocols.cend())
continue;
@ -805,7 +814,7 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
std::string type, remark, hostname, port, username, password, method;
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
std::string id, aid, transproto, faketype, host, path, quicsecure, quicsecret;
std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret;
std::string output_nodelist;
std::vector<nodeInfo> nodelist;
unsigned short local_port = 1080;
@ -886,12 +895,15 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
aid = GetMember(json, "AlterID");
transproto = GetMember(json, "TransferProtocol");
host = GetMember(json, "Host");
edge = GetMember(json, "Edge");
path = GetMember(json, "Path");
tlssecure = GetMember(json, "TLSSecure") == "true";
proxy = "vmess, " + hostname + ", " + port + ", username=" + id + ", tls=" + (tlssecure ? "true" : "false");
if(transproto == "ws")
{
proxy += ", ws=true, ws-path=" + path + ", ws-headers=Host:" + host;
if(edge.size())
proxy += "|Edge:" + edge;
}
if(ext.skip_cert_verify)
proxy += ", skip-cert-verify=1";
@ -1317,7 +1329,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
std::string remark, hostname, port, method, password;
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
std::string id, aid, transproto, faketype, host, path, quicsecure, quicsecret;
std::string id, aid, transproto, faketype, host, edge, path, quicsecure, quicsecret;
std::string proxyStr, allLinks;
bool tlssecure;
std::vector<nodeInfo> nodelist;
@ -1369,6 +1381,7 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
transproto = GetMember(json, "TransferProtocol");
host = GetMember(json, "Host");
path = GetMember(json, "Path");
edge = GetMember(json, "Edge");
faketype = GetMember(json, "FakeType");
tlssecure = GetMember(json, "TLSSecure") == "true";
@ -1378,7 +1391,12 @@ void netchToQuan(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rules
if(tlssecure)
proxyStr += ", over-tls=true, tls-host=" + host;
if(transproto == "ws")
proxyStr += ", obfs=ws, obfs-path=\"" + path + "\", obfs-header=\"Host: " + host + "\"";
{
proxyStr += ", obfs=ws, obfs-path=\"" + path + "\", obfs-header=\"Host: " + host;
if(edge.size())
proxyStr += "[Rr][Nn]Edge: " + edge;
proxyStr += "\"";
}
if(ext.nodelist)
proxyStr = "vmess://" + urlsafe_base64_encode(proxyStr);

View File

@ -1,7 +1,7 @@
#include <iostream>
#include <fstream>
#include <map>
#include <mutex>
#include <atomic>
#include <thread>
#include <pthread.h>
@ -23,44 +23,9 @@ struct responseRoute
std::vector<responseRoute> responses;
//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;
std::mutex working_mutex, server_exit_flag_mutex;
static inline void working_acc()
{
guarded_mutex guard(working_mutex);
working_thread++;
}
static inline void working_dec()
{
guarded_mutex guard(working_mutex);
working_thread--;
}
static inline int safe_read_working()
{
int retVal;
guarded_mutex guard(working_mutex);
retVal = working_thread;
return retVal;
}
static inline bool safe_read_server_exit_flag()
{
bool retVal;
guarded_mutex guard(server_exit_flag_mutex);
retVal = SERVER_EXIT_FLAG;
return retVal;
}
static inline void safe_set_server_exit_flag()
{
guarded_mutex guard(server_exit_flag_mutex);
SERVER_EXIT_FLAG = true;
}
int max_send_failure = 10;
std::atomic_bool SERVER_EXIT_FLAG(false);
std::atomic_int working_thread(0)
int sendall(SOCKET sock, std::string data)
{
@ -214,7 +179,7 @@ int setTimeout(SOCKET s, int timeout)
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};
struct timeval timeo = {timeout / 1000, (timeout % 1000) * 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
@ -224,7 +189,7 @@ int setTimeout(SOCKET s, int timeout)
void handle_req(std::string request, int client_sock)
{
working_acc();
working_thread++;
std::cerr<<"worker startup"<<std::endl;
string_array vArray;
char command[16] = {};
@ -279,7 +244,7 @@ end:
std::cerr<<"worker stop"<<std::endl;
sleep(1);
closesocket(client_sock);
working_dec();
working_thread--;
}
void append_response(std::string type, std::string request, std::string content_type, response_callback response)
@ -292,6 +257,18 @@ void append_response(std::string type, std::string request, std::string content_
responses.push_back(rr);
}
void stop_web_server()
{
SERVER_EXIT_FLAG = true;
}
int start_web_server(void *argv)
{
struct listener_args *args = (listener_args*)argv;
args->max_workers = 1;
return start_web_server_multi(args);
}
int start_web_server_multi(void *argv)
{
//log startup
@ -373,10 +350,10 @@ int start_web_server_multi(void *argv)
//handle_req(buf, acc_socket);
while(safe_read_working() >= max_workers)
while(working_thread >= max_workers)
{
sleep(10);
if(safe_read_server_exit_flag())
if(SERVER_EXIT_FLAG)
break;
}
while(workers[worker_index].get_id() != std::thread::id())

View File

@ -16,5 +16,6 @@ struct listener_args
void append_response(std::string method, std::string uri, std::string content_type, response_callback response);
int start_web_server(void *argv);
int start_web_server_multi(void *argv);
void stop_web_server();
#endif // WEBSERVER_H_INCLUDED

View File

@ -2,6 +2,7 @@
#include <cstdint>
#include <iostream>
#include <evhttp.h>
#include <atomic>
#ifdef MALLOC_TRIM
#include <malloc.h>
#endif // MALLOC_TRIM
@ -17,6 +18,7 @@
#include "socket.h"
extern std::string user_agent_str;
std::atomic_bool SERVER_EXIT_FLAG(false);
struct responseRoute
{
@ -178,6 +180,7 @@ int start_web_server(void *argv)
void* httpserver_dispatch(void *arg)
{
event_base_dispatch((struct event_base*)arg);
event_base_free((struct event_base*)arg);
return NULL;
}
@ -235,12 +238,13 @@ int start_web_server_multi(void *argv)
return -1;
pthread_t ths[nthreads];
struct event_base *base[nthreads];
for (i = 0; i < nthreads; i++)
{
struct event_base *base = event_init();
if (base == NULL)
base[i] = event_init();
if (base[i] == NULL)
return -1;
struct evhttp *httpd = evhttp_new(base);
struct evhttp *httpd = evhttp_new(base[i]);
if (httpd == NULL)
return -1;
ret = evhttp_accept_socket(httpd, nfd);
@ -249,16 +253,24 @@ 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);
ret = pthread_create(&ths[i], NULL, httpserver_dispatch, base);
ret = pthread_create(&ths[i], NULL, httpserver_dispatch, base[i]);
if (ret != 0)
return -1;
}
while(true)
sleep(10000); //block forever
while(!SERVER_EXIT_FLAG)
sleep(200); //block forever until receive stop signal
for (i = 0; i < nthreads; i++)
event_base_loopbreak(base[i]);
return 0;
}
void stop_web_server()
{
SERVER_EXIT_FLAG = true;
}
void append_response(std::string method, std::string uri, std::string content_type, response_callback response)
{
responseRoute rr;