Fix UDP async write

This commit is contained in:
世界 2023-08-03 15:03:29 +08:00
parent 2123b216c0
commit c40140bbae
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
6 changed files with 42 additions and 18 deletions

4
go.mod
View File

@ -27,7 +27,7 @@ require (
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.2.10-0.20230802105922-c6a69b4912ee github.com/sagernet/sing v0.2.10-0.20230802105922-c6a69b4912ee
github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659
github.com/sagernet/sing-mux v0.1.2 github.com/sagernet/sing-mux v0.1.3-0.20230803070305-ea4a972acd21
github.com/sagernet/sing-shadowsocks v0.2.4 github.com/sagernet/sing-shadowsocks v0.2.4
github.com/sagernet/sing-shadowsocks2 v0.1.3 github.com/sagernet/sing-shadowsocks2 v0.1.3
github.com/sagernet/sing-shadowtls v0.1.4 github.com/sagernet/sing-shadowtls v0.1.4
@ -45,7 +45,7 @@ require (
go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28 go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28
golang.org/x/crypto v0.11.0 golang.org/x/crypto v0.11.0
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/net v0.12.0 golang.org/x/net v0.13.0
golang.org/x/sys v0.10.0 golang.org/x/sys v0.10.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.57.0 google.golang.org/grpc v1.57.0

8
go.sum
View File

@ -122,8 +122,8 @@ github.com/sagernet/sing v0.2.10-0.20230802105922-c6a69b4912ee h1:5MATgtWMh2TCAV
github.com/sagernet/sing v0.2.10-0.20230802105922-c6a69b4912ee/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA= github.com/sagernet/sing v0.2.10-0.20230802105922-c6a69b4912ee/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA=
github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 h1:1DAKccGNqTYJ8nsBR765FS0LVBVXfuFlFAHqKsGN3EI= github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 h1:1DAKccGNqTYJ8nsBR765FS0LVBVXfuFlFAHqKsGN3EI=
github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659/go.mod h1:W7GHTZFS8RkoLI3bA2LFY27/0E+uoQESWtMFLepO/JA= github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659/go.mod h1:W7GHTZFS8RkoLI3bA2LFY27/0E+uoQESWtMFLepO/JA=
github.com/sagernet/sing-mux v0.1.2 h1:av2/m6e+Gh+ECTuJZqYCjJz55BNkot0VyRMkREqyF/g= github.com/sagernet/sing-mux v0.1.3-0.20230803070305-ea4a972acd21 h1:IQ7oBBKz+lwIqwI9IMStlQ9YSUu3eKJmNTip0aLbvOI=
github.com/sagernet/sing-mux v0.1.2/go.mod h1:r2V8AlOzXaRCHXK7fILCUGzuI2iILweTaG8C5xlpHxo= github.com/sagernet/sing-mux v0.1.3-0.20230803070305-ea4a972acd21/go.mod h1:TKxqIvfQQgd36jp2tzsPavGjYTVZilV+atip1cssjIY=
github.com/sagernet/sing-shadowsocks v0.2.4 h1:s/CqXlvFAZhlIoHWUwPw5CoNnQ9Ibki9pckjuugtVfY= github.com/sagernet/sing-shadowsocks v0.2.4 h1:s/CqXlvFAZhlIoHWUwPw5CoNnQ9Ibki9pckjuugtVfY=
github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM= github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM=
github.com/sagernet/sing-shadowsocks2 v0.1.3 h1:WXoLvCFi5JTFBRYorf1YePGYIQyJ/zbsBM6Fwbl5kGA= github.com/sagernet/sing-shadowsocks2 v0.1.3 h1:WXoLvCFi5JTFBRYorf1YePGYIQyJ/zbsBM6Fwbl5kGA=
@ -187,8 +187,8 @@ golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -16,7 +16,7 @@ require (
github.com/spyzhov/ajson v0.7.1 github.com/spyzhov/ajson v0.7.1
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
go.uber.org/goleak v1.2.0 go.uber.org/goleak v1.2.0
golang.org/x/net v0.12.0 golang.org/x/net v0.13.0
) )
require ( require (
@ -74,7 +74,7 @@ require (
github.com/sagernet/quic-go v0.0.0-20230731012313-1327e4015111 // indirect github.com/sagernet/quic-go v0.0.0-20230731012313-1327e4015111 // indirect
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 // indirect github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 // indirect
github.com/sagernet/sing-mux v0.1.2 // indirect github.com/sagernet/sing-mux v0.1.3-0.20230803070305-ea4a972acd21 // indirect
github.com/sagernet/sing-shadowtls v0.1.4 // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect
github.com/sagernet/sing-tun v0.1.11 // indirect github.com/sagernet/sing-tun v0.1.11 // indirect
github.com/sagernet/sing-vmess v0.1.7 // indirect github.com/sagernet/sing-vmess v0.1.7 // indirect

View File

@ -150,6 +150,7 @@ github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659/go.mod h1:W7GH
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90 h1:aEe2HrRc9OTS7IZ8RHyh224OhltnwRQs4/y89UsHPo8= github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90 h1:aEe2HrRc9OTS7IZ8RHyh224OhltnwRQs4/y89UsHPo8=
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90/go.mod h1:sm126rB5EUi9HLf4jCSHTqo+XRPbh4BoEVeLbr2WRbE= github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90/go.mod h1:sm126rB5EUi9HLf4jCSHTqo+XRPbh4BoEVeLbr2WRbE=
github.com/sagernet/sing-mux v0.1.2/go.mod h1:r2V8AlOzXaRCHXK7fILCUGzuI2iILweTaG8C5xlpHxo= github.com/sagernet/sing-mux v0.1.2/go.mod h1:r2V8AlOzXaRCHXK7fILCUGzuI2iILweTaG8C5xlpHxo=
github.com/sagernet/sing-mux v0.1.3-0.20230803070305-ea4a972acd21/go.mod h1:TKxqIvfQQgd36jp2tzsPavGjYTVZilV+atip1cssjIY=
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355 h1:XOgNZYnkDrx5qtNS4kqIOHMhjZuc7mJ2pY/x3EyZX8Q= github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355 h1:XOgNZYnkDrx5qtNS4kqIOHMhjZuc7mJ2pY/x3EyZX8Q=
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355/go.mod h1:atEATsxqPo8qCPcFt8Rw7TFEJ70egCoMR7PziX4jmjI= github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355/go.mod h1:atEATsxqPo8qCPcFt8Rw7TFEJ70egCoMR7PziX4jmjI=
github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM= github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM=
@ -229,6 +230,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@ -6,6 +6,7 @@ import (
"encoding/hex" "encoding/hex"
"net" "net"
"os" "os"
"sync"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/buf"
@ -84,6 +85,7 @@ func (c *ClientConn) Upstream() any {
type ClientPacketConn struct { type ClientPacketConn struct {
net.Conn net.Conn
access sync.Mutex
key [KeyLength]byte key [KeyLength]byte
headerWritten bool headerWritten bool
} }
@ -105,10 +107,16 @@ func (c *ClientPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
func (c *ClientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { func (c *ClientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
if !c.headerWritten { if !c.headerWritten {
c.access.Lock()
if c.headerWritten {
c.access.Unlock()
} else {
err := ClientHandshakePacket(c.Conn, c.key, destination, buffer) err := ClientHandshakePacket(c.Conn, c.key, destination, buffer)
c.headerWritten = true c.headerWritten = true
c.access.Unlock()
return err return err
} }
}
return WritePacket(c.Conn, buffer, destination) return WritePacket(c.Conn, buffer, destination)
} }

View File

@ -4,6 +4,7 @@ import (
"encoding/binary" "encoding/binary"
"io" "io"
"net" "net"
"sync"
"github.com/sagernet/sing-vmess" "github.com/sagernet/sing-vmess"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
@ -190,6 +191,7 @@ func (c *Conn) Upstream() any {
type PacketConn struct { type PacketConn struct {
net.Conn net.Conn
access sync.Mutex
key [16]byte key [16]byte
destination M.Socksaddr destination M.Socksaddr
flow string flow string
@ -218,11 +220,17 @@ func (c *PacketConn) Read(b []byte) (n int, err error) {
func (c *PacketConn) Write(b []byte) (n int, err error) { func (c *PacketConn) Write(b []byte) (n int, err error) {
if !c.requestWritten { if !c.requestWritten {
c.access.Lock()
if c.requestWritten {
c.access.Unlock()
} else {
err = WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination, c.flow}, nil) err = WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination, c.flow}, nil)
if err == nil { if err == nil {
n = len(b) n = len(b)
} }
c.requestWritten = true c.requestWritten = true
c.access.Unlock()
}
} }
err = binary.Write(c.Conn, binary.BigEndian, uint16(len(b))) err = binary.Write(c.Conn, binary.BigEndian, uint16(len(b)))
if err != nil { if err != nil {
@ -236,10 +244,16 @@ func (c *PacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) er
dataLen := buffer.Len() dataLen := buffer.Len()
binary.BigEndian.PutUint16(buffer.ExtendHeader(2), uint16(dataLen)) binary.BigEndian.PutUint16(buffer.ExtendHeader(2), uint16(dataLen))
if !c.requestWritten { if !c.requestWritten {
c.access.Lock()
if c.requestWritten {
c.access.Unlock()
} else {
err := WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination, c.flow}, buffer.Bytes()) err := WritePacketRequest(c.Conn, Request{c.key, vmess.CommandUDP, c.destination, c.flow}, buffer.Bytes())
c.requestWritten = true c.requestWritten = true
c.access.Unlock()
return err return err
} }
}
return common.Error(c.Conn.Write(buffer.Bytes())) return common.Error(c.Conn.Write(buffer.Bytes()))
} }