mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-25 18:11:27 +00:00
Fix: TFO AsIs bug (#452)
This commit is contained in:
parent
a9e11075d1
commit
b63049f404
|
@ -478,22 +478,19 @@ type SocketConfig struct {
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||||
tfo := int32(-1)
|
tfo := int32(0) // don't invoke setsockopt() for TFO
|
||||||
if c.TFO != nil {
|
if c.TFO != nil {
|
||||||
switch v := c.TFO.(type) {
|
switch v := c.TFO.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
if v {
|
if v {
|
||||||
tfo = 256
|
tfo = 256
|
||||||
} else {
|
} else {
|
||||||
tfo = 0
|
tfo = -1 // TFO need to be disabled
|
||||||
}
|
}
|
||||||
case float64:
|
case float64:
|
||||||
if v < 0 {
|
|
||||||
return nil, newError("tcpFastOpen: only boolean and non-negative integer value is acceptable")
|
|
||||||
}
|
|
||||||
tfo = int32(math.Min(v, math.MaxInt32))
|
tfo = int32(math.Min(v, math.MaxInt32))
|
||||||
default:
|
default:
|
||||||
return nil, newError("tcpFastOpen: only boolean and non-negative integer value is acceptable")
|
return nil, newError("tcpFastOpen: only boolean and integer value is acceptable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var tproxy internet.SocketConfig_TProxyMode
|
var tproxy internet.SocketConfig_TProxyMode
|
||||||
|
|
|
@ -31,6 +31,13 @@ func TestSocketConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test "tcpFastOpen": true, queue length 256 is expected. other parameters are tested here too
|
||||||
|
expectedOutput := &internet.SocketConfig{
|
||||||
|
Mark: 1,
|
||||||
|
Tfo: 256,
|
||||||
|
DomainStrategy: internet.DomainStrategy_USE_IP,
|
||||||
|
DialerProxy: "tag",
|
||||||
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
Input: `{
|
Input: `{
|
||||||
|
@ -40,38 +47,118 @@ func TestSocketConfig(t *testing.T) {
|
||||||
"dialerProxy": "tag"
|
"dialerProxy": "tag"
|
||||||
}`,
|
}`,
|
||||||
Parser: createParser(),
|
Parser: createParser(),
|
||||||
Output: &internet.SocketConfig{
|
Output: expectedOutput,
|
||||||
Mark: 1,
|
|
||||||
Tfo: 256,
|
|
||||||
DomainStrategy: internet.DomainStrategy_USE_IP,
|
|
||||||
DialerProxy: "tag",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
if expectedOutput.ParseTFOValue() != 256 {
|
||||||
|
t.Fatalf("unexpected parsed TFO value, which should be 256")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test "tcpFastOpen": false, disabled TFO is expected
|
||||||
|
expectedOutput = &internet.SocketConfig{
|
||||||
|
Mark: 0,
|
||||||
|
Tfo: -1,
|
||||||
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
Input: `{
|
Input: `{
|
||||||
"tcpFastOpen": false
|
"tcpFastOpen": false
|
||||||
}`,
|
}`,
|
||||||
Parser: createParser(),
|
Parser: createParser(),
|
||||||
Output: &internet.SocketConfig{
|
Output: expectedOutput,
|
||||||
Mark: 0,
|
|
||||||
Tfo: 0,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
if expectedOutput.ParseTFOValue() != 0 {
|
||||||
|
t.Fatalf("unexpected parsed TFO value, which should be 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test "tcpFastOpen": 65535, queue length 65535 is expected
|
||||||
|
expectedOutput = &internet.SocketConfig{
|
||||||
|
Mark: 0,
|
||||||
|
Tfo: 65535,
|
||||||
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
Input: `{
|
Input: `{
|
||||||
"tcpFastOpen": 65535
|
"tcpFastOpen": 65535
|
||||||
}`,
|
}`,
|
||||||
Parser: createParser(),
|
Parser: createParser(),
|
||||||
Output: &internet.SocketConfig{
|
Output: expectedOutput,
|
||||||
Mark: 0,
|
|
||||||
Tfo: 65535,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
if expectedOutput.ParseTFOValue() != 65535 {
|
||||||
|
t.Fatalf("unexpected parsed TFO value, which should be 65535")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test "tcpFastOpen": -65535, disable TFO is expected
|
||||||
|
expectedOutput = &internet.SocketConfig{
|
||||||
|
Mark: 0,
|
||||||
|
Tfo: -65535,
|
||||||
|
}
|
||||||
|
runMultiTestCase(t, []TestCase{
|
||||||
|
{
|
||||||
|
Input: `{
|
||||||
|
"tcpFastOpen": -65535
|
||||||
|
}`,
|
||||||
|
Parser: createParser(),
|
||||||
|
Output: expectedOutput,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if expectedOutput.ParseTFOValue() != 0 {
|
||||||
|
t.Fatalf("unexpected parsed TFO value, which should be 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test "tcpFastOpen": 0, no operation is expected
|
||||||
|
expectedOutput = &internet.SocketConfig{
|
||||||
|
Mark: 0,
|
||||||
|
Tfo: 0,
|
||||||
|
}
|
||||||
|
runMultiTestCase(t, []TestCase{
|
||||||
|
{
|
||||||
|
Input: `{
|
||||||
|
"tcpFastOpen": 0
|
||||||
|
}`,
|
||||||
|
Parser: createParser(),
|
||||||
|
Output: expectedOutput,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if expectedOutput.ParseTFOValue() != -1 {
|
||||||
|
t.Fatalf("unexpected parsed TFO value, which should be -1")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test omit "tcpFastOpen", no operation is expected
|
||||||
|
expectedOutput = &internet.SocketConfig{
|
||||||
|
Mark: 0,
|
||||||
|
Tfo: 0,
|
||||||
|
}
|
||||||
|
runMultiTestCase(t, []TestCase{
|
||||||
|
{
|
||||||
|
Input: `{}`,
|
||||||
|
Parser: createParser(),
|
||||||
|
Output: expectedOutput,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if expectedOutput.ParseTFOValue() != -1 {
|
||||||
|
t.Fatalf("unexpected parsed TFO value, which should be -1")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test "tcpFastOpen": null, no operation is expected
|
||||||
|
expectedOutput = &internet.SocketConfig{
|
||||||
|
Mark: 0,
|
||||||
|
Tfo: 0,
|
||||||
|
}
|
||||||
|
runMultiTestCase(t, []TestCase{
|
||||||
|
{
|
||||||
|
Input: `{
|
||||||
|
"tcpFastOpen": null
|
||||||
|
}`,
|
||||||
|
Parser: createParser(),
|
||||||
|
Output: expectedOutput,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if expectedOutput.ParseTFOValue() != -1 {
|
||||||
|
t.Fatalf("unexpected parsed TFO value, which should be -1")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransportConfig(t *testing.T) {
|
func TestTransportConfig(t *testing.T) {
|
||||||
|
|
|
@ -17,3 +17,14 @@ func isUDPSocket(network string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *SocketConfig) ParseTFOValue() int {
|
||||||
|
if v.Tfo == 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
tfo := int(v.Tfo)
|
||||||
|
if tfo < 0 {
|
||||||
|
tfo = 0
|
||||||
|
}
|
||||||
|
return tfo
|
||||||
|
}
|
||||||
|
|
|
@ -15,12 +15,12 @@ const (
|
||||||
|
|
||||||
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
|
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
tfo := config.Tfo
|
tfo := config.ParseTFOValue()
|
||||||
if tfo > 0 {
|
if tfo > 0 {
|
||||||
tfo = TCP_FASTOPEN_CLIENT
|
tfo = TCP_FASTOPEN_CLIENT
|
||||||
}
|
}
|
||||||
if tfo >= 0 {
|
if tfo >= 0 {
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, int(tfo)); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,12 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||||
|
|
||||||
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
|
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
tfo := config.Tfo
|
tfo := config.ParseTFOValue()
|
||||||
if tfo > 0 {
|
if tfo > 0 {
|
||||||
tfo = TCP_FASTOPEN_SERVER
|
tfo = TCP_FASTOPEN_SERVER
|
||||||
}
|
}
|
||||||
if tfo >= 0 {
|
if tfo >= 0 {
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, int(tfo)); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||||
}
|
}
|
||||||
|
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
tfo := int(config.Tfo)
|
tfo := config.ParseTFOValue()
|
||||||
if tfo > 0 {
|
if tfo > 0 {
|
||||||
tfo = 1
|
tfo = 1
|
||||||
}
|
}
|
||||||
|
@ -163,9 +163,10 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
if config.Tfo >= 0 {
|
tfo := config.ParseTFOValue()
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_FASTOPEN, int(config.Tfo)); err != nil {
|
if tfo >= 0 {
|
||||||
return newError("failed to set TCP_FASTOPEN=", config.Tfo).Base(err)
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_FASTOPEN, tfo); err != nil {
|
||||||
|
return newError("failed to set TCP_FASTOPEN=", tfo).Base(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||||
}
|
}
|
||||||
|
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
tfo := int(config.Tfo)
|
tfo := config.ParseTFOValue()
|
||||||
if tfo > 0 {
|
if tfo > 0 {
|
||||||
tfo = 1
|
tfo = 1
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,10 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
if config.Tfo >= 0 {
|
tfo := config.ParseTFOValue()
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, int(config.Tfo)); err != nil {
|
if tfo >= 0 {
|
||||||
return newError("failed to set TCP_FASTOPEN=", config.Tfo).Base(err)
|
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||||
|
return newError("failed to set TCP_FASTOPEN=", tfo).Base(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ const (
|
||||||
TCP_FASTOPEN = 15
|
TCP_FASTOPEN = 15
|
||||||
)
|
)
|
||||||
|
|
||||||
func setTFO(fd syscall.Handle, tfo int32) error {
|
func setTFO(fd syscall.Handle, tfo int) error {
|
||||||
if tfo > 0 {
|
if tfo > 0 {
|
||||||
tfo = 1
|
tfo = 1
|
||||||
}
|
}
|
||||||
if tfo >= 0 {
|
if tfo >= 0 {
|
||||||
if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, TCP_FASTOPEN, int(tfo)); err != nil {
|
if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ func setTFO(fd syscall.Handle, tfo int32) error {
|
||||||
|
|
||||||
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
|
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil {
|
if err := setTFO(syscall.Handle(fd), config.ParseTFOValue()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||||
|
|
||||||
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
|
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
|
||||||
if isTCPSocket(network) {
|
if isTCPSocket(network) {
|
||||||
if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil {
|
if err := setTFO(syscall.Handle(fd), config.ParseTFOValue()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue