Repository: cnlangzi/proxyclient
Pull request #23: fix(leak):goroutine leak
Author: login: cnlangzi
Created: 2025-05-11T06:44:00Z | Merged: 2025-05-11T07:26:21Z

## Summary by Sourcery

Refactor proxy implementations to use direct connection dialers, improve resource management to prevent leaks, and reduce logging verbosity in Xray configurations.

Bug Fixes:
- Fix potential goroutine and connection leaks by ensuring connections are closed on error and deadlines are set appropriately.

Enhancements:
- Refactor proxy implementations to use direct dialers instead of local SOCKS proxies for VLESS, VMess, SSR, and Trojan protocols.
- Update logging configuration in Xray-related configs to reduce log verbosity and disable access logs.


Diff:
diff --git a/proxy.go b/proxy.go
index 6a1972b..357175a 100644
--- a/proxy.go
+++ b/proxy.go
@@ -41,6 +41,18 @@ func CreateTransport(o *Options) *http.Transport {
 	return tr
 }
 
+func SetDeadline(conn net.Conn, timeout time.Duration, disableKeepAlives bool) (net.Conn, error) {
+	if timeout > 0 && disableKeepAlives {
+		err := conn.SetDeadline(time.Now().Add(timeout))
+		if err != nil {
+			// Ensure the connection is closed to avoid resource leaks
+			conn.Close() // nolint: errcheck
+			return nil, fmt.Errorf("failed to set deadline: %w", err)
+		}
+	}
+	return conn, nil
+}
+
 func GetFreePort() (int, error) {
 	listener, err := net.Listen("tcp", "127.0.0.1:0")
 	if err != nil {
diff --git a/proxy_socks.go b/proxy_socks.go
index 51cac86..b27ab5e 100644
--- a/proxy_socks.go
+++ b/proxy_socks.go
@@ -6,6 +6,7 @@ import (
 	"net"
 	"net/http"
 	"net/url"
+	"time"
 
 	"golang.org/x/net/proxy"
 	"h12.io/socks"
@@ -66,7 +67,17 @@ func ProxySocks4(u *url.URL, o *Options) (http.RoundTripper, error) {
 		return socks.Dial(proxyURL)(network, addr)
 	}
 	tr.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-		return dialTLSContext(ctx, tr.DialContext, network, addr, tr.TLSClientConfig)
+		conn, err := dialTLSContext(ctx, tr.DialContext, network, addr, tr.TLSClientConfig)
+		if err != nil {
+			return nil, err
+		}
+
+		err = conn.SetDeadline(time.Now().Add(o.Timeout))
+		if err != nil {
+			conn.Close() // Ensure the connection is closed to avoid resource leaks
+			return nil, err
+		}
+		return conn, nil
 	}
 
 	tr.Proxy = nil
diff --git a/ss/proxy_ss.go b/ss/proxy_ss.go
index e680d04..4ccfdb4 100644
--- a/ss/proxy_ss.go
+++ b/ss/proxy_ss.go
@@ -18,19 +18,19 @@ func init() {
 	proxyclient.RegisterProxy("ss", DialSS)
 }
 
-// ProxySS creates a RoundTripper for Shadowsocks proxy
-func ProxySS(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	// Start Shadowsocks instance
-	port, err := StartSS(u, 0)
-	if err != nil {
-		return nil, err
-	}
+// // ProxySS creates a RoundTripper for Shadowsocks proxy
+// func ProxySS(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	// Start Shadowsocks instance
+// 	port, err := StartSS(u, 0)
+// 	if err != nil {
+// 		return nil, err
+// 	}
 
-	// Get SOCKS5 proxy URL
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	// Get SOCKS5 proxy URL
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
 
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
 func DialSS(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 
@@ -48,7 +48,6 @@ func DialSS(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 	tr := proxyclient.CreateTransport(o)
 
 	tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-
 		serverAddr := net.JoinHostPort(cfg.Server, strconv.Itoa(cfg.Port))
 		conn, err := net.Dial("tcp", serverAddr)
 		if err != nil {
@@ -58,16 +57,22 @@ func DialSS(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 		destination := metadata.ParseSocksaddr(addr)
 
 		ssConn, err := proxyclient.WithRecover(func() (net.Conn, error) {
-			return m.DialConn(conn, destination)
+			conn, err := m.DialConn(conn, destination)
+			if err != nil {
+				return nil, err
+			}
+
+			return proxyclient.SetDeadline(conn, o.Timeout, tr.DisableKeepAlives)
 		})
 
 		if ssConn == nil {
+			conn.Close() // nolint: errcheck
 			log.Printf("ss: panic on %s \n", su.Raw().String())
 			return nil, fmt.Errorf("failed to create Shadowsocks connection: %w", err)
 		}
 
 		if err != nil {
-			conn.Close()
+			conn.Close() // nolint: errcheck
 			log.Printf("ss: panic on %s \n", su.Raw().String())
 			return nil, fmt.Errorf("failed to create Shadowsocks connection: %w", err)
 		}
diff --git a/xray/proxy_ssr.go b/xray/proxy_ssr.go
index 00284ce..4382ded 100644
--- a/xray/proxy_ssr.go
+++ b/xray/proxy_ssr.go
@@ -15,17 +15,17 @@ func init() {
 }
 
 // ProxySSR creates a RoundTripper for SSR proxy
-func ProxySSR(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	// Start SSR client through Xray
-	_, port, err := StartSSR(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start ssr proxy: %w", err)
-	}
-
-	// Use SOCKS5 proxy created by Xray
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// func ProxySSR(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	// Start SSR client through Xray
+// 	_, port, err := StartSSR(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start ssr proxy: %w", err)
+// 	}
+
+// 	// Use SOCKS5 proxy created by Xray
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
 // DialSSR creates a custom transport that dials directly to the v2ray server
 // instead of using a local SOCKS proxy.
@@ -38,7 +38,12 @@ func DialSSR(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 	// Create a transport that uses our custom dialer
 	tr := proxyclient.CreateTransport(o)
 	tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-		return dialContext(ctx, instance, network, addr)
+		conn, err := dialContext(ctx, instance, network, addr)
+		if err != nil {
+			return nil, err
+		}
+
+		return proxyclient.SetDeadline(conn, o.Timeout, tr.DisableKeepAlives)
 	}
 	tr.Proxy = nil
 
diff --git a/xray/proxy_trojan.go b/xray/proxy_trojan.go
index 894f913..6a1d547 100644
--- a/xray/proxy_trojan.go
+++ b/xray/proxy_trojan.go
@@ -15,17 +15,17 @@ func init() {
 }
 
 // ProxyTrojan creates a RoundTripper for Trojan proxy
-func ProxyTrojan(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	// Start Trojan client through Xray
-	_, port, err := StartTrojan(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start Trojan proxy: %w", err)
-	}
-
-	// Use SOCKS5 proxy created by Xray
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// func ProxyTrojan(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	// Start Trojan client through Xray
+// 	_, port, err := StartTrojan(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start Trojan proxy: %w", err)
+// 	}
+
+// 	// Use SOCKS5 proxy created by Xray
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
 // DialTrojan creates a custom transport that dials directly to the v2ray server
 // instead of using a local SOCKS proxy.
@@ -38,7 +38,12 @@ func DialTrojan(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 	// Create a transport that uses our custom dialer
 	tr := proxyclient.CreateTransport(o)
 	tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-		return dialContext(ctx, instance, network, addr)
+		conn, err := dialContext(ctx, instance, network, addr)
+		if err != nil {
+			return nil, err
+		}
+
+		return proxyclient.SetDeadline(conn, o.Timeout, tr.DisableKeepAlives)
 	}
 	tr.Proxy = nil
 
diff --git a/xray/proxy_vless.go b/xray/proxy_vless.go
index c23de03..194fdf5 100644
--- a/xray/proxy_vless.go
+++ b/xray/proxy_vless.go
@@ -14,15 +14,15 @@ func init() {
 	proxyclient.RegisterProxy("vless", DialVless)
 }
 
-func ProxyVless(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	_, port, err := StartVless(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start vless proxy: %w", err)
-	}
+// func ProxyVless(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	_, port, err := StartVless(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start vless proxy: %w", err)
+// 	}
 
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
 // DialVless creates a custom transport that dials directly to the v2ray server
 // instead of using a local SOCKS proxy.
@@ -35,7 +35,12 @@ func DialVless(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 	// Create a transport that uses our custom dialer
 	tr := proxyclient.CreateTransport(o)
 	tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-		return dialContext(ctx, instance, network, addr)
+		conn, err := dialContext(ctx, instance, network, addr)
+		if err != nil {
+			return nil, err
+		}
+
+		return proxyclient.SetDeadline(conn, o.Timeout, tr.DisableKeepAlives)
 	}
 	tr.Proxy = nil
 
diff --git a/xray/proxy_vmess.go b/xray/proxy_vmess.go
index 750ff4b..d19bfcf 100644
--- a/xray/proxy_vmess.go
+++ b/xray/proxy_vmess.go
@@ -14,15 +14,15 @@ func init() {
 	proxyclient.RegisterProxy("vmess", DialVmess)
 }
 
-func ProxyVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	_, port, err := StartVmess(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start vmess proxy: %w", err)
-	}
+// func ProxyVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	_, port, err := StartVmess(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start vmess proxy: %w", err)
+// 	}
 
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
 // DialVmess creates a custom transport that dials directly to the v2ray server
 // instead of using a local SOCKS proxy.
@@ -35,7 +35,12 @@ func DialVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 	// Create a transport that uses our custom dialer
 	tr := proxyclient.CreateTransport(o)
 	tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-		return dialContext(ctx, instance, network, addr)
+		conn, err := dialContext(ctx, instance, network, addr)
+		if err != nil {
+			return nil, err
+		}
+
+		return proxyclient.SetDeadline(conn, o.Timeout, tr.DisableKeepAlives)
 	}
 	tr.Proxy = nil
 
diff --git a/xray/ssr.go b/xray/ssr.go
index 855418e..d707626 100644
--- a/xray/ssr.go
+++ b/xray/ssr.go
@@ -132,25 +132,26 @@ func SSRToXRay(u *url.URL, port int) ([]byte, int, error) {
 	// Create configuration based on Xray JSON format
 	config := &XRayConfig{
 		Log: &LogConfig{
-			Loglevel: "warning",
-		},
-		Inbounds: []Inbound{
-			{
-				Tag:      "socks-in",
-				Port:     port,
-				Listen:   "127.0.0.1",
-				Protocol: "socks",
-				Settings: &SocksSetting{
-					Auth: "noauth",
-					UDP:  true,
-					IP:   "127.0.0.1",
-				},
-				Sniffing: &Sniffing{
-					Enabled:      true,
-					DestOverride: []string{"http", "tls"},
-				},
-			},
+			Access:   "none",
+			Loglevel: "error",
 		},
+		// Inbounds: []Inbound{
+		// 	{
+		// 		Tag:      "socks-in",
+		// 		Port:     port,
+		// 		Listen:   "127.0.0.1",
+		// 		Protocol: "socks",
+		// 		Settings: &SocksSetting{
+		// 			Auth: "noauth",
+		// 			UDP:  true,
+		// 			IP:   "127.0.0.1",
+		// 		},
+		// 		Sniffing: &Sniffing{
+		// 			Enabled:      true,
+		// 			DestOverride: []string{"http", "tls"},
+		// 		},
+		// 	},
+		// },
 		Outbounds: []Outbound{
 			{
 				Tag:      "shadowsocks-out",
@@ -211,6 +212,6 @@ func StartSSR(u *url.URL, port int) (*core.Instance, int, error) {
 	// Register the running server
 	setServer(ssrURL, instance, port)
 
-	fmt.Printf("SSR proxy started on socks5://127.0.0.1:%d\n", port)
+	// fmt.Printf("SSR proxy started on socks5://127.0.0.1:%d\n", port)
 	return instance, port, nil
 }
diff --git a/xray/trojan.go b/xray/trojan.go
index 6c57eb2..277d502 100644
--- a/xray/trojan.go
+++ b/xray/trojan.go
@@ -141,25 +141,26 @@ func TrojanToXRay(u *url.URL, port int) ([]byte, int, error) {
 	// Create complete configuration
 	config := &XRayConfig{
 		Log: &LogConfig{
-			Loglevel: "warning",
-		},
-		Inbounds: []Inbound{
-			{
-				Tag:      "socks-in",
-				Port:     port,
-				Listen:   "127.0.0.1",
-				Protocol: "socks",
-				Settings: &SocksSetting{
-					Auth: "noauth",
-					UDP:  true,
-					IP:   "127.0.0.1",
-				},
-				Sniffing: &Sniffing{
-					Enabled:      true,
-					DestOverride: []string{"http", "tls"},
-				},
-			},
+			Access:   "none",
+			Loglevel: "error",
 		},
+		// Inbounds: []Inbound{
+		// 	{
+		// 		Tag:      "socks-in",
+		// 		Port:     port,
+		// 		Listen:   "127.0.0.1",
+		// 		Protocol: "socks",
+		// 		Settings: &SocksSetting{
+		// 			Auth: "noauth",
+		// 			UDP:  true,
+		// 			IP:   "127.0.0.1",
+		// 		},
+		// 		Sniffing: &Sniffing{
+		// 			Enabled:      true,
+		// 			DestOverride: []string{"http", "tls"},
+		// 		},
+		// 	},
+		// },
 		Outbounds: []Outbound{
 			{
 				Tag:            "trojan-out",
diff --git a/xray/vless.go b/xray/vless.go
index a649f31..2a135d8 100644
--- a/xray/vless.go
+++ b/xray/vless.go
@@ -13,7 +13,7 @@ import (
 )
 
 func init() {
-	proxyclient.RegisterProxy("vless", ProxyVless)
+	proxyclient.RegisterProxy("vless", DialVless)
 }
 
 // VlessToXRay converts VLESS URL to Xray JSON configuration
@@ -153,25 +153,26 @@ func VlessToXRay(vu *VlessURL, port int) ([]byte, int, error) {
 	// Create complete configuration
 	config := &XRayConfig{
 		Log: &LogConfig{
-			Loglevel: "warning",
-		},
-		Inbounds: []Inbound{
-			{
-				Tag:      "socks-in",
-				Port:     port,
-				Listen:   "127.0.0.1",
-				Protocol: "socks",
-				Settings: &SocksSetting{
-					Auth: "noauth",
-					UDP:  true,
-					IP:   "127.0.0.1",
-				},
-				Sniffing: &Sniffing{
-					Enabled:      true,
-					DestOverride: []string{"http", "tls"},
-				},
-			},
+			Access:   "none",
+			Loglevel: "error",
 		},
+		// Inbounds: []Inbound{
+		// 	{
+		// 		Tag:      "socks-in",
+		// 		Port:     port,
+		// 		Listen:   "127.0.0.1",
+		// 		Protocol: "socks",
+		// 		Settings: &SocksSetting{
+		// 			Auth: "noauth",
+		// 			UDP:  true,
+		// 			IP:   "127.0.0.1",
+		// 		},
+		// 		Sniffing: &Sniffing{
+		// 			Enabled:      true,
+		// 			DestOverride: []string{"http", "tls"},
+		// 		},
+		// 	},
+		// },
 		Outbounds: []Outbound{
 			{
 				Tag:            "vless-out",
@@ -239,6 +240,6 @@ func StartVless(u *url.URL, port int) (*core.Instance, int, error) {
 	// Register the running server
 	setServer(vlessURL, instance, port)
 
-	fmt.Printf("VLESS proxy started on socks5://127.0.0.1:%d\n", port)
+	// fmt.Printf("VLESS proxy started on socks5://127.0.0.1:%d\n", port)
 	return instance, port, nil
 }
diff --git a/xray/vmess.go b/xray/vmess.go
index e41d0be..4b20c8b 100644
--- a/xray/vmess.go
+++ b/xray/vmess.go
@@ -50,26 +50,28 @@ func createCompleteVmessConfig(vmess *VmessConfig, port int) *XRayConfig {
 
 	return &XRayConfig{
 		Log: &LogConfig{
-			Loglevel: "warning",
-		},
-		Inbounds: []Inbound{
-			{
-				Tag:      "socks-in",
-				Port:     port,
-				Listen:   "127.0.0.1",
-				Protocol: "socks",
-				Settings: &SocksSetting{
-					Auth:      "noauth",
-					UDP:       true,
-					IP:        "127.0.0.1",
-					UserLevel: 0,
-				},
-				Sniffing: &Sniffing{
-					Enabled:      true,
-					DestOverride: []string{"http", "tls"},
-				},
-			},
+			Access: "none", // Disable access logs
+			// Error:    "none", // Disable error log file (Loglevel controls console error log verbosity)
+			Loglevel: "error", // Set to "none" to disable console error logs, or "error" for errors only
 		},
+		// Inbounds: []Inbound{
+		// 	{
+		// 		Tag:      "socks-in",
+		// 		Port:     port,
+		// 		Listen:   "127.0.0.1",
+		// 		Protocol: "socks",
+		// 		Settings: &SocksSetting{
+		// 			Auth:      "noauth",
+		// 			UDP:       true,
+		// 			IP:        "127.0.0.1",
+		// 			UserLevel: 0,
+		// 		},
+		// 		Sniffing: &Sniffing{
+		// 			Enabled:      true,
+		// 			DestOverride: []string{"http", "tls"},
+		// 		},
+		// 	},
+		// },
 		Outbounds: []Outbound{
 			{
 				Tag:      "vmess-out",


Reviews:
user: login: sourcery-ai[bot]
body: Hey @cnlangzi - I've reviewed your changes - here's some feedback:

- The inbound configuration blocks are now commented out in all protocol config generators; if this is intentional for leak mitigation, consider adding a code comment explaining why and the expected runtime behavior.
- Setting both Timeout and Deadline in the net.Dialer may cause unexpected behavior; Deadline is an absolute time and may not be appropriate for repeated dial operations.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟢 **General issues**: all looks good
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-11T06:45:21Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR addresses a potential goroutine leak by improving transport timeout handling, while also reducing logging verbosity and disabling unused inbound configurations in Xray.  
- Adjusts logging configuration by setting "Access" to "none" and "Loglevel" to "error".  
- Comments out unused inbound configuration blocks and proxy functions to reduce unnecessary overhead.  
- Adds a transport dialer deadline to help mitigate goroutine leaks.

### Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

<details>
<summary>Show a summary per file</summary>

| File                     | Description                                                         |
| ------------------------ | ------------------------------------------------------------------- |
| xray/vmess.go            | Updates log config and comments out unused inbound configurations.  |
| xray/vless.go            | Similar log updates and removal of inbound code.                    |
| xray/trojan.go           | Log changes and unused inbound code commented out.                  |
| xray/ssr.go              | Applies log adjustments and disables inbound configuration.         |
| xray/proxy_vmess.go       | Disables ProxyVmess by commenting out the function body.            |
| xray/proxy_vless.go       | Disables ProxyVless by commenting out the function body.            |
| xray/proxy_trojan.go      | Disables ProxyTrojan by commenting out the function body.           |
| xray/proxy_ssr.go         | Disables ProxySSR by commenting out the function body.              |
| proxy.go                 | Adds a transport dialer deadline to address potential goroutine leak. |
</details>



<details>
<summary>Comments suppressed due to low confidence (4)</summary>

**xray/vmess.go:57**
* If the inbound configuration is no longer required, consider removing the commented out code entirely to reduce clutter and improve maintainability.
```
// Inbounds: []Inbound{ ... }
```
**xray/vless.go:159**
* If the commented inbound block is deprecated, it would be cleaner to remove it instead of leaving commented code in the repository.
```
// Inbounds: []Inbound{ ... }
```
**xray/trojan.go:147**
* Consider removing the commented inbound configuration block if it is no longer needed to improve code clarity and maintainability.
```
// Inbounds: []Inbound{ ... }
```
**xray/ssr.go:138**
* Removing the commented code block for inbound configuration can help keep the codebase cleaner and more maintainable if it is not planned for future use.
```
// Inbounds: []Inbound{ ... }
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-11T06:51:31Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR reduces logging verbosity and disables access logs across various Xray configuration files while addressing a potential goroutine leak by improving transport timeout handling.  
- Logging configuration in Xray and proxy files updated (set "Access" to "none" and "Loglevel" to "error").  
- Unused inbound configuration blocks and startup log messages are commented out.  
- All Dial* functions now set connection deadlines via the provided timeout.

### Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

<details>
<summary>Show a summary per file</summary>

| File                     | Description                                                                       |
| ------------------------ | --------------------------------------------------------------------------------- |
| xray/vmess.go            | Logging config updated and obsolete inbounds commented out.                       |
| xray/vless.go            | Updated proxy registration to use DialVless and updated logging config.             |
| xray/trojan.go           | Similar logging config update and removal of unused inbound config.                |
| xray/ssr.go              | Logging config updated with inbounds commented out and startup print suppressed.    |
| xray/proxy_vmess.go       | Dial function enhanced with deadline handling.                                   |
| xray/proxy_vless.go       | Similar updated dial context logic with deadline handling.                        |
| xray/proxy_trojan.go      | Dial function updated to set deadline after dialing.                              |
| xray/proxy_ssr.go         | Dial function updated with deadline handling.                                     |
| ss/proxy_ss.go           | Updated dial function now sets deadlines and handles errors with resource cleanup.  |
| proxy_socks.go           | TLS dial context updated with deadline checks.                                    |
</details>



<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**xray/vmess.go:57**
* [nitpick] If the inbound configuration code is no longer intended for use, consider removing it entirely to reduce clutter; if it's kept for future reference, adding a clear explanatory comment would improve maintainability.
```
// Inbounds: []Inbound{ ...
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-11T07:02:33Z
user: login: sourcery-ai[bot]
body: Hey @cnlangzi - I've reviewed your changes - here's some feedback:

- Consider removing or consolidating the large blocks of commented-out code to keep the codebase clean and maintainable.
- If the inbound configuration and startup log messages are no longer needed, it may be better to delete them rather than commenting them out.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 3 issues found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-11T07:06:01Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR addresses a potential goroutine leak by improving transport timeout handling while also reducing logging verbosity and disabling access logs in Xray configurations. Key changes include updating log settings across multiple proxy configurations, commenting out unused inbound blocks, and refactoring dialer functions to set connection deadlines.

### Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

<details>
<summary>Show a summary per file</summary>

| File                    | Description                                                                                  |
| ----------------------- | -------------------------------------------------------------------------------------------- |
| xray/vmess.go           | Updated log configuration and commented out unused inbound settings to reduce verbosity.     |
| xray/vless.go           | Adjusted logging settings and removed debug prints in the VLESS configuration.               |
| xray/trojan.go          | Revised log settings to reduce console noise and grouped unused inbound code as comments.      |
| xray/ssr.go             | Updated logging configuration and suppressed debug output for SSR proxy.                     |
| xray/proxy_vmess.go     | Enhanced DialVmess function with deadline setting to mitigate potential resource leaks.      |
| xray/proxy_vless.go     | Made similar deadline handling improvements in the DialVless function.                       |
| xray/proxy_trojan.go    | Added deadline setting in DialTrojan to ensure proper connection closure on error.           |
| xray/proxy_ssr.go       | Applied deadline handling in DialSSR to prevent lingering connections.                     |
| ss/proxy_ss.go          | Improved dialer logic with deadline settings and refined error handling with connection closure.|
| proxy_socks.go          | Integrated deadline settings after TLS handshake to reduce resource leakage risks.           |
</details>



<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**xray/vmess.go:57**
* Consider removing the commented-out inbound configuration if it is no longer required to reduce clutter and improve maintainability.
```
// Inbounds: []Inbound{ ... }
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-11T07:06:04Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR refactors proxy implementations to use direct dialers with connection timeouts and updates Xray proxy logging configurations to mitigate goroutine leaks. Changes include removing legacy SOCKS5 startup code (commented out), replacing legacy proxy functions with direct dialers, and standardizing log settings across proxy implementations.

### Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

<details>
<summary>Show a summary per file</summary>

| File                     | Description                                                          |
| ------------------------ | -------------------------------------------------------------------- |
| xray/vmess.go            | Updated logging configuration and commented out legacy inbound code. |
| xray/vless.go            | Adjusted logging and replaced legacy proxy registration; commented out inbound block. |
| xray/trojan.go, xray/ssr.go | Similar logging updates with commented-out legacy inbound configurations. |
| proxy_v* files           | Removed legacy proxy functions in favor of Dial* functions with proper deadline handling. |
| ss/proxy_ss.go, proxy_socks.go, proxy.go | Added deadline setting to prevent connection leaks and improved error handling. |
</details>



<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**xray/vmess.go:57**
* [nitpick] Consider removing the commented legacy inbound configuration code if it is no longer needed to reduce clutter and improve maintainability.
```
// Inbounds: []Inbound{ ... }
```
**xray/vless.go:159**
* [nitpick] If the legacy inbound configuration is now obsolete, it is advisable to remove the commented-out code to keep the codebase clean.
```
// Inbounds: []Inbound{ ... }
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-11T07:20:38Z
user: login: sourcery-ai[bot]
body: Hey @cnlangzi - I've reviewed your changes - here's some feedback:

- Consider fully removing legacy and commented-out code if it is no longer needed, rather than leaving large blocks commented out.
- Ensure that all new direct dialers consistently handle connection closure on error to prevent resource leaks.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 4 issues found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-11T07:24:49Z

Review comments:
diff_hunk: @@ -31,7 +31,8 @@ func CreateTransport(o *Options) *http.Transport {
 
 	if o.Timeout > 0 {
 		tr.DialContext = (&net.Dialer{
-			Timeout: o.Timeout / 2,
+			Timeout:  o.Timeout / 2,
+			Deadline: time.Now().Add(o.Timeout),
 		}).DialContext
path: proxy.go
user: login: Copilot
body: Using a fixed deadline computed with time.Now() at transport creation may lead to unexpected timeouts for later connections. Consider calculating the deadline dynamically per dial attempt or re-instantiating the dialer for each connection.
```suggestion
		dialer := &net.Dialer{
			Timeout: o.Timeout / 2,
		}
		tr.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) {
			deadlineCtx, cancel := context.WithDeadline(ctx, time.Now().Add(o.Timeout))
			defer cancel()
			return dialer.DialContext(deadlineCtx, network, address)
		}
```
created_at: 2025-05-11T06:51:30Z
author_association: NONE
diff_hunk: @@ -14,15 +14,15 @@ func init() {
 	proxyclient.RegisterProxy("vmess", DialVmess)
 }
 
-func ProxyVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	_, port, err := StartVmess(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start vmess proxy: %w", err)
-	}
-
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// func ProxyVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	_, port, err := StartVmess(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start vmess proxy: %w", err)
+// 	}
+
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
path: xray/proxy_vmess.go
user: login: Copilot
body: Commented-out functions should be removed if they are no longer intended for use to avoid confusion and reduce code clutter.
```suggestion
// Removed commented-out ProxyVmess function to reduce code clutter and avoid confusion.
```
created_at: 2025-05-11T06:51:30Z
author_association: NONE
diff_hunk: @@ -14,15 +14,15 @@ func init() {
 	proxyclient.RegisterProxy("vless", DialVless)
 }
 
-func ProxyVless(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	_, port, err := StartVless(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start vless proxy: %w", err)
-	}
-
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// func ProxyVless(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	_, port, err := StartVless(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start vless proxy: %w", err)
+// 	}
+
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
path: xray/proxy_vless.go
user: login: Copilot
body: If ProxyVless is deprecated, consider deleting the commented out implementation to keep the codebase clean.
```suggestion
// (Commented-out implementation of ProxyVless removed for codebase cleanliness)
```
created_at: 2025-05-11T06:51:30Z
author_association: NONE
diff_hunk: @@ -15,17 +15,17 @@ func init() {
 }
 
 // ProxyTrojan creates a RoundTripper for Trojan proxy
-func ProxyTrojan(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	// Start Trojan client through Xray
-	_, port, err := StartTrojan(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start Trojan proxy: %w", err)
-	}
-
-	// Use SOCKS5 proxy created by Xray
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// func ProxyTrojan(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	// Start Trojan client through Xray
+// 	_, port, err := StartTrojan(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start Trojan proxy: %w", err)
+// 	}
+
+// 	// Use SOCKS5 proxy created by Xray
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
path: xray/proxy_trojan.go
user: login: Copilot
body: Consider removing deprecated proxy function code to simplify the codebase if it is no longer required.
created_at: 2025-05-11T06:51:31Z
author_association: NONE
diff_hunk: @@ -15,17 +15,17 @@ func init() {
 }
 
 // ProxySSR creates a RoundTripper for SSR proxy
-func ProxySSR(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	// Start SSR client through Xray
-	_, port, err := StartSSR(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start ssr proxy: %w", err)
-	}
-
-	// Use SOCKS5 proxy created by Xray
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// func ProxySSR(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	// Start SSR client through Xray
+// 	_, port, err := StartSSR(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start ssr proxy: %w", err)
+// 	}
+
+// 	// Use SOCKS5 proxy created by Xray
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
 
path: xray/proxy_ssr.go
user: login: Copilot
body: If the ProxySSR function is not used, removing the commented code can enhance clarity and reduce maintenance overhead.
created_at: 2025-05-11T06:51:31Z
author_association: NONE
diff_hunk: @@ -35,7 +36,12 @@ func DialVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 	// Create a transport that uses our custom dialer
 	tr := proxyclient.CreateTransport(o)
 	tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-		return dialContext(ctx, instance, network, addr)
+		conn, err := dialContext(ctx, instance, network, addr)
+		if err != nil {
+			return nil, err
+		}
+
+		return conn, conn.SetDeadline(time.Now().Add(o.Timeout))
path: xray/proxy_vmess.go
user: login: Copilot
body: [nitpick] Consider setting the connection deadline and handling any potential error separately instead of returning conn along with the deadline-setting error directly; this can improve clarity when distinguishing between a successful connection and deadline failure.
```suggestion
		if err := conn.SetDeadline(time.Now().Add(o.Timeout)); err != nil {
			conn.Close() // Ensure the connection is closed to avoid resource leaks
			return nil, err
		}

		return conn, nil
```
created_at: 2025-05-11T07:02:33Z
author_association: NONE
diff_hunk: @@ -9,6 +9,7 @@ import (
 	"net/http"
 	"net/url"
 	"strconv"
+	"time"
path: ss/proxy_ss.go
user: login: sourcery-ai[bot]
body: **suggestion (bug_risk):** Using SetDeadline impacts entire connection lifetime

SetDeadline applies to the entire connection and can close idle connections prematurely. Use context.WithTimeout or Dialer.Timeout for per-dial timeouts.
created_at: 2025-05-11T07:06:01Z
author_association: NONE
diff_hunk: @@ -6,6 +6,7 @@ import (
 	"net"
 	"net/http"
 	"net/url"
+	"time"
path: xray/proxy_ssr.go
user: login: sourcery-ai[bot]
body: **suggestion (bug_risk):** Global deadline applied to SSR connections

SetDeadline applies to the entire connection. Use context.WithTimeout or DialContext’s timeout for safer, per-request timeouts.
created_at: 2025-05-11T07:06:01Z
author_association: NONE
diff_hunk: @@ -6,6 +6,7 @@ import (
 	"net"
 	"net/http"
 	"net/url"
+	"time"
path: xray/proxy_trojan.go
user: login: sourcery-ai[bot]
body: **suggestion:** SetDeadline used for Trojan dial; consider context timeouts

Prefer using context.WithTimeout for per-dial timeouts to avoid closing long-lived connections.
created_at: 2025-05-11T07:06:01Z
author_association: NONE
diff_hunk: @@ -35,7 +36,17 @@ func DialVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 	// Create a transport that uses our custom dialer
 	tr := proxyclient.CreateTransport(o)
 	tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
-		return dialContext(ctx, instance, network, addr)
+		conn, err := dialContext(ctx, instance, network, addr)
path: xray/proxy_vmess.go
user: login: Copilot
body: The pattern of setting a connection deadline is repeated in multiple Dial functions; consider abstracting this logic into a helper function to reduce duplication.
created_at: 2025-05-11T07:06:04Z
author_association: NONE
diff_hunk: @@ -58,16 +58,27 @@ func DialSS(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
 		destination := metadata.ParseSocksaddr(addr)
 
 		ssConn, err := proxyclient.WithRecover(func() (net.Conn, error) {
-			return m.DialConn(conn, destination)
+			conn, err := m.DialConn(conn, destination)
+			if err != nil {
+				return nil, err
+			}
+
+			err = conn.SetDeadline(time.Now().Add(o.Timeout))
+			if err != nil {
+				conn.Close() // Ensure the connection is closed to avoid resource leaks
+				return nil, err
+			}
+			return conn, nil
 		})
 
 		if ssConn == nil {
+			conn.Close() // nolint: errcheck
path: ss/proxy_ss.go
user: login: Copilot
body: [nitpick] When closing the connection in error paths, consider logging the close error if it might provide useful debug information or clarifying with a comment that closing errors are intentionally ignored.
```suggestion
			if closeErr := conn.Close(); closeErr != nil {
				log.Printf("failed to close connection: %v", closeErr)
			}
```
created_at: 2025-05-11T07:06:04Z
author_association: NONE
diff_hunk: @@ -14,15 +14,15 @@ func init() {
 	proxyclient.RegisterProxy("vmess", DialVmess)
 }
 
-func ProxyVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
-	_, port, err := StartVmess(u, 0)
-	if err != nil {
-		return nil, fmt.Errorf("failed to start vmess proxy: %w", err)
-	}
+// func ProxyVmess(u *url.URL, o *proxyclient.Options) (http.RoundTripper, error) {
+// 	_, port, err := StartVmess(u, 0)
+// 	if err != nil {
+// 		return nil, fmt.Errorf("failed to start vmess proxy: %w", err)
+// 	}
 
-	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
-	return proxyclient.ProxySocks5(proxyURL, o)
-}
+// 	proxyURL, _ := url.Parse(fmt.Sprintf("socks5://127.0.0.1:%d", port))
+// 	return proxyclient.ProxySocks5(proxyURL, o)
+// }
path: xray/proxy_vmess.go
user: login: Copilot
body: [nitpick] Since the ProxyVmess function is deprecated in favor of DialVmess, consider removing its commented-out implementation to avoid confusion.
created_at: 2025-05-11T07:20:37Z
author_association: NONE

PR comments:
user: login: sourcery-ai[bot]
created_at: 2025-05-11T06:44:05Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## Reviewer's Guide

This PR refactors proxy implementations to eliminate legacy SOCKS5 proxy startup code in favor of direct dialers with connection timeouts, and updates Xray-based proxy logging to reduce verbosity and disable access logs. These changes address goroutine leaks by ensuring all custom dialers set connection deadlines and by removing unused or legacy proxy registration and print statements.

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Refactor proxy implementations to use direct dialers with connection timeouts instead of legacy SOCKS5 proxy startup code. | <ul><li>Comment out or remove ProxySS, ProxySSR, ProxyTrojan, ProxyVless, and ProxyVmess functions that started local SOCKS5 proxies.</li><li>Update DialSS, DialSSR, DialTrojan, DialVless, and DialVmess to set connection deadlines using SetDeadline and configurable timeouts.</li><li>Register proxies with new direct dialer functions.</li></ul> | `ss/proxy_ss.go`<br/>`xray/proxy_ssr.go`<br/>`xray/proxy_trojan.go`<br/>`xray/proxy_vless.go`<br/>`xray/proxy_vmess.go` |
| Add SetDeadline utility to enforce connection timeouts and prevent resource leaks. | <ul><li>Implement SetDeadline in proxy.go to set deadlines on connections when keep-alives are disabled.</li><li>Apply SetDeadline in all custom dialers.</li></ul> | `proxy.go`<br/>`ss/proxy_ss.go`<br/>`xray/proxy_ssr.go`<br/>`xray/proxy_trojan.go`<br/>`xray/proxy_vless.go`<br/>`xray/proxy_vmess.go` |
| Update Xray-based proxy logging configurations to reduce verbosity and disable access logs. | <ul><li>Set loglevel to 'error' and access to 'none' in Xray config for VLESS, VMess, SSR, and Trojan.</li><li>Comment out or remove legacy inbound SOCKS5 configuration and related print statements.</li></ul> | `xray/vless.go`<br/>`xray/vmess.go`<br/>`xray/ssr.go`<br/>`xray/trojan.go` |
| Ensure connection deadlines are set for SOCKS4 proxies to prevent leaks. | <ul><li>Update ProxySocks4 to set deadlines on TLS connections and close on error.</li></ul> | `proxy_socks.go` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: NONE
user: login: cnlangzi
created_at: 2025-05-11T07:02:44Z
body: @sourcery-ai review
author_association: OWNER
user: login: cnlangzi
created_at: 2025-05-11T07:17:32Z
body: @sourcery-ai review
author_association: OWNER