diff --git a/go.mod b/go.mod index b14991e32a2e..7255def51621 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/xtls/xray-core go 1.26 require ( - github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178 + github.com/apernet/quic-go v0.59.1-0.20260217092621-db4786c77a22 github.com/cloudflare/circl v1.6.3 github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 github.com/golang/mock v1.7.0-rc.1 diff --git a/go.sum b/go.sum index 94a578ea447f..9e71f83f1111 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178 h1:bSq8n+gX4oO/qnM3MKf4kroW75n+phO9Qp6nigJKZ1E= -github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178/go.mod h1:N1WIjPphkqs4efXWuyDNQ6OjjIK04vM3h+bEgwV+eVU= +github.com/apernet/quic-go v0.59.1-0.20260217092621-db4786c77a22 h1:00ziBGnLWQEcR9LThDwvxOznJJquJ9bYUdmBFnawLMU= +github.com/apernet/quic-go v0.59.1-0.20260217092621-db4786c77a22/go.mod h1:Npbg8qBtAZlsAB3FWmqwlVh5jtVG6a4DlYsOylUpvzA= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= diff --git a/transport/internet/hysteria/congestion/bbr/bandwidth_sampler.go b/transport/internet/hysteria/congestion/bbr/bandwidth_sampler.go index a1e22d6fe00f..35b63c064454 100644 --- a/transport/internet/hysteria/congestion/bbr/bandwidth_sampler.go +++ b/transport/internet/hysteria/congestion/bbr/bandwidth_sampler.go @@ -5,6 +5,7 @@ import ( "time" "github.com/apernet/quic-go/congestion" + "github.com/apernet/quic-go/monotime" ) const ( @@ -103,7 +104,7 @@ type maxAckHeightTracker struct { // bandwidth. maxAckHeightFilter *WindowedFilter[extraAckedEvent, roundTripCount] // The time this aggregation started and the number of bytes acked during it. - aggregationEpochStartTime congestion.Time + aggregationEpochStartTime monotime.Time aggregationEpochBytes congestion.ByteCount // The last sent packet number before the current aggregation epoch started. lastSentPacketNumberBeforeEpoch congestion.PacketNumber @@ -133,7 +134,7 @@ func (m *maxAckHeightTracker) Update( roundTripCount roundTripCount, lastSentPacketNumber congestion.PacketNumber, lastAckedPacketNumber congestion.PacketNumber, - ackTime congestion.Time, + ackTime monotime.Time, bytesAcked congestion.ByteCount, ) congestion.ByteCount { forceNewEpoch := false @@ -241,7 +242,7 @@ func (m *maxAckHeightTracker) NumAckAggregationEpochs() uint64 { // AckPoint represents a point on the ack line. type ackPoint struct { - ackTime congestion.Time + ackTime monotime.Time totalBytesAcked congestion.ByteCount } @@ -250,7 +251,7 @@ type recentAckPoints struct { ackPoints [2]ackPoint } -func (r *recentAckPoints) Update(ackTime congestion.Time, totalBytesAcked congestion.ByteCount) { +func (r *recentAckPoints) Update(ackTime monotime.Time, totalBytesAcked congestion.ByteCount) { if ackTime.Before(r.ackPoints[1].ackTime) { r.ackPoints[1].ackTime = ackTime } else if ackTime.After(r.ackPoints[1].ackTime) { @@ -284,7 +285,7 @@ func (r *recentAckPoints) LessRecentPoint() *ackPoint { // that moment. type connectionStateOnSentPacket struct { // Time at which the packet is sent. - sentTime congestion.Time + sentTime monotime.Time // Size of the packet. size congestion.ByteCount // The value of |totalBytesSentAtLastAckedPacket| at the time the @@ -292,10 +293,10 @@ type connectionStateOnSentPacket struct { totalBytesSentAtLastAckedPacket congestion.ByteCount // The value of |lastAckedPacketSentTime| at the time the packet was // sent. - lastAckedPacketSentTime congestion.Time + lastAckedPacketSentTime monotime.Time // The value of |lastAckedPacketAckTime| at the time the packet was // sent. - lastAckedPacketAckTime congestion.Time + lastAckedPacketAckTime monotime.Time // Send time states that are returned to the congestion controller when the // packet is acked or lost. sendTimeState sendTimeState @@ -305,7 +306,7 @@ type connectionStateOnSentPacket struct { // sampler. // |bytes_in_flight| is the bytes in flight right after the packet is sent. func newConnectionStateOnSentPacket( - sentTime congestion.Time, + sentTime monotime.Time, size congestion.ByteCount, bytesInFlight congestion.ByteCount, sampler *bandwidthSampler, @@ -456,10 +457,10 @@ type bandwidthSampler struct { // The time at which the last acknowledged packet was sent. Set to // QuicTime::Zero() if no valid timestamp is available. - lastAckedPacketSentTime congestion.Time + lastAckedPacketSentTime monotime.Time // The time at which the most recent packet was acknowledged. - lastAckedPacketAckTime congestion.Time + lastAckedPacketAckTime monotime.Time // The most recently sent packet. lastSentPacket congestion.PacketNumber @@ -551,7 +552,7 @@ func (b *bandwidthSampler) IsOverestimateAvoidanceEnabled() bool { } func (b *bandwidthSampler) OnPacketSent( - sentTime congestion.Time, + sentTime monotime.Time, packetNumber congestion.PacketNumber, bytes congestion.ByteCount, bytesInFlight congestion.ByteCount, @@ -595,7 +596,7 @@ func (b *bandwidthSampler) OnPacketSent( } func (b *bandwidthSampler) OnCongestionEvent( - ackTime congestion.Time, + ackTime monotime.Time, ackedPackets []congestion.AckedPacketInfo, lostPackets []congestion.LostPacketInfo, maxBandwidth Bandwidth, @@ -758,7 +759,7 @@ func (b *bandwidthSampler) chooseA0Point(totalBytesAcked congestion.ByteCount, a return true } -func (b *bandwidthSampler) onPacketAcknowledged(ackTime congestion.Time, packetNumber congestion.PacketNumber) bandwidthSample { +func (b *bandwidthSampler) onPacketAcknowledged(ackTime monotime.Time, packetNumber congestion.PacketNumber) bandwidthSample { sample := newBandwidthSample() b.lastAckedPacket = packetNumber sentPacketPointer := b.connectionStateMap.GetEntry(packetNumber) diff --git a/transport/internet/hysteria/congestion/bbr/bbr_sender.go b/transport/internet/hysteria/congestion/bbr/bbr_sender.go index 93c5bf84db95..e8787f15a0f6 100644 --- a/transport/internet/hysteria/congestion/bbr/bbr_sender.go +++ b/transport/internet/hysteria/congestion/bbr/bbr_sender.go @@ -9,6 +9,7 @@ import ( "time" "github.com/apernet/quic-go/congestion" + "github.com/apernet/quic-go/monotime" "github.com/xtls/xray-core/transport/internet/hysteria/congestion/common" ) @@ -130,7 +131,7 @@ type bbrSender struct { // triggers PROBE_RTT mode) if no new value is sampled during that period. minRtt time.Duration // The time at which the current value of |min_rtt_| was assigned. - minRttTimestamp congestion.Time + minRttTimestamp monotime.Time // The maximum allowed number of bytes in flight. congestionWindow congestion.ByteCount @@ -171,7 +172,7 @@ type bbrSender struct { // pacing gain cycle. cycleCurrentOffset int // The time at which the last pacing gain cycle was started. - lastCycleStart congestion.Time + lastCycleStart monotime.Time // Indicates whether the connection has reached the full bandwidth mode. isAtFullBandwidth bool @@ -186,7 +187,7 @@ type bbrSender struct { // Time at which PROBE_RTT has to be exited. Setting it to zero indicates // that the time is yet unknown as the number of packets in flight has not // reached the required value. - exitProbeRttAt congestion.Time + exitProbeRttAt monotime.Time // Indicates whether a round-trip has passed since PROBE_RTT became active. probeRttRoundPassed bool @@ -313,18 +314,18 @@ func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsProvider) { } // TimeUntilSend implements the SendAlgorithm interface. -func (b *bbrSender) TimeUntilSend(bytesInFlight congestion.ByteCount) congestion.Time { +func (b *bbrSender) TimeUntilSend(bytesInFlight congestion.ByteCount) monotime.Time { return b.pacer.TimeUntilSend() } // HasPacingBudget implements the SendAlgorithm interface. -func (b *bbrSender) HasPacingBudget(now congestion.Time) bool { +func (b *bbrSender) HasPacingBudget(now monotime.Time) bool { return b.pacer.Budget(now) >= b.maxDatagramSize } // OnPacketSent implements the SendAlgorithm interface. func (b *bbrSender) OnPacketSent( - sentTime congestion.Time, + sentTime monotime.Time, bytesInFlight congestion.ByteCount, packetNumber congestion.PacketNumber, bytes congestion.ByteCount, @@ -353,7 +354,7 @@ func (b *bbrSender) MaybeExitSlowStart() { } // OnPacketAcked implements the SendAlgorithm interface. -func (b *bbrSender) OnPacketAcked(number congestion.PacketNumber, ackedBytes, priorInFlight congestion.ByteCount, eventTime congestion.Time) { +func (b *bbrSender) OnPacketAcked(number congestion.PacketNumber, ackedBytes, priorInFlight congestion.ByteCount, eventTime monotime.Time) { // Do nothing. } @@ -407,7 +408,7 @@ func (b *bbrSender) OnCongestionEvent(number congestion.PacketNumber, lostBytes, // Do nothing. } -func (b *bbrSender) OnCongestionEventEx(priorInFlight congestion.ByteCount, eventTime congestion.Time, ackedPackets []congestion.AckedPacketInfo, lostPackets []congestion.LostPacketInfo) { +func (b *bbrSender) OnCongestionEventEx(priorInFlight congestion.ByteCount, eventTime monotime.Time, ackedPackets []congestion.AckedPacketInfo, lostPackets []congestion.LostPacketInfo) { totalBytesAckedBefore := b.sampler.TotalBytesAcked() totalBytesLostBefore := b.sampler.TotalBytesLost() @@ -598,7 +599,7 @@ func (b *bbrSender) probeRttCongestionWindow() congestion.ByteCount { return b.minCongestionWindow } -func (b *bbrSender) maybeUpdateMinRtt(now congestion.Time, sampleMinRtt time.Duration) bool { +func (b *bbrSender) maybeUpdateMinRtt(now monotime.Time, sampleMinRtt time.Duration) bool { // Do not expire min_rtt if none was ever available. minRttExpired := b.minRtt != 0 && now.After(b.minRttTimestamp.Add(minRttExpiry)) if minRttExpired || sampleMinRtt < b.minRtt || b.minRtt == 0 { @@ -610,7 +611,7 @@ func (b *bbrSender) maybeUpdateMinRtt(now congestion.Time, sampleMinRtt time.Dur } // Enters the STARTUP mode. -func (b *bbrSender) enterStartupMode(now congestion.Time) { +func (b *bbrSender) enterStartupMode(now monotime.Time) { b.mode = bbrModeStartup // b.maybeTraceStateChange(logging.CongestionStateStartup) b.pacingGain = b.highGain @@ -622,7 +623,7 @@ func (b *bbrSender) enterStartupMode(now congestion.Time) { } // Enters the PROBE_BW mode. -func (b *bbrSender) enterProbeBandwidthMode(now congestion.Time) { +func (b *bbrSender) enterProbeBandwidthMode(now monotime.Time) { b.mode = bbrModeProbeBw // b.maybeTraceStateChange(logging.CongestionStateProbeBw) b.congestionWindowGain = b.congestionWindowGainConstant @@ -655,7 +656,7 @@ func (b *bbrSender) updateRoundTripCounter(lastAckedPacket congestion.PacketNumb } // Updates the current gain used in PROBE_BW mode. -func (b *bbrSender) updateGainCyclePhase(now congestion.Time, priorInFlight congestion.ByteCount, hasLosses bool) { +func (b *bbrSender) updateGainCyclePhase(now monotime.Time, priorInFlight congestion.ByteCount, hasLosses bool) { // In most cases, the cycle is advanced after an RTT passes. shouldAdvanceGainCycling := now.After(b.lastCycleStart.Add(b.getMinRtt())) // If the pacing gain is above 1.0, the connection is trying to probe the @@ -722,7 +723,7 @@ func (b *bbrSender) maybeAppLimited(bytesInFlight congestion.ByteCount) { // Transitions from STARTUP to DRAIN and from DRAIN to PROBE_BW if // appropriate. -func (b *bbrSender) maybeExitStartupOrDrain(now congestion.Time) { +func (b *bbrSender) maybeExitStartupOrDrain(now monotime.Time) { if b.mode == bbrModeStartup && b.isAtFullBandwidth { b.mode = bbrModeDrain // b.maybeTraceStateChange(logging.CongestionStateDrain) @@ -739,7 +740,7 @@ func (b *bbrSender) maybeExitStartupOrDrain(now congestion.Time) { } // Decides whether to enter or exit PROBE_RTT. -func (b *bbrSender) maybeEnterOrExitProbeRtt(now congestion.Time, isRoundStart, minRttExpired bool) { +func (b *bbrSender) maybeEnterOrExitProbeRtt(now monotime.Time, isRoundStart, minRttExpired bool) { if minRttExpired && !b.exitingQuiescence && b.mode != bbrModeProbeRtt { b.mode = bbrModeProbeRtt // b.maybeTraceStateChange(logging.CongestionStateProbRtt) diff --git a/transport/internet/hysteria/congestion/bbr/clock.go b/transport/internet/hysteria/congestion/bbr/clock.go index fee7df6ab74f..541987ef805c 100644 --- a/transport/internet/hysteria/congestion/bbr/clock.go +++ b/transport/internet/hysteria/congestion/bbr/clock.go @@ -1,10 +1,10 @@ package bbr -import "github.com/apernet/quic-go/congestion" +import "github.com/apernet/quic-go/monotime" // A Clock returns the current time type Clock interface { - Now() congestion.Time + Now() monotime.Time } // DefaultClock implements the Clock interface using the Go stdlib clock. @@ -13,6 +13,6 @@ type DefaultClock struct{} var _ Clock = DefaultClock{} // Now gets the current time -func (DefaultClock) Now() congestion.Time { - return congestion.Now() +func (DefaultClock) Now() monotime.Time { + return monotime.Now() } diff --git a/transport/internet/hysteria/congestion/brutal/brutal.go b/transport/internet/hysteria/congestion/brutal/brutal.go index ba0bfda81104..969923a51ab1 100644 --- a/transport/internet/hysteria/congestion/brutal/brutal.go +++ b/transport/internet/hysteria/congestion/brutal/brutal.go @@ -9,6 +9,7 @@ import ( "github.com/xtls/xray-core/transport/internet/hysteria/congestion/common" "github.com/apernet/quic-go/congestion" + "github.com/apernet/quic-go/monotime" ) const ( @@ -60,11 +61,11 @@ func (b *BrutalSender) SetRTTStatsProvider(rttStats congestion.RTTStatsProvider) b.rttStats = rttStats } -func (b *BrutalSender) TimeUntilSend(bytesInFlight congestion.ByteCount) congestion.Time { +func (b *BrutalSender) TimeUntilSend(bytesInFlight congestion.ByteCount) monotime.Time { return b.pacer.TimeUntilSend() } -func (b *BrutalSender) HasPacingBudget(now congestion.Time) bool { +func (b *BrutalSender) HasPacingBudget(now monotime.Time) bool { return b.pacer.Budget(now) >= b.maxDatagramSize } @@ -84,14 +85,14 @@ func (b *BrutalSender) GetCongestionWindow() congestion.ByteCount { return cwnd } -func (b *BrutalSender) OnPacketSent(sentTime congestion.Time, bytesInFlight congestion.ByteCount, +func (b *BrutalSender) OnPacketSent(sentTime monotime.Time, bytesInFlight congestion.ByteCount, packetNumber congestion.PacketNumber, bytes congestion.ByteCount, isRetransmittable bool, ) { b.pacer.SentPacket(sentTime, bytes) } func (b *BrutalSender) OnPacketAcked(number congestion.PacketNumber, ackedBytes congestion.ByteCount, - priorInFlight congestion.ByteCount, eventTime congestion.Time, + priorInFlight congestion.ByteCount, eventTime monotime.Time, ) { // Stub } @@ -102,7 +103,7 @@ func (b *BrutalSender) OnCongestionEvent(number congestion.PacketNumber, lostByt // Stub } -func (b *BrutalSender) OnCongestionEventEx(priorInFlight congestion.ByteCount, eventTime congestion.Time, ackedPackets []congestion.AckedPacketInfo, lostPackets []congestion.LostPacketInfo) { +func (b *BrutalSender) OnCongestionEventEx(priorInFlight congestion.ByteCount, eventTime monotime.Time, ackedPackets []congestion.AckedPacketInfo, lostPackets []congestion.LostPacketInfo) { currentTimestamp := int64(time.Duration(eventTime) / time.Second) slot := currentTimestamp % pktInfoSlotCount if b.pktInfoSlots[slot].Timestamp == currentTimestamp { diff --git a/transport/internet/hysteria/congestion/common/pacer.go b/transport/internet/hysteria/congestion/common/pacer.go index 779c2f1d1c45..e0bddbe2e75b 100644 --- a/transport/internet/hysteria/congestion/common/pacer.go +++ b/transport/internet/hysteria/congestion/common/pacer.go @@ -4,6 +4,7 @@ import ( "time" "github.com/apernet/quic-go/congestion" + "github.com/apernet/quic-go/monotime" ) const ( @@ -15,7 +16,7 @@ const ( type Pacer struct { budgetAtLastSent congestion.ByteCount maxDatagramSize congestion.ByteCount - lastSentTime congestion.Time + lastSentTime monotime.Time getBandwidth func() congestion.ByteCount // in bytes/s } @@ -28,7 +29,7 @@ func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer { return p } -func (p *Pacer) SentPacket(sendTime congestion.Time, size congestion.ByteCount) { +func (p *Pacer) SentPacket(sendTime monotime.Time, size congestion.ByteCount) { budget := p.Budget(sendTime) if size > budget { p.budgetAtLastSent = 0 @@ -38,7 +39,7 @@ func (p *Pacer) SentPacket(sendTime congestion.Time, size congestion.ByteCount) p.lastSentTime = sendTime } -func (p *Pacer) Budget(now congestion.Time) congestion.ByteCount { +func (p *Pacer) Budget(now monotime.Time) congestion.ByteCount { if p.lastSentTime.IsZero() { return p.maxBurstSize() } @@ -58,7 +59,7 @@ func (p *Pacer) maxBurstSize() congestion.ByteCount { // TimeUntilSend returns when the next packet should be sent. // It returns the zero value if a packet can be sent immediately. -func (p *Pacer) TimeUntilSend() congestion.Time { +func (p *Pacer) TimeUntilSend() monotime.Time { if p.budgetAtLastSent >= p.maxDatagramSize { return 0 } diff --git a/transport/internet/hysteria/hub.go b/transport/internet/hysteria/hub.go index 32a4def9982c..d7b8b879543f 100644 --- a/transport/internet/hysteria/hub.go +++ b/transport/internet/hysteria/hub.go @@ -14,6 +14,7 @@ import ( "github.com/apernet/quic-go" "github.com/apernet/quic-go/http3" + "github.com/apernet/quic-go/quicvarint" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/net" @@ -221,13 +222,17 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.masqHandler.ServeHTTP(w, r) } -func (h *httpHandler) ProxyStreamHijacker(ft http3.FrameType, id quic.ConnectionTracingID, stream *quic.Stream, err error) (bool, error) { +func (h *httpHandler) StreamDispatcher(ft http3.FrameType, stream *quic.Stream, err error) (bool, error) { if err != nil || !h.auth { return false, nil } switch ft { case FrameTypeTCPRequest: + if _, err := quicvarint.Read(quicvarint.NewReader(stream)); err != nil { + return false, err + } + h.addConn(&interConn{ stream: stream, local: h.conn.LocalAddr(), @@ -263,8 +268,8 @@ func (l *Listener) handleClient(conn *quic.Conn) { masqHandler: l.masqHandler, } h3 := http3.Server{ - Handler: handler, - StreamHijacker: handler.ProxyStreamHijacker, + Handler: handler, + StreamDispatcher: handler.StreamDispatcher, } err := h3.ServeQUICConn(conn) errors.LogDebug(context.Background(), conn.RemoteAddr(), " disconnected with err ", err)