diff options
| author | Brad Fitzpatrick <bradfitz@tailscale.com> | 2020-12-23 13:03:16 -0800 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@tailscale.com> | 2021-01-08 09:19:06 -0800 |
| commit | bc77c66290b9eee2c9050c6a96a0987a7f2904be (patch) | |
| tree | 8ded7495f60bb5114da5cf41092515d41a69e32d /control/controlclient/direct.go | |
| parent | e692e3866bf2cbe240b64f96e03d590539e67aef (diff) | |
| download | tailscale-bradfitz/lite_endpoint_update.tar.xz tailscale-bradfitz/lite_endpoint_update.zip | |
control/controlclient: use lite map request handler to avoid aborting streamsbradfitz/lite_endpoint_update
Previously, any change to endpoints or hostinfo (or hostinfo's
netinfo) would result in the long-running map request HTTP stream
being torn down and restarted, losing all compression context along
with it.
This change makes us instead send a lite map request (OmitPeers: true,
Stream: false) that doesn't subscribe to anything, and then the
coordination server knows to not close other streams for that node
when it recives a lite request.
Fixes tailscale/corp#797
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Diffstat (limited to 'control/controlclient/direct.go')
| -rw-r--r-- | control/controlclient/direct.go | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index c985037ae..612ccbfc6 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -521,6 +521,18 @@ func inTest() bool { return flag.Lookup("test.v") != nil } // maxPolls is how many network maps to download; common values are 1 // or -1 (to keep a long-poll query open to the server). func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkMap)) error { + return c.sendMapRequest(ctx, maxPolls, cb) +} + +// SendLiteMapUpdate makes a /map request to update the server of our latest state, +// but does not fetch anything. It returns an error if the server did not return a +// successful 200 OK response. +func (c *Direct) SendLiteMapUpdate(ctx context.Context) error { + return c.sendMapRequest(ctx, 1, nil) +} + +// cb nil means to omit peers. +func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*NetworkMap)) error { c.mu.Lock() persist := c.persist serverURL := c.serverURL @@ -555,6 +567,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM Stream: allowStream, Hostinfo: hostinfo, DebugFlags: c.debugFlags, + OmitPeers: cb == nil, } if hostinfo != nil && ipForwardingBroken(hostinfo.RoutableIPs) { old := request.DebugFlags @@ -607,6 +620,11 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM } defer res.Body.Close() + if cb == nil { + io.Copy(ioutil.Discard, res.Body) + 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. @@ -724,6 +742,14 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM lastParsedPacketFilter = c.parsePacketFilter(pf) } + // Get latest localPort. This might've changed if + // a lite map update occured meanwhile. This only affects + // the end-to-end test. + // TODO(bradfitz): remove the NetworkMap.LocalPort field entirely. + c.mu.Lock() + localPort = c.localPort + c.mu.Unlock() + nm := &NetworkMap{ NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()), PrivateKey: persist.PrivateNodeKey, |
