alroyso 3 years ago
parent
commit
776e8579ed

+ 17 - 9
SProxy/CApp.cpp

@@ -4,7 +4,7 @@
 
 CApp* SSingleton<CApp>::ms_Singleton = NULL;
 
-CApp::CApp() : m_is_out(0), m_userinfo(nullptr), m_proxy_mode(PROXY_MODE::sys_mode), m_route_mode(ROUT_MODE::cn_mode)
+CApp::CApp() : m_is_out(0),m_userinfo(nullptr), m_server_list(nullptr), m_proxy_mode(PROXY_MODE::sys_mode), m_route_mode(ROUT_MODE::cn_mode)
 {
 	m_hInst = nullptr;
 }
@@ -20,6 +20,11 @@ void CApp::Init()
 	{
 		m_userinfo = new CUserInfo();
 	}
+	if (!m_server_list)
+	{
+		m_server_list = new CServerList();
+	}
+ 
 
 }
 
@@ -27,24 +32,27 @@ void CApp::UnInit() {
 	if (m_userinfo)
 	{
 		delete m_userinfo;
-		m_userinfo = NULL;
+		m_userinfo = nullptr;
 	}
-}
-
-bool CApp::DataToUserInfo(std::string data)
-{
-	if (m_userinfo)
+	if (m_server_list)
 	{
-		return m_userinfo->Init(data);
+		delete m_server_list;
+		m_server_list = nullptr;
 	}
-	return false;
+	 
 }
 
+ 
 CUserInfo* CApp::GetUserinfo()
 {
 	return m_userinfo;
 }
 
+CServerList* CApp::GetServerList()
+{
+	return m_server_list;
+}
+
 void CApp::SetOut(int out)
 {
 	m_is_out = out;

+ 12 - 11
SProxy/CApp.h

@@ -1,8 +1,8 @@
 #pragma once
-
+#include "CBaseMode.h"
 #include "CUserInfo.h"
-
-enum PROXY_MODE {
+#include "CServerList.h"
+enum struct PROXY_MODE {
 
 	sys_mode = 0,
 	tun_mode,
@@ -10,7 +10,7 @@ enum PROXY_MODE {
 };
 
 
-enum ROUT_MODE {
+enum struct ROUT_MODE{
 
 	cn_mode = 0,
 	qg_mode,
@@ -39,11 +39,9 @@ public:
 
 	void UnInit();
 
-
-	bool DataToUserInfo(std::string data);
-
-
+ 
 	CUserInfo* GetUserinfo();
+	CServerList* GetServerList();
 
 	void SetOut(int out);
 
@@ -77,10 +75,12 @@ public:
 	bool GetClashRuning();
 
 
+	std::string GetToken() const { return m_token; }
+	void SetToken(std::string val) { m_token = val; }
 private:
 	int m_is_out;
-
-	CUserInfo*   m_userinfo;
+	CServerList* m_server_list;
+	CUserInfo* m_userinfo;
 	PROXY_MODE m_proxy_mode;
 	ROUT_MODE  m_route_mode;
 	HINSTANCE  m_hInst;
@@ -89,6 +89,7 @@ private:
 	std::filesystem::path m_config_Gui_Path;
 
 	bool m_clashRuning = true;
-
+	std::string m_token;
+	/**/
 };
 

+ 20 - 0
SProxy/CBaseMode.cpp

@@ -0,0 +1,20 @@
+#include "stdafx.h"
+#include "CBaseMode.h"
+
+CBaseMode::CBaseMode()
+{
+}
+
+CBaseMode::~CBaseMode()
+{
+}
+
+SStringA CBaseMode::GetLastErrorA()
+{
+	return S_CW2A(m_error_msg, CP_UTF8);
+}
+
+SStringW CBaseMode::GetLastErrorW()
+{
+    return m_error_msg;
+}

+ 13 - 0
SProxy/CBaseMode.h

@@ -0,0 +1,13 @@
+#pragma once
+class CBaseMode
+{
+
+public:
+	CBaseMode();
+	~CBaseMode();
+	SStringA GetLastErrorA();
+	SStringW GetLastErrorW();
+
+	SStringW m_error_msg;
+};
+

+ 339 - 57
SProxy/CLashConfig.cpp

@@ -5,8 +5,11 @@
 #include "FileOperate.h"
 
 
-CLashConfig::CLashConfig() : m_socks_port(9200), m_http_port(9300), m_c_port(9090), m_process(nullptr), m_Asyntask(1), m_is_qut(false), m_log(nullptr)
+CLashConfig::CLashConfig() : m_socks_port(9200), m_http_port(9300), m_c_port(9090), m_process(nullptr), m_Asyntask(1), m_AsyntaskProcessMonitor(1), m_is_qut(false), m_log(nullptr)
 {
+
+	_hEvent = nullptr;
+
 }
 
 CLashConfig::~CLashConfig(void)
@@ -25,7 +28,120 @@ CLashConfig::~CLashConfig(void)
 
 BOOL CLashConfig::MakeClash()
 {
-    return 0;
+	buildRules();
+	YAML::Node root;
+	root["port"] = m_http_port;
+	root["socks-port"] = m_socks_port;
+	root["allow-lan"] = true;
+	root["external-controller"] = "127.0.0.1:" + std::to_string(m_c_port);
+	if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode)
+	{
+		root["mode"] = "rule";
+	}
+	else {
+		root["mode"] = "rule";
+	}
+
+
+
+#ifdef _DEBUG
+	root["log-level"] = "debug";
+#else
+	root["log-level"] = "info";
+#endif
+
+	root["dns"] = buildDnsConfig();
+
+	if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode)
+	{
+		root["tun"] = builTunConfig();
+	}
+
+	//proxys.reserve(0);
+
+	//CList_node::getSingletonPtr()->listnode;
+	YAML::Node proxies;
+	//for each (LISTNODE node in CList_node::getSingletonPtr()->listnode)
+	//{
+	//	if (node.type == "shadowsocks") {
+	//		proxies.push_back(buildShadowsocks(&node));
+	//	}
+	//	else if (node.type == "trojan") {
+	//		proxies.push_back(buildtrojan(&node));
+	//	}
+	//	else if (node.type == "v2ray") {
+	//		proxies.push_back(buildv2ray(&node));
+	//	}
+	//}
+
+
+	root["proxies"] = proxies;
+	root["proxy-groups"] = buildProxyGroups();
+
+	YAML::Node reject;
+	YAML::Node google;
+	YAML::Node gfw;
+	YAML::Node proxy;
+	YAML::Node cncidr;
+
+
+	reject["type"] = "http";
+	reject["behavior"] = "domain";
+	reject["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt";
+	reject["path"] = "./ruleset/reject.yaml";
+	reject["interval"] = 86400;
+
+	google["type"] = "http";
+	google["behavior"] = "domain";
+	google["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt";
+	google["path"] = "./ruleset/google.yaml";
+	google["interval"] = 86400;
+
+
+	gfw["type"] = "http";
+	gfw["behavior"] = "domain";
+	gfw["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt";
+	gfw["path"] = "./ruleset/gfw.yaml";
+	gfw["interval"] = 86400;
+
+
+
+
+	proxy["type"] = "http";
+	proxy["behavior"] = "domain";
+	proxy["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt";
+	proxy["path"] = "./ruleset/proxy.yaml";
+	proxy["interval"] = 86400;
+
+
+	cncidr["type"] = "http";
+	cncidr["behavior"] = "domain";
+	cncidr["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt";
+	cncidr["path"] = "./ruleset/cncidr.yaml";
+	cncidr["interval"] = 86400;
+
+	if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode)
+	{
+		root["rule-providers"]["reject"] = reject;
+		root["rule-providers"]["cncidr"] = cncidr;
+		root["rule-providers"]["proxy"] = proxy;
+		root["rule-providers"]["gfw"] = gfw;
+		root["rule-providers"]["google"] = google;
+	}
+
+	root["rules"] = m_rules;
+	auto name_file = "config.yaml";
+
+	if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode) {
+		name_file = "tun_config.yaml";
+	}
+
+	//std::ofstream ofstream(path + "\\config\\" + name_file);
+	//// ÉèÖÃÅäÖÃÎļþnodeÊý
+	//ofstream << root << std::endl;
+	//ofstream.close();
+
+	return TRUE;
 }
 
 BOOL CLashConfig::InitClash()
@@ -34,22 +150,22 @@ BOOL CLashConfig::InitClash()
 	{
 		m_process = new CProcess();
 	}
-	
+	std::string logfile = std::filesystem::current_path().string() + "\\log\\log.log";
+	if (m_log == nullptr)
+	{
+		m_log = new Logger(Logger::file_and_terminal, Logger::info, logfile);
+	}
 	m_http_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9300,9500);
 	m_socks_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9600,9800);
 	m_c_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9900);
 
-     
+ ;
 
 	/*std::string dir = CLASHCONFIGDIR;
 
 	auto name_file = dir + "\\" + CLASHCONFIINIT;
 
-	std::string logfile = path + "\\config\\log.log";
-	if (m_log == nullptr)
-	{
-		m_log = new Logger(Logger::file_and_terminal, Logger::info, logfile);
-	}*/
+	*/
 	
 	auto name_file = DSPROXY_CONFIG_INIT_ClASH_NAME;
 
@@ -83,7 +199,8 @@ BOOL CLashConfig::InitClash()
 
 BOOL CLashConfig::StartClash()
 {
- 
+	/*wil::unique_handle hEvent(CreateEventW(nullptr, FALSE, FALSE, nullptr));
+	THROW_LAST_ERROR_IF_NULL(hEvent);*/
 	//std::wstring config = path + L"\\" + WCLASHCONFIGDIR;
 	////args.push_back("-d");
 	//////args.push_back(std::filesystem::current_path().string() + "\\route");
@@ -93,19 +210,24 @@ BOOL CLashConfig::StartClash()
 	//std::wstring run_config = config + L"\\" + S_CA2W(CLASHCONFIINIT).GetBuffer(0);
 	//SStringW path_config;
 	//path_config.Format(L"%s\\%s -d %s -f %s", config.c_str(),CLASHEXE,config.c_str(), run_config.c_str());
+
+
+
 	auto assetsDir = std::filesystem::current_path() / CLASH_ASSETS_DIR_NAME;
 	auto confg_path = CApp::getSingletonPtr()->GetConfigPath() / DSPROXY_CONFIG_INIT_ClASH_NAME;
 	CProcessManager::getSingletonPtr()->SetArgs(assetsDir / DSPROXY_EXE_NAME, assetsDir, std::move(confg_path));
 
 	/*ProcessManager::SetConfigFile(confg_path / DSPROXY_CONFIG_INIT_ClASH_NAME);*/
-	//m_Asyntask.AddTask(&CLashConfig::ThreadFun_process_Config, this, (LPARAM)NULL);
-
+	/* m_Asyntask.AddTask(&CLashConfig::ThreadFun_process_Config, this, (LPARAM)CProcessManager::getSingletonPtr());*/
 
 	if (CProcessManager::getSingletonPtr()->Start())
 	{
 		CApp::getSingletonPtr()->SetCLashRuning(true);
-	}
+		m_AsyntaskProcessMonitor.AddTask(&CLashConfig::ThreadFun_ProcessMonitor_Config, this, (LPARAM)CProcessManager::getSingletonPtr());
 
+		
+	}
+	
 	/*if (m_process)
 	{
 		m_process->Create(CProcess::ASYNC);
@@ -122,7 +244,8 @@ BOOL CLashConfig::StartClash()
 BOOL CLashConfig::StopClash()
 {
 	m_is_qut = true;
-	CProcessManager::getSingletonPtr()->Stop();
+	/*SetEvent(_hEvent.get());*/
+
 	//char ch[MAX_PATH];
 	//memset(ch, 0, MAX_PATH);
 	//sprintf_s(ch, "ok\n");
@@ -147,72 +270,231 @@ YAML::Node CLashConfig::buildv2ray()
 
 std::vector<YAML::Node> CLashConfig::buildv2rayHost()
 {
-    return std::vector<YAML::Node>();
+	std::vector<YAML::Node> p;
+	/*if (node) {
+		YAML::Node t_map;
+		t_map["host"] = node->v2_host;
+		p.push_back(t_map);
+	}*/
+	return p;
 }
 
 YAML::Node CLashConfig::builTunConfig()
 {
-    return YAML::Node();
+	std::vector<std::string> dns;
+	dns.push_back("198.18.0.2:53");
+	YAML::Node node;
+	node["enable"] = true;
+	node["stack"] = "gvisor";
+	node["dns-hijack"] = dns;
+	node["auto-route"] = true;
+	node["auto-detect-interface"] = true;
+	return node;
 }
 
 YAML::Node CLashConfig::buildDnsConfig()
 {
-    return YAML::Node();
+	YAML::Node dns;
+
+	std::vector<std::string> dns_arr;
+	dns_arr.push_back("114.114.114.114");
+	dns_arr.push_back("8.8.8.8");
+	dns_arr.push_back("tls://dns.rubyfish.cn:853");
+	dns_arr.push_back("https://1.1.1.1/dns-query");
+	dns["enable"] = true;
+	if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode)
+	{
+
+		dns["enhanced-mode"] = "redir-host";
+	}
+	else
+	{
+		//dns["enable"] = false;
+	}
+	dns["nameserver"] = dns_arr;
+	//dns["use-hosts"] = true;
+
+
+	return dns;
 }
 
 std::vector<YAML::Node> CLashConfig::buildProxyGroups()
 {
-    return std::vector<YAML::Node>();
+	std::vector<YAML::Node> dns_arr;
+	std::vector<std::string> proxy;
+	YAML::Node proxies;
+	/*for each (LISTNODE node in CList_node::getSingletonPtr()->listnode)
+	{
+		proxy.push_back(node.name.c_str());
+
+	}*/
+	YAML::Node li;
+	li["name"] = "Proxy";
+	li["type"] = "select";
+	li["proxies"] = proxy;
+	dns_arr.push_back(li);
+
+	return dns_arr;
 }
 
 std::vector<YAML::Node> CLashConfig::buildRules()
 {
-    return std::vector<YAML::Node>();
-}
+	std::vector<YAML::Node> p;
 
-void CLashConfig::ThreadFun_process_Config(LPARAM lParam)
-{
+	m_rules.clear();
 
-	if (CProcessManager::getSingletonPtr()->Start())
+	if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode)
 	{
-		CApp::getSingletonPtr()->SetCLashRuning(true);
+		m_rules.push_back("RULE-SET,proxy,Proxy");
+		m_rules.push_back("RULE-SET,google,Proxy");
+		m_rules.push_back("RULE-SET,gfw,Proxy");
+		m_rules.push_back("RULE-SET,cncidr,DIRECT");
+
+		m_rules.push_back("GEOIP,CN,DIRECT");
+		m_rules.push_back("IP-CIDR,127.0.0.0/8,DIRECT");
+		m_rules.push_back("IP-CIDR,172.16.0.0/12,DIRECT");
+		m_rules.push_back("IP-CIDR,192.168.0.0/16,DIRECT");
+		m_rules.push_back("IP-CIDR,10.0.0.0/8,DIRECT");
+		m_rules.push_back("IP-CIDR,100.64.0.0/10,DIRECT");
+	}
+	else
+	{
+		// m_rules.push_back("RULE-SET,proxy,Proxy");
+		// m_rules.push_back("RULE-SET,google,Proxy");
+		// m_rules.push_back("RULE-SET,gfw,Proxy");
+		// m_rules.push_back("RULE-SET,cncidr,Proxy");
+		m_rules.push_back("GEOIP,CN,Proxy");
+		m_rules.push_back("IP-CIDR,127.0.0.0/8,DIRECT");
+		m_rules.push_back("IP-CIDR,172.16.0.0/12,DIRECT");
+		m_rules.push_back("IP-CIDR,192.168.0.0/16,DIRECT");
+		m_rules.push_back("IP-CIDR,10.0.0.0/8,DIRECT");
+		m_rules.push_back("IP-CIDR,100.64.0.0/10,DIRECT");
+	}
 
-		HANDLE hClashProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess;
+	m_rules.push_back("MATCH,Proxy");
 
-		for (size_t i = 0; i < 5; ++i) {
+	return p;
+}
 
-		}
+std::vector<YAML::Node> CLashConfig::buildruleproviders()
+{
+	std::vector<YAML::Node> pp;
+	YAML::Node node;
+	YAML::Node reject;
+	YAML::Node google;
+	YAML::Node gfw;
+	YAML::Node proxy;
+	YAML::Node cncidr;
+	reject["type"] = "http";
+	reject["behavior"] = "domain";
+	reject["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt";
+	reject["path"] = "./ruleset/reject.yaml";
+	reject["interval"] = 86400;
+	node["reject"] = reject;
+	pp.push_back(node);
+
+	google["type"] = "http";
+	google["behavior"] = "domain";
+	google["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt";
+	google["path"] = "./ruleset/google.yaml";
+	google["interval"] = 86400;
+	node["google"] = google;
+	pp.push_back(node);
+
+
+	gfw["type"] = "http";
+	gfw["behavior"] = "domain";
+	gfw["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt";
+	gfw["path"] = "./ruleset/gfw.yaml";
+	gfw["interval"] = 86400;
+	node["gfw"] = gfw;
+	pp.push_back(node);
+
+
+	proxy["type"] = "http";
+	proxy["behavior"] = "domain";
+	proxy["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt";
+	proxy["path"] = "./ruleset/proxy.yaml";
+	proxy["interval"] = 86400;
+	node["proxy"] = proxy;
+	pp.push_back(node);
+
+	cncidr["type"] = "http";
+	cncidr["behavior"] = "domain";
+	cncidr["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt";
+	cncidr["path"] = "./ruleset/cncidr.yaml";
+	cncidr["interval"] = 86400;
+	node["cncidr"] = proxy;
+	pp.push_back(node);
+
+
+	return pp;
+}
+
+void CLashConfig::ThreadFun_process_Config(LPARAM lParam)
+{
+	
+	CProcessManager* p = (CProcessManager*)lParam;
+	
+	if (p->Start())
+	{
+	
 	}
 
+	 
+	 WaitForSingleObject(_hEvent.get(),INFINITE);
+}
 
-	//if (m_process)
-	//{
-	//	//char ch[MAX_PATH];
-	//	//memset(ch, 0, MAX_PATH);
-	//	//do
-	//	//{
-	//	//	size_t bytesRead = m_process->ReadLine(ch, sizeof(ch));
-	//	//	
-	//	//	if (bytesRead == 0)
-	//	//	{
-	//	//		
-	//	//		break;
-	//	//	}
-
-	//	//	if (m_is_qut)
-	//	//	{
-	//	//		
-	//	//		break;
-	//	//	}
-
-	//	//	if (m_log)
-	//	//	{
-	//	//		std::string log(ch);
-	//	//		m_log->INFO(log);
-	//	//	}
-
-	//	//	/*if (ch[bytesRead - 1] == '\n') break;*/
-	//	//} while (true);
-	//	
-	//}
+void CLashConfig::ThreadFun_ProcessMonitor_Config(LPARAM lParam)
+{
+	CProcessManager* p = (CProcessManager*)lParam;
+	if (p)
+	{
+		HANDLE hClashProcess = nullptr;
+		HANDLE hSubProcess = nullptr;
+ 
+		do 
+		{
+			if (p->IsRunning() != State::Running)
+			{
+				break;
+			}
+
+		} while (hClashProcess = p->GetClashProcessInfo().hProcess);
+	}
+	 
 }
+
+//winrt::fire_and_forget CLashConfig::_StartClash()
+//{
+//	if (CProcessManager::getSingletonPtr()->Start())
+//	{
+//		CApp::getSingletonPtr()->SetCLashRuning(true);
+//
+//
+//
+//		/*HANDLE hClashProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess;
+//
+//		for (size_t i = 0; i < 5; ++i) {
+//
+//		}*/
+//	}
+//
+//
+// 
+//}
+//
+//winrt::Windows::Foundation::IAsyncAction CLashConfig::ProcessMonitor()
+//{
+//	HANDLE hSubProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess,
+//		hClashProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess;
+//
+//	 winrt::resume_on_signal(hClashProcess);
+//
+//	 /*std::future<void> f = std::async(std::launch::async, []() {
+//		 })*/
+//
+//
+//
+// 
+//}

+ 7 - 1
SProxy/CLashConfig.h

@@ -34,9 +34,12 @@ private:
 	YAML::Node buildDnsConfig();
 	std::vector<YAML::Node> buildProxyGroups();
 	std::vector<YAML::Node> buildRules();
+	std::vector<YAML::Node> buildruleproviders();
 private:
 	void ThreadFun_process_Config(LPARAM lParam);
-
+	void ThreadFun_ProcessMonitor_Config(LPARAM lParam);
+	/*winrt::fire_and_forget _StartClash();
+	winrt::Windows::Foundation::IAsyncAction ProcessMonitor();*/
 private:
 	int m_socks_port;
 	int m_http_port;
@@ -44,6 +47,9 @@ private:
 	bool   m_is_qut;
 	CProcess* m_process;
 	AsynTaskHandle<LPARAM>	m_Asyntask;
+	AsynTaskHandle<LPARAM>	m_AsyntaskProcessMonitor;
 	Logger*     m_log;
+	std::vector<std::string> m_rules;
+	wil::unique_handle _hEvent;
 };
 

+ 42 - 1
SProxy/CManageNetWork.cpp

@@ -5,6 +5,9 @@
 #include "FileOperate.h"
 #include <nlohmann/json.hpp>
 
+CManageNetWork* SSingleton<CManageNetWork>::ms_Singleton = NULL;
+
+
 CManageNetWork::CManageNetWork() : m_base_curl(nullptr), m_Asyntask(4)
 {
 }
@@ -80,6 +83,15 @@ void CManageNetWork::DonloadConfg()
 	m_Asyntask.AddTask(&CManageNetWork::ThreadFun_Dowlon_Config, this, (LPARAM)m_base_curl);
 }
 
+void CManageNetWork::GetNodeList()
+{
+	if (!m_base_curl)
+	{
+		return;
+	}
+	m_Asyntask.AddTask(&CManageNetWork::ThreadFun_Node_Config, this, (LPARAM)m_base_curl);
+}
+
 void CManageNetWork::ThreadFun_login(LPARAM lParam)
 {
 	IBaseCurl* lpAsyncParam = reinterpret_cast<IBaseCurl*>(lParam);
@@ -95,7 +107,7 @@ void CManageNetWork::ThreadFun_login(LPARAM lParam)
 
 	if (!data.empty())
 	{
-		if (!CApp::getSingletonPtr()->DataToUserInfo(data))
+		if (!CApp::getSingletonPtr()->GetUserinfo()->Init(data))
 		{
 			code = -1;
 			msg = CApp::getSingletonPtr()->GetUserinfo()->GetLastErrorW();
@@ -121,6 +133,7 @@ void CManageNetWork::ThreadFun_Dowlon_Config(LPARAM lParam)
 	if (!m_base_curl->Download(CApp::getSingletonPtr()->GetUserinfo()->clash_config)) {
 		code = 0;
 		msg = L"ÏÂÔØÎļþʧ°Ü";
+		 
 	}
 	EventDoWNload* pEvt = new EventDoWNload(nullptr);
 	pEvt->status = code;
@@ -129,6 +142,34 @@ void CManageNetWork::ThreadFun_Dowlon_Config(LPARAM lParam)
 	pEvt->Release();
 }
 
+void CManageNetWork::ThreadFun_Node_Config(LPARAM lParam)
+{
+	IBaseCurl* lpAsyncParam = reinterpret_cast<IBaseCurl*>(lParam);
+	int code = 200;
+	SStringW msg = L"";
+	std::string data;
+	HTTPRET httpstatus = m_base_curl->GetServerNode(data);
+	if (httpstatus == http_f) {
+		code = 0;
+		msg = m_base_curl->GetLastErrorW();
+	}
+
+	if (!data.empty())
+	{
+		if (!CApp::getSingletonPtr()->GetServerList()->Init(data))
+		{
+			code = -1;
+			msg = CApp::getSingletonPtr()->GetServerList()->GetLastErrorW();
+		}
+	}
+
+	EventNodeList* pEvt = new EventNodeList(nullptr);
+	pEvt->status = code;
+	pEvt->msg = msg;
+	SNotifyCenter::getSingleton().FireEventAsync(pEvt);
+	pEvt->Release();
+}
+
 void CManageNetWork::LoadFileToData() {
 
 	try

+ 4 - 1
SProxy/CManageNetWork.h

@@ -6,7 +6,7 @@
 
 
 
-class CManageNetWork
+class CManageNetWork : public SSingleton<CManageNetWork>
 {
 public:
 	CManageNetWork();
@@ -23,9 +23,12 @@ public:
 	
 	void DonloadConfg();
 
+	void GetNodeList();
+
 private:
 	void ThreadFun_login(LPARAM lParam);
 	void ThreadFun_Dowlon_Config(LPARAM lParam);
+	void ThreadFun_Node_Config(LPARAM lParam);
 	void LoadFileToData();
 
 	void DataToFile();

+ 51 - 2
SProxy/CNetWork.cpp

@@ -14,6 +14,19 @@ CNetWork::~CNetWork(void)
 {
 
 }
+HTTPRET CNetWork::GetServerNode(std::string& data) {
+	std::vector<cpr::Parameter> p;
+	std::string text = GetUrl("/api/client/v3/nodes",p,CApp::getSingletonPtr()->GetUserinfo()->access_token);
+	if (text.empty()) {
+
+		return http_f;
+	}
+
+	data = text.c_str();
+
+
+	return http_yes;
+}
 
 HTTPRET CNetWork::PostLogin(LPCSTR username, LPCSTR password, std::string& data)
 {
@@ -46,9 +59,45 @@ SStringW CNetWork::GetLastErrorW()
 	return S_CA2W(m_error_msg.c_str(),CP_UTF8).GetBuffer(0);
 }
 
-std::string CNetWork::GetUrl(std::string path, std::vector<cpr::Parameter> parame)
+std::string CNetWork::GetUrl(std::string path, std::vector<cpr::Parameter> parame,std::string token)
 {
-    return std::string();
+
+	cpr::Header hander;
+
+	if (!token.empty())
+	{
+		hander = cpr::Header{ {"accept", "application/json"} , {"Authorization", "bearer " + token} };
+	}
+	else {
+		hander = cpr::Header{ {"accept", "application/json"} };
+	}
+
+	auto s = fmt::format("{0}{1}", m_url, path.c_str());
+
+	cpr::Response r;
+
+	if (parame.empty())
+	{
+		r = cpr::Get(cpr::Url{ s.c_str() });
+	}
+	else {
+		r = cpr::Get(cpr::Url{ s.c_str() });
+	}
+	if (r.status_code == 200 || r.status_code == 201)
+	{
+		return std::move(r.text);
+	}
+	else {
+		m_http_status = r.status_code;
+		if (m_http_status == 0)
+		{
+			//m_http_status = r.error.code;
+			m_error_msg = r.error.message;
+		}
+
+		return "";
+	}
+	return std::string("");
 }
 
 std::string CNetWork::PostUrl(std::string path, std::vector<cpr::Pair> parame)

+ 5 - 1
SProxy/CNetWork.h

@@ -8,6 +8,8 @@ public:
 	CNetWork();
 	~CNetWork(void);
 
+	HTTPRET GetServerNode(std::string& data);
+
 
 	HTTPRET PostLogin(LPCSTR username, LPCSTR password, std::string& data);
 	void SetUrl(LPCSTR url);
@@ -17,9 +19,11 @@ public:
 
 	bool Download(std::string path);
 
+	 
+
 
 private:
-	std::string GetUrl(std::string path, std::vector<cpr::Parameter> parame);
+	std::string GetUrl(std::string path, std::vector<cpr::Parameter> parame, std::string token = "");
 	std::string PostUrl(std::string path, std::vector<cpr::Pair> parame);
 
 	 

+ 121 - 1
SProxy/CProcessManager.cpp

@@ -66,6 +66,121 @@ void CProcessManager::SetInsTanCe(HINSTANCE m) {
 	_UpdateClashCmd();
 }
 
+ State CProcessManager::IsRunning()
+ {
+	 return _state;
+ }
+
+ const PROCESS_INFORMATION& CProcessManager::GetSubProcessInfo()
+ {
+	 
+	 return _subProcInfo;
+ }
+
+ const PROCESS_INFORMATION& CProcessManager::GetClashProcessInfo()
+ {
+	 return _clashProcInfo;
+ }
+
+ HWND CProcessManager::GetConsoleWindow()
+ {
+	 return _hWndConsole;
+ }
+
+ void CProcessManager::StartTest() {
+	 try
+	 {
+		 THROW_IF_WIN32_BOOL_FALSE(AllocConsole());
+		 freopen("CONOUT$", "w", stdout);
+		 wchar_t objName[objNameSize + 1] = OBJPREFIX;
+		 GUID guid = {};
+		 THROW_IF_FAILED(CoCreateGuid(&guid));
+		 THROW_HR_IF(E_OUTOFMEMORY, StringFromGUID2(guid, objName + prefixSize, guidSize) != guidSize);
+
+		 size_t size = (std::max)((_exePath.native().size() + 1) + (_clashCmd.size() + 1) * sizeof(wchar_t), sizeof(ProcessInfo));
+
+		 objName[objNameSize - 1] = L'F';
+		 std::wstring name(objName);
+		  
+
+		 printf("%ws\n", name.c_str());
+
+		 wil::unique_handle hFileMapping(CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, static_cast<DWORD>(size), objName));
+		 THROW_LAST_ERROR_IF_NULL(hFileMapping);
+		 auto error = GetLastError();
+		 if (error == ERROR_ALREADY_EXISTS) THROW_WIN32(error);
+
+		 wil::unique_mapview_ptr<wchar_t> buffer(reinterpret_cast<wchar_t*>(MapViewOfFile(hFileMapping.get(), FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0)));
+		 THROW_LAST_ERROR_IF_NULL(buffer);
+
+
+		 objName[objNameSize - 1] = L'E';
+		 wil::unique_handle hEvent(CreateEventW(nullptr, FALSE, FALSE, objName));
+		 THROW_LAST_ERROR_IF_NULL(hEvent);
+		 error = GetLastError();
+		 if (error == ERROR_ALREADY_EXISTS) THROW_WIN32(error);
+
+		 auto exePathPtr = buffer.get();
+		 size_t i = _exePath.native().copy(exePathPtr, std::filesystem::path::string_type::npos);
+		 exePathPtr[i] = 0;
+
+		 auto cmdPtr = buffer.get() + i + 1;
+		 i = _clashCmd.copy(cmdPtr, std::wstring::npos);
+		 cmdPtr[i] = 0;
+
+
+		 auto selfPath = GetModuleFsPath(mInstance);
+		 auto guidStr = objName + prefixSize;
+		 std::wstring cmd(LR"(")");
+		 cmd.append(selfPath);
+		 cmd.append(LR"(" --pm=)");
+		 cmd.append(guidStr, guidSize - 1);
+
+
+		 HANDLE handles[] = { hEvent.get()};
+		 auto ret = WaitForMultipleObjects(static_cast<DWORD>(std::size(handles)), handles, FALSE, INFINITE);
+		 error = ERROR_TIMEOUT;
+
+		 switch (ret)
+		 {
+		 case WAIT_OBJECT_0: // Event signaled, clash process started suspended
+		 {
+			 auto info = reinterpret_cast<ProcessInfo*>(buffer.get());
+			 _clashProcInfo.dwProcessId = info->processId;
+			 _clashProcInfo.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, _clashProcInfo.dwProcessId);
+			 THROW_LAST_ERROR_IF_NULL(_clashProcInfo.hProcess);
+
+			 _clashProcInfo.dwThreadId = info->threadId;
+			 _clashProcInfo.hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, _clashProcInfo.dwThreadId);
+			 THROW_LAST_ERROR_IF_NULL(_clashProcInfo.hThread);
+
+			 _hWndConsole = info->hWndConsole;
+		 }
+		 break;
+		 case WAIT_OBJECT_0 + 1: // Sub process exited before event signaled
+		 {
+			 //DWORD exitCode;
+			 //THROW_IF_WIN32_BOOL_FALSE(GetExitCodeProcess(_subProcInfo.hProcess, &exitCode));
+			 //HRESULT hr = static_cast<HRESULT>(exitCode); // Treat exit code as hresult
+			 //if (SUCCEEDED(hr)) hr = E_UNEXPECTED;
+			 //THROW_HR(hr);
+		 }
+		 return;
+		 case WAIT_FAILED:
+			 error = GetLastError();
+			 [[fallthrough]];
+		 case WAIT_TIMEOUT:
+			 THROW_WIN32(error);
+			 return;
+		 }
+		 _hEvent = std::move(hEvent);
+	 }
+	 catch (...)
+	 {
+		 LOG_CAUGHT_EXCEPTION();
+	 }
+ }
+ 
  bool CProcessManager::Start()
 {
 	if (_state != State::Stop)
@@ -192,7 +307,11 @@ void CProcessManager::SetInsTanCe(HINSTANCE m) {
 	}
 	catch (...)
 	{
-		_hJob.reset();
+		if (_hJob)
+		{
+			_hJob.reset();
+		}
+		
 		LOG_CAUGHT_EXCEPTION();
 		return false;
 	}
@@ -249,6 +368,7 @@ void CProcessManager::SetInsTanCe(HINSTANCE m) {
 		auto clashCmd = buffer.get() + wcslen(exePath) + 1;
 
 		STARTUPINFOW si;
+		ZeroMemory(&si, sizeof(si));
 		si.cb = sizeof(si);
 		wil::unique_process_information procInfo;
 		THROW_IF_WIN32_BOOL_FALSE(CreateProcessW(exePath, clashCmd, nullptr, nullptr, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &si, &procInfo));

+ 13 - 11
SProxy/CProcessManager.h

@@ -11,17 +11,17 @@ struct ProcessInfo
 	HWND hWndConsole;
 };
 
+enum struct State
+{
+	Stop,
+	Running,
+	WaitStop
+};
 
 class CProcessManager : public SSingleton<CProcessManager>
 {
 public:
-	enum struct State
-	{
-		Stop,
-		Running,
-		WaitStop
-	};
-
+	
 	CProcessManager();
 	~CProcessManager();
 
@@ -35,10 +35,12 @@ public:
 	void SetConfigFile(std::filesystem::path configFile);
 
 
-	inline State IsRunning() { return _state; }
-	inline const PROCESS_INFORMATION& GetSubProcessInfo() { return _subProcInfo; }
-	inline const PROCESS_INFORMATION& GetClashProcessInfo() { return _clashProcInfo; }
-	inline HWND GetConsoleWindow() { return _hWndConsole; }
+	State IsRunning();
+	const PROCESS_INFORMATION& GetSubProcessInfo();
+	const PROCESS_INFORMATION& GetClashProcessInfo();
+	HWND GetConsoleWindow();
+
+	void StartTest();
 
 
 	bool Start();

+ 85 - 0
SProxy/CServerList.cpp

@@ -0,0 +1,85 @@
+#include "stdafx.h"
+#include "CServerList.h"
+
+
+
+
+
+
+CServerList::CServerList() 
+{
+}
+
+CServerList::~CServerList()
+{
+}
+
+bool CServerList::Init(std::string data)
+{
+	try
+	{
+		nlohmann::json j = nlohmann::json::parse(data.begin(), data.end());
+
+		if (j["ret"].get<int>() == 1)
+		{
+			
+			auto data = j["data"];
+			for (int i = 0; i < data.size(); i++) {
+				
+				CServerListMode m_serverlist_mode;
+				m_serverlist_mode.type = data[i]["type"].get<std::string>();
+				m_serverlist_mode.id = data[i]["id"].get<int>();
+				m_serverlist_mode.name = data[i]["name"].get<std::string>();
+				m_serverlist_mode.host = data[i]["host"].get<std::string>();
+				m_serverlist_mode.group = data[i]["group"].get<std::string>();
+
+				if (m_serverlist_mode.type == "shadowsocks")
+				{
+					m_serverlist_mode.method = data[i]["method"].get<std::string>();
+					m_serverlist_mode.passwd = data[i]["passwd"].get<std::string>();
+				}
+				else if (m_serverlist_mode.type == "v2ray")
+				{
+					m_serverlist_mode.method = data[i]["method"].get<std::string>();
+					m_serverlist_mode.uuid = data[i]["uuid"].get<std::string>();
+					m_serverlist_mode.v2_net = data[i]["v2_net"].get<std::string>();
+					m_serverlist_mode.v2_type = data[i]["v2_type"].get<std::string>();
+					m_serverlist_mode.v2_host = data[i]["v2_host"].get<std::string>();
+					m_serverlist_mode.v2_path = data[i]["v2_path"].get<std::string>();
+					m_serverlist_mode.v2_tls = data[i]["v2_tls"].get<std::string>();
+					m_serverlist_mode.v2_sni = data[i]["v2_sni"].get<std::string>();
+				}
+				else if (m_serverlist_mode.type == "trojan") {
+					m_serverlist_mode.passwd = data[i]["passwd"].get<std::string>();
+					m_serverlist_mode.sni = data[i]["sni"].get<std::string>();
+				}
+				m_serverlist_mode.udp = data[i]["udp"].get<int>();
+				m_serverlist_mode.port = data[i]["port"].get<int>();
+
+				vectlistmode.push_back(m_serverlist_mode);
+			}
+
+			 
+			return true;
+
+		}
+		if (j["ret"].get<int>() == 445 || j["ret"].get<int>() == 446)
+		{
+		 
+			this->m_error_msg = S_CA2W(j["msg"].get<std::string>().c_str(), CP_UTF8).GetBuffer(0);
+			return false;
+		}
+		else
+		{
+			this->m_error_msg = S_CA2W(j["msg"].get<std::string>().c_str(), CP_UTF8).GetBuffer(0);
+			return false;
+		}
+
+
+	}
+	catch (...)
+	{
+		this->m_error_msg = L"½âÎöÊý¾Ý´íÎó";
+		return false;
+	}
+}

+ 18 - 0
SProxy/CServerList.h

@@ -0,0 +1,18 @@
+#pragma once
+#include "CBaseMode.h"
+#include "CServerListMode.h"
+
+class CServerList : public CBaseMode
+{
+public:
+	CServerList();
+	~CServerList();
+
+	bool Init(std::string data);
+
+
+	std::vector<CServerListMode> vectlistmode;
+	
+
+};
+

+ 9 - 0
SProxy/CServerListMode.cpp

@@ -0,0 +1,9 @@
+#include "stdafx.h"
+#include "CServerListMode.h"
+CServerListMode::CServerListMode() : online_users(0), port(0), id(0), udp(0), v2_alter_id(0)
+{
+}
+
+CServerListMode::~CServerListMode()
+{
+}

+ 41 - 0
SProxy/CServerListMode.h

@@ -0,0 +1,41 @@
+#pragma once
+#include "CBaseMode.h"
+
+
+class CServerListMode 
+{
+public:
+	CServerListMode();
+	~CServerListMode();
+
+
+public:
+	int online_users;
+	int id;
+
+	/*ss*/
+	std::string name;
+	std::string host;
+	std::string group;
+	std::string type;
+	std::string method;
+	std::string passwd;
+
+
+	int udp;
+	int port;
+
+
+
+	/*v2ray*/
+	std::string uuid;
+	int v2_alter_id;
+	std::string v2_net;
+	std::string v2_type;
+	std::string v2_host;
+	std::string v2_path;
+	std::string v2_tls;
+	std::string v2_sni;
+
+	std::string sni;
+};

+ 1 - 10
SProxy/CUserInfo.cpp

@@ -60,14 +60,5 @@ bool CUserInfo::Init(std::string data)
     return false;
 }
 
-SStringA CUserInfo::GetLastErrorA()
-{
-	return S_CW2A(m_error_msg,CP_UTF8);
-}
-
-SStringW CUserInfo::GetLastErrorW()
-{
-	return m_error_msg.GetBuffer(0);
-}
-
+ 
 

+ 3 - 12
SProxy/CUserInfo.h

@@ -1,9 +1,9 @@
 #pragma once
-#include <nlohmann/json.hpp>
-
  
 
-class CUserInfo 
+#include "CBaseMode.h"
+
+class CUserInfo : public CBaseMode
 {
 
 public:
@@ -13,13 +13,7 @@ public:
 
 	bool Init(std::string data);
 
- 
-
-	SStringA GetLastErrorA();
 
-	SStringW GetLastErrorW();
- 
-	
 
 public:
 	//user
@@ -37,8 +31,5 @@ public:
 	std::string clash_config; //ÅäÖõØÖ·
 	int id;
 	int port;
-
-private:
-	SStringW m_error_msg;
 };
 

+ 137 - 0
SProxy/ClashApi.cpp

@@ -0,0 +1,137 @@
+#include "stdafx.h"
+#include "ClashApi.h"
+
+ClashApi::ClashApi():m_port(0)
+{
+}
+
+ClashApi::~ClashApi()
+{
+}
+
+void ClashApi::SetProt(int port)
+{
+    std::string t;
+    t.append("http://172.0.0.1:");
+    t.append(std::to_string(port));
+    m_api_base_url = t;
+}
+
+std::string ClashApi::GetVersion()
+{
+    auto url = m_api_base_url + "/version";
+    m_cpr_session.SetUrl(cpr::Url{ url });
+    auto res = m_cpr_session.Get();
+
+    THROW_HR_IF(HTTP_E_STATUS_UNEXPECTED, res.status_code != 200);
+
+    return nlohmann::json::parse(res.text).at("version").get<std::string>();
+}
+
+ClashConfig ClashApi::GetConfig()
+{
+	auto url = m_api_base_url + "/configs";
+	m_cpr_session.SetUrl(cpr::Url{ url });
+	auto res = m_cpr_session.Get();
+    THROW_HR_IF(HTTP_E_STATUS_UNEXPECTED, res.status_code != 200);
+    return  nlohmann::json::parse(res.text).get<ClashConfig>();
+}
+
+std::optional<std::wstring> ClashApi::RequestConfigUpdate(std::filesystem::path configPath)
+{
+	nlohmann::json j = {
+	    {"path",configPath.u8string()}
+	};
+    // cpr::Put(cpr::Url{ url }, cpr::Body{ j.dump() });
+
+	auto url = m_api_base_url + "/configs";
+	m_cpr_session.SetUrl(cpr::Url{ url });
+    m_cpr_session.SetBody(cpr::Body{j.dump()});
+    auto res = m_cpr_session.Put();
+	if (res.status_code != 204)
+	{
+		std::wstring errorDesp = L"Error occoured, Please try to fix it by restarting .";
+		try
+		{
+			errorDesp = Utf8ToUtf16(nlohmann::json::parse(res.text).at("message").get<std::string_view>());
+		}
+		CATCH_LOG();
+		return errorDesp;
+	}
+
+    return std::nullopt;
+}
+
+bool ClashApi::UpdateProxyMode(ClashProxyMode mode)
+{
+	nlohmann::json j = {
+	{"mode",mode}
+	};
+	auto url = m_api_base_url + "/configs";
+	m_cpr_session.SetUrl(cpr::Url{ url });
+	m_cpr_session.SetBody(cpr::Body{ j.dump() });
+	auto res = m_cpr_session.Patch();
+    return res.status_code == 204;
+}
+
+bool ClashApi::UpdateLogLevel(ClashLogLevel level)
+{
+	nlohmann::json j = {
+	{"log-level",level}
+	};
+	auto url = m_api_base_url + "/configs";
+	m_cpr_session.SetUrl(cpr::Url{ url });
+	m_cpr_session.SetBody(cpr::Body{ j.dump() });
+	auto res = m_cpr_session.Patch();
+	return res.status_code == 204;
+}
+
+bool ClashApi::UpdateAllowLan(bool allow)
+{
+	nlohmann::json j = {
+	 {"allow-lan",allow}
+	};
+	auto url = m_api_base_url + "/configs";
+	m_cpr_session.SetUrl(cpr::Url{ url });
+	m_cpr_session.SetBody(cpr::Body{ j.dump() });
+	auto res = m_cpr_session.Patch();
+	return res.status_code == 204;
+}
+
+u16milliseconds ClashApi::GetProxyDelay(std::string_view proxyName)
+{
+	std::string path = m_api_base_url + "/proxies/";
+	path.append(Utf16ToUtf8(Utf8ToUtf16(proxyName)));
+	path.append("/delay"); // "/proxies/\(proxyName.encoded)/delay"
+
+	path.append("?timeout=5000&url=");
+	path.append("http://cp.cloudflare.com/generate_204");
+	m_cpr_session.SetUrl(cpr::Url{ path });
+	auto res = m_cpr_session.Get();
+	THROW_HR_IF(HTTP_E_STATUS_UNEXPECTED, res.status_code != 200);
+	return u16milliseconds(nlohmann::json::parse(res.text).at("delay").get<uint16_t>());
+}
+
+ClashProxies ClashApi::GetProxies()
+{
+	auto url = m_api_base_url + "/proxies";
+	m_cpr_session.SetUrl(cpr::Url{ url });
+	auto res = m_cpr_session.Get();
+	THROW_HR_IF(HTTP_E_STATUS_UNEXPECTED, res.status_code != 200);
+	return  nlohmann::json::parse(res.text).get<ClashProxies>();
+ 
+}
+
+bool ClashApi::UpdateProxyGroup(std::string_view group, std::string_view selectProxy)
+{
+	nlohmann::json j = {
+		{"allow-lan",selectProxy}
+	};
+	std::string path = "/proxies/";
+	path.append(Utf16ToUtf8(Utf8ToUtf16(group)));
+	m_cpr_session.SetUrl(cpr::Url{ path });
+	m_cpr_session.SetBody(cpr::Body{ j.dump() });
+	auto res = m_cpr_session.Put();
+	return res.status_code == 204; // HTTP 204 No Content
+ 
+}

+ 35 - 0
SProxy/ClashApi.h

@@ -0,0 +1,35 @@
+#pragma once
+#include <cpr/cpr.h>
+struct Response
+{
+	uint32_t statusCode;
+	std::string data;
+};
+
+using u16milliseconds = std::chrono::duration<uint16_t, std::milli>;
+
+
+class ClashApi
+{
+public:
+	ClashApi();
+	~ClashApi();
+
+	void SetProt(int port);
+
+	std::string GetVersion();
+	ClashConfig GetConfig();
+	std::optional<std::wstring> RequestConfigUpdate(std::filesystem::path configPath);
+	bool UpdateProxyMode(ClashProxyMode mode);
+	bool UpdateLogLevel(ClashLogLevel level);
+	bool UpdateAllowLan(bool allow);
+	//L"http://cp.cloudflare.com/generate_204"
+	u16milliseconds GetProxyDelay(std::string_view proxyName);
+	ClashProxies GetProxies();
+	bool UpdateProxyGroup(std::string_view group, std::string_view selectProxy);
+private:
+	cpr::Session   m_cpr_session;
+	int			   m_port;
+	std::string	   m_api_base_url;
+};
+

+ 2 - 0
SProxy/ClashModel.cpp

@@ -0,0 +1,2 @@
+#include "stdafx.h"
+#include "ClashModel.h"

+ 186 - 0
SProxy/ClashModel.h

@@ -0,0 +1,186 @@
+#pragma once
+
+
+struct ClashProxySpeedHistory
+{
+	// Date time; // FIXME
+	uint32_t delay;
+
+	friend void from_json(const nlohmann::json& j, ClashProxySpeedHistory& value) {
+		JSON_FROM(delay);
+	}
+};
+
+
+
+struct ClashProxy
+{
+	using Name = std::string; // UTF-8
+
+	enum struct Type
+	{
+		Unknown,
+		URLTest,
+		Fallback,
+		LoadBalance,
+		Selector,
+		Direct,
+		Reject,
+		Shadowsocks,
+		ShadowsocksR,
+		Socks5,
+		Http,
+		Vmess,
+		Snell,
+		Trojan,
+		Relay,
+	};
+
+	Name name;
+	Type type = Type::Unknown;
+	std::vector<Name> all;
+	std::vector<ClashProxySpeedHistory> history;
+	std::optional<Name> now;
+
+	friend void from_json(const nlohmann::json& j, ClashProxy& value) {
+		JSON_FROM(name);
+		JSON_FROM(type);
+		JSON_TRY_FROM(all);
+		JSON_FROM(history);
+		try { value.now.emplace(j.at("now").get<decltype(now)::value_type>()); }
+		catch (...) {}
+	}
+};
+
+NLOHMANN_JSON_SERIALIZE_ENUM(ClashProxy::Type, {
+	{ClashProxy::Type::Unknown, nullptr},
+	{ClashProxy::Type::URLTest, "URLTest"},
+	{ClashProxy::Type::Fallback, "Fallback"},
+	{ClashProxy::Type::LoadBalance, "LoadBalance"},
+	{ClashProxy::Type::Selector, "Selector"},
+	{ClashProxy::Type::Direct, "Direct"},
+	{ClashProxy::Type::Reject, "Reject"},
+	{ClashProxy::Type::Shadowsocks, "Shadowsocks"},
+	{ClashProxy::Type::ShadowsocksR, "ShadowsocksR"},
+	{ClashProxy::Type::Socks5, "Socks5"},
+	{ClashProxy::Type::Http, "Http"},
+	{ClashProxy::Type::Vmess, "Vmess"},
+	{ClashProxy::Type::Snell, "Snell"},
+	{ClashProxy::Type::Trojan, "Trojan"},
+	{ClashProxy::Type::Relay, "Relay"},
+	});
+
+struct ClashProxies
+{
+	using MapType = std::unordered_map<ClashProxy::Name, ClashProxy>;
+
+	MapType proxies;
+
+	friend void from_json(const nlohmann::json& j, ClashProxies& value) {
+		JSON_FROM(proxies);
+	}
+};
+
+ClashProxies g_clashProxies;
+
+struct ClashProvider
+{
+	using Name = std::string; // UTF-8
+
+	enum struct Type
+	{
+		Unknown,
+		Proxy,
+		String,
+	};
+
+	enum struct VehicleType
+	{
+		Unknown,
+		HTTP,
+		File,
+		Compatible,
+	};
+
+	Name name;
+	std::vector<ClashProxy> proxies;
+	Type type;
+	VehicleType vehicleType;
+};
+
+NLOHMANN_JSON_SERIALIZE_ENUM(ClashProvider::Type, {
+	{ClashProvider::Type::Unknown, nullptr},
+	{ClashProvider::Type::Proxy, "Proxy"},
+	{ClashProvider::Type::String, "String"},
+	});
+
+NLOHMANN_JSON_SERIALIZE_ENUM(ClashProvider::VehicleType, {
+	{ClashProvider::VehicleType::Unknown, nullptr},
+	{ClashProvider::VehicleType::HTTP, "HTTP"},
+	{ClashProvider::VehicleType::File, "File"},
+	{ClashProvider::VehicleType::Compatible, "Compatible"},
+	});
+
+struct ClashProviders
+{
+	std::map<ClashProvider::Name, ClashProvider> providers;
+
+	/*friend void from_json(const json& j, ClashProviders& value) {
+		JSON_FROM(providers);
+	}*/
+};
+
+enum struct ClashProxyMode
+{
+	Unknown,
+	Global,
+	Rule,
+	Direct
+};
+
+NLOHMANN_JSON_SERIALIZE_ENUM(ClashProxyMode, {
+	{ClashProxyMode::Unknown, nullptr},
+	{ClashProxyMode::Global, "global"},
+	{ClashProxyMode::Rule, "rule"},
+	{ClashProxyMode::Direct, "direct"},
+	})
+
+	enum struct ClashLogLevel
+{
+	Unknown,
+	Error,
+	Warning,
+	Info,
+	Debug,
+	Silent
+};
+
+NLOHMANN_JSON_SERIALIZE_ENUM(ClashLogLevel, {
+	{ClashLogLevel::Unknown, nullptr},
+	{ClashLogLevel::Error, "error"},
+	{ClashLogLevel::Warning, "warning"},
+	{ClashLogLevel::Info, "info"},
+	{ClashLogLevel::Debug, "debug"},
+	{ClashLogLevel::Silent, "silent"},
+	}
+)
+
+
+struct ClashConfig
+{
+	uint16_t port;
+	uint16_t socksPort;
+	uint16_t mixedPort;
+	bool allowLan;
+	ClashProxyMode mode;
+	ClashLogLevel logLevel;
+
+	friend void from_json(const nlohmann::json& j, ClashConfig& c) {
+		j.at("port").get_to(c.port);
+		j.at("socks-port").get_to(c.socksPort);
+		j.at("mixed-port").get_to(c.mixedPort);
+		j.at("allow-lan").get_to(c.allowLan);
+		j.at("mode").get_to(c.mode);
+		j.at("log-level").get_to(c.logLevel);
+	}
+};

+ 4 - 0
SProxy/IBaseCurl.h

@@ -24,6 +24,10 @@ public:
 	//怬xia'zai
 	virtual HTTPRET PostLogin(LPCSTR username, LPCSTR password, std::string& data) = 0;
 
+	//»ñÈ¡Ïß·
+	virtual HTTPRET GetServerNode(std::string& data) = 0;
+
+
 
 	virtual SStringA  GetLastErrorA() = 0;
 	virtual SStringW  GetLastErrorW() = 0;

+ 1 - 1
SProxy/Logger.cpp

@@ -14,7 +14,7 @@ Logger::Logger(log_target target, log_level level, string path) {
 	this->path = path;
 	this->level = level;
 	string tmp = "";  // 双引号下的常量不能直接相加,所以用一个string类型做转换
-	string welcome_dialog = tmp + "[Welcome] " + __FILE__ + " " + currTime() + " : " + "=== Start logging ===\n";
+	string welcome_dialog = tmp + "[SProxy] " + __FILE__ + " " + currTime() + " : " + "=== Start logging ===\n";
 	if (target != terminal) {
 		this->outfile.open(path, ios::out | ios::app);   // 打开输出文件
 		this->outfile << welcome_dialog;

BIN
SProxy/LoginDlg.cpp


BIN
SProxy/LoginDlg.h


BIN
SProxy/MainDlg.cpp


BIN
SProxy/MainDlg.h


BIN
SProxy/SProxy.cpp


+ 10 - 0
SProxy/SProxy.vcxproj

@@ -192,11 +192,16 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="CApp.cpp" />
+    <ClCompile Include="CBaseMode.cpp" />
+    <ClCompile Include="ClashApi.cpp" />
     <ClCompile Include="CLashConfig.cpp" />
+    <ClCompile Include="ClashModel.cpp" />
     <ClCompile Include="CManageNetWork.cpp" />
     <ClCompile Include="CNetWork.cpp" />
     <ClCompile Include="CProcess.cpp" />
     <ClCompile Include="CProcessManager.cpp" />
+    <ClCompile Include="CServerList.cpp" />
+    <ClCompile Include="CServerListMode.cpp" />
     <ClCompile Include="CTool.cpp" />
     <ClCompile Include="CUserInfo.cpp" />
     <ClCompile Include="FileOperate.cpp" />
@@ -223,12 +228,17 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="CApp.h" />
+    <ClInclude Include="CBaseMode.h" />
+    <ClInclude Include="ClashApi.h" />
     <ClInclude Include="CLashConfig.h" />
+    <ClInclude Include="ClashModel.h" />
     <ClInclude Include="CManageNetWork.h" />
     <ClInclude Include="CNetWork.h" />
     <ClInclude Include="comm.h" />
     <ClInclude Include="CProcess.h" />
     <ClInclude Include="CProcessManager.h" />
+    <ClInclude Include="CServerList.h" />
+    <ClInclude Include="CServerListMode.h" />
     <ClInclude Include="CTool.h" />
     <ClInclude Include="CUserInfo.h" />
     <ClInclude Include="event.h" />

+ 33 - 3
SProxy/SProxy.vcxproj.filters

@@ -53,9 +53,6 @@
     <ClCompile Include="LoginDlg.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="CApp.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="SShellNotifyIcon.cpp">
       <Filter>ShellNotify</Filter>
     </ClCompile>
@@ -101,6 +98,24 @@
     <ClCompile Include="CProcessManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="ClashApi.cpp">
+      <Filter>clash</Filter>
+    </ClCompile>
+    <ClCompile Include="CApp.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="ClashModel.cpp">
+      <Filter>clash</Filter>
+    </ClCompile>
+    <ClCompile Include="CServerListMode.cpp">
+      <Filter>Model</Filter>
+    </ClCompile>
+    <ClCompile Include="CServerList.cpp">
+      <Filter>Model</Filter>
+    </ClCompile>
+    <ClCompile Include="CBaseMode.cpp">
+      <Filter>Model</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="SProxy.rc">
@@ -186,6 +201,21 @@
     <ClInclude Include="CProcessManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="ClashModel.h">
+      <Filter>clash</Filter>
+    </ClInclude>
+    <ClInclude Include="ClashApi.h">
+      <Filter>clash</Filter>
+    </ClInclude>
+    <ClInclude Include="CServerListMode.h">
+      <Filter>Model</Filter>
+    </ClInclude>
+    <ClInclude Include="CServerList.h">
+      <Filter>Model</Filter>
+    </ClInclude>
+    <ClInclude Include="CBaseMode.h">
+      <Filter>Model</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\soui_res.rc2">

+ 6 - 0
SProxy/SProxy.vcxproj.user

@@ -3,4 +3,10 @@
   <PropertyGroup>
     <ShowAllFiles>false</ShowAllFiles>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LocalDebuggerAttach>false</LocalDebuggerAttach>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerCommandArguments>
+    </LocalDebuggerCommandArguments>
+  </PropertyGroup>
 </Project>

+ 4 - 1
SProxy/comm.h

@@ -14,4 +14,7 @@ constexpr auto DSPROXY_CONFIG_TUN_ClASH_NAME = L"config.yaml";
 
 
 constexpr auto DSPROXY_CONFIG_DIR_NAME = L"Config";
-constexpr auto DSPROXY_EXE_NAME = L"syscode.exe";
+constexpr auto DSPROXY_EXE_NAME = L"syscode.exe"; 
+
+
+constexpr auto CONNECT_NODE_MSG = L"ÕýÔÚ»ñÈ¡½Úµã..";

+ 19 - 0
SProxy/event.h

@@ -36,6 +36,25 @@ public:
 		EventID = EVT_DOWNLOAD
 	};
 
+	int		 status;
+	SStringW msg;
+};
+
+
+#define EVT_NODELIST (SOUI::EVT_EXTERNAL_BEGIN + 1002)
+
+class EventNodeList : public TplEventArgs<EventNodeList>
+{
+	SOUI_CLASS_NAME(EventNodeList, L"on_event_nodelist")
+public:
+	EventNodeList(SOUI::SWindow* pSender) : TplEventArgs<EventNodeList>(pSender)
+	{
+
+	}
+	enum {
+		EventID = EVT_NODELIST
+	};
+
 	int		 status;
 	SStringW msg;
 };

BIN
SProxy/stdafx.h


+ 1 - 0
SProxy/uires/xml/menu_tray.xml

@@ -1,3 +1,4 @@
 <menu itemHeight="26" iconMargin="4" textMargin="8">
+  <item id="2">显示控制台</item>
   <item id="6">退出</item>
 </menu>