mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-10-20 16:24:25 +00:00
Fix HTTP/2 stream errors leaking into nested readers and transport data races
This commit is contained in:
@@ -45,9 +45,9 @@ require (
|
||||
github.com/sagernet/netlink v0.0.0-20260814022025-64455d367bbf
|
||||
github.com/sagernet/nftables v0.3.0-mod.4
|
||||
github.com/sagernet/quic-go v0.61.0-sing-box-mod.7
|
||||
github.com/sagernet/sing v0.9.4
|
||||
github.com/sagernet/sing v0.9.5
|
||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3
|
||||
github.com/sagernet/sing-mux v0.3.6
|
||||
github.com/sagernet/sing-mux v0.3.8
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260810065514-53aa8058f8df
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260729104525-103eb5fe5eb6
|
||||
github.com/sagernet/sing-quic v0.7.0
|
||||
|
||||
@@ -318,12 +318,12 @@ github.com/sagernet/nftables v0.3.0-mod.4 h1:vnOtcDYeSXv2e5RoRuGH0lrpttQFJ8iC4IC
|
||||
github.com/sagernet/nftables v0.3.0-mod.4/go.mod h1:8kslHG4VvYNihcco+i6uxIX7qbT8A56T0y5q7U44ZaQ=
|
||||
github.com/sagernet/quic-go v0.61.0-sing-box-mod.7 h1:sW2O+DoNF+my1PGlSZ3zG2N+fdxLR3DC0l4sXCM0lBE=
|
||||
github.com/sagernet/quic-go v0.61.0-sing-box-mod.7/go.mod h1:hmLC8GJPp+BrpBgrgJnacvI4fZGIhasuy1ROJJ8GR4E=
|
||||
github.com/sagernet/sing v0.9.4 h1:nIdH+Yvy4NzTezB+c3z/9of1jLRggnrtMtb3uMOIaNM=
|
||||
github.com/sagernet/sing v0.9.4/go.mod h1:K3Owt3xPhHugvlnlPPxZJ/exXdaJfEPOTNorGk4AXjo=
|
||||
github.com/sagernet/sing v0.9.5 h1:BHaElRqhHhkH747xIkxgsqgRJxkIiuAlpnfwiJnu2aY=
|
||||
github.com/sagernet/sing v0.9.5/go.mod h1:K3Owt3xPhHugvlnlPPxZJ/exXdaJfEPOTNorGk4AXjo=
|
||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3 h1:3y6++yIa8XlDhxPkpR4p+7RUHVY2KTP9CPIGnWmOlO8=
|
||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3/go.mod h1:XEqEDYRCAYLaoPjZ1ifVWJg5iWAJHL2gOAXe/PM28Cg=
|
||||
github.com/sagernet/sing-mux v0.3.6 h1:ix+CPhZsR9XIAmEVLIUdz+itDzXs1T6iKO8eF/XOVOQ=
|
||||
github.com/sagernet/sing-mux v0.3.6/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
||||
github.com/sagernet/sing-mux v0.3.8 h1:mM0TLUkr36aEhgUHi9Qh60qcAbD2fZcmnJ30937xxrY=
|
||||
github.com/sagernet/sing-mux v0.3.8/go.mod h1:jricpwCOndDsTEM1TM3piJvhL/2Mm7OhLkm+JadJJ1Q=
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260810065514-53aa8058f8df h1:ogyC7KPTWueN7kXFhKSdHeS5/t/zBjQgAOpWjqnrMos=
|
||||
github.com/sagernet/sing-openconnect v0.0.0-20260810065514-53aa8058f8df/go.mod h1:4AKZLVcvY3r54UaK2Gbnm7aN8pOwdLz+y4EP0QFZ5Eg=
|
||||
github.com/sagernet/sing-openvpn v0.0.0-20260729104525-103eb5fe5eb6 h1:ZAvhkor0prJ8KEX9EmTEH+gJ1WlA3ffjS8GZT6KKq9c=
|
||||
|
||||
@@ -64,7 +64,7 @@ func (c *GunConn) Read(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (c *GunConn) read(b []byte) (n int, err error) {
|
||||
if c.reader == nil {
|
||||
if c.create != nil {
|
||||
<-c.create
|
||||
if c.err != nil {
|
||||
return 0, c.err
|
||||
@@ -144,7 +144,17 @@ func (c *GunConn) FrontHeadroom() int {
|
||||
}
|
||||
|
||||
func (c *GunConn) Close() error {
|
||||
err := common.Close(c.rawReader, c.writer)
|
||||
var reader io.Reader
|
||||
if c.create != nil {
|
||||
select {
|
||||
case <-c.create:
|
||||
reader = c.rawReader
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
reader = c.rawReader
|
||||
}
|
||||
err := common.Close(reader, c.writer)
|
||||
if c.cancel != nil {
|
||||
c.cancel()
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
@@ -30,7 +31,7 @@ type Client struct {
|
||||
ctx context.Context
|
||||
dialer N.Dialer
|
||||
serverAddr M.Socksaddr
|
||||
transport http.RoundTripper
|
||||
transport common.TypedValue[http.RoundTripper]
|
||||
http2 bool
|
||||
requestURL url.URL
|
||||
host []string
|
||||
@@ -77,7 +78,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
||||
if !strings.HasPrefix(requestURL.Path, "/") {
|
||||
requestURL.Path = "/" + requestURL.Path
|
||||
}
|
||||
return &Client{
|
||||
client := &Client{
|
||||
ctx: ctx,
|
||||
dialer: dialer,
|
||||
serverAddr: serverAddr,
|
||||
@@ -85,9 +86,10 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
||||
host: options.Host,
|
||||
method: options.Method,
|
||||
headers: options.Headers.Build(),
|
||||
transport: transport,
|
||||
http2: tlsConfig != nil,
|
||||
}, nil
|
||||
}
|
||||
client.transport.Store(transport)
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||
@@ -151,7 +153,7 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
|
||||
cancel()
|
||||
})
|
||||
go func() {
|
||||
response, err := c.transport.RoundTrip(request)
|
||||
response, err := c.transport.Load().RoundTrip(request)
|
||||
handshakeTimer.Stop()
|
||||
if err != nil {
|
||||
if handshakeTimedOut.Load() {
|
||||
@@ -169,6 +171,6 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
|
||||
}
|
||||
|
||||
func (c *Client) Close() error {
|
||||
c.transport = ResetTransport(c.transport)
|
||||
c.transport.Store(ResetTransport(c.transport.Load()))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -159,10 +159,10 @@ func (c *HTTP2Conn) Setup(reader io.Reader, err error) {
|
||||
}
|
||||
|
||||
func (c *HTTP2Conn) Read(b []byte) (n int, err error) {
|
||||
if c.reader == nil {
|
||||
if c.create != nil {
|
||||
<-c.create
|
||||
if c.err != nil {
|
||||
return 0, c.err
|
||||
return 0, baderror.WrapH2(c.err)
|
||||
}
|
||||
}
|
||||
n, err = c.reader.Read(b)
|
||||
@@ -175,7 +175,17 @@ func (c *HTTP2Conn) Write(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (c *HTTP2Conn) Close() error {
|
||||
err := common.Close(c.reader, c.writer)
|
||||
var reader io.Reader
|
||||
if c.create != nil {
|
||||
select {
|
||||
case <-c.create:
|
||||
reader = c.reader
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
reader = c.reader
|
||||
}
|
||||
err := common.Close(reader, c.writer)
|
||||
if c.cancel != nil {
|
||||
c.cancel()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user