mirror of
https://github.com/cedar2025/hysteria.git
synced 2025-06-09 22:19:55 +00:00
Improve UDP Relay timeout handling
This commit is contained in:
parent
70fd2ffc0d
commit
3b7aefb10d
@ -48,9 +48,8 @@ func NewUDPRelay(hyClient *core.Client, listen, remote string, timeout time.Dura
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cmEntry struct {
|
type cmEntry struct {
|
||||||
HyConn core.UDPConn
|
HyConn core.UDPConn
|
||||||
Addr *net.UDPAddr
|
Deadline atomic.Value
|
||||||
LastActiveTime atomic.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *UDPRelay) ListenAndServe() error {
|
func (r *UDPRelay) ListenAndServe() error {
|
||||||
@ -62,31 +61,6 @@ func (r *UDPRelay) ListenAndServe() error {
|
|||||||
// src <-> HyClient UDPConn
|
// src <-> HyClient UDPConn
|
||||||
connMap := make(map[string]*cmEntry)
|
connMap := make(map[string]*cmEntry)
|
||||||
var connMapMutex sync.RWMutex
|
var connMapMutex sync.RWMutex
|
||||||
// Timeout cleanup routine
|
|
||||||
stopChan := make(chan bool)
|
|
||||||
defer close(stopChan)
|
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(udpMinTimeout)
|
|
||||||
defer ticker.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-stopChan:
|
|
||||||
return
|
|
||||||
case t := <-ticker.C:
|
|
||||||
allowedLAT := t.Add(-r.Timeout)
|
|
||||||
connMapMutex.Lock()
|
|
||||||
for k, v := range connMap {
|
|
||||||
if v.LastActiveTime.Load().(time.Time).Before(allowedLAT) {
|
|
||||||
// Timeout
|
|
||||||
r.ErrorFunc(v.Addr, ErrTimeout)
|
|
||||||
_ = v.HyConn.Close()
|
|
||||||
delete(connMap, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connMapMutex.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// Read loop
|
// Read loop
|
||||||
buf := make([]byte, udpBufferSize)
|
buf := make([]byte, udpBufferSize)
|
||||||
for {
|
for {
|
||||||
@ -97,7 +71,7 @@ func (r *UDPRelay) ListenAndServe() error {
|
|||||||
connMapMutex.RUnlock()
|
connMapMutex.RUnlock()
|
||||||
if cme != nil {
|
if cme != nil {
|
||||||
// Existing conn
|
// Existing conn
|
||||||
cme.LastActiveTime.Store(time.Now())
|
cme.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
_ = cme.HyConn.WriteTo(buf[:n], r.Remote)
|
_ = cme.HyConn.WriteTo(buf[:n], r.Remote)
|
||||||
} else {
|
} else {
|
||||||
// New
|
// New
|
||||||
@ -107,8 +81,8 @@ func (r *UDPRelay) ListenAndServe() error {
|
|||||||
r.ErrorFunc(rAddr, err)
|
r.ErrorFunc(rAddr, err)
|
||||||
} else {
|
} else {
|
||||||
// Add it to the map
|
// Add it to the map
|
||||||
ent := &cmEntry{HyConn: hyConn, Addr: rAddr}
|
ent := &cmEntry{HyConn: hyConn}
|
||||||
ent.LastActiveTime.Store(time.Now())
|
ent.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
connMapMutex.Lock()
|
connMapMutex.Lock()
|
||||||
connMap[rAddr.String()] = ent
|
connMap[rAddr.String()] = ent
|
||||||
connMapMutex.Unlock()
|
connMapMutex.Unlock()
|
||||||
@ -119,10 +93,27 @@ func (r *UDPRelay) ListenAndServe() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ent.LastActiveTime.Store(time.Now())
|
ent.Deadline.Store(time.Now().Add(r.Timeout))
|
||||||
_, _ = conn.WriteToUDP(bs, rAddr)
|
_, _ = conn.WriteToUDP(bs, rAddr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
// Timeout cleanup routine
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
ttl := ent.Deadline.Load().(time.Time).Sub(time.Now())
|
||||||
|
if ttl < 0 {
|
||||||
|
// Time to die
|
||||||
|
connMapMutex.Lock()
|
||||||
|
_ = hyConn.Close()
|
||||||
|
delete(connMap, rAddr.String())
|
||||||
|
connMapMutex.Unlock()
|
||||||
|
r.ErrorFunc(rAddr, ErrTimeout)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
time.Sleep(ttl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
// Send the packet
|
// Send the packet
|
||||||
_ = hyConn.WriteTo(buf[:n], r.Remote)
|
_ = hyConn.WriteTo(buf[:n], r.Remote)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user