summaryrefslogtreecommitdiffhomepage
path: root/control/controlclient/direct.go
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@tailscale.com>2020-12-23 13:03:16 -0800
committerBrad Fitzpatrick <bradfitz@tailscale.com>2021-01-08 09:19:06 -0800
commitbc77c66290b9eee2c9050c6a96a0987a7f2904be (patch)
tree8ded7495f60bb5114da5cf41092515d41a69e32d /control/controlclient/direct.go
parente692e3866bf2cbe240b64f96e03d590539e67aef (diff)
downloadtailscale-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.go26
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,