ipn/ipnstate: move tailscale status "active" determination to tailscaled

Fixes #2579

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/2584/head
Brad Fitzpatrick 3 years ago committed by Brad Fitzpatrick
parent 0858673f1f
commit f3c96df162

@ -14,7 +14,6 @@ import (
"net/http"
"os"
"strings"
"time"
"github.com/peterbourgon/ff/v2/ffcli"
"github.com/toqueteos/webbrowser"
@ -23,7 +22,6 @@ import (
"tailscale.com/ipn"
"tailscale.com/ipn/ipnstate"
"tailscale.com/net/interfaces"
"tailscale.com/tstime/mono"
"tailscale.com/util/dnsname"
)
@ -63,7 +61,7 @@ func runStatus(ctx context.Context, args []string) error {
if statusArgs.json {
if statusArgs.active {
for peer, ps := range st.Peer {
if !peerActive(ps) {
if !ps.Active {
delete(st.Peer, peer)
}
}
@ -131,7 +129,6 @@ func runStatus(ctx context.Context, args []string) error {
var buf bytes.Buffer
f := func(format string, a ...interface{}) { fmt.Fprintf(&buf, format, a...) }
printPS := func(ps *ipnstate.PeerStatus) {
active := peerActive(ps)
f("%-15s %-20s %-12s %-7s ",
firstIPString(ps.TailscaleIPs),
dnsOrQuoteHostname(st, ps),
@ -140,7 +137,7 @@ func runStatus(ctx context.Context, args []string) error {
)
relay := ps.Relay
anyTraffic := ps.TxBytes != 0 || ps.RxBytes != 0
if !active {
if !ps.Active {
if ps.ExitNode {
f("idle; exit node")
} else if anyTraffic {
@ -179,8 +176,7 @@ func runStatus(ctx context.Context, args []string) error {
}
ipnstate.SortPeers(peers)
for _, ps := range peers {
active := peerActive(ps)
if statusArgs.active && !active {
if statusArgs.active && !ps.Active {
continue
}
printPS(ps)
@ -190,13 +186,6 @@ func runStatus(ctx context.Context, args []string) error {
return nil
}
// peerActive reports whether ps has recent activity.
//
// TODO: have the server report this bool instead.
func peerActive(ps *ipnstate.PeerStatus) bool {
return !ps.LastWrite.IsZero() && mono.Since(ps.LastWrite) < 2*time.Minute
}
func dnsOrQuoteHostname(st *ipnstate.Status, ps *ipnstate.PeerStatus) string {
baseName := dnsname.TrimSuffix(ps.DNSName, st.MagicDNSSuffix)
if baseName != "" {

@ -49,7 +49,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
tailscale.com/syncs from tailscale.com/net/interfaces+
tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+
W tailscale.com/tsconst from tailscale.com/net/interfaces
💣 tailscale.com/tstime/mono from tailscale.com/cmd/tailscale/cli+
💣 tailscale.com/tstime/mono from tailscale.com/tstime/rate
tailscale.com/tstime/rate from tailscale.com/wgengine/filter
tailscale.com/types/empty from tailscale.com/ipn
tailscale.com/types/ipproto from tailscale.com/net/flowtrack+

@ -20,7 +20,6 @@ import (
"inet.af/netaddr"
"tailscale.com/tailcfg"
"tailscale.com/tstime/mono"
"tailscale.com/types/key"
"tailscale.com/util/dnsname"
)
@ -91,12 +90,19 @@ type PeerStatus struct {
RxBytes int64
TxBytes int64
Created time.Time // time registered with tailcontrol
LastWrite mono.Time // time last packet sent
LastWrite time.Time // time last packet sent
LastSeen time.Time // last seen to tailcontrol
LastHandshake time.Time // with local wireguard
KeepAlive bool
ExitNode bool // true if this is the currently selected exit node.
// Active is whether the node was recently active. The
// definition is somewhat undefined but has historically and
// currently means that there was some packet sent to this
// peer in the past two minutes. That definition is subject to
// change.
Active bool
PeerAPIURL []string
Capabilities []string `json:",omitempty"`
@ -278,6 +284,9 @@ func (sb *StatusBuilder) AddPeer(peer key.Public, st *PeerStatus) {
if st.ShareeNode {
e.ShareeNode = true
}
if st.Active {
e.Active = true
}
}
type StatusUpdater interface {
@ -321,7 +330,7 @@ table tbody tr:nth-child(even) td { background-color: #f5f5f5; }
f("<tr><th>Peer</th><th>OS</th><th>Node</th><th>Owner</th><th>Rx</th><th>Tx</th><th>Activity</th><th>Connection</th></tr>\n")
f("</thead>\n<tbody>\n")
now := mono.Now()
now := time.Now()
var peers []*PeerStatus
for _, peer := range st.Peers() {
@ -378,9 +387,7 @@ table tbody tr:nth-child(even) td { background-color: #f5f5f5; }
)
f("<td>")
// TODO: let server report this active bool instead
active := !ps.LastWrite.IsZero() && mono.Since(ps.LastWrite) < 2*time.Minute
if active {
if ps.Active {
if ps.Relay != "" && ps.CurAddr == "" {
f("relay <b>%s</b>", html.EscapeString(ps.Relay))
} else if ps.CurAddr != "" {

@ -95,16 +95,21 @@ func (t Time) String() string {
return fmt.Sprintf("mono.Time(ns=%d, estimated wall=%v)", int64(t), baseWall.Add(t.Sub(baseMono)).Truncate(0))
}
// WallTime returns an approximate wall time that corresponded to t.
func (t Time) WallTime() time.Time {
if !t.IsZero() {
return baseWall.Add(t.Sub(baseMono)).Truncate(0)
}
return time.Time{}
}
// MarshalJSON formats t for JSON as if it were a time.Time.
// We format Time this way for backwards-compatibility.
// This is best-effort only. Time does not survive a MarshalJSON/UnmarshalJSON round trip unchanged.
// Since t is a monotonic time, it can vary from the actual wall clock by arbitrary amounts.
// Even in the best of circumstances, it may vary by a few milliseconds.
func (t Time) MarshalJSON() ([]byte, error) {
var tt time.Time
if !t.IsZero() {
tt = baseWall.Add(t.Sub(baseMono)).Truncate(0)
}
tt := t.WallTime()
return tt.MarshalJSON()
}

@ -538,7 +538,7 @@ func (as *addrSet) populatePeerStatus(ps *ipnstate.PeerStatus) {
as.mu.Lock()
defer as.mu.Unlock()
ps.LastWrite = as.lastSend
ps.LastWrite = as.lastSend.WallTime()
for i, ua := range as.ipPorts {
if ua.IP() == derpMagicIPAddr {
continue

@ -3836,9 +3836,10 @@ func (de *discoEndpoint) populatePeerStatus(ps *ipnstate.PeerStatus) {
return
}
ps.LastWrite = de.lastSend
now := mono.Now()
ps.LastWrite = de.lastSend.WallTime()
ps.Active = now.Sub(de.lastSend) < sessionActiveTimeout
if udpAddr, derpAddr := de.addrForSendLocked(now); !udpAddr.IsZero() && derpAddr.IsZero() {
ps.CurAddr = udpAddr.String()
}

Loading…
Cancel
Save