options for enable TFO

pull/1269/head
Darien Raymond 2018-09-10 13:23:27 +02:00
parent 7b28a19013
commit 6d750e8149
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
12 changed files with 251 additions and 88 deletions

View File

@ -48,7 +48,36 @@ func (x TransportProtocol) String() string {
return proto.EnumName(TransportProtocol_name, int32(x))
}
func (TransportProtocol) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_config_807c5df32db81c88, []int{0}
return fileDescriptor_config_d7068fe3707ce485, []int{0}
}
type SocketConfig_TCPFastOpenState int32
const (
// AsIs is to leave the current TFO state as is, unmodified.
SocketConfig_AsIs SocketConfig_TCPFastOpenState = 0
// Enable is for enabling TFO explictly.
SocketConfig_Enable SocketConfig_TCPFastOpenState = 1
// Disable is for disabling TFO explictly.
SocketConfig_Disable SocketConfig_TCPFastOpenState = 2
)
var SocketConfig_TCPFastOpenState_name = map[int32]string{
0: "AsIs",
1: "Enable",
2: "Disable",
}
var SocketConfig_TCPFastOpenState_value = map[string]int32{
"AsIs": 0,
"Enable": 1,
"Disable": 2,
}
func (x SocketConfig_TCPFastOpenState) String() string {
return proto.EnumName(SocketConfig_TCPFastOpenState_name, int32(x))
}
func (SocketConfig_TCPFastOpenState) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_config_d7068fe3707ce485, []int{3, 0}
}
type TransportConfig struct {
@ -68,7 +97,7 @@ func (m *TransportConfig) Reset() { *m = TransportConfig{} }
func (m *TransportConfig) String() string { return proto.CompactTextString(m) }
func (*TransportConfig) ProtoMessage() {}
func (*TransportConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_config_807c5df32db81c88, []int{0}
return fileDescriptor_config_d7068fe3707ce485, []int{0}
}
func (m *TransportConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_TransportConfig.Unmarshal(m, b)
@ -129,7 +158,7 @@ func (m *StreamConfig) Reset() { *m = StreamConfig{} }
func (m *StreamConfig) String() string { return proto.CompactTextString(m) }
func (*StreamConfig) ProtoMessage() {}
func (*StreamConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_config_807c5df32db81c88, []int{1}
return fileDescriptor_config_d7068fe3707ce485, []int{1}
}
func (m *StreamConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamConfig.Unmarshal(m, b)
@ -203,7 +232,7 @@ func (m *ProxyConfig) Reset() { *m = ProxyConfig{} }
func (m *ProxyConfig) String() string { return proto.CompactTextString(m) }
func (*ProxyConfig) ProtoMessage() {}
func (*ProxyConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_config_807c5df32db81c88, []int{2}
return fileDescriptor_config_d7068fe3707ce485, []int{2}
}
func (m *ProxyConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ProxyConfig.Unmarshal(m, b)
@ -230,18 +259,22 @@ func (m *ProxyConfig) GetTag() string {
return ""
}
// SocketConfig is options to be applied on network sockets.
type SocketConfig struct {
Mark int32 `protobuf:"varint,1,opt,name=mark,proto3" json:"mark,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
// Mark of the connection. If non-zero, the value will be set to SO_MARK.
Mark int32 `protobuf:"varint,1,opt,name=mark,proto3" json:"mark,omitempty"`
// TFO is the state of TFO settings.
Tfo SocketConfig_TCPFastOpenState `protobuf:"varint,2,opt,name=tfo,proto3,enum=v2ray.core.transport.internet.SocketConfig_TCPFastOpenState" json:"tfo,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SocketConfig) Reset() { *m = SocketConfig{} }
func (m *SocketConfig) String() string { return proto.CompactTextString(m) }
func (*SocketConfig) ProtoMessage() {}
func (*SocketConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_config_807c5df32db81c88, []int{3}
return fileDescriptor_config_d7068fe3707ce485, []int{3}
}
func (m *SocketConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SocketConfig.Unmarshal(m, b)
@ -268,47 +301,59 @@ func (m *SocketConfig) GetMark() int32 {
return 0
}
func (m *SocketConfig) GetTfo() SocketConfig_TCPFastOpenState {
if m != nil {
return m.Tfo
}
return SocketConfig_AsIs
}
func init() {
proto.RegisterType((*TransportConfig)(nil), "v2ray.core.transport.internet.TransportConfig")
proto.RegisterType((*StreamConfig)(nil), "v2ray.core.transport.internet.StreamConfig")
proto.RegisterType((*ProxyConfig)(nil), "v2ray.core.transport.internet.ProxyConfig")
proto.RegisterType((*SocketConfig)(nil), "v2ray.core.transport.internet.SocketConfig")
proto.RegisterEnum("v2ray.core.transport.internet.TransportProtocol", TransportProtocol_name, TransportProtocol_value)
proto.RegisterEnum("v2ray.core.transport.internet.SocketConfig_TCPFastOpenState", SocketConfig_TCPFastOpenState_name, SocketConfig_TCPFastOpenState_value)
}
func init() {
proto.RegisterFile("v2ray.com/core/transport/internet/config.proto", fileDescriptor_config_807c5df32db81c88)
proto.RegisterFile("v2ray.com/core/transport/internet/config.proto", fileDescriptor_config_d7068fe3707ce485)
}
var fileDescriptor_config_807c5df32db81c88 = []byte{
// 456 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xe1, 0x8a, 0x13, 0x31,
0x10, 0xc7, 0xdd, 0x6e, 0x7b, 0xb6, 0xd3, 0xde, 0xdd, 0x36, 0x9f, 0x8a, 0x70, 0x58, 0x57, 0x90,
0xa2, 0x90, 0x3d, 0xd6, 0x37, 0x68, 0xef, 0x83, 0xa2, 0xa7, 0xcb, 0x76, 0x55, 0x38, 0x90, 0x92,
0x8b, 0xb1, 0x2c, 0x77, 0x49, 0x4a, 0x12, 0xc5, 0x7d, 0x25, 0x3f, 0xfb, 0x10, 0x3e, 0x96, 0x24,
0xbb, 0x09, 0x45, 0xa5, 0x1e, 0xf8, 0x6d, 0xc8, 0xfc, 0xe7, 0x3f, 0xf3, 0x9b, 0x09, 0xe0, 0xaf,
0xb9, 0x22, 0x0d, 0xa6, 0x92, 0x67, 0x54, 0x2a, 0x96, 0x19, 0x45, 0x84, 0xde, 0x49, 0x65, 0xb2,
0x5a, 0x18, 0xa6, 0x04, 0x33, 0x19, 0x95, 0xe2, 0x73, 0xbd, 0xc5, 0x3b, 0x25, 0x8d, 0x44, 0x67,
0x5e, 0xaf, 0x18, 0x0e, 0x5a, 0xec, 0xb5, 0x0f, 0xce, 0x7f, 0xb3, 0xa3, 0x92, 0x73, 0x29, 0x32,
0xcd, 0x54, 0x4d, 0x6e, 0x33, 0xd3, 0xec, 0xd8, 0xa7, 0x0d, 0x67, 0x5a, 0x93, 0x2d, 0x6b, 0x0d,
0xd3, 0x9f, 0x11, 0x9c, 0x56, 0xde, 0x68, 0xe5, 0x5a, 0xa1, 0xd7, 0x30, 0x74, 0x49, 0x2a, 0x6f,
0x67, 0xd1, 0x3c, 0x5a, 0x9c, 0xe4, 0xe7, 0xf8, 0x60, 0x5f, 0x1c, 0x1c, 0x8a, 0xae, 0xae, 0x0c,
0x0e, 0xe8, 0x31, 0x1c, 0xfb, 0x78, 0x23, 0x08, 0x67, 0xb3, 0x78, 0x1e, 0x2d, 0x46, 0xe5, 0xc4,
0x3f, 0xbe, 0x21, 0x9c, 0xa1, 0x25, 0x0c, 0x35, 0x33, 0xa6, 0x16, 0x5b, 0x3d, 0xeb, 0xcd, 0xa3,
0xc5, 0x38, 0x7f, 0xb2, 0xdf, 0xb2, 0xe5, 0xc0, 0x2d, 0x07, 0xae, 0x2c, 0xc7, 0x65, 0x8b, 0x51,
0x86, 0xba, 0xf4, 0x47, 0x0c, 0x93, 0xb5, 0x51, 0x8c, 0xf0, 0x8e, 0xa3, 0xf8, 0x7f, 0x8e, 0x65,
0x6f, 0x16, 0x1d, 0x62, 0x19, 0xfc, 0x85, 0xe5, 0x23, 0xa0, 0x60, 0xbd, 0xd9, 0xa3, 0x8a, 0x17,
0xe3, 0x1c, 0xdf, 0x75, 0x80, 0x16, 0xa1, 0x9c, 0x06, 0xcd, 0xba, 0x33, 0xb2, 0x33, 0x68, 0x46,
0xbf, 0xa8, 0xda, 0x34, 0x1b, 0x7b, 0x51, 0xbf, 0x4f, 0xff, 0x68, 0xb7, 0x83, 0xd6, 0x30, 0x0d,
0xa2, 0x30, 0x42, 0xdf, 0x8d, 0x70, 0xd7, 0xc5, 0x26, 0xde, 0x20, 0x74, 0xae, 0xe0, 0x54, 0x4b,
0x7a, 0xc3, 0xf6, 0xa8, 0x8e, 0xdc, 0xad, 0x9e, 0xfd, 0x83, 0x6a, 0xed, 0xaa, 0x3a, 0xa4, 0x93,
0xd6, 0xc3, 0xbb, 0xa6, 0x0f, 0x61, 0x5c, 0x28, 0xf9, 0xad, 0xe9, 0x8e, 0x96, 0x40, 0x6c, 0xc8,
0xd6, 0xdd, 0x6b, 0x54, 0xda, 0x30, 0x4d, 0x61, 0xb2, 0x6f, 0x80, 0x10, 0xf4, 0x39, 0x51, 0x37,
0x4e, 0x32, 0x28, 0x5d, 0xfc, 0xf4, 0x0a, 0xa6, 0x7f, 0xdc, 0x0e, 0xdd, 0x87, 0xb8, 0x5a, 0x15,
0xc9, 0x3d, 0x1b, 0xbc, 0xbb, 0x28, 0x92, 0x08, 0x0d, 0xa1, 0x7f, 0xf9, 0x6a, 0x55, 0x24, 0x3d,
0x74, 0x0c, 0xa3, 0x0f, 0xec, 0xba, 0xf5, 0x4d, 0x62, 0x9b, 0x78, 0x51, 0x55, 0x45, 0xd2, 0x47,
0x09, 0x4c, 0x2e, 0x24, 0x27, 0xb5, 0xe8, 0x72, 0x83, 0xe5, 0x5b, 0x78, 0x44, 0x25, 0x3f, 0x8c,
0x58, 0x44, 0x57, 0x43, 0x1f, 0x7f, 0xef, 0x9d, 0xbd, 0xcf, 0x4b, 0xd2, 0xe0, 0x95, 0xd5, 0x86,
0xb1, 0xf0, 0xcb, 0x2e, 0x7f, 0x7d, 0xe4, 0xbe, 0xcb, 0xf3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff,
0xba, 0x0d, 0x33, 0xbb, 0xfd, 0x03, 0x00, 0x00,
var fileDescriptor_config_d7068fe3707ce485 = []byte{
// 518 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xd1, 0x8a, 0x13, 0x31,
0x14, 0x86, 0x77, 0x3a, 0x6d, 0xb7, 0x3d, 0xed, 0x76, 0xd3, 0x5c, 0x15, 0x61, 0xb1, 0x56, 0x90,
0xa2, 0x90, 0x59, 0x46, 0xbc, 0xf3, 0xc6, 0xb6, 0x8a, 0x8b, 0xee, 0xee, 0x30, 0x1d, 0x15, 0x16,
0xa4, 0xa4, 0x63, 0xb6, 0x0c, 0xdb, 0x99, 0x94, 0x24, 0x8a, 0x7d, 0x24, 0xbd, 0xf6, 0x21, 0x7c,
0x2c, 0x49, 0x66, 0x12, 0xca, 0x2a, 0x75, 0xc5, 0xbb, 0x33, 0x73, 0xfe, 0xfc, 0xe7, 0xff, 0x72,
0x02, 0xe4, 0x4b, 0x28, 0xe8, 0x96, 0xa4, 0x3c, 0x0f, 0x52, 0x2e, 0x58, 0xa0, 0x04, 0x2d, 0xe4,
0x86, 0x0b, 0x15, 0x64, 0x85, 0x62, 0xa2, 0x60, 0x2a, 0x48, 0x79, 0x71, 0x9d, 0xad, 0xc8, 0x46,
0x70, 0xc5, 0xf1, 0x89, 0xd5, 0x0b, 0x46, 0x9c, 0x96, 0x58, 0xed, 0xbd, 0xd3, 0x5b, 0x76, 0x29,
0xcf, 0x73, 0x5e, 0x04, 0x92, 0x89, 0x8c, 0xae, 0x03, 0xb5, 0xdd, 0xb0, 0x4f, 0x8b, 0x9c, 0x49,
0x49, 0x57, 0xac, 0x34, 0x1c, 0xfd, 0xf4, 0xe0, 0x38, 0xb1, 0x46, 0x53, 0x33, 0x0a, 0xbf, 0x85,
0x96, 0x69, 0xa6, 0x7c, 0x3d, 0xf0, 0x86, 0xde, 0xb8, 0x17, 0x9e, 0x92, 0xbd, 0x73, 0x89, 0x73,
0x88, 0xaa, 0x73, 0xb1, 0x73, 0xc0, 0x0f, 0xe1, 0xc8, 0xd6, 0x8b, 0x82, 0xe6, 0x6c, 0xe0, 0x0f,
0xbd, 0x71, 0x3b, 0xee, 0xda, 0x9f, 0x17, 0x34, 0x67, 0x78, 0x02, 0x2d, 0xc9, 0x94, 0xca, 0x8a,
0x95, 0x1c, 0xd4, 0x86, 0xde, 0xb8, 0x13, 0x3e, 0xda, 0x1d, 0x59, 0x72, 0x90, 0x92, 0x83, 0x24,
0x9a, 0xe3, 0xbc, 0xc4, 0x88, 0xdd, 0xb9, 0xd1, 0x0f, 0x1f, 0xba, 0x73, 0x25, 0x18, 0xcd, 0x2b,
0x8e, 0xe8, 0xff, 0x39, 0x26, 0xb5, 0x81, 0xb7, 0x8f, 0xa5, 0xf1, 0x07, 0x96, 0x8f, 0x80, 0x9d,
0xf5, 0x62, 0x87, 0xca, 0x1f, 0x77, 0x42, 0x72, 0xd7, 0x00, 0x25, 0x42, 0xdc, 0x77, 0x9a, 0x79,
0x65, 0xa4, 0x33, 0x48, 0x96, 0x7e, 0x16, 0x99, 0xda, 0x2e, 0xf4, 0x46, 0xed, 0x7d, 0xda, 0x9f,
0xfa, 0x76, 0xf0, 0x1c, 0xfa, 0x4e, 0xe4, 0x22, 0xd4, 0x4d, 0x84, 0xbb, 0x5e, 0x2c, 0xb2, 0x06,
0x6e, 0x72, 0x02, 0xc7, 0x92, 0xa7, 0x37, 0x6c, 0x87, 0xaa, 0x69, 0x76, 0xf5, 0xe4, 0x2f, 0x54,
0x73, 0x73, 0xaa, 0x42, 0xea, 0x95, 0x1e, 0xd6, 0x75, 0x74, 0x1f, 0x3a, 0x91, 0xe0, 0x5f, 0xb7,
0xd5, 0xd2, 0x10, 0xf8, 0x8a, 0xae, 0xcc, 0xbe, 0xda, 0xb1, 0x2e, 0x47, 0xdf, 0x3c, 0xe8, 0xee,
0x3a, 0x60, 0x0c, 0xf5, 0x9c, 0x8a, 0x1b, 0xa3, 0x69, 0xc4, 0xa6, 0xc6, 0x17, 0xe0, 0xab, 0x6b,
0x6e, 0xde, 0x4e, 0x2f, 0x7c, 0xfe, 0x0f, 0x79, 0x48, 0x32, 0x8d, 0x5e, 0x51, 0xa9, 0x2e, 0x37,
0xac, 0x98, 0x2b, 0xaa, 0x58, 0xac, 0x8d, 0x46, 0xcf, 0x00, 0xdd, 0x6e, 0xe0, 0x16, 0xd4, 0x5f,
0xc8, 0x33, 0x89, 0x0e, 0x30, 0x40, 0xf3, 0x65, 0x41, 0x97, 0x6b, 0x86, 0x3c, 0xdc, 0x81, 0xc3,
0x59, 0x26, 0xcd, 0x47, 0xed, 0xf1, 0x15, 0xf4, 0x7f, 0x7b, 0x43, 0xf8, 0x10, 0xfc, 0x64, 0x1a,
0xa1, 0x03, 0x5d, 0xbc, 0x9b, 0x45, 0xc8, 0xd3, 0x4e, 0xe7, 0x6f, 0xa6, 0x11, 0xaa, 0xe1, 0x23,
0x68, 0x7f, 0x60, 0xcb, 0x32, 0x10, 0xf2, 0x75, 0xe3, 0x75, 0x92, 0x44, 0xa8, 0x8e, 0x11, 0x74,
0x67, 0x3c, 0xa7, 0x59, 0x51, 0xf5, 0x1a, 0x93, 0x4b, 0x78, 0x90, 0xf2, 0x7c, 0x3f, 0x5a, 0xe4,
0x5d, 0xb5, 0x6c, 0xfd, 0xbd, 0x76, 0xf2, 0x3e, 0x8c, 0xe9, 0x96, 0x4c, 0xb5, 0xd6, 0xc5, 0x22,
0x67, 0x55, 0x7f, 0xd9, 0x34, 0xcf, 0xf6, 0xe9, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf3, 0x8d,
0xe5, 0xd8, 0x85, 0x04, 0x00, 0x00,
}

View File

@ -55,4 +55,16 @@ message ProxyConfig {
message SocketConfig {
// Mark of the connection. If non-zero, the value will be set to SO_MARK.
int32 mark = 1;
enum TCPFastOpenState {
// AsIs is to leave the current TFO state as is, unmodified.
AsIs = 0;
// Enable is for enabling TFO explictly.
Enable = 1;
// Disable is for disabling TFO explictly.
Disable = 2;
}
// TFO is the state of TFO settings.
TCPFastOpenState tfo = 2;
}

View File

@ -9,6 +9,7 @@ import (
"v2ray.com/core/common"
"v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/common/session"
"v2ray.com/core/common/signal/done"
"v2ray.com/core/transport/internet"
"v2ray.com/core/transport/internet/tls"
@ -116,9 +117,18 @@ func Listen(ctx context.Context, address net.Address, port net.Port, handler int
listener.server = server
go func() {
err := server.ListenAndServeTLS("", "")
tcpListener, err := internet.ListenSystemTCP(ctx, &net.TCPAddr{
IP: address.IP(),
Port: int(port),
})
if err != nil {
newError("stoping serving TLS").Base(err).WriteToLog()
newError("failed to listen on", address, ":", port).Base(err).WriteToLog(session.ExportIDToError(ctx))
return
}
err = server.ServeTLS(tcpListener, "", "")
if err != nil {
newError("stoping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
}()

View File

@ -0,0 +1 @@
package internet

View File

@ -1,12 +1,53 @@
package internet
import "syscall"
import (
"strings"
"syscall"
)
func applySocketOptions(fd uintptr, config *SocketConfig) error {
const (
// For incoming connections.
TCP_FASTOPEN = 23
// For out-going connections.
TCP_FASTOPEN_CONNECT = 30
)
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
if config.Mark != 0 {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(config.Mark)); err != nil {
return err
}
}
if strings.HasPrefix(network, "tcp") {
switch config.Tfo {
case SocketConfig_Enable:
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN_CONNECT, 1); err != nil {
return err
}
case SocketConfig_Disable:
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN_CONNECT, 0); err != nil {
return err
}
}
}
return nil
}
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
if strings.HasPrefix(network, "tcp") {
switch config.Tfo {
case SocketConfig_Enable:
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, 1); err != nil {
return err
}
case SocketConfig_Disable:
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, 0); err != nil {
return err
}
}
}
return nil
}

View File

@ -2,6 +2,10 @@
package internet
func applySocketOptions(fd uintptr, config *SocketConfig) error {
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
return nil
}
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
return nil
}

View File

@ -31,7 +31,7 @@ func (DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.D
config := streamSettings.SocketSettings
dialer.Control = func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
if err := applySocketOptions(fd, config); err != nil {
if err := applyOutboundSocketOptions(network, address, fd, config); err != nil {
newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
})

View File

@ -0,0 +1,39 @@
package internet
import (
"context"
"v2ray.com/core/common/net"
"v2ray.com/core/common/session"
)
var (
effectiveTCPListener = DefaultTCPListener{}
)
type DefaultTCPListener struct{}
func (tl *DefaultTCPListener) Listen(ctx context.Context, addr *net.TCPAddr) (*net.TCPListener, error) {
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return nil, err
}
streamSettings := StreamSettingsFromContext(ctx)
if streamSettings != nil && streamSettings.SocketSettings != nil {
config := streamSettings.SocketSettings
rawConn, err := l.SyscallConn()
if err != nil {
return nil, err
}
if err := rawConn.Control(func(fd uintptr) {
if err := applyInboundSocketOptions("tcp", fd, config); err != nil {
newError("failed to apply socket options to incoming connection").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
}); err != nil {
return nil, err
}
}
return l, nil
}

View File

@ -23,7 +23,7 @@ type Listener struct {
// ListenTCP creates a new Listener based on configurations.
func ListenTCP(ctx context.Context, address net.Address, port net.Port, handler internet.ConnHandler) (internet.Listener, error) {
listener, err := net.ListenTCP("tcp", &net.TCPAddr{
listener, err := internet.ListenSystemTCP(ctx, &net.TCPAddr{
IP: address.IP(),
Port: int(port),
})

View File

@ -38,6 +38,10 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, handler
ctx = ContextWithStreamSettings(ctx, settings)
}
if address.Family().IsDomain() && address.Domain() == "localhost" {
address = net.LocalHostIP
}
protocol := settings.ProtocolName
listenFunc := transportListenerCache[protocol]
if listenFunc == nil {
@ -49,3 +53,7 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, handler
}
return listener, nil
}
func ListenSystemTCP(ctx context.Context, addr *net.TCPAddr) (*net.TCPListener, error) {
return effectiveTCPListener.Listen(ctx, addr)
}

View File

@ -4,7 +4,6 @@ import (
"context"
"crypto/tls"
"net/http"
"strconv"
"sync"
"time"
@ -13,6 +12,7 @@ import (
"v2ray.com/core/common"
"v2ray.com/core/common/net"
http_proto "v2ray.com/core/common/protocol/http"
"v2ray.com/core/common/session"
"v2ray.com/core/transport/internet"
v2tls "v2ray.com/core/transport/internet/tls"
)
@ -50,58 +50,61 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
type Listener struct {
sync.Mutex
listener net.Listener
tlsConfig *tls.Config
config *Config
addConn internet.ConnHandler
listener net.Listener
config *Config
addConn internet.ConnHandler
}
func ListenWS(ctx context.Context, address net.Address, port net.Port, addConn internet.ConnHandler) (internet.Listener, error) {
networkSettings := internet.StreamSettingsFromContext(ctx)
wsSettings := networkSettings.ProtocolSettings.(*Config)
l := &Listener{
config: wsSettings,
addConn: addConn,
}
var tlsConfig *tls.Config
if config := v2tls.ConfigFromContext(ctx); config != nil {
l.tlsConfig = config.GetTLSConfig()
tlsConfig = config.GetTLSConfig()
}
err := l.listenws(address, port)
listener, err := listenTCP(ctx, address, port, tlsConfig)
if err != nil {
return nil, err
}
l := &Listener{
config: wsSettings,
addConn: addConn,
listener: listener,
}
go func() {
if err := l.serve(); err != nil {
newError("failed to serve http for WebSocket").Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
}
}()
return l, err
}
func (ln *Listener) listenws(address net.Address, port net.Port) error {
netAddr := address.String() + ":" + strconv.Itoa(int(port.Value()))
var listener net.Listener
if ln.tlsConfig == nil {
l, err := net.Listen("tcp", netAddr)
if err != nil {
return newError("failed to listen TCP ", netAddr).Base(err)
}
listener = l
} else {
l, err := tls.Listen("tcp", netAddr, ln.tlsConfig)
if err != nil {
return newError("failed to listen TLS ", netAddr).Base(err)
}
listener = l
func listenTCP(ctx context.Context, address net.Address, port net.Port, tlsConfig *tls.Config) (net.Listener, error) {
listener, err := internet.ListenSystemTCP(ctx, &net.TCPAddr{
IP: address.IP(),
Port: int(port),
})
if err != nil {
return nil, newError("failed to listen TCP on", address, ":", port).Base(err)
}
ln.listener = listener
go func() {
err := http.Serve(listener, &requestHandler{
path: ln.config.GetNormalizedPath(),
ln: ln,
})
if err != nil {
newError("failed to serve http for WebSocket").Base(err).AtWarning().WriteToLog()
}
}()
if tlsConfig != nil {
return tls.NewListener(listener, tlsConfig), nil
}
return nil
return listener, nil
}
func (ln *Listener) serve() error {
return http.Serve(ln.listener, &requestHandler{
path: ln.config.GetNormalizedPath(),
ln: ln,
})
}
// Addr implements net.Listener.Addr().

View File

@ -24,7 +24,7 @@ func Test_listenWSAndDial(t *testing.T) {
Path: "ws",
},
})
listen, err := ListenWS(lctx, net.DomainAddress("localhost"), 13146, func(conn internet.Connection) {
listen, err := ListenWS(lctx, net.LocalHostIP, 13146, func(conn internet.Connection) {
go func(c internet.Connection) {
defer c.Close()
@ -79,7 +79,7 @@ func TestDialWithRemoteAddr(t *testing.T) {
Path: "ws",
},
})
listen, err := ListenWS(lctx, net.DomainAddress("localhost"), 13148, func(conn internet.Connection) {
listen, err := ListenWS(lctx, net.LocalHostIPv6, 13148, func(conn internet.Connection) {
go func(c internet.Connection) {
defer c.Close()
@ -138,7 +138,7 @@ func Test_listenWSAndDial_TLS(t *testing.T) {
},
})
listen, err := ListenWS(ctx, net.DomainAddress("localhost"), 13143, func(conn internet.Connection) {
listen, err := ListenWS(ctx, net.LocalHostIP, 13143, func(conn internet.Connection) {
go func() {
_ = conn.Close()
}()