Browse Source

derp/derphttp: determine whether a region connect was to non-ideal node

... and then do approximately nothing with that information, other
than a big TODO. This is mostly me relearning this code and leaving
breadcrumbs for others in the future.

Updates #12724

Signed-off-by: Brad Fitzpatrick <[email protected]>
Brad Fitzpatrick 1 year ago
parent
commit
f77821fd63
1 changed files with 14 additions and 0 deletions
  1. 14 0
      derp/derphttp/derphttp_client.go

+ 14 - 0
derp/derphttp/derphttp_client.go

@@ -381,6 +381,7 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
 	}()
 
 	var node *tailcfg.DERPNode // nil when using c.url to dial
+	var idealNodeInRegion bool
 	switch {
 	case useWebsockets():
 		var urlStr string
@@ -421,6 +422,7 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
 	default:
 		c.logf("%s: connecting to derp-%d (%v)", caller, reg.RegionID, reg.RegionCode)
 		tcpConn, node, err = c.dialRegion(ctx, reg)
+		idealNodeInRegion = err == nil && reg.Nodes[0] == node
 	}
 	if err != nil {
 		return nil, 0, err
@@ -494,6 +496,18 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
 	}
 	req.Header.Set("Upgrade", "DERP")
 	req.Header.Set("Connection", "Upgrade")
+	if !idealNodeInRegion && reg != nil {
+		// This is purely informative for now (2024-07-06) for stats:
+		req.Header.Set("Ideal-Node", reg.Nodes[0].Name)
+		// TODO(bradfitz,raggi): start a time.AfterFunc for 30m-1h or so to
+		// dialNode(reg.Nodes[0]) and see if we can even TCP connect to it. If
+		// so, TLS handshake it as well (which is mixed up in this massive
+		// connect method) and then if it all appears good, grab the mutex, bump
+		// connGen, finish the Upgrade, close the old one, and set a new field
+		// on Client that's like "here's the connect result and connGen for the
+		// next connect that comes in"). Tracking bug for all this is:
+		// https://github.com/tailscale/tailscale/issues/12724
+	}
 
 	if !serverPub.IsZero() && serverProtoVersion != 0 {
 		// parseMetaCert found the server's public key (no TLS