fix: latency comparison had potential arithmetic overflow problem

This commit is contained in:
mzz2017 2023-02-13 15:27:36 +08:00
parent d88961681e
commit 11f8683d8f
3 changed files with 28 additions and 3 deletions

View File

@ -6,9 +6,11 @@
package dialer
import (
"fmt"
"github.com/mzz2017/softwind/pkg/fastrand"
"github.com/sirupsen/logrus"
"github.com/v2rayA/dae/common/consts"
"strings"
"sync"
"time"
)
@ -87,6 +89,19 @@ func (a *AliveDialerSet) GetMinLatency() (d *Dialer, latency time.Duration) {
return a.minLatency.dialer, a.minLatency.latency
}
func (a *AliveDialerSet) printLatencies() {
var builder strings.Builder
builder.WriteString(fmt.Sprintf("%v (%v):\n", a.dialerGroupName, a.CheckTyp.String()))
for _, d := range a.inorderedAliveDialerSet {
latency, ok := a.dialerToLatency[d]
if !ok {
continue
}
builder.WriteString(fmt.Sprintf("%v: %v\n", d.Name(), latency.String()))
}
a.log.Traceln(builder.String())
}
// NotifyLatencyChange should be invoked when dialer every time latency and alive state changes.
func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
a.mu.Lock()
@ -146,7 +161,9 @@ func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
bakOldBestDialer := a.minLatency.dialer
// Calc minLatency.
a.dialerToLatency[dialer] = latency
if alive && latency <= a.minLatency.latency-a.tolerance {
if alive &&
latency <= a.minLatency.latency && // To avoid arithmetic overflow.
latency <= a.minLatency.latency-a.tolerance {
a.minLatency.latency = latency
a.minLatency.dialer = dialer
} else if a.minLatency.dialer == dialer {
@ -189,6 +206,9 @@ func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
"network": a.CheckTyp.String(),
}).Infof("Group has no dialer alive")
}
if a.log.IsLevelEnabled(logrus.TraceLevel) {
a.printLatencies()
}
}
} else {
if alive && minPolicy && a.minLatency.dialer == nil {
@ -219,7 +239,9 @@ func (a *AliveDialerSet) calcMinLatency() {
if a.minLatency.dialer == nil {
a.minLatency.latency = minLatency
a.minLatency.dialer = minDialer
} else if minDialer != nil && minLatency <= a.minLatency.latency-a.tolerance {
} else if minDialer != nil &&
minLatency <= a.minLatency.latency && // To avoid arithmetic overflow.
minLatency <= a.minLatency.latency-a.tolerance {
a.minLatency.latency = minLatency
a.minLatency.dialer = minDialer
}

View File

@ -73,6 +73,7 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
c.log.WithFields(logrus.Fields{
"network": networkType.String(),
"outbound": outbound.Name,
"policy": outbound.GetSelectionPolicy(),
"dialer": d.Name(),
}).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr(), consts.LanWanFlag_NotApplicable), RefineAddrPortToShow(dst))
rConn, err := d.Dial("tcp", dst.String())

View File

@ -309,7 +309,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
Target: destToSend,
})
if err != nil {
return fmt.Errorf("failed to GetOrCreate (%v): %w", outbound.GetSelectionPolicy(), err)
return fmt.Errorf("failed to GetOrCreate (policy: %v): %w", outbound.GetSelectionPolicy(), err)
}
// If the udp endpoint has been not alive, remove it from pool and get a new one.
if !isNew && !ue.Dialer.MustGetAlive(networkType) {
@ -396,6 +396,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
c.log.WithFields(logrus.Fields{
"network": string(l4proto) + string(ipversion) + "(DNS)",
"outbound": outbound.Name,
"policy": outbound.GetSelectionPolicy(),
"dialer": realDialer.Name(),
"qname": strings.ToLower(q.Name.String()),
"qtype": q.Type,
@ -407,6 +408,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
c.log.WithFields(logrus.Fields{
"network": string(l4proto) + string(ipversion),
"outbound": outbound.Name,
"policy": outbound.GetSelectionPolicy(),
"dialer": realDialer.Name(),
}).Infof("%v <-> %v",
RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag), RefineAddrPortToShow(destToSend),