mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-12 09:07:05 +00:00
wip
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,6 +799,7 @@ func (p *Prefs) SetExitNodeIP(s string, st *ipnstate.Status) error {
|
||||
if err == nil {
|
||||
p.ExitNodeIP = ip
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user