From 1016dcb3d1e788c436df5598dc5c06ae7da5f080 Mon Sep 17 00:00:00 2001
From: 2dust <31833384+2dust@users.noreply.github.com>
Date: Fri, 15 Nov 2024 11:59:22 +0800
Subject: [PATCH] Improve PAC

---
 v2rayN/PacLib/PacHandler.cs                   | 45 ++++++++++---------
 .../Handler/SysProxy/SysProxyHandler.cs       | 39 +++++++---------
 2 files changed, 40 insertions(+), 44 deletions(-)

diff --git a/v2rayN/PacLib/PacHandler.cs b/v2rayN/PacLib/PacHandler.cs
index 1481b94d..6801c69b 100644
--- a/v2rayN/PacLib/PacHandler.cs
+++ b/v2rayN/PacLib/PacHandler.cs
@@ -11,11 +11,11 @@ public class PacHandler
     private static int _httpPort;
     private static int _pacPort;
     private static TcpListener? _tcpListener;
-    private static string _pacText;
+    private static byte[] _writeContent;
     private static bool _isRunning;
     private static bool _needRestart = true;
 
-    public static void Start(string configPath, int httpPort, int pacPort)
+    public static async Task Start(string configPath, int httpPort, int pacPort)
     {
         _needRestart = (configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning);
 
@@ -23,7 +23,7 @@ public class PacHandler
         _httpPort = httpPort;
         _pacPort = pacPort;
 
-        InitText();
+        await InitText();
 
         if (_needRestart)
         {
@@ -32,15 +32,24 @@ public class PacHandler
         }
     }
 
-    private static void InitText()
+    private static async Task InitText()
     {
         var path = Path.Combine(_configPath, "pac.txt");
         if (!File.Exists(path))
         {
-            File.AppendAllText(path, Resources.ResourceManager.GetString("pac"));
+            await File.AppendAllTextAsync(path, Resources.ResourceManager.GetString("pac"));
         }
 
-        _pacText = File.ReadAllText(path).Replace("__PROXY__", $"PROXY 127.0.0.1:{_httpPort};DIRECT;");
+        var pacText = (await File.ReadAllTextAsync(path)).Replace("__PROXY__", $"PROXY 127.0.0.1:{_httpPort};DIRECT;");
+
+        var sb = new StringBuilder();
+        sb.AppendLine("HTTP/1.0 200 OK");
+        sb.AppendLine("Content-type:application/x-ns-proxy-autoconfig");
+        sb.AppendLine("Connection:close");
+        sb.AppendLine("Content-Length:" + Encoding.UTF8.GetByteCount(pacText));
+        sb.AppendLine();
+        sb.Append(pacText);
+        _writeContent = Encoding.UTF8.GetBytes(sb.ToString());
     }
 
     private static void RunListener()
@@ -60,21 +69,8 @@ public class PacHandler
                         continue;
                     }
 
-                    var client = _tcpListener.AcceptTcpClient();
-                    await Task.Run(() =>
-                      {
-                          var stream = client.GetStream();
-                          var sb = new StringBuilder();
-                          sb.AppendLine("HTTP/1.0 200 OK");
-                          sb.AppendLine("Content-type:application/x-ns-proxy-autoconfig");
-                          sb.AppendLine("Connection:close");
-                          sb.AppendLine("Content-Length:" + Encoding.UTF8.GetByteCount(_pacText));
-                          sb.AppendLine();
-                          sb.Append(_pacText);
-                          var content = Encoding.UTF8.GetBytes(sb.ToString());
-                          stream.Write(content, 0, content.Length);
-                          stream.Flush();
-                      });
+                    var client = await _tcpListener.AcceptTcpClientAsync();
+                    await Task.Run(() => { WriteContent(client); });
                 }
                 catch
                 {
@@ -84,6 +80,13 @@ public class PacHandler
         }, TaskCreationOptions.LongRunning);
     }
 
+    private static void WriteContent(TcpClient client)
+    {
+        var stream = client.GetStream();
+        stream.Write(_writeContent, 0, _writeContent.Length);
+        stream.Flush();
+    }
+
     public static void Stop()
     {
         if (_tcpListener == null) return;
diff --git a/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs b/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs
index d6735e4b..de2ac9db 100644
--- a/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs
+++ b/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs
@@ -33,15 +33,10 @@ namespace ServiceLib.Handler.SysProxy
                         await ProxySettingLinux.SetProxy(Global.Loopback, port);
                         break;
 
-                    case ESysProxyType.ForcedChange:
-                        {
-                            if (Utils.IsOSX())
-                            {
-                                await ProxySettingOSX.SetProxy(Global.Loopback, port);
-                            }
+                    case ESysProxyType.ForcedChange when Utils.IsOSX():
+                        await ProxySettingOSX.SetProxy(Global.Loopback, port);
+                        break;
 
-                            break;
-                        }
                     case ESysProxyType.ForcedClear when Utils.IsWindows():
                         ProxySettingWindows.UnsetProxy();
                         break;
@@ -50,23 +45,13 @@ namespace ServiceLib.Handler.SysProxy
                         await ProxySettingLinux.UnsetProxy();
                         break;
 
-                    case ESysProxyType.ForcedClear:
-                        {
-                            if (Utils.IsOSX())
-                            {
-                                await ProxySettingOSX.UnsetProxy();
-                            }
+                    case ESysProxyType.ForcedClear when Utils.IsOSX():
+                        await ProxySettingOSX.UnsetProxy();
+                        break;
 
-                            break;
-                        }
                     case ESysProxyType.Pac when Utils.IsWindows():
-                        {
-                            var portPac = AppHandler.Instance.GetLocalPort(EInboundProtocol.pac);
-                            PacHandler.Start(Utils.GetConfigPath(), port, portPac);
-                            var strProxy = $"{Global.HttpProtocol}{Global.Loopback}:{portPac}/pac?t={DateTime.Now.Ticks}";
-                            ProxySettingWindows.SetProxy(strProxy, "", 4);
-                            break;
-                        }
+                        await SetWindowsProxyPac(port);
+                        break;
                 }
 
                 if (type != ESysProxyType.Pac && Utils.IsWindows())
@@ -102,5 +87,13 @@ namespace ServiceLib.Handler.SysProxy
                     .Replace("{socks_port}", portSocks.ToString());
             }
         }
+
+        private static async Task SetWindowsProxyPac(int port)
+        {
+            var portPac = AppHandler.Instance.GetLocalPort(EInboundProtocol.pac);
+            await PacHandler.Start(Utils.GetConfigPath(), port, portPac);
+            var strProxy = $"{Global.HttpProtocol}{Global.Loopback}:{portPac}/pac?t={DateTime.Now.Ticks}";
+            ProxySettingWindows.SetProxy(strProxy, "", 4);
+        }
     }
 }
\ No newline at end of file