mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-20 11:58:39 +00:00
control/controlclient, tailcfg: add Debug.SleepSeconds (mapver 19)
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
c91a22c82e
commit
6f52fa02a3
@ -570,6 +570,11 @@ func (c *Direct) SendLiteMapUpdate(ctx context.Context) error {
|
|||||||
return c.sendMapRequest(ctx, 1, nil)
|
return c.sendMapRequest(ctx, 1, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we go more than pollTimeout without hearing from the server,
|
||||||
|
// end the long poll. We should be receiving a keep alive ping
|
||||||
|
// every minute.
|
||||||
|
const pollTimeout = 120 * time.Second
|
||||||
|
|
||||||
// cb nil means to omit peers.
|
// cb nil means to omit peers.
|
||||||
func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netmap.NetworkMap)) error {
|
func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netmap.NetworkMap)) error {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
@ -694,10 +699,6 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we go more than pollTimeout without hearing from the server,
|
|
||||||
// end the long poll. We should be receiving a keep alive ping
|
|
||||||
// every minute.
|
|
||||||
const pollTimeout = 120 * time.Second
|
|
||||||
timeout := time.NewTimer(pollTimeout)
|
timeout := time.NewTimer(pollTimeout)
|
||||||
timeoutReset := make(chan struct{})
|
timeoutReset := make(chan struct{})
|
||||||
pollDone := make(chan struct{})
|
pollDone := make(chan struct{})
|
||||||
@ -795,6 +796,11 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
|
|||||||
}
|
}
|
||||||
setControlAtomic(&controlUseDERPRoute, resp.Debug.DERPRoute)
|
setControlAtomic(&controlUseDERPRoute, resp.Debug.DERPRoute)
|
||||||
setControlAtomic(&controlTrimWGConfig, resp.Debug.TrimWGConfig)
|
setControlAtomic(&controlTrimWGConfig, resp.Debug.TrimWGConfig)
|
||||||
|
if sleep := time.Duration(resp.Debug.SleepSeconds * float64(time.Second)); sleep > 0 {
|
||||||
|
if err := sleepAsRequested(ctx, c.logf, timeoutReset, sleep); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nm := sess.netmapForResponse(&resp)
|
nm := sess.netmapForResponse(&resp)
|
||||||
@ -1181,3 +1187,34 @@ func answerPing(logf logger.Logf, c *http.Client, pr *tailcfg.PingRequest) {
|
|||||||
logf("answerPing complete to %v (after %v)", pr.URL, d)
|
logf("answerPing complete to %v (after %v)", pr.URL, d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sleepAsRequested(ctx context.Context, logf logger.Logf, timeoutReset chan<- struct{}, d time.Duration) error {
|
||||||
|
const maxSleep = 5 * time.Minute
|
||||||
|
if d > maxSleep {
|
||||||
|
logf("sleeping for %v, capped from server-requested %v ...", maxSleep, d)
|
||||||
|
d = maxSleep
|
||||||
|
} else {
|
||||||
|
logf("sleeping for server-requested %v ...", d)
|
||||||
|
}
|
||||||
|
|
||||||
|
ticker := time.NewTicker(pollTimeout / 2)
|
||||||
|
defer ticker.Stop()
|
||||||
|
timer := time.NewTimer(d)
|
||||||
|
defer timer.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-timer.C:
|
||||||
|
return nil
|
||||||
|
case <-ticker.C:
|
||||||
|
select {
|
||||||
|
case timeoutReset <- struct{}{}:
|
||||||
|
case <-timer.C:
|
||||||
|
return nil
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -41,7 +41,8 @@ import (
|
|||||||
// 16: 2021-04-15: client understands Node.Online, MapResponse.OnlineChange
|
// 16: 2021-04-15: client understands Node.Online, MapResponse.OnlineChange
|
||||||
// 17: 2021-04-18: MapResponse.Domain empty means unchanged
|
// 17: 2021-04-18: MapResponse.Domain empty means unchanged
|
||||||
// 18: 2021-04-19: MapResponse.Node nil means unchanged (all fields now omitempty)
|
// 18: 2021-04-19: MapResponse.Node nil means unchanged (all fields now omitempty)
|
||||||
const CurrentMapRequestVersion = 18
|
// 19: 2021-04-21: MapResponse.Debug.SleepSeconds
|
||||||
|
const CurrentMapRequestVersion = 19
|
||||||
|
|
||||||
type StableID string
|
type StableID string
|
||||||
|
|
||||||
@ -1012,6 +1013,12 @@ type Debug struct {
|
|||||||
// GoroutineDumpURL, if non-empty, requests that the client do
|
// GoroutineDumpURL, if non-empty, requests that the client do
|
||||||
// a one-time dump of its active goroutines to the given URL.
|
// a one-time dump of its active goroutines to the given URL.
|
||||||
GoroutineDumpURL string `json:",omitempty"`
|
GoroutineDumpURL string `json:",omitempty"`
|
||||||
|
|
||||||
|
// SleepSeconds requests that the client sleep for the
|
||||||
|
// provided number of seconds.
|
||||||
|
// The client can (and should) limit the value (such as 5
|
||||||
|
// minutes).
|
||||||
|
SleepSeconds float64 `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k MachineKey) String() string { return fmt.Sprintf("mkey:%x", k[:]) }
|
func (k MachineKey) String() string { return fmt.Sprintf("mkey:%x", k[:]) }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user