mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
Hysteria & XHTTP/3: Unified Finalmask's quicParams to set congestion, brutalUp, brutalDown, udpHop (ports & interval), etc. (#5772)
https://github.com/XTLS/Xray-core/pull/5772#issuecomment-4023006179
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -500,7 +501,7 @@ func (b Bandwidth) Bps() (uint64, error) {
|
||||
}
|
||||
|
||||
type UdpHop struct {
|
||||
PortList json.RawMessage `json:"port"`
|
||||
PortList json.RawMessage `json:"ports"`
|
||||
Interval *Int32Range `json:"interval"`
|
||||
}
|
||||
|
||||
@@ -519,21 +520,13 @@ type Masquerade struct {
|
||||
}
|
||||
|
||||
type HysteriaConfig struct {
|
||||
Version int32 `json:"version"`
|
||||
Auth string `json:"auth"`
|
||||
Congestion string `json:"congestion"`
|
||||
Up Bandwidth `json:"up"`
|
||||
Down Bandwidth `json:"down"`
|
||||
UdpHop UdpHop `json:"udphop"`
|
||||
Version int32 `json:"version"`
|
||||
Auth string `json:"auth"`
|
||||
|
||||
InitStreamReceiveWindow uint64 `json:"initStreamReceiveWindow"`
|
||||
MaxStreamReceiveWindow uint64 `json:"maxStreamReceiveWindow"`
|
||||
InitConnectionReceiveWindow uint64 `json:"initConnectionReceiveWindow"`
|
||||
MaxConnectionReceiveWindow uint64 `json:"maxConnectionReceiveWindow"`
|
||||
MaxIdleTimeout int64 `json:"maxIdleTimeout"`
|
||||
KeepAlivePeriod int64 `json:"keepAlivePeriod"`
|
||||
DisablePathMTUDiscovery bool `json:"disablePathMTUDiscovery"`
|
||||
MaxIncomingStreams int64 `json:"maxIncomingStreams"`
|
||||
Congestion *string `json:"congestion"`
|
||||
Up *Bandwidth `json:"up"`
|
||||
Down *Bandwidth `json:"down"`
|
||||
UdpHop *UdpHop `json:"udphop"`
|
||||
|
||||
UdpIdleTimeout int64 `json:"udpIdleTimeout"`
|
||||
Masquerade Masquerade `json:"masquerade"`
|
||||
@@ -544,62 +537,10 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
|
||||
return nil, errors.New("version != 2")
|
||||
}
|
||||
|
||||
up, err := c.Up.Bps()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
down, err := c.Down.Bps()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if c.Congestion != nil || c.Up != nil || c.Down != nil || c.UdpHop != nil {
|
||||
errors.LogWarning(context.Background(), "congestion & up & down & udphop move to finalmask/quicParams")
|
||||
}
|
||||
|
||||
c.Congestion = strings.ToLower(c.Congestion)
|
||||
if c.Congestion == "force-brutal" && up == 0 {
|
||||
return nil, errors.New("force-brutal require up")
|
||||
}
|
||||
|
||||
var hop *PortList
|
||||
if err := json.Unmarshal(c.UdpHop.PortList, &hop); err != nil {
|
||||
hop = &PortList{}
|
||||
}
|
||||
|
||||
var inertvalMin, inertvalMax int64
|
||||
if c.UdpHop.Interval != nil {
|
||||
inertvalMin = int64(c.UdpHop.Interval.From)
|
||||
inertvalMax = int64(c.UdpHop.Interval.To)
|
||||
}
|
||||
|
||||
if up > 0 && up < 65536 {
|
||||
return nil, errors.New("Up must be at least 65536 bytes per second")
|
||||
}
|
||||
if down > 0 && down < 65536 {
|
||||
return nil, errors.New("Down must be at least 65536 bytes per second")
|
||||
}
|
||||
if (inertvalMin != 0 && inertvalMin < 5) || (inertvalMax != 0 && inertvalMax < 5) {
|
||||
return nil, errors.New("Interval must be at least 5")
|
||||
}
|
||||
|
||||
if c.InitStreamReceiveWindow > 0 && c.InitStreamReceiveWindow < 16384 {
|
||||
return nil, errors.New("InitStreamReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.MaxStreamReceiveWindow > 0 && c.MaxStreamReceiveWindow < 16384 {
|
||||
return nil, errors.New("MaxStreamReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.InitConnectionReceiveWindow > 0 && c.InitConnectionReceiveWindow < 16384 {
|
||||
return nil, errors.New("InitConnectionReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.MaxConnectionReceiveWindow > 0 && c.MaxConnectionReceiveWindow < 16384 {
|
||||
return nil, errors.New("MaxConnectionReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.MaxIdleTimeout != 0 && (c.MaxIdleTimeout < 4 || c.MaxIdleTimeout > 120) {
|
||||
return nil, errors.New("MaxIdleTimeout must be between 4 and 120")
|
||||
}
|
||||
if c.KeepAlivePeriod != 0 && (c.KeepAlivePeriod < 2 || c.KeepAlivePeriod > 60) {
|
||||
return nil, errors.New("KeepAlivePeriod must be between 2 and 60")
|
||||
}
|
||||
if c.MaxIncomingStreams != 0 && c.MaxIncomingStreams < 8 {
|
||||
return nil, errors.New("MaxIncomingStreams must be at least 8")
|
||||
}
|
||||
if c.UdpIdleTimeout != 0 && (c.UdpIdleTimeout < 2 || c.UdpIdleTimeout > 600) {
|
||||
return nil, errors.New("UdpIdleTimeout must be between 2 and 600")
|
||||
}
|
||||
@@ -607,20 +548,6 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
|
||||
config := &hysteria.Config{}
|
||||
config.Version = c.Version
|
||||
config.Auth = c.Auth
|
||||
config.Congestion = c.Congestion
|
||||
config.Up = up
|
||||
config.Down = down
|
||||
config.Ports = hop.Build().Ports()
|
||||
config.IntervalMin = inertvalMin
|
||||
config.IntervalMax = inertvalMax
|
||||
config.InitStreamReceiveWindow = c.InitStreamReceiveWindow
|
||||
config.MaxStreamReceiveWindow = c.MaxStreamReceiveWindow
|
||||
config.InitConnReceiveWindow = c.InitConnectionReceiveWindow
|
||||
config.MaxConnReceiveWindow = c.MaxConnectionReceiveWindow
|
||||
config.MaxIdleTimeout = c.MaxIdleTimeout
|
||||
config.KeepAlivePeriod = c.KeepAlivePeriod
|
||||
config.DisablePathMtuDiscovery = c.DisablePathMTUDiscovery
|
||||
config.MaxIncomingStreams = c.MaxIncomingStreams
|
||||
config.UdpIdleTimeout = c.UdpIdleTimeout
|
||||
config.MasqType = c.Masquerade.Type
|
||||
config.MasqFile = c.Masquerade.Dir
|
||||
@@ -631,27 +558,6 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
|
||||
config.MasqStringHeaders = c.Masquerade.Headers
|
||||
config.MasqStringStatusCode = c.Masquerade.StatusCode
|
||||
|
||||
if config.InitStreamReceiveWindow == 0 {
|
||||
config.InitStreamReceiveWindow = 8388608
|
||||
}
|
||||
if config.MaxStreamReceiveWindow == 0 {
|
||||
config.MaxStreamReceiveWindow = 8388608
|
||||
}
|
||||
if config.InitConnReceiveWindow == 0 {
|
||||
config.InitConnReceiveWindow = 8388608 * 5 / 2
|
||||
}
|
||||
if config.MaxConnReceiveWindow == 0 {
|
||||
config.MaxConnReceiveWindow = 8388608 * 5 / 2
|
||||
}
|
||||
if config.MaxIdleTimeout == 0 {
|
||||
config.MaxIdleTimeout = 30
|
||||
}
|
||||
// if config.KeepAlivePeriod == 0 {
|
||||
// config.KeepAlivePeriod = 10
|
||||
// }
|
||||
if config.MaxIncomingStreams == 0 {
|
||||
config.MaxIncomingStreams = 1024
|
||||
}
|
||||
if config.UdpIdleTimeout == 0 {
|
||||
config.UdpIdleTimeout = 60
|
||||
}
|
||||
@@ -722,8 +628,19 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
|
||||
}
|
||||
|
||||
type QuicParamsConfig struct {
|
||||
Congestion string `json:"congestion"`
|
||||
Up Bandwidth `json:"up"`
|
||||
Congestion string `json:"congestion"`
|
||||
Debug bool `json:"debug"`
|
||||
BrutalUp Bandwidth `json:"brutalUp"`
|
||||
BrutalDown Bandwidth `json:"brutalDown"`
|
||||
UdpHop UdpHop `json:"udpHop"`
|
||||
InitStreamReceiveWindow uint64 `json:"initStreamReceiveWindow"`
|
||||
MaxStreamReceiveWindow uint64 `json:"maxStreamReceiveWindow"`
|
||||
InitConnectionReceiveWindow uint64 `json:"initConnectionReceiveWindow"`
|
||||
MaxConnectionReceiveWindow uint64 `json:"maxConnectionReceiveWindow"`
|
||||
MaxIdleTimeout int64 `json:"maxIdleTimeout"`
|
||||
KeepAlivePeriod int64 `json:"keepAlivePeriod"`
|
||||
DisablePathMTUDiscovery bool `json:"disablePathMTUDiscovery"`
|
||||
MaxIncomingStreams int64 `json:"maxIncomingStreams"`
|
||||
}
|
||||
|
||||
type TLSConfig struct {
|
||||
@@ -1918,25 +1835,92 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
config.Udpmasks = append(config.Udpmasks, serial.ToTypedMessage(u))
|
||||
}
|
||||
if c.FinalMask.QuicParams != nil {
|
||||
up, err := c.FinalMask.QuicParams.Up.Bps()
|
||||
up, err := c.FinalMask.QuicParams.BrutalUp.Bps()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if up > 0 && up < 65536 {
|
||||
return nil, errors.New("Up must be at least 65536 bytes per second")
|
||||
down, err := c.FinalMask.QuicParams.BrutalDown.Bps()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if up > 0 && up < 65536 {
|
||||
return nil, errors.New("BrutalUp must be at least 65536 bytes per second")
|
||||
}
|
||||
if down > 0 && down < 65536 {
|
||||
return nil, errors.New("BrutalDown must be at least 65536 bytes per second")
|
||||
}
|
||||
|
||||
c.FinalMask.QuicParams.Congestion = strings.ToLower(c.FinalMask.QuicParams.Congestion)
|
||||
switch c.FinalMask.QuicParams.Congestion {
|
||||
case "", "bbr", "reno":
|
||||
case "", "brutal", "reno", "bbr":
|
||||
case "force-brutal":
|
||||
if up == 0 {
|
||||
return nil, errors.New("force-brutal requires up")
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: bbr, reno, force-brutal")
|
||||
return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: reno, bbr, brutal, force-brutal")
|
||||
}
|
||||
|
||||
var hop *PortList
|
||||
if err := json.Unmarshal(c.FinalMask.QuicParams.UdpHop.PortList, &hop); err != nil {
|
||||
hop = &PortList{}
|
||||
}
|
||||
|
||||
var inertvalMin, inertvalMax int64
|
||||
if c.FinalMask.QuicParams.UdpHop.Interval != nil {
|
||||
inertvalMin = int64(c.FinalMask.QuicParams.UdpHop.Interval.From)
|
||||
inertvalMax = int64(c.FinalMask.QuicParams.UdpHop.Interval.To)
|
||||
}
|
||||
|
||||
if (inertvalMin != 0 && inertvalMin < 5) || (inertvalMax != 0 && inertvalMax < 5) {
|
||||
return nil, errors.New("Interval must be at least 5")
|
||||
}
|
||||
|
||||
if c.FinalMask.QuicParams.InitStreamReceiveWindow > 0 && c.FinalMask.QuicParams.InitStreamReceiveWindow < 16384 {
|
||||
return nil, errors.New("InitStreamReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.FinalMask.QuicParams.MaxStreamReceiveWindow > 0 && c.FinalMask.QuicParams.MaxStreamReceiveWindow < 16384 {
|
||||
return nil, errors.New("MaxStreamReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.FinalMask.QuicParams.InitConnectionReceiveWindow > 0 && c.FinalMask.QuicParams.InitConnectionReceiveWindow < 16384 {
|
||||
return nil, errors.New("InitConnectionReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.FinalMask.QuicParams.MaxConnectionReceiveWindow > 0 && c.FinalMask.QuicParams.MaxConnectionReceiveWindow < 16384 {
|
||||
return nil, errors.New("MaxConnectionReceiveWindow must be at least 16384")
|
||||
}
|
||||
if c.FinalMask.QuicParams.MaxIdleTimeout != 0 && (c.FinalMask.QuicParams.MaxIdleTimeout < 4 || c.FinalMask.QuicParams.MaxIdleTimeout > 120) {
|
||||
return nil, errors.New("MaxIdleTimeout must be between 4 and 120")
|
||||
}
|
||||
if c.FinalMask.QuicParams.KeepAlivePeriod != 0 && (c.FinalMask.QuicParams.KeepAlivePeriod < 2 || c.FinalMask.QuicParams.KeepAlivePeriod > 60) {
|
||||
return nil, errors.New("KeepAlivePeriod must be between 2 and 60")
|
||||
}
|
||||
if c.FinalMask.QuicParams.MaxIncomingStreams != 0 && c.FinalMask.QuicParams.MaxIncomingStreams < 8 {
|
||||
return nil, errors.New("MaxIncomingStreams must be at least 8")
|
||||
}
|
||||
|
||||
if c.FinalMask.QuicParams.Debug {
|
||||
os.Setenv("HYSTERIA_BBR_DEBUG", "true")
|
||||
os.Setenv("HYSTERIA_BRUTAL_DEBUG", "true")
|
||||
}
|
||||
|
||||
config.QuicParams = &internet.QuicParams{
|
||||
Congestion: c.FinalMask.QuicParams.Congestion,
|
||||
Up: up,
|
||||
BrutalUp: up,
|
||||
BrutalDown: down,
|
||||
UdpHop: &internet.UdpHop{
|
||||
Ports: hop.Build().Ports(),
|
||||
IntervalMin: inertvalMin,
|
||||
IntervalMax: inertvalMax,
|
||||
},
|
||||
InitStreamReceiveWindow: c.FinalMask.QuicParams.InitStreamReceiveWindow,
|
||||
MaxStreamReceiveWindow: c.FinalMask.QuicParams.MaxStreamReceiveWindow,
|
||||
InitConnReceiveWindow: c.FinalMask.QuicParams.InitConnectionReceiveWindow,
|
||||
MaxConnReceiveWindow: c.FinalMask.QuicParams.MaxConnectionReceiveWindow,
|
||||
MaxIdleTimeout: c.FinalMask.QuicParams.MaxIdleTimeout,
|
||||
KeepAlivePeriod: c.FinalMask.QuicParams.KeepAlivePeriod,
|
||||
DisablePathMtuDiscovery: c.FinalMask.QuicParams.DisablePathMTUDiscovery,
|
||||
MaxIncomingStreams: c.FinalMask.QuicParams.MaxIncomingStreams,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ func (x SocketConfig_TProxyMode) Number() protoreflect.EnumNumber {
|
||||
|
||||
// Deprecated: Use SocketConfig_TProxyMode.Descriptor instead.
|
||||
func (SocketConfig_TProxyMode) EnumDescriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{5, 0}
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{6, 0}
|
||||
}
|
||||
|
||||
type TransportConfig struct {
|
||||
@@ -382,17 +382,87 @@ func (x *StreamConfig) GetSocketSettings() *SocketConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
type QuicParams struct {
|
||||
type UdpHop struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Congestion string `protobuf:"bytes,1,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
||||
Up uint64 `protobuf:"varint,2,opt,name=up,proto3" json:"up,omitempty"`
|
||||
Ports []uint32 `protobuf:"varint,1,rep,packed,name=ports,proto3" json:"ports,omitempty"`
|
||||
IntervalMin int64 `protobuf:"varint,2,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
|
||||
IntervalMax int64 `protobuf:"varint,3,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *UdpHop) Reset() {
|
||||
*x = UdpHop{}
|
||||
mi := &file_transport_internet_config_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *UdpHop) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UdpHop) ProtoMessage() {}
|
||||
|
||||
func (x *UdpHop) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_config_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UdpHop.ProtoReflect.Descriptor instead.
|
||||
func (*UdpHop) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *UdpHop) GetPorts() []uint32 {
|
||||
if x != nil {
|
||||
return x.Ports
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UdpHop) GetIntervalMin() int64 {
|
||||
if x != nil {
|
||||
return x.IntervalMin
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *UdpHop) GetIntervalMax() int64 {
|
||||
if x != nil {
|
||||
return x.IntervalMax
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type QuicParams struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Congestion string `protobuf:"bytes,1,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
||||
BrutalUp uint64 `protobuf:"varint,2,opt,name=brutal_up,json=brutalUp,proto3" json:"brutal_up,omitempty"`
|
||||
BrutalDown uint64 `protobuf:"varint,3,opt,name=brutal_down,json=brutalDown,proto3" json:"brutal_down,omitempty"`
|
||||
UdpHop *UdpHop `protobuf:"bytes,4,opt,name=udp_hop,json=udpHop,proto3" json:"udp_hop,omitempty"`
|
||||
InitStreamReceiveWindow uint64 `protobuf:"varint,5,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"`
|
||||
MaxStreamReceiveWindow uint64 `protobuf:"varint,6,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"`
|
||||
InitConnReceiveWindow uint64 `protobuf:"varint,7,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"`
|
||||
MaxConnReceiveWindow uint64 `protobuf:"varint,8,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"`
|
||||
MaxIdleTimeout int64 `protobuf:"varint,9,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"`
|
||||
KeepAlivePeriod int64 `protobuf:"varint,10,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"`
|
||||
DisablePathMtuDiscovery bool `protobuf:"varint,11,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"`
|
||||
MaxIncomingStreams int64 `protobuf:"varint,12,opt,name=max_incoming_streams,json=maxIncomingStreams,proto3" json:"max_incoming_streams,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *QuicParams) Reset() {
|
||||
*x = QuicParams{}
|
||||
mi := &file_transport_internet_config_proto_msgTypes[2]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -404,7 +474,7 @@ func (x *QuicParams) String() string {
|
||||
func (*QuicParams) ProtoMessage() {}
|
||||
|
||||
func (x *QuicParams) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_config_proto_msgTypes[2]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -417,7 +487,7 @@ func (x *QuicParams) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use QuicParams.ProtoReflect.Descriptor instead.
|
||||
func (*QuicParams) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{2}
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetCongestion() string {
|
||||
@@ -427,9 +497,79 @@ func (x *QuicParams) GetCongestion() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetUp() uint64 {
|
||||
func (x *QuicParams) GetBrutalUp() uint64 {
|
||||
if x != nil {
|
||||
return x.Up
|
||||
return x.BrutalUp
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetBrutalDown() uint64 {
|
||||
if x != nil {
|
||||
return x.BrutalDown
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetUdpHop() *UdpHop {
|
||||
if x != nil {
|
||||
return x.UdpHop
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetInitStreamReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.InitStreamReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetMaxStreamReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.MaxStreamReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetInitConnReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.InitConnReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetMaxConnReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.MaxConnReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetMaxIdleTimeout() int64 {
|
||||
if x != nil {
|
||||
return x.MaxIdleTimeout
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetKeepAlivePeriod() int64 {
|
||||
if x != nil {
|
||||
return x.KeepAlivePeriod
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetDisablePathMtuDiscovery() bool {
|
||||
if x != nil {
|
||||
return x.DisablePathMtuDiscovery
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *QuicParams) GetMaxIncomingStreams() int64 {
|
||||
if x != nil {
|
||||
return x.MaxIncomingStreams
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -444,7 +584,7 @@ type ProxyConfig struct {
|
||||
|
||||
func (x *ProxyConfig) Reset() {
|
||||
*x = ProxyConfig{}
|
||||
mi := &file_transport_internet_config_proto_msgTypes[3]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -456,7 +596,7 @@ func (x *ProxyConfig) String() string {
|
||||
func (*ProxyConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ProxyConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_config_proto_msgTypes[3]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -469,7 +609,7 @@ func (x *ProxyConfig) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use ProxyConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ProxyConfig) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{3}
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *ProxyConfig) GetTag() string {
|
||||
@@ -500,7 +640,7 @@ type CustomSockopt struct {
|
||||
|
||||
func (x *CustomSockopt) Reset() {
|
||||
*x = CustomSockopt{}
|
||||
mi := &file_transport_internet_config_proto_msgTypes[4]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -512,7 +652,7 @@ func (x *CustomSockopt) String() string {
|
||||
func (*CustomSockopt) ProtoMessage() {}
|
||||
|
||||
func (x *CustomSockopt) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_config_proto_msgTypes[4]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -525,7 +665,7 @@ func (x *CustomSockopt) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use CustomSockopt.ProtoReflect.Descriptor instead.
|
||||
func (*CustomSockopt) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{4}
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *CustomSockopt) GetSystem() string {
|
||||
@@ -607,7 +747,7 @@ type SocketConfig struct {
|
||||
|
||||
func (x *SocketConfig) Reset() {
|
||||
*x = SocketConfig{}
|
||||
mi := &file_transport_internet_config_proto_msgTypes[5]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -619,7 +759,7 @@ func (x *SocketConfig) String() string {
|
||||
func (*SocketConfig) ProtoMessage() {}
|
||||
|
||||
func (x *SocketConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_config_proto_msgTypes[5]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -632,7 +772,7 @@ func (x *SocketConfig) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use SocketConfig.ProtoReflect.Descriptor instead.
|
||||
func (*SocketConfig) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{5}
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *SocketConfig) GetMark() int32 {
|
||||
@@ -808,7 +948,7 @@ type HappyEyeballsConfig struct {
|
||||
|
||||
func (x *HappyEyeballsConfig) Reset() {
|
||||
*x = HappyEyeballsConfig{}
|
||||
mi := &file_transport_internet_config_proto_msgTypes[6]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -820,7 +960,7 @@ func (x *HappyEyeballsConfig) String() string {
|
||||
func (*HappyEyeballsConfig) ProtoMessage() {}
|
||||
|
||||
func (x *HappyEyeballsConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_config_proto_msgTypes[6]
|
||||
mi := &file_transport_internet_config_proto_msgTypes[7]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -833,7 +973,7 @@ func (x *HappyEyeballsConfig) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use HappyEyeballsConfig.ProtoReflect.Descriptor instead.
|
||||
func (*HappyEyeballsConfig) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{6}
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *HappyEyeballsConfig) GetPrioritizeIpv6() bool {
|
||||
@@ -884,13 +1024,29 @@ const file_transport_internet_config_proto_rawDesc = "" +
|
||||
"\btcpmasks\x18\v \x03(\v2 .xray.common.serial.TypedMessageR\btcpmasks\x12D\n" +
|
||||
"\vquic_params\x18\f \x01(\v2#.xray.transport.internet.QuicParamsR\n" +
|
||||
"quicParams\x12N\n" +
|
||||
"\x0fsocket_settings\x18\x06 \x01(\v2%.xray.transport.internet.SocketConfigR\x0esocketSettings\"<\n" +
|
||||
"\x0fsocket_settings\x18\x06 \x01(\v2%.xray.transport.internet.SocketConfigR\x0esocketSettings\"d\n" +
|
||||
"\x06UdpHop\x12\x14\n" +
|
||||
"\x05ports\x18\x01 \x03(\rR\x05ports\x12!\n" +
|
||||
"\finterval_min\x18\x02 \x01(\x03R\vintervalMin\x12!\n" +
|
||||
"\finterval_max\x18\x03 \x01(\x03R\vintervalMax\"\xd1\x04\n" +
|
||||
"\n" +
|
||||
"QuicParams\x12\x1e\n" +
|
||||
"\n" +
|
||||
"congestion\x18\x01 \x01(\tR\n" +
|
||||
"congestion\x12\x0e\n" +
|
||||
"\x02up\x18\x02 \x01(\x04R\x02up\"Q\n" +
|
||||
"congestion\x12\x1b\n" +
|
||||
"\tbrutal_up\x18\x02 \x01(\x04R\bbrutalUp\x12\x1f\n" +
|
||||
"\vbrutal_down\x18\x03 \x01(\x04R\n" +
|
||||
"brutalDown\x128\n" +
|
||||
"\audp_hop\x18\x04 \x01(\v2\x1f.xray.transport.internet.UdpHopR\x06udpHop\x12;\n" +
|
||||
"\x1ainit_stream_receive_window\x18\x05 \x01(\x04R\x17initStreamReceiveWindow\x129\n" +
|
||||
"\x19max_stream_receive_window\x18\x06 \x01(\x04R\x16maxStreamReceiveWindow\x127\n" +
|
||||
"\x18init_conn_receive_window\x18\a \x01(\x04R\x15initConnReceiveWindow\x125\n" +
|
||||
"\x17max_conn_receive_window\x18\b \x01(\x04R\x14maxConnReceiveWindow\x12(\n" +
|
||||
"\x10max_idle_timeout\x18\t \x01(\x03R\x0emaxIdleTimeout\x12*\n" +
|
||||
"\x11keep_alive_period\x18\n" +
|
||||
" \x01(\x03R\x0fkeepAlivePeriod\x12;\n" +
|
||||
"\x1adisable_path_mtu_discovery\x18\v \x01(\bR\x17disablePathMtuDiscovery\x120\n" +
|
||||
"\x14max_incoming_streams\x18\f \x01(\x03R\x12maxIncomingStreams\"Q\n" +
|
||||
"\vProxyConfig\x12\x10\n" +
|
||||
"\x03tag\x18\x01 \x01(\tR\x03tag\x120\n" +
|
||||
"\x13transportLayerProxy\x18\x02 \x01(\bR\x13transportLayerProxy\"\x93\x01\n" +
|
||||
@@ -979,40 +1135,42 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte {
|
||||
}
|
||||
|
||||
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
|
||||
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||
var file_transport_internet_config_proto_goTypes = []any{
|
||||
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
|
||||
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
|
||||
(SocketConfig_TProxyMode)(0), // 2: xray.transport.internet.SocketConfig.TProxyMode
|
||||
(*TransportConfig)(nil), // 3: xray.transport.internet.TransportConfig
|
||||
(*StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig
|
||||
(*QuicParams)(nil), // 5: xray.transport.internet.QuicParams
|
||||
(*ProxyConfig)(nil), // 6: xray.transport.internet.ProxyConfig
|
||||
(*CustomSockopt)(nil), // 7: xray.transport.internet.CustomSockopt
|
||||
(*SocketConfig)(nil), // 8: xray.transport.internet.SocketConfig
|
||||
(*HappyEyeballsConfig)(nil), // 9: xray.transport.internet.HappyEyeballsConfig
|
||||
(*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage
|
||||
(*net.IPOrDomain)(nil), // 11: xray.common.net.IPOrDomain
|
||||
(*UdpHop)(nil), // 5: xray.transport.internet.UdpHop
|
||||
(*QuicParams)(nil), // 6: xray.transport.internet.QuicParams
|
||||
(*ProxyConfig)(nil), // 7: xray.transport.internet.ProxyConfig
|
||||
(*CustomSockopt)(nil), // 8: xray.transport.internet.CustomSockopt
|
||||
(*SocketConfig)(nil), // 9: xray.transport.internet.SocketConfig
|
||||
(*HappyEyeballsConfig)(nil), // 10: xray.transport.internet.HappyEyeballsConfig
|
||||
(*serial.TypedMessage)(nil), // 11: xray.common.serial.TypedMessage
|
||||
(*net.IPOrDomain)(nil), // 12: xray.common.net.IPOrDomain
|
||||
}
|
||||
var file_transport_internet_config_proto_depIdxs = []int32{
|
||||
10, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
||||
11, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||
11, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
||||
12, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||
3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
||||
10, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
||||
10, // 4: xray.transport.internet.StreamConfig.udpmasks:type_name -> xray.common.serial.TypedMessage
|
||||
10, // 5: xray.transport.internet.StreamConfig.tcpmasks:type_name -> xray.common.serial.TypedMessage
|
||||
5, // 6: xray.transport.internet.StreamConfig.quic_params:type_name -> xray.transport.internet.QuicParams
|
||||
8, // 7: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
||||
2, // 8: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
||||
0, // 9: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||
7, // 10: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
||||
1, // 11: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
|
||||
9, // 12: xray.transport.internet.SocketConfig.happy_eyeballs:type_name -> xray.transport.internet.HappyEyeballsConfig
|
||||
13, // [13:13] is the sub-list for method output_type
|
||||
13, // [13:13] is the sub-list for method input_type
|
||||
13, // [13:13] is the sub-list for extension type_name
|
||||
13, // [13:13] is the sub-list for extension extendee
|
||||
0, // [0:13] is the sub-list for field type_name
|
||||
11, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
||||
11, // 4: xray.transport.internet.StreamConfig.udpmasks:type_name -> xray.common.serial.TypedMessage
|
||||
11, // 5: xray.transport.internet.StreamConfig.tcpmasks:type_name -> xray.common.serial.TypedMessage
|
||||
6, // 6: xray.transport.internet.StreamConfig.quic_params:type_name -> xray.transport.internet.QuicParams
|
||||
9, // 7: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
||||
5, // 8: xray.transport.internet.QuicParams.udp_hop:type_name -> xray.transport.internet.UdpHop
|
||||
2, // 9: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
||||
0, // 10: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||
8, // 11: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
||||
1, // 12: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
|
||||
10, // 13: xray.transport.internet.SocketConfig.happy_eyeballs:type_name -> xray.transport.internet.HappyEyeballsConfig
|
||||
14, // [14:14] is the sub-list for method output_type
|
||||
14, // [14:14] is the sub-list for method input_type
|
||||
14, // [14:14] is the sub-list for extension type_name
|
||||
14, // [14:14] is the sub-list for extension extendee
|
||||
0, // [0:14] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_transport_internet_config_proto_init() }
|
||||
@@ -1026,7 +1184,7 @@ func file_transport_internet_config_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_config_proto_rawDesc), len(file_transport_internet_config_proto_rawDesc)),
|
||||
NumEnums: 3,
|
||||
NumMessages: 7,
|
||||
NumMessages: 8,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -64,9 +64,25 @@ message StreamConfig {
|
||||
SocketConfig socket_settings = 6;
|
||||
}
|
||||
|
||||
message UdpHop {
|
||||
repeated uint32 ports = 1;
|
||||
int64 interval_min = 2;
|
||||
int64 interval_max = 3;
|
||||
}
|
||||
|
||||
message QuicParams {
|
||||
string congestion = 1;
|
||||
uint64 up = 2;
|
||||
uint64 brutal_up = 2;
|
||||
uint64 brutal_down = 3;
|
||||
UdpHop udp_hop = 4;
|
||||
uint64 init_stream_receive_window = 5;
|
||||
uint64 max_stream_receive_window = 6;
|
||||
uint64 init_conn_receive_window = 7;
|
||||
uint64 max_conn_receive_window = 8;
|
||||
int64 max_idle_timeout = 9;
|
||||
int64 keep_alive_period = 10;
|
||||
bool disable_path_mtu_discovery = 11;
|
||||
int64 max_incoming_streams = 12;
|
||||
}
|
||||
|
||||
message ProxyConfig {
|
||||
|
||||
@@ -372,9 +372,6 @@ func runHysteria2Case(t *testing.T, bin string, mode trafficMode, payloadSize in
|
||||
Settings: serial.ToTypedMessage(&hytransport.Config{
|
||||
Version: 2,
|
||||
Auth: auth,
|
||||
Congestion: "bbr",
|
||||
Up: 10 * 1024 * 1024,
|
||||
Down: 10 * 1024 * 1024,
|
||||
UdpIdleTimeout: 60,
|
||||
}),
|
||||
},
|
||||
@@ -438,9 +435,6 @@ func runHysteria2Case(t *testing.T, bin string, mode trafficMode, payloadSize in
|
||||
Settings: serial.ToTypedMessage(&hytransport.Config{
|
||||
Version: 2,
|
||||
Auth: auth,
|
||||
Congestion: "bbr",
|
||||
Up: 10 * 1024 * 1024,
|
||||
Down: 10 * 1024 * 1024,
|
||||
UdpIdleTimeout: 60,
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -22,34 +22,20 @@ const (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Auth string `protobuf:"bytes,2,opt,name=auth,proto3" json:"auth,omitempty"`
|
||||
Congestion string `protobuf:"bytes,3,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
||||
Up uint64 `protobuf:"varint,4,opt,name=up,proto3" json:"up,omitempty"`
|
||||
Down uint64 `protobuf:"varint,5,opt,name=down,proto3" json:"down,omitempty"`
|
||||
Ports []uint32 `protobuf:"varint,6,rep,packed,name=ports,proto3" json:"ports,omitempty"`
|
||||
IntervalMin int64 `protobuf:"varint,7,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
|
||||
IntervalMax int64 `protobuf:"varint,8,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
|
||||
InitStreamReceiveWindow uint64 `protobuf:"varint,9,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"`
|
||||
MaxStreamReceiveWindow uint64 `protobuf:"varint,10,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"`
|
||||
InitConnReceiveWindow uint64 `protobuf:"varint,11,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"`
|
||||
MaxConnReceiveWindow uint64 `protobuf:"varint,12,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"`
|
||||
MaxIdleTimeout int64 `protobuf:"varint,13,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"`
|
||||
KeepAlivePeriod int64 `protobuf:"varint,14,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"`
|
||||
DisablePathMtuDiscovery bool `protobuf:"varint,15,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"`
|
||||
MaxIncomingStreams int64 `protobuf:"varint,16,opt,name=max_incoming_streams,json=maxIncomingStreams,proto3" json:"max_incoming_streams,omitempty"`
|
||||
UdpIdleTimeout int64 `protobuf:"varint,17,opt,name=udp_idle_timeout,json=udpIdleTimeout,proto3" json:"udp_idle_timeout,omitempty"`
|
||||
MasqType string `protobuf:"bytes,18,opt,name=masq_type,json=masqType,proto3" json:"masq_type,omitempty"`
|
||||
MasqFile string `protobuf:"bytes,19,opt,name=masq_file,json=masqFile,proto3" json:"masq_file,omitempty"`
|
||||
MasqUrl string `protobuf:"bytes,20,opt,name=masq_url,json=masqUrl,proto3" json:"masq_url,omitempty"`
|
||||
MasqUrlRewriteHost bool `protobuf:"varint,21,opt,name=masq_url_rewrite_host,json=masqUrlRewriteHost,proto3" json:"masq_url_rewrite_host,omitempty"`
|
||||
MasqUrlInsecure bool `protobuf:"varint,22,opt,name=masq_url_insecure,json=masqUrlInsecure,proto3" json:"masq_url_insecure,omitempty"`
|
||||
MasqString string `protobuf:"bytes,23,opt,name=masq_string,json=masqString,proto3" json:"masq_string,omitempty"`
|
||||
MasqStringHeaders map[string]string `protobuf:"bytes,24,rep,name=masq_string_headers,json=masqStringHeaders,proto3" json:"masq_string_headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
MasqStringStatusCode int32 `protobuf:"varint,25,opt,name=masq_string_status_code,json=masqStringStatusCode,proto3" json:"masq_string_status_code,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Auth string `protobuf:"bytes,2,opt,name=auth,proto3" json:"auth,omitempty"`
|
||||
UdpIdleTimeout int64 `protobuf:"varint,3,opt,name=udp_idle_timeout,json=udpIdleTimeout,proto3" json:"udp_idle_timeout,omitempty"`
|
||||
MasqType string `protobuf:"bytes,4,opt,name=masq_type,json=masqType,proto3" json:"masq_type,omitempty"`
|
||||
MasqFile string `protobuf:"bytes,5,opt,name=masq_file,json=masqFile,proto3" json:"masq_file,omitempty"`
|
||||
MasqUrl string `protobuf:"bytes,6,opt,name=masq_url,json=masqUrl,proto3" json:"masq_url,omitempty"`
|
||||
MasqUrlRewriteHost bool `protobuf:"varint,7,opt,name=masq_url_rewrite_host,json=masqUrlRewriteHost,proto3" json:"masq_url_rewrite_host,omitempty"`
|
||||
MasqUrlInsecure bool `protobuf:"varint,8,opt,name=masq_url_insecure,json=masqUrlInsecure,proto3" json:"masq_url_insecure,omitempty"`
|
||||
MasqString string `protobuf:"bytes,9,opt,name=masq_string,json=masqString,proto3" json:"masq_string,omitempty"`
|
||||
MasqStringHeaders map[string]string `protobuf:"bytes,10,rep,name=masq_string_headers,json=masqStringHeaders,proto3" json:"masq_string_headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
MasqStringStatusCode int32 `protobuf:"varint,11,opt,name=masq_string_status_code,json=masqStringStatusCode,proto3" json:"masq_string_status_code,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
@@ -96,104 +82,6 @@ func (x *Config) GetAuth() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetCongestion() string {
|
||||
if x != nil {
|
||||
return x.Congestion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetUp() uint64 {
|
||||
if x != nil {
|
||||
return x.Up
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetDown() uint64 {
|
||||
if x != nil {
|
||||
return x.Down
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetPorts() []uint32 {
|
||||
if x != nil {
|
||||
return x.Ports
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetIntervalMin() int64 {
|
||||
if x != nil {
|
||||
return x.IntervalMin
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetIntervalMax() int64 {
|
||||
if x != nil {
|
||||
return x.IntervalMax
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetInitStreamReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.InitStreamReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetMaxStreamReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.MaxStreamReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetInitConnReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.InitConnReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetMaxConnReceiveWindow() uint64 {
|
||||
if x != nil {
|
||||
return x.MaxConnReceiveWindow
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetMaxIdleTimeout() int64 {
|
||||
if x != nil {
|
||||
return x.MaxIdleTimeout
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetKeepAlivePeriod() int64 {
|
||||
if x != nil {
|
||||
return x.KeepAlivePeriod
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetDisablePathMtuDiscovery() bool {
|
||||
if x != nil {
|
||||
return x.DisablePathMtuDiscovery
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *Config) GetMaxIncomingStreams() int64 {
|
||||
if x != nil {
|
||||
return x.MaxIncomingStreams
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetUdpIdleTimeout() int64 {
|
||||
if x != nil {
|
||||
return x.UdpIdleTimeout
|
||||
@@ -261,37 +149,21 @@ var File_transport_internet_hysteria_config_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_transport_internet_hysteria_config_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"(transport/internet/hysteria/config.proto\x12 xray.transport.internet.hysteria\"\xf0\b\n" +
|
||||
"(transport/internet/hysteria/config.proto\x12 xray.transport.internet.hysteria\"\xa3\x04\n" +
|
||||
"\x06Config\x12\x18\n" +
|
||||
"\aversion\x18\x01 \x01(\x05R\aversion\x12\x12\n" +
|
||||
"\x04auth\x18\x02 \x01(\tR\x04auth\x12\x1e\n" +
|
||||
"\n" +
|
||||
"congestion\x18\x03 \x01(\tR\n" +
|
||||
"congestion\x12\x0e\n" +
|
||||
"\x02up\x18\x04 \x01(\x04R\x02up\x12\x12\n" +
|
||||
"\x04down\x18\x05 \x01(\x04R\x04down\x12\x14\n" +
|
||||
"\x05ports\x18\x06 \x03(\rR\x05ports\x12!\n" +
|
||||
"\finterval_min\x18\a \x01(\x03R\vintervalMin\x12!\n" +
|
||||
"\finterval_max\x18\b \x01(\x03R\vintervalMax\x12;\n" +
|
||||
"\x1ainit_stream_receive_window\x18\t \x01(\x04R\x17initStreamReceiveWindow\x129\n" +
|
||||
"\x19max_stream_receive_window\x18\n" +
|
||||
" \x01(\x04R\x16maxStreamReceiveWindow\x127\n" +
|
||||
"\x18init_conn_receive_window\x18\v \x01(\x04R\x15initConnReceiveWindow\x125\n" +
|
||||
"\x17max_conn_receive_window\x18\f \x01(\x04R\x14maxConnReceiveWindow\x12(\n" +
|
||||
"\x10max_idle_timeout\x18\r \x01(\x03R\x0emaxIdleTimeout\x12*\n" +
|
||||
"\x11keep_alive_period\x18\x0e \x01(\x03R\x0fkeepAlivePeriod\x12;\n" +
|
||||
"\x1adisable_path_mtu_discovery\x18\x0f \x01(\bR\x17disablePathMtuDiscovery\x120\n" +
|
||||
"\x14max_incoming_streams\x18\x10 \x01(\x03R\x12maxIncomingStreams\x12(\n" +
|
||||
"\x10udp_idle_timeout\x18\x11 \x01(\x03R\x0eudpIdleTimeout\x12\x1b\n" +
|
||||
"\tmasq_type\x18\x12 \x01(\tR\bmasqType\x12\x1b\n" +
|
||||
"\tmasq_file\x18\x13 \x01(\tR\bmasqFile\x12\x19\n" +
|
||||
"\bmasq_url\x18\x14 \x01(\tR\amasqUrl\x121\n" +
|
||||
"\x15masq_url_rewrite_host\x18\x15 \x01(\bR\x12masqUrlRewriteHost\x12*\n" +
|
||||
"\x11masq_url_insecure\x18\x16 \x01(\bR\x0fmasqUrlInsecure\x12\x1f\n" +
|
||||
"\vmasq_string\x18\x17 \x01(\tR\n" +
|
||||
"\x04auth\x18\x02 \x01(\tR\x04auth\x12(\n" +
|
||||
"\x10udp_idle_timeout\x18\x03 \x01(\x03R\x0eudpIdleTimeout\x12\x1b\n" +
|
||||
"\tmasq_type\x18\x04 \x01(\tR\bmasqType\x12\x1b\n" +
|
||||
"\tmasq_file\x18\x05 \x01(\tR\bmasqFile\x12\x19\n" +
|
||||
"\bmasq_url\x18\x06 \x01(\tR\amasqUrl\x121\n" +
|
||||
"\x15masq_url_rewrite_host\x18\a \x01(\bR\x12masqUrlRewriteHost\x12*\n" +
|
||||
"\x11masq_url_insecure\x18\b \x01(\bR\x0fmasqUrlInsecure\x12\x1f\n" +
|
||||
"\vmasq_string\x18\t \x01(\tR\n" +
|
||||
"masqString\x12o\n" +
|
||||
"\x13masq_string_headers\x18\x18 \x03(\v2?.xray.transport.internet.hysteria.Config.MasqStringHeadersEntryR\x11masqStringHeaders\x125\n" +
|
||||
"\x17masq_string_status_code\x18\x19 \x01(\x05R\x14masqStringStatusCode\x1aD\n" +
|
||||
"\x13masq_string_headers\x18\n" +
|
||||
" \x03(\v2?.xray.transport.internet.hysteria.Config.MasqStringHeadersEntryR\x11masqStringHeaders\x125\n" +
|
||||
"\x17masq_string_status_code\x18\v \x01(\x05R\x14masqStringStatusCode\x1aD\n" +
|
||||
"\x16MasqStringHeadersEntry\x12\x10\n" +
|
||||
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
||||
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\x82\x01\n" +
|
||||
|
||||
@@ -9,29 +9,14 @@ option java_multiple_files = true;
|
||||
message Config {
|
||||
int32 version = 1;
|
||||
string auth = 2;
|
||||
string congestion = 3;
|
||||
uint64 up = 4;
|
||||
uint64 down = 5;
|
||||
repeated uint32 ports = 6;
|
||||
int64 interval_min = 7;
|
||||
int64 interval_max = 8;
|
||||
|
||||
uint64 init_stream_receive_window = 9;
|
||||
uint64 max_stream_receive_window = 10;
|
||||
uint64 init_conn_receive_window = 11;
|
||||
uint64 max_conn_receive_window = 12;
|
||||
int64 max_idle_timeout = 13;
|
||||
int64 keep_alive_period = 14;
|
||||
bool disable_path_mtu_discovery = 15;
|
||||
int64 max_incoming_streams = 16;
|
||||
|
||||
int64 udp_idle_timeout = 17;
|
||||
string masq_type = 18;
|
||||
string masq_file = 19;
|
||||
string masq_url = 20;
|
||||
bool masq_url_rewrite_host = 21;
|
||||
bool masq_url_insecure = 22;
|
||||
string masq_string = 23;
|
||||
map<string, string> masq_string_headers = 24;
|
||||
int32 masq_string_status_code = 25;
|
||||
int64 udp_idle_timeout = 3;
|
||||
string masq_type = 4;
|
||||
string masq_file = 5;
|
||||
string masq_url = 6;
|
||||
bool masq_url_rewrite_host = 7;
|
||||
bool masq_url_insecure = 8;
|
||||
string masq_string = 9;
|
||||
map<string, string> masq_string_headers = 10;
|
||||
int32 masq_string_status_code = 11;
|
||||
}
|
||||
@@ -120,8 +120,10 @@ type client struct {
|
||||
tlsConfig *go_tls.Config
|
||||
socketConfig *internet.SocketConfig
|
||||
udpmaskManager *finalmask.UdpmaskManager
|
||||
udpSM *udpSessionManagerClient
|
||||
mutex sync.Mutex
|
||||
quicParams *internet.QuicParams
|
||||
|
||||
udpSM *udpSessionManagerClient
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func (c *client) status() Status {
|
||||
@@ -153,10 +155,18 @@ func (c *client) dial() error {
|
||||
c.close()
|
||||
}
|
||||
|
||||
quicParams := c.quicParams
|
||||
if quicParams == nil {
|
||||
quicParams = &internet.QuicParams{}
|
||||
}
|
||||
if quicParams.UdpHop == nil {
|
||||
quicParams.UdpHop = &internet.UdpHop{}
|
||||
}
|
||||
|
||||
var index int
|
||||
if len(c.config.Ports) > 0 {
|
||||
index = rand.Intn(len(c.config.Ports))
|
||||
c.dest.Port = net.Port(c.config.Ports[index])
|
||||
if len(quicParams.UdpHop.Ports) > 0 {
|
||||
index = rand.Intn(len(quicParams.UdpHop.Ports))
|
||||
c.dest.Port = net.Port(quicParams.UdpHop.Ports[index])
|
||||
}
|
||||
|
||||
raw, err := internet.DialSystem(c.ctx, c.dest, c.socketConfig)
|
||||
@@ -179,7 +189,7 @@ func (c *client) dial() error {
|
||||
pktConn = fakeConn
|
||||
remote = fakeConn.RemoteAddr().(*net.UDPAddr)
|
||||
|
||||
if len(c.config.Ports) > 0 {
|
||||
if len(quicParams.UdpHop.Ports) > 0 {
|
||||
raw.Close()
|
||||
return errors.New("udphop requires being at the outermost level")
|
||||
}
|
||||
@@ -188,12 +198,12 @@ func (c *client) dial() error {
|
||||
return errors.New("unknown conn ", reflect.TypeOf(conn))
|
||||
}
|
||||
|
||||
if len(c.config.Ports) > 0 {
|
||||
if len(quicParams.UdpHop.Ports) > 0 {
|
||||
addr := &udphop.UDPHopAddr{
|
||||
IP: remote.IP,
|
||||
Ports: c.config.Ports,
|
||||
Ports: quicParams.UdpHop.Ports,
|
||||
}
|
||||
pktConn, err = udphop.NewUDPHopPacketConn(addr, c.config.IntervalMin, c.config.IntervalMax, c.udphopDialer, pktConn, index)
|
||||
pktConn, err = udphop.NewUDPHopPacketConn(addr, index, quicParams.UdpHop.IntervalMin, quicParams.UdpHop.IntervalMax, c.udphopDialer, pktConn)
|
||||
if err != nil {
|
||||
raw.Close()
|
||||
return errors.New("udphop err").Base(err)
|
||||
@@ -208,21 +218,41 @@ func (c *client) dial() error {
|
||||
}
|
||||
}
|
||||
|
||||
quicConfig := &quic.Config{
|
||||
InitialStreamReceiveWindow: quicParams.InitStreamReceiveWindow,
|
||||
MaxStreamReceiveWindow: quicParams.MaxStreamReceiveWindow,
|
||||
InitialConnectionReceiveWindow: quicParams.InitConnReceiveWindow,
|
||||
MaxConnectionReceiveWindow: quicParams.MaxConnReceiveWindow,
|
||||
MaxIdleTimeout: time.Duration(quicParams.MaxIdleTimeout) * time.Second,
|
||||
KeepAlivePeriod: time.Duration(quicParams.KeepAlivePeriod) * time.Second,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery,
|
||||
EnableDatagrams: true,
|
||||
MaxDatagramFrameSize: MaxDatagramFrameSize,
|
||||
DisablePathManager: true,
|
||||
}
|
||||
if quicParams.InitStreamReceiveWindow == 0 {
|
||||
quicConfig.InitialStreamReceiveWindow = 8388608
|
||||
}
|
||||
if quicParams.MaxStreamReceiveWindow == 0 {
|
||||
quicConfig.MaxStreamReceiveWindow = 8388608
|
||||
}
|
||||
if quicParams.InitConnReceiveWindow == 0 {
|
||||
quicConfig.InitialConnectionReceiveWindow = 8388608 * 5 / 2
|
||||
}
|
||||
if quicParams.MaxConnReceiveWindow == 0 {
|
||||
quicConfig.MaxConnectionReceiveWindow = 8388608 * 5 / 2
|
||||
}
|
||||
if quicParams.MaxIdleTimeout == 0 {
|
||||
quicConfig.MaxIdleTimeout = 30 * time.Second
|
||||
}
|
||||
// if quicParams.KeepAlivePeriod == 0 {
|
||||
// quicConfig.KeepAlivePeriod = 10 * time.Second
|
||||
// }
|
||||
|
||||
var quicConn *quic.Conn
|
||||
rt := &http3.Transport{
|
||||
TLSClientConfig: c.tlsConfig,
|
||||
QUICConfig: &quic.Config{
|
||||
InitialStreamReceiveWindow: c.config.InitStreamReceiveWindow,
|
||||
MaxStreamReceiveWindow: c.config.MaxStreamReceiveWindow,
|
||||
InitialConnectionReceiveWindow: c.config.InitConnReceiveWindow,
|
||||
MaxConnectionReceiveWindow: c.config.MaxConnReceiveWindow,
|
||||
MaxIdleTimeout: time.Duration(c.config.MaxIdleTimeout) * time.Second,
|
||||
KeepAlivePeriod: time.Duration(c.config.KeepAlivePeriod) * time.Second,
|
||||
DisablePathMTUDiscovery: c.config.DisablePathMtuDiscovery,
|
||||
EnableDatagrams: true,
|
||||
MaxDatagramFrameSize: MaxDatagramFrameSize,
|
||||
DisablePathManager: true,
|
||||
},
|
||||
QUICConfig: quicConfig,
|
||||
Dial: func(ctx context.Context, _ string, tlsCfg *go_tls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
||||
qc, err := quic.DialEarly(ctx, pktConn, remote, tlsCfg, cfg)
|
||||
if err != nil {
|
||||
@@ -241,7 +271,7 @@ func (c *client) dial() error {
|
||||
},
|
||||
Header: http.Header{
|
||||
RequestHeaderAuth: []string{c.config.Auth},
|
||||
CommonHeaderCCRX: []string{strconv.FormatUint(c.config.Down, 10)},
|
||||
CommonHeaderCCRX: []string{strconv.FormatUint(quicParams.BrutalDown, 10)},
|
||||
CommonHeaderPadding: []string{authRequestPadding.String()},
|
||||
},
|
||||
}
|
||||
@@ -264,23 +294,23 @@ func (c *client) dial() error {
|
||||
serverAuto := resp.Header.Get(CommonHeaderCCRX)
|
||||
serverDown, _ := strconv.ParseUint(serverAuto, 10, 64)
|
||||
|
||||
switch c.config.Congestion {
|
||||
switch quicParams.Congestion {
|
||||
case "reno":
|
||||
errors.LogDebug(c.ctx, "congestion reno")
|
||||
case "bbr":
|
||||
errors.LogDebug(c.ctx, "congestion bbr")
|
||||
congestion.UseBBR(quicConn)
|
||||
case "brutal", "":
|
||||
if serverAuto == "auto" || c.config.Up == 0 || serverDown == 0 {
|
||||
if serverAuto == "auto" || quicParams.BrutalUp == 0 || serverDown == 0 {
|
||||
errors.LogDebug(c.ctx, "congestion bbr")
|
||||
congestion.UseBBR(quicConn)
|
||||
} else {
|
||||
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", min(c.config.Up, serverDown))
|
||||
congestion.UseBrutal(quicConn, min(c.config.Up, serverDown))
|
||||
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", min(quicParams.BrutalUp, serverDown))
|
||||
congestion.UseBrutal(quicConn, min(quicParams.BrutalUp, serverDown))
|
||||
}
|
||||
case "force-brutal":
|
||||
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", c.config.Up)
|
||||
congestion.UseBrutal(quicConn, c.config.Up)
|
||||
errors.LogDebug(c.ctx, "congestion brutal bytes per second ", quicParams.BrutalUp)
|
||||
congestion.UseBrutal(quicConn, quicParams.BrutalUp)
|
||||
default:
|
||||
errors.LogDebug(c.ctx, "congestion reno")
|
||||
}
|
||||
@@ -359,13 +389,14 @@ func (c *client) udphopDialer(addr *net.UDPAddr) (net.PacketConn, error) {
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
if c.status() != StatusActive {
|
||||
errors.LogDebug(c.ctx, "skip hop: disconnected QUIC")
|
||||
errors.LogDebug(context.Background(), "skip hop: disconnected QUIC")
|
||||
return nil, errors.New()
|
||||
}
|
||||
|
||||
raw, err := internet.DialSystem(c.ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), c.socketConfig)
|
||||
if err != nil {
|
||||
errors.LogDebug(c.ctx, "skip hop: failed to dial to dest")
|
||||
errors.LogDebug(context.Background(), "skip hop: failed to dial to dest")
|
||||
raw.Close()
|
||||
return nil, errors.New()
|
||||
}
|
||||
|
||||
@@ -377,10 +408,12 @@ func (c *client) udphopDialer(addr *net.UDPAddr) (net.PacketConn, error) {
|
||||
case *net.UDPConn:
|
||||
pktConn = conn
|
||||
case *cnc.Connection:
|
||||
errors.LogDebug(c.ctx, "skip hop: udphop requires being at the outermost level")
|
||||
errors.LogDebug(context.Background(), "skip hop: udphop requires being at the outermost level")
|
||||
raw.Close()
|
||||
return nil, errors.New()
|
||||
default:
|
||||
errors.LogDebug(c.ctx, "skip hop: unknown conn ", reflect.TypeOf(conn))
|
||||
errors.LogDebug(context.Background(), "skip hop: unknown conn ", reflect.TypeOf(conn))
|
||||
raw.Close()
|
||||
return nil, errors.New()
|
||||
}
|
||||
|
||||
@@ -424,6 +457,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
||||
tlsConfig: tlsConfig.GetTLSConfig(),
|
||||
socketConfig: streamSettings.SocketSettings,
|
||||
udpmaskManager: streamSettings.UdpmaskManager,
|
||||
quicParams: streamSettings.QuicParams,
|
||||
}
|
||||
manger.m[addr] = c
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ type httpHandler struct {
|
||||
addConn internet.ConnHandler
|
||||
|
||||
config *Config
|
||||
quicParams *internet.QuicParams
|
||||
validator *account.Validator
|
||||
masqHandler http.Handler
|
||||
|
||||
@@ -155,7 +156,7 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if h.auth {
|
||||
w.Header().Set(ResponseHeaderUDPEnabled, strconv.FormatBool(hyCtx.RequireDatagramFromContext(h.ctx)))
|
||||
w.Header().Set(CommonHeaderCCRX, strconv.FormatUint(h.config.Down, 10))
|
||||
w.Header().Set(CommonHeaderCCRX, strconv.FormatUint(h.quicParams.BrutalDown, 10))
|
||||
w.Header().Set(CommonHeaderPadding, authResponsePadding.String())
|
||||
w.WriteHeader(StatusAuthOK)
|
||||
return
|
||||
@@ -176,23 +177,23 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.auth = true
|
||||
h.user = user
|
||||
|
||||
switch h.config.Congestion {
|
||||
switch h.quicParams.Congestion {
|
||||
case "reno":
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion reno")
|
||||
case "bbr":
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion bbr")
|
||||
congestion.UseBBR(h.conn)
|
||||
case "brutal", "":
|
||||
if h.config.Up == 0 || clientDown == 0 {
|
||||
if h.quicParams.BrutalUp == 0 || clientDown == 0 {
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion bbr")
|
||||
congestion.UseBBR(h.conn)
|
||||
} else {
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion brutal bytes per second ", min(h.config.Up, clientDown))
|
||||
congestion.UseBrutal(h.conn, min(h.config.Up, clientDown))
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion brutal bytes per second ", min(h.quicParams.BrutalUp, clientDown))
|
||||
congestion.UseBrutal(h.conn, min(h.quicParams.BrutalUp, clientDown))
|
||||
}
|
||||
case "force-brutal":
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion brutal bytes per second ", h.config.Up)
|
||||
congestion.UseBrutal(h.conn, h.config.Up)
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion brutal bytes per second ", h.quicParams.BrutalUp)
|
||||
congestion.UseBrutal(h.conn, h.quicParams.BrutalUp)
|
||||
default:
|
||||
errors.LogDebug(context.Background(), h.conn.RemoteAddr(), " ", "congestion reno")
|
||||
}
|
||||
@@ -212,7 +213,7 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
w.Header().Set(ResponseHeaderUDPEnabled, strconv.FormatBool(hyCtx.RequireDatagramFromContext(h.ctx)))
|
||||
w.Header().Set(CommonHeaderCCRX, strconv.FormatUint(h.config.Down, 10))
|
||||
w.Header().Set(CommonHeaderCCRX, strconv.FormatUint(h.quicParams.BrutalDown, 10))
|
||||
w.Header().Set(CommonHeaderPadding, authResponsePadding.String())
|
||||
w.WriteHeader(StatusAuthOK)
|
||||
return
|
||||
@@ -253,6 +254,7 @@ type Listener struct {
|
||||
addConn internet.ConnHandler
|
||||
|
||||
config *Config
|
||||
quicParams *internet.QuicParams
|
||||
validator *account.Validator
|
||||
masqHandler http.Handler
|
||||
}
|
||||
@@ -264,6 +266,7 @@ func (l *Listener) handleClient(conn *quic.Conn) {
|
||||
addConn: l.addConn,
|
||||
|
||||
config: l.config,
|
||||
quicParams: l.quicParams,
|
||||
validator: l.validator,
|
||||
masqHandler: l.masqHandler,
|
||||
}
|
||||
@@ -272,8 +275,8 @@ func (l *Listener) handleClient(conn *quic.Conn) {
|
||||
StreamDispatcher: handler.StreamDispatcher,
|
||||
}
|
||||
err := h3.ServeQUICConn(conn)
|
||||
errors.LogDebug(context.Background(), conn.RemoteAddr(), " disconnected with err ", err)
|
||||
_ = conn.CloseWithError(closeErrCodeOK, "")
|
||||
errors.LogDebug(context.Background(), conn.RemoteAddr(), " disconnected with err ", err)
|
||||
}
|
||||
|
||||
func (l *Listener) keepAccepting() {
|
||||
@@ -377,18 +380,41 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
||||
}
|
||||
}
|
||||
|
||||
quicParams := streamSettings.QuicParams
|
||||
if quicParams == nil {
|
||||
quicParams = &internet.QuicParams{}
|
||||
}
|
||||
|
||||
quicConfig := &quic.Config{
|
||||
InitialStreamReceiveWindow: config.InitStreamReceiveWindow,
|
||||
MaxStreamReceiveWindow: config.MaxStreamReceiveWindow,
|
||||
InitialConnectionReceiveWindow: config.InitConnReceiveWindow,
|
||||
MaxConnectionReceiveWindow: config.MaxConnReceiveWindow,
|
||||
MaxIdleTimeout: time.Duration(config.MaxIdleTimeout) * time.Second,
|
||||
MaxIncomingStreams: config.MaxIncomingStreams,
|
||||
DisablePathMTUDiscovery: config.DisablePathMtuDiscovery,
|
||||
InitialStreamReceiveWindow: quicParams.InitStreamReceiveWindow,
|
||||
MaxStreamReceiveWindow: quicParams.MaxStreamReceiveWindow,
|
||||
InitialConnectionReceiveWindow: quicParams.InitConnReceiveWindow,
|
||||
MaxConnectionReceiveWindow: quicParams.MaxConnReceiveWindow,
|
||||
MaxIdleTimeout: time.Duration(quicParams.MaxIdleTimeout) * time.Second,
|
||||
MaxIncomingStreams: quicParams.MaxIncomingStreams,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery,
|
||||
EnableDatagrams: true,
|
||||
MaxDatagramFrameSize: MaxDatagramFrameSize,
|
||||
DisablePathManager: true,
|
||||
}
|
||||
if quicParams.InitStreamReceiveWindow == 0 {
|
||||
quicConfig.InitialStreamReceiveWindow = 8388608
|
||||
}
|
||||
if quicParams.MaxStreamReceiveWindow == 0 {
|
||||
quicConfig.MaxStreamReceiveWindow = 8388608
|
||||
}
|
||||
if quicParams.InitConnReceiveWindow == 0 {
|
||||
quicConfig.InitialConnectionReceiveWindow = 8388608 * 5 / 2
|
||||
}
|
||||
if quicParams.MaxConnReceiveWindow == 0 {
|
||||
quicConfig.MaxConnectionReceiveWindow = 8388608 * 5 / 2
|
||||
}
|
||||
if quicParams.MaxIdleTimeout == 0 {
|
||||
quicConfig.MaxIdleTimeout = 30 * time.Second
|
||||
}
|
||||
if quicParams.MaxIncomingStreams == 0 {
|
||||
quicConfig.MaxIncomingStreams = 1024
|
||||
}
|
||||
|
||||
qListener, err := quic.Listen(pktConn, tlsConfig.GetTLSConfig(), quicConfig)
|
||||
if err != nil {
|
||||
@@ -403,6 +429,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
||||
addConn: handler,
|
||||
|
||||
config: config,
|
||||
quicParams: quicParams,
|
||||
validator: validator,
|
||||
masqHandler: masqHandler,
|
||||
}
|
||||
|
||||
@@ -9,11 +9,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common/crypto"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||
)
|
||||
|
||||
const (
|
||||
packetQueueSize = 1024
|
||||
udpBufferSize = 2048 // QUIC packets are at most 1500 bytes long, so 2k should be more than enough
|
||||
udpBufferSize = finalmask.UDPSize
|
||||
|
||||
defaultHopInterval = 30 * time.Second
|
||||
)
|
||||
@@ -49,7 +50,7 @@ type udpPacket struct {
|
||||
|
||||
type ListenUDPFunc = func(*net.UDPAddr) (net.PacketConn, error)
|
||||
|
||||
func NewUDPHopPacketConn(addr *UDPHopAddr, intervalMin int64, intervalMax int64, listenUDPFunc ListenUDPFunc, pktConn net.PacketConn, index int) (net.PacketConn, error) {
|
||||
func NewUDPHopPacketConn(addr *UDPHopAddr, index int, intervalMin int64, intervalMax int64, listenUDPFunc ListenUDPFunc, pktConn net.PacketConn) (net.PacketConn, error) {
|
||||
if intervalMin == 0 || intervalMax == 0 {
|
||||
intervalMin = int64(defaultHopInterval)
|
||||
intervalMax = int64(defaultHopInterval)
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PortUnion is a collection of multiple port ranges.
|
||||
type PortUnion []PortRange
|
||||
|
||||
// PortRange represents a range of ports.
|
||||
// Start and End are inclusive. [Start, End]
|
||||
type PortRange struct {
|
||||
Start, End uint16
|
||||
}
|
||||
|
||||
// ParsePortUnion parses a string of comma-separated port ranges (or single ports) into a PortUnion.
|
||||
// Returns nil if the input is invalid.
|
||||
// The returned PortUnion is guaranteed to be normalized.
|
||||
func ParsePortUnion(s string) PortUnion {
|
||||
if s == "all" || s == "*" {
|
||||
// Wildcard special case
|
||||
return PortUnion{PortRange{0, 65535}}
|
||||
}
|
||||
var result PortUnion
|
||||
portStrs := strings.Split(s, ",")
|
||||
for _, portStr := range portStrs {
|
||||
if strings.Contains(portStr, "-") {
|
||||
// Port range
|
||||
portRange := strings.Split(portStr, "-")
|
||||
if len(portRange) != 2 {
|
||||
return nil
|
||||
}
|
||||
start, err := strconv.ParseUint(portRange[0], 10, 16)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
end, err := strconv.ParseUint(portRange[1], 10, 16)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if start > end {
|
||||
start, end = end, start
|
||||
}
|
||||
result = append(result, PortRange{uint16(start), uint16(end)})
|
||||
} else {
|
||||
// Single port
|
||||
port, err := strconv.ParseUint(portStr, 10, 16)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
result = append(result, PortRange{uint16(port), uint16(port)})
|
||||
}
|
||||
}
|
||||
if result == nil {
|
||||
return nil
|
||||
}
|
||||
return result.Normalize()
|
||||
}
|
||||
|
||||
// Normalize normalizes a PortUnion.
|
||||
// No overlapping ranges, ranges are sorted from low to high.
|
||||
func (u PortUnion) Normalize() PortUnion {
|
||||
if len(u) == 0 {
|
||||
return u
|
||||
}
|
||||
sort.Slice(u, func(i, j int) bool {
|
||||
if u[i].Start == u[j].Start {
|
||||
return u[i].End < u[j].End
|
||||
}
|
||||
return u[i].Start < u[j].Start
|
||||
})
|
||||
normalized := PortUnion{u[0]}
|
||||
for _, current := range u[1:] {
|
||||
last := &normalized[len(normalized)-1]
|
||||
if uint32(current.Start) <= uint32(last.End)+1 {
|
||||
if current.End > last.End {
|
||||
last.End = current.End
|
||||
}
|
||||
} else {
|
||||
normalized = append(normalized, current)
|
||||
}
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
// Ports returns all ports in the PortUnion as a slice.
|
||||
func (u PortUnion) Ports() []uint16 {
|
||||
var ports []uint16
|
||||
for _, r := range u {
|
||||
for i := uint32(r.Start); i <= uint32(r.End); i++ {
|
||||
ports = append(ports, uint16(i))
|
||||
}
|
||||
}
|
||||
return ports
|
||||
}
|
||||
|
||||
// Contains returns true if the PortUnion contains the given port.
|
||||
func (u PortUnion) Contains(port uint16) bool {
|
||||
for _, r := range u {
|
||||
if port >= r.Start && port <= r.End {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParsePortUnion(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
s string
|
||||
want PortUnion
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
s: "",
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "all 1",
|
||||
s: "all",
|
||||
want: PortUnion{{0, 65535}},
|
||||
},
|
||||
{
|
||||
name: "all 2",
|
||||
s: "*",
|
||||
want: PortUnion{{0, 65535}},
|
||||
},
|
||||
{
|
||||
name: "single port",
|
||||
s: "1234",
|
||||
want: PortUnion{{1234, 1234}},
|
||||
},
|
||||
{
|
||||
name: "multiple ports (unsorted)",
|
||||
s: "5678,1234,9012",
|
||||
want: PortUnion{{1234, 1234}, {5678, 5678}, {9012, 9012}},
|
||||
},
|
||||
{
|
||||
name: "one range",
|
||||
s: "1234-1240",
|
||||
want: PortUnion{{1234, 1240}},
|
||||
},
|
||||
{
|
||||
name: "one range (reversed)",
|
||||
s: "1240-1234",
|
||||
want: PortUnion{{1234, 1240}},
|
||||
},
|
||||
{
|
||||
name: "multiple ports and ranges (reversed, unsorted, overlapping)",
|
||||
s: "5678,1200-1236,9100-9012,1234-1240",
|
||||
want: PortUnion{{1200, 1240}, {5678, 5678}, {9012, 9100}},
|
||||
},
|
||||
{
|
||||
name: "multiple ports and ranges with 65535 (reversed, unsorted, overlapping)",
|
||||
s: "5678,1200-1236,65531-65535,65532-65534,9100-9012,1234-1240",
|
||||
want: PortUnion{{1200, 1240}, {5678, 5678}, {9012, 9100}, {65531, 65535}},
|
||||
},
|
||||
{
|
||||
name: "multiple ports and ranges with 65535 (reversed, unsorted, overlapping) 2",
|
||||
s: "5678,1200-1236,65532-65535,65531-65534,9100-9012,1234-1240",
|
||||
want: PortUnion{{1200, 1240}, {5678, 5678}, {9012, 9100}, {65531, 65535}},
|
||||
},
|
||||
{
|
||||
name: "invalid 1",
|
||||
s: "1234-",
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "invalid 2",
|
||||
s: "1234-ggez",
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "invalid 3",
|
||||
s: "233,",
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "invalid 4",
|
||||
s: "1234-1240-1250",
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "invalid 5",
|
||||
s: "-,,",
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "invalid 6",
|
||||
s: "http",
|
||||
want: nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := ParsePortUnion(tt.s); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ParsePortUnion() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPortUnion_Ports(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pu PortUnion
|
||||
want []uint16
|
||||
}{
|
||||
{
|
||||
name: "single port",
|
||||
pu: PortUnion{{1234, 1234}},
|
||||
want: []uint16{1234},
|
||||
},
|
||||
{
|
||||
name: "multiple ports",
|
||||
pu: PortUnion{{1234, 1236}},
|
||||
want: []uint16{1234, 1235, 1236},
|
||||
},
|
||||
{
|
||||
name: "multiple ports and ranges",
|
||||
pu: PortUnion{{1234, 1236}, {5678, 5680}, {9000, 9002}},
|
||||
want: []uint16{1234, 1235, 1236, 5678, 5679, 5680, 9000, 9001, 9002},
|
||||
},
|
||||
{
|
||||
name: "single port 65535",
|
||||
pu: PortUnion{{65535, 65535}},
|
||||
want: []uint16{65535},
|
||||
},
|
||||
{
|
||||
name: "port range with 65535",
|
||||
pu: PortUnion{{65530, 65535}},
|
||||
want: []uint16{65530, 65531, 65532, 65533, 65534, 65535},
|
||||
},
|
||||
{
|
||||
name: "multiple ports and ranges with 65535",
|
||||
pu: PortUnion{{65530, 65535}, {1234, 1236}},
|
||||
want: []uint16{65530, 65531, 65532, 65533, 65534, 65535, 1234, 1235, 1236},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.pu.Ports(); !slices.Equal(got, tt.want) {
|
||||
t.Errorf("PortUnion.Ports() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,11 @@ import (
|
||||
gotls "crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/http/httptrace"
|
||||
"net/url"
|
||||
reflect "reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -24,6 +26,7 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/browser_dialer"
|
||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
@@ -153,25 +156,73 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
||||
var transport http.RoundTripper
|
||||
|
||||
if httpVersion == "3" {
|
||||
if keepAlivePeriod == 0 {
|
||||
keepAlivePeriod = net.QuicgoH3KeepAlivePeriod
|
||||
quicParams := streamSettings.QuicParams
|
||||
if quicParams == nil {
|
||||
quicParams = &internet.QuicParams{}
|
||||
}
|
||||
if keepAlivePeriod < 0 {
|
||||
keepAlivePeriod = 0
|
||||
if quicParams.UdpHop == nil {
|
||||
quicParams.UdpHop = &internet.UdpHop{}
|
||||
}
|
||||
quicConfig := &quic.Config{
|
||||
MaxIdleTimeout: net.ConnIdleTimeout,
|
||||
|
||||
quicConfig := &quic.Config{
|
||||
InitialStreamReceiveWindow: quicParams.InitStreamReceiveWindow,
|
||||
MaxStreamReceiveWindow: quicParams.MaxStreamReceiveWindow,
|
||||
InitialConnectionReceiveWindow: quicParams.InitConnReceiveWindow,
|
||||
MaxConnectionReceiveWindow: quicParams.MaxConnReceiveWindow,
|
||||
MaxIdleTimeout: time.Duration(quicParams.MaxIdleTimeout) * time.Second,
|
||||
KeepAlivePeriod: time.Duration(quicParams.KeepAlivePeriod) * time.Second,
|
||||
MaxIncomingStreams: quicParams.MaxIncomingStreams,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery,
|
||||
}
|
||||
if quicParams.MaxIdleTimeout == 0 {
|
||||
quicConfig.MaxIdleTimeout = net.ConnIdleTimeout
|
||||
}
|
||||
if quicParams.KeepAlivePeriod == 0 {
|
||||
if keepAlivePeriod == 0 {
|
||||
quicConfig.KeepAlivePeriod = net.QuicgoH3KeepAlivePeriod
|
||||
}
|
||||
}
|
||||
if quicParams.MaxIncomingStreams == 0 {
|
||||
// these two are defaults of quic-go/http3. the default of quic-go (no
|
||||
// http3) is different, so it is hardcoded here for clarity.
|
||||
// https://github.com/quic-go/quic-go/blob/b8ea5c798155950fb5bbfdd06cad1939c9355878/http3/client.go#L36-L39
|
||||
MaxIncomingStreams: -1,
|
||||
KeepAlivePeriod: keepAlivePeriod,
|
||||
quicConfig.MaxIncomingStreams = -1
|
||||
}
|
||||
|
||||
transport = &http3.Transport{
|
||||
QUICConfig: quicConfig,
|
||||
TLSClientConfig: gotlsConfig,
|
||||
Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
||||
udphopDialer := func(addr *net.UDPAddr) (net.PacketConn, error) {
|
||||
conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
errors.LogDebug(context.Background(), "skip hop: failed to dial to dest")
|
||||
conn.Close()
|
||||
return nil, errors.New()
|
||||
}
|
||||
|
||||
var udpConn net.PacketConn
|
||||
|
||||
switch c := conn.(type) {
|
||||
case *internet.PacketConnWrapper:
|
||||
udpConn = c.PacketConn
|
||||
case *net.UDPConn:
|
||||
udpConn = c
|
||||
default:
|
||||
errors.LogDebug(context.Background(), "skip hop: udphop requires being at the outermost level ", reflect.TypeOf(c))
|
||||
conn.Close()
|
||||
return nil, errors.New()
|
||||
}
|
||||
|
||||
return udpConn, nil
|
||||
}
|
||||
|
||||
var index int
|
||||
if len(quicParams.UdpHop.Ports) > 0 {
|
||||
index = rand.Intn(len(quicParams.UdpHop.Ports))
|
||||
dest.Port = net.Port(quicParams.UdpHop.Ports[index])
|
||||
}
|
||||
|
||||
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -182,54 +233,69 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
||||
|
||||
switch c := conn.(type) {
|
||||
case *internet.PacketConnWrapper:
|
||||
var ok bool
|
||||
udpConn, ok = c.PacketConn.(*net.UDPConn)
|
||||
if !ok {
|
||||
return nil, errors.New("PacketConnWrapper does not contain a UDP connection")
|
||||
}
|
||||
udpConn = c.PacketConn
|
||||
udpAddr, err = net.ResolveUDPAddr("udp", c.Dest.String())
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
case *net.UDPConn:
|
||||
udpConn = c
|
||||
udpAddr, err = net.ResolveUDPAddr("udp", c.RemoteAddr().String())
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
udpConn = &internet.FakePacketConn{Conn: c}
|
||||
udpAddr, err = net.ResolveUDPAddr("udp", c.RemoteAddr().String())
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(quicParams.UdpHop.Ports) > 0 {
|
||||
conn.Close()
|
||||
return nil, errors.New("udphop requires being at the outermost level ", reflect.TypeOf(c))
|
||||
}
|
||||
}
|
||||
|
||||
if len(quicParams.UdpHop.Ports) > 0 {
|
||||
addr := &udphop.UDPHopAddr{
|
||||
IP: udpAddr.IP,
|
||||
Ports: quicParams.UdpHop.Ports,
|
||||
}
|
||||
udpConn, err = udphop.NewUDPHopPacketConn(addr, index, quicParams.UdpHop.IntervalMin, quicParams.UdpHop.IntervalMax, udphopDialer, udpConn)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, errors.New("udphop err").Base(err)
|
||||
}
|
||||
}
|
||||
|
||||
if streamSettings.UdpmaskManager != nil {
|
||||
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(udpConn)
|
||||
udpConn, err = streamSettings.UdpmaskManager.WrapPacketConnClient(udpConn)
|
||||
if err != nil {
|
||||
udpConn.Close()
|
||||
conn.Close()
|
||||
return nil, errors.New("mask err").Base(err)
|
||||
}
|
||||
udpConn = pktConn
|
||||
}
|
||||
|
||||
quicConn, err := quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if streamSettings.QuicParams != nil {
|
||||
switch streamSettings.QuicParams.Congestion {
|
||||
case "force-brutal":
|
||||
congestion.UseBrutal(quicConn, streamSettings.QuicParams.Up)
|
||||
case "reno":
|
||||
// quic-go default, do nothing
|
||||
default:
|
||||
congestion.UseBBR(quicConn)
|
||||
}
|
||||
} else {
|
||||
|
||||
switch quicParams.Congestion {
|
||||
case "force-brutal":
|
||||
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion brutal bytes per second ", quicParams.BrutalUp)
|
||||
congestion.UseBrutal(quicConn, quicParams.BrutalUp)
|
||||
case "reno":
|
||||
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion reno")
|
||||
default:
|
||||
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion bbr")
|
||||
congestion.UseBBR(quicConn)
|
||||
}
|
||||
|
||||
return quicConn, nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ import (
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||
http_proto "github.com/xtls/xray-core/common/protocol/http"
|
||||
"github.com/xtls/xray-core/common/signal/done"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
@@ -254,7 +254,7 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
|
||||
dataPlacement := h.config.GetNormalizedUplinkDataPlacement()
|
||||
var headerPayload []byte
|
||||
if dataPlacement == PlacementAuto || dataPlacement == PlacementHeader {
|
||||
var headerPayloadChunks [] string
|
||||
var headerPayloadChunks []string
|
||||
for i := 0; true; i++ {
|
||||
chunk := request.Header.Get(fmt.Sprintf("%s-%d", uplinkDataKey, i))
|
||||
if chunk == "" {
|
||||
@@ -463,7 +463,6 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to listen UDP for XHTTP/3 on ", address, ":", port).Base(err)
|
||||
}
|
||||
|
||||
if streamSettings.UdpmaskManager != nil {
|
||||
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnServer(Conn)
|
||||
if err != nil {
|
||||
@@ -473,7 +472,22 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
||||
Conn = pktConn
|
||||
}
|
||||
|
||||
l.h3listener, err = quic.ListenEarly(Conn, tlsConfig, nil)
|
||||
quicParams := streamSettings.QuicParams
|
||||
if quicParams == nil {
|
||||
quicParams = &internet.QuicParams{}
|
||||
}
|
||||
|
||||
quicConfig := &quic.Config{
|
||||
InitialStreamReceiveWindow: quicParams.InitStreamReceiveWindow,
|
||||
MaxStreamReceiveWindow: quicParams.MaxStreamReceiveWindow,
|
||||
InitialConnectionReceiveWindow: quicParams.InitConnReceiveWindow,
|
||||
MaxConnectionReceiveWindow: quicParams.MaxConnReceiveWindow,
|
||||
MaxIdleTimeout: time.Duration(quicParams.MaxIdleTimeout) * time.Second,
|
||||
MaxIncomingStreams: quicParams.MaxIncomingStreams,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery,
|
||||
}
|
||||
|
||||
l.h3listener, err = quic.ListenEarly(Conn, tlsConfig, quicConfig)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to listen QUIC for XHTTP/3 on ", address, ":", port).Base(err)
|
||||
}
|
||||
@@ -491,22 +505,23 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
||||
errors.LogInfoInner(ctx, err, "XHTTP/3 listener closed")
|
||||
return
|
||||
}
|
||||
if streamSettings.QuicParams != nil {
|
||||
switch streamSettings.QuicParams.Congestion {
|
||||
case "force-brutal":
|
||||
congestion.UseBrutal(conn, streamSettings.QuicParams.Up)
|
||||
case "reno":
|
||||
// quic-go default, do nothing
|
||||
default:
|
||||
congestion.UseBBR(conn)
|
||||
}
|
||||
} else {
|
||||
|
||||
switch quicParams.Congestion {
|
||||
case "force-brutal":
|
||||
errors.LogDebug(context.Background(), conn.RemoteAddr(), " ", "congestion brutal bytes per second ", quicParams.BrutalUp)
|
||||
congestion.UseBrutal(conn, quicParams.BrutalUp)
|
||||
case "reno":
|
||||
errors.LogDebug(context.Background(), conn.RemoteAddr(), " ", "congestion reno")
|
||||
default:
|
||||
errors.LogDebug(context.Background(), conn.RemoteAddr(), " ", "congestion bbr")
|
||||
congestion.UseBBR(conn)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := l.h3server.ServeQUICConn(conn); err != nil {
|
||||
errors.LogDebugInner(ctx, err, "XHTTP/3 connection ended")
|
||||
}
|
||||
_ = conn.CloseWithError(0, "")
|
||||
}()
|
||||
}
|
||||
}()
|
||||
@@ -573,6 +588,7 @@ func (ln *Listener) Addr() net.Addr {
|
||||
func (ln *Listener) Close() error {
|
||||
if ln.h3server != nil {
|
||||
if err := ln.h3server.Close(); err != nil {
|
||||
_ = ln.h3listener.Close()
|
||||
return err
|
||||
}
|
||||
return ln.h3listener.Close()
|
||||
|
||||
Reference in New Issue
Block a user