This commit is contained in:
Claire Wang
2024-01-31 10:38:15 -05:00
parent 1ae16546af
commit d32aaffca6
5 changed files with 77 additions and 8 deletions

View File

@@ -13,6 +13,7 @@ import (
"io"
"log"
"maps"
"math"
"net"
"net/http"
"net/netip"
@@ -107,6 +108,8 @@ import (
var controlDebugFlags = getControlDebugFlags()
const derpPrefix = "127.3.3.40:"
func getControlDebugFlags() []string {
if e := envknob.String("TS_DEBUG_CONTROL_FLAGS"); e != "" {
return strings.Split(e, ",")
@@ -306,7 +309,8 @@ type LocalBackend struct {
clock tstime.Clock
// Last ClientVersion received in MapResponse, guarded by mu.
lastClientVersion *tailcfg.ClientVersion
lastClientVersion *tailcfg.ClientVersion
suggestedExitNodeMap map[tailcfg.NodeID]tailcfg.DERPRegion
}
type updateStatus struct {
@@ -1431,7 +1435,6 @@ func setExitNodeID(prefs *ipn.Prefs, nm *netmap.NetworkMap) (prefsChanged bool)
return oldExitNodeID != prefs.ExitNodeID
}
}
return prefsChanged
}
@@ -5909,3 +5912,36 @@ func mayDeref[T any](p *T) (v T) {
}
return *p
}
func (b *LocalBackend) SuggestExitNode() error {
//b.mu.Lock()
netMap := b.netMap
peers := netMap.Peers
lastReport := b.MagicConn().GetLastNetcheckReport()
var fastestRegionLatency = time.Duration(math.MaxInt64)
var preferredExitNodeID tailcfg.StableNodeID
for _, peer := range peers {
if tsaddr.ContainsExitRoutes(peer.AllowedIPs()) && strings.HasPrefix(peer.DERP(), derpPrefix) {
ipp, _ := netip.ParseAddrPort(peer.DERP())
regionID := int(ipp.Port())
if lastReport.RegionLatency[regionID] < fastestRegionLatency {
fastestRegionLatency = lastReport.RegionLatency[regionID]
preferredExitNodeID = peer.StableID()
b.logf("fastest region latency %v preferred exit node id %v", lastReport.RegionLatency[regionID], peer.StableID())
}
}
}
// b.mu.Unlock()
prefs := b.Prefs().AsStruct()
prefs.ExitNodeID = preferredExitNodeID
_, err := b.EditPrefs(&ipn.MaskedPrefs{
Prefs: ipn.Prefs{
ExitNodeID: preferredExitNodeID,
},
ExitNodeIDSet: true,
})
if err != nil {
return fmt.Errorf("Failed to suggest exit node %v, err %v", preferredExitNodeID, err)
}
return nil
}

View File

@@ -129,6 +129,7 @@ var handler = map[string]localAPIHandler{
"update/check": (*Handler).serveUpdateCheck,
"update/install": (*Handler).serveUpdateInstall,
"update/progress": (*Handler).serveUpdateProgress,
"suggest-exit-node": (*Handler).serveSuggestExitNode,
}
var (
@@ -2504,3 +2505,19 @@ var (
// User-visible LocalAPI endpoints.
metricFilePutCalls = clientmetric.NewCounter("localapi_file_put")
)
func (h *Handler) serveSuggestExitNode(w http.ResponseWriter, r *http.Request) {
if !h.PermitWrite {
http.Error(w, "access denied", http.StatusForbidden)
return
}
if r.Method != "POST" {
http.Error(w, "want POST", http.StatusBadRequest)
return
}
err := h.b.SuggestExitNode()
if err != nil {
writeErrorJSON(w, err)
return
}
}

View File

@@ -799,6 +799,7 @@ func (p *Prefs) SetExitNodeIP(s string, st *ipnstate.Status) error {
if err == nil {
p.ExitNodeIP = ip
}
return err
}