From 046079639e56f242bbf1944e709d5bcadbb705a0 Mon Sep 17 00:00:00 2001
From: ChsBuffer <33744752+chsbuffer@users.noreply.github.com>
Date: Mon, 1 Mar 2021 22:30:22 +0800
Subject: [PATCH] Update PAC Http Server
---
Netch/Controllers/HTTPController.cs | 21 ++++-
Netch/Models/Setting.cs | 4 +-
Netch/Utils/HttpProxyHandler/HttpWebServer.cs | 88 ++++++++-----------
.../Utils/HttpProxyHandler/PACServerHandle.cs | 74 +++++-----------
4 files changed, 78 insertions(+), 109 deletions(-)
diff --git a/Netch/Controllers/HTTPController.cs b/Netch/Controllers/HTTPController.cs
index e880bac0..0963ff29 100644
--- a/Netch/Controllers/HTTPController.cs
+++ b/Netch/Controllers/HTTPController.cs
@@ -3,6 +3,7 @@ using WindowsProxy;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Servers.Trojan;
+using Netch.Utils;
using Netch.Utils.HttpProxyHandler;
namespace Netch.Controllers
@@ -24,16 +25,30 @@ namespace Netch.Controllers
{
PrivoxyController.Start(MainController.Server!);
Global.Job.AddProcess(PrivoxyController.Instance!);
+ string? pacUrl = null;
+
+ if (MainController.Server is Socks5 or Trojan && mode.BypassChina || (Global.Settings.AlwaysStartPACServer ?? false))
+ {
+ try
+ {
+ PortHelper.CheckPort(Global.Settings.Pac_Port);
+ }
+ catch
+ {
+ Global.Settings.Pac_Port = PortHelper.GetAvailablePort();
+ }
+
+ pacUrl = PACServerHandle.InitPACServer("127.0.0.1");
+ }
if (mode.Type is 3)
{
using var service = new ProxyService();
_oldState = service.Query();
- if (MainController.Server is Socks5 or Trojan && mode.BypassChina)
+ if (pacUrl != null)
{
- service.AutoConfigUrl = PACServerHandle.InitPACServer("127.0.0.1");
-
+ service.AutoConfigUrl = pacUrl;
service.Pac();
}
else
diff --git a/Netch/Models/Setting.cs b/Netch/Models/Setting.cs
index a2c4414e..0e7b3912 100644
--- a/Netch/Models/Setting.cs
+++ b/Netch/Models/Setting.cs
@@ -174,7 +174,7 @@ namespace Netch.Models
///
/// PAC端口
///
- public int Pac_Port { get; set; } = 2803;
+ public ushort Pac_Port { get; set; } = 2803;
///
/// 不代理TCP
@@ -293,6 +293,8 @@ namespace Netch.Models
public V2rayConfig V2RayConfig { get; set; } = new();
+ public bool? AlwaysStartPACServer { get; set; }
+
public Setting Clone()
{
return (Setting) MemberwiseClone();
diff --git a/Netch/Utils/HttpProxyHandler/HttpWebServer.cs b/Netch/Utils/HttpProxyHandler/HttpWebServer.cs
index 30c4ccbe..00ad981a 100644
--- a/Netch/Utils/HttpProxyHandler/HttpWebServer.cs
+++ b/Netch/Utils/HttpProxyHandler/HttpWebServer.cs
@@ -1,85 +1,67 @@
using System;
using System.Net;
using System.Text;
-using System.Threading;
namespace Netch.Utils.HttpProxyHandler
{
public class HttpWebServer
{
- private HttpListener? _listener;
private readonly Func? _responderMethod;
+ private HttpListener? _listener;
public HttpWebServer(string[] prefixes, Func method)
{
- try
- {
- _listener = new HttpListener();
+ _listener = new HttpListener();
- if (!HttpListener.IsSupported)
- throw new NotSupportedException("Needs Windows XP SP2, Server 2003 or later.");
+ // URI prefixes are required, for example
+ // "http://localhost:8080/index/".
+ if (prefixes == null || prefixes.Length == 0)
+ throw new ArgumentException("prefixes");
- // URI prefixes are required, for example
- // "http://localhost:8080/index/".
- if (prefixes == null || prefixes.Length == 0)
- throw new ArgumentException("prefixes");
+ // A responder method is required
+ if (method == null)
+ throw new ArgumentException("method");
- // A responder method is required
- if (method == null)
- throw new ArgumentException("method");
+ foreach (var s in prefixes)
+ _listener.Prefixes.Add(s);
- foreach (var s in prefixes)
- _listener.Prefixes.Add(s);
-
- _responderMethod = method;
- _listener.Start();
- }
- catch (Exception ex)
- {
- Logging.Error("HttpWebServer():" + ex.Message);
- }
+ _responderMethod = method;
+ _listener.Start();
}
public HttpWebServer(Func method, params string[] prefixes) : this(prefixes, method)
{
}
- public void Run()
+ public void StartWaitingRequest()
{
- ThreadPool.QueueUserWorkItem(o =>
+ Logging.Info("Webserver running...");
+ while (_listener?.IsListening ?? false)
{
- Logging.Info("Webserver running...");
+ HttpListenerContext ctx;
try
{
- while (_listener!.IsListening)
- ThreadPool.QueueUserWorkItem(c =>
- {
- var ctx = (HttpListenerContext) c;
- try
- {
- var rstr = _responderMethod!(ctx.Request);
- var buf = Encoding.UTF8.GetBytes(rstr);
- ctx.Response.StatusCode = 200;
- ctx.Response.ContentType = "application/x-ns-proxy-autoconfig";
- ctx.Response.ContentLength64 = buf.Length;
- ctx.Response.OutputStream.Write(buf, 0, buf.Length);
- }
- catch
- {
- // ignored
- }
- finally
- {
- ctx.Response.OutputStream.Close();
- }
- },
- _listener.GetContext());
+ ctx = _listener.GetContext();
}
- catch (Exception ex)
+ catch
{
- Logging.Error(ex.Message);
+ break;
}
- });
+
+ try
+ {
+ var rstr = _responderMethod!(ctx.Request);
+ var buf = Encoding.UTF8.GetBytes(rstr);
+ ctx.Response.StatusCode = 200;
+ ctx.Response.ContentType = "application/x-ns-proxy-autoconfig";
+ ctx.Response.ContentLength64 = buf.Length;
+ ctx.Response.OutputStream.Write(buf, 0, buf.Length);
+ }
+ finally
+ {
+ ctx.Response.OutputStream.Close();
+ }
+ }
}
public void Stop()
diff --git a/Netch/Utils/HttpProxyHandler/PACServerHandle.cs b/Netch/Utils/HttpProxyHandler/PACServerHandle.cs
index d4e925fc..c252233a 100644
--- a/Netch/Utils/HttpProxyHandler/PACServerHandle.cs
+++ b/Netch/Utils/HttpProxyHandler/PACServerHandle.cs
@@ -1,102 +1,74 @@
using System;
-using System.Collections;
-using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
+using System.Threading.Tasks;
+using Netch.Controllers;
namespace Netch.Utils.HttpProxyHandler
{
///
/// 提供PAC功能支持
///
- internal class PACServerHandle
+ internal static class PACServerHandle
{
- private static readonly Hashtable httpWebServer = new();
- private static readonly Hashtable pacList = new();
+ private static HttpWebServer? _httpWebServer;
+ private static string? _pacContent;
public static string InitPACServer(string address)
{
try
{
- if (!pacList.ContainsKey(address))
- pacList.Add(address, GetPacList(address));
-
+ _pacContent = GetPacList(address);
var prefixes = $"http://{address}:{Global.Settings.Pac_Port}/pac/";
- var ws = new HttpWebServer(SendResponse, prefixes);
- ws.Run();
-
- if (!httpWebServer.ContainsKey(address))
- httpWebServer.Add(address, ws);
+ _httpWebServer = new HttpWebServer(SendResponse, prefixes);
+ Task.Run(() => _httpWebServer.StartWaitingRequest());
var pacUrl = GetPacUrl();
Logging.Info($"Webserver InitServer OK: {pacUrl}");
return pacUrl;
}
- catch (Exception ex)
+ catch
{
- throw new Exception("Webserver InitServer Error:" + ex.Message);
+ Logging.Error("Webserver InitServer Failed");
+ throw;
}
}
public static string SendResponse(HttpListenerRequest request)
{
- try
- {
- var arrAddress = request.UserHostAddress.Split(':');
- var address = "127.0.0.1";
- if (arrAddress.Length > 0)
- address = arrAddress[0];
-
- return pacList[address].ToString();
- }
- catch (Exception ex)
- {
- Logging.Error("Webserver SendResponse " + ex.Message);
- return ex.Message;
- }
+ return _pacContent!;
}
public static void Stop()
{
try
{
- if (httpWebServer == null)
- return;
-
- foreach (var key in httpWebServer.Keys)
- {
- Logging.Info("Webserver Stop " + key);
- ((HttpWebServer) httpWebServer[key]).Stop();
- }
-
- httpWebServer.Clear();
+ _httpWebServer?.Stop();
}
- catch (Exception ex)
+ catch
{
- Logging.Error("Webserver Stop " + ex.Message);
+ // ignored
}
+
+ _httpWebServer = null;
}
private static string GetPacList(string address)
{
try
{
- var lstProxy = new List();
- lstProxy.Add(string.Format("PROXY {0}:{1};", address, Global.Settings.HTTPLocalPort));
+ var proxy = $"PROXY {address}:{Global.Settings.HTTPLocalPort};";
+ var pacfile = Path.Combine(Global.NetchDir, "bin\\pac.txt");
- var proxy = string.Join("", lstProxy.ToArray());
- var strPacfile = Path.Combine(Global.NetchDir, "bin\\pac.txt");
-
- var pac = File.ReadAllText(strPacfile, Encoding.UTF8).Replace("__PROXY__", proxy);
+ var pac = File.ReadAllText(pacfile, Encoding.UTF8).Replace("__PROXY__", proxy);
return pac;
}
catch
{
+ throw new MessageException("Pac file not found!");
}
-
- return "No pac content";
}
///
@@ -105,9 +77,7 @@ namespace Netch.Utils.HttpProxyHandler
///
public static string GetPacUrl()
{
- var pacUrl = string.Format("http://127.0.0.1:{0}/pac/?t={1}", Global.Settings.Pac_Port, DateTime.Now.ToString("yyyyMMddHHmmssfff"));
-
- return pacUrl;
+ return $"http://127.0.0.1:{Global.Settings.Pac_Port}/pac/?t={DateTime.Now:yyyyMMddHHmmssfff}";
}
}
}
\ No newline at end of file