Hysteria client: Fix sendThrough (#6063)

And fixes https://github.com/XTLS/Xray-core/issues/6046
This commit is contained in:
LjhAUMEM
2026-05-03 15:18:23 +08:00
committed by GitHub
parent b279076ba1
commit 756a2d1327
14 changed files with 87 additions and 224 deletions
+21 -19
View File
@@ -5,6 +5,7 @@ import (
gotls "crypto/tls"
"fmt"
"io"
"math/rand"
"net/http"
"net/http/httptrace"
"net/url"
@@ -199,7 +200,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), streamSettings.SocketSettings)
if err != nil {
errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest")
return nil, errors.New("failed to dial to dest").Base(err)
return nil, errors.New("")
}
var pktConn net.PacketConn
@@ -207,12 +208,8 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
case *net.UDPConn:
pktConn = c
default:
errors.LogInfo(context.Background(), "skip hop: invalid conn ", reflect.TypeOf(c))
conn.Close()
return nil, errors.New("invalid conn ", reflect.TypeOf(c))
panic(reflect.TypeOf(c))
}
return pktConn, nil
@@ -220,28 +217,33 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
var pktConn net.PacketConn
var udpAddr *net.UDPAddr
var err error
udpAddr, err = net.ResolveUDPAddr("udp", dest.NetAddr())
if err != nil {
return nil, err
}
if len(quicParams.UdpHop.Ports) > 0 {
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 {
return nil, err
}
} else {
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
return nil, errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
case *net.UDPConn:
pktConn = c
udpAddr = conn.RemoteAddr().(*net.UDPAddr)
default:
panic(reflect.TypeOf(c))
}
pktConn = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer, pktConn, index)
} else {
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil {
return nil, errors.New("failed to dial to dest").Base(err)
}
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
udpAddr = c.RemoteAddr().(*net.UDPAddr)
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
default:
panic(reflect.TypeOf(c))
}
+5 -13
View File
@@ -441,7 +441,7 @@ type Listener struct {
server http.Server
h3server *http3.Server
listener net.Listener
h3listener Qface
h3listener http3.QUICListener
config *Config
addConn internet.ConnHandler
isH3 bool
@@ -519,8 +519,8 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
return nil, errors.New("failed to listen QUIC for XHTTP/3 on ", address, ":", port).Base(err)
}
l.h3listener = &QListener{
Qface: l.h3listener,
quicParams: quicParams,
QUICListener: l.h3listener,
quicParams: quicParams,
}
errors.LogInfo(ctx, "listening QUIC for XHTTP/3 on ", address, ":", port)
@@ -615,21 +615,13 @@ 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
http3.QUICListener
quicParams *internet.QuicParams
}
func (l *QListener) Accept(ctx context.Context) (*quic.Conn, error) {
conn, err := l.Qface.Accept(ctx)
conn, err := l.QUICListener.Accept(ctx)
if err != nil {
return nil, err
}