mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-07-04 02:38:42 +00:00
Hysteria: Upgrade to official v2.8.2 (#6041)
https://github.com/XTLS/Xray-core/pull/6041#issuecomment-4357417742 And fixes https://github.com/XTLS/Xray-core/issues/6039
This commit is contained in:
@@ -5,11 +5,11 @@ import (
|
||||
gotls "crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/http/httptrace"
|
||||
"net/url"
|
||||
reflect "reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/net/cnc"
|
||||
"github.com/xtls/xray-core/common/signal/done"
|
||||
"github.com/xtls/xray-core/common/uuid"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
@@ -173,7 +174,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
||||
MaxIdleTimeout: time.Duration(quicParams.MaxIdleTimeout) * time.Second,
|
||||
KeepAlivePeriod: time.Duration(quicParams.KeepAlivePeriod) * time.Second,
|
||||
MaxIncomingStreams: quicParams.MaxIncomingStreams,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery || (runtime.GOOS != "linux" && runtime.GOOS != "windows" && runtime.GOOS != "darwin"),
|
||||
}
|
||||
if quicParams.MaxIdleTimeout == 0 {
|
||||
quicConfig.MaxIdleTimeout = net.ConnIdleTimeout
|
||||
@@ -194,110 +195,83 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
||||
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) {
|
||||
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()
|
||||
errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest")
|
||||
return nil, errors.New("failed to dial to dest").Base(err)
|
||||
}
|
||||
|
||||
var udpConn net.PacketConn
|
||||
var pktConn net.PacketConn
|
||||
|
||||
switch c := conn.(type) {
|
||||
case *internet.PacketConnWrapper:
|
||||
udpConn = c.PacketConn
|
||||
pktConn = c.PacketConn
|
||||
case *net.UDPConn:
|
||||
udpConn = c
|
||||
pktConn = c
|
||||
default:
|
||||
errors.LogDebug(context.Background(), "skip hop: udphop requires being at the outermost level ", reflect.TypeOf(c))
|
||||
errors.LogInfo(context.Background(), "skip hop: invalid conn ", reflect.TypeOf(c))
|
||||
conn.Close()
|
||||
return nil, errors.New()
|
||||
return nil, errors.New("invalid conn ", reflect.TypeOf(c))
|
||||
}
|
||||
|
||||
return udpConn, nil
|
||||
return pktConn, 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)
|
||||
var pktConn net.PacketConn
|
||||
var udpAddr *net.UDPAddr
|
||||
var err error
|
||||
udpAddr, err = net.ResolveUDPAddr("udp", dest.NetAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var udpConn net.PacketConn
|
||||
var udpAddr *net.UDPAddr
|
||||
|
||||
switch c := conn.(type) {
|
||||
case *internet.PacketConnWrapper:
|
||||
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)
|
||||
pktConn, err = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, errors.New("udphop err").Base(err)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch c := conn.(type) {
|
||||
case *internet.PacketConnWrapper:
|
||||
pktConn = c.PacketConn
|
||||
case *net.UDPConn:
|
||||
pktConn = c
|
||||
case *cnc.Connection:
|
||||
pktConn = &internet.FakePacketConn{Conn: c}
|
||||
default:
|
||||
panic(reflect.TypeOf(c))
|
||||
}
|
||||
}
|
||||
|
||||
if streamSettings.UdpmaskManager != nil {
|
||||
udpConn, err = streamSettings.UdpmaskManager.WrapPacketConnClient(udpConn)
|
||||
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(pktConn)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
pktConn.Close()
|
||||
return nil, errors.New("mask err").Base(err)
|
||||
}
|
||||
pktConn = newConn
|
||||
}
|
||||
|
||||
quicConn, err := quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg)
|
||||
conn, err := quic.DialEarly(ctx, pktConn, udpAddr, tlsCfg, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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")
|
||||
case "", "bbr":
|
||||
congestion.UseBBR(conn, bbr.Profile(quicParams.BbrProfile))
|
||||
case "force-brutal":
|
||||
congestion.UseBrutal(conn, quicParams.BrutalUp)
|
||||
default:
|
||||
errors.LogDebug(context.Background(), quicConn.RemoteAddr(), " ", "congestion bbr ", quicParams.BbrProfile)
|
||||
congestion.UseBBR(quicConn, bbr.Profile(quicParams.BbrProfile))
|
||||
panic(quicParams.Congestion)
|
||||
}
|
||||
|
||||
return quicConn, nil
|
||||
return conn, nil
|
||||
},
|
||||
}
|
||||
} else if httpVersion == "2" {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -440,7 +441,7 @@ type Listener struct {
|
||||
server http.Server
|
||||
h3server *http3.Server
|
||||
listener net.Listener
|
||||
h3listener *quic.EarlyListener
|
||||
h3listener Qface
|
||||
config *Config
|
||||
addConn internet.ConnHandler
|
||||
isH3 bool
|
||||
@@ -487,12 +488,12 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
||||
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)
|
||||
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnServer(Conn)
|
||||
if err != nil {
|
||||
Conn.Close()
|
||||
return nil, errors.New("mask err").Base(err)
|
||||
}
|
||||
Conn = pktConn
|
||||
Conn = newConn
|
||||
}
|
||||
|
||||
quicParams := streamSettings.QuicParams
|
||||
@@ -510,13 +511,17 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
||||
MaxConnectionReceiveWindow: quicParams.MaxConnReceiveWindow,
|
||||
MaxIdleTimeout: time.Duration(quicParams.MaxIdleTimeout) * time.Second,
|
||||
MaxIncomingStreams: quicParams.MaxIncomingStreams,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery,
|
||||
DisablePathMTUDiscovery: quicParams.DisablePathMtuDiscovery || (runtime.GOOS != "linux" && runtime.GOOS != "windows" && runtime.GOOS != "darwin"),
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
l.h3listener = &QListener{
|
||||
Qface: l.h3listener,
|
||||
quicParams: quicParams,
|
||||
}
|
||||
errors.LogInfo(ctx, "listening QUIC for XHTTP/3 on ", address, ":", port)
|
||||
|
||||
handler.localAddr = l.h3listener.Addr()
|
||||
@@ -525,30 +530,8 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
||||
Handler: handler,
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
conn, err := l.h3listener.Accept(context.Background())
|
||||
if err != nil {
|
||||
errors.LogInfoInner(ctx, err, "XHTTP/3 listener closed")
|
||||
return
|
||||
}
|
||||
|
||||
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 ", quicParams.BbrProfile)
|
||||
congestion.UseBBR(conn, bbr.Profile(quicParams.BbrProfile))
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := l.h3server.ServeQUICConn(conn); err != nil {
|
||||
errors.LogDebugInner(ctx, err, "XHTTP/3 connection ended")
|
||||
}
|
||||
_ = conn.CloseWithError(0, "")
|
||||
}()
|
||||
if err := l.h3server.ServeListener(l.h3listener); err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to serve HTTP/3 for XHTTP/3")
|
||||
}
|
||||
}()
|
||||
} else { // tcp
|
||||
@@ -614,10 +597,8 @@ 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()
|
||||
} else if ln.listener != nil {
|
||||
return ln.listener.Close()
|
||||
}
|
||||
@@ -633,3 +614,33 @@ func getTLSConfig(streamSettings *internet.MemoryStreamConfig) *gotls.Config {
|
||||
func init() {
|
||||
common.Must(internet.RegisterTransportListener(protocolName, ListenXH))
|
||||
}
|
||||
|
||||
type Qface interface {
|
||||
Accept(ctx context.Context) (*quic.Conn, error)
|
||||
Addr() net.Addr
|
||||
Close() error
|
||||
}
|
||||
|
||||
var _ Qface = (*quic.EarlyListener)(nil)
|
||||
|
||||
type QListener struct {
|
||||
Qface
|
||||
quicParams *internet.QuicParams
|
||||
}
|
||||
|
||||
func (l *QListener) Accept(ctx context.Context) (*quic.Conn, error) {
|
||||
conn, err := l.Qface.Accept(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch l.quicParams.Congestion {
|
||||
case "reno":
|
||||
case "", "bbr":
|
||||
congestion.UseBBR(conn, bbr.Profile(l.quicParams.BbrProfile))
|
||||
case "force-brutal":
|
||||
congestion.UseBrutal(conn, l.quicParams.BrutalUp)
|
||||
default:
|
||||
panic(l.quicParams.Congestion)
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user