mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-11-04 02:01:14 +01:00 
			
		
		
		
	PR #17258 extracted `derp.Server` into `derp/derpserver.Server`. This followup patch adds the following cleanups: 1. Rename `derp_server*.go` files to `derpserver*.go` to match the package name. 2. Rename the `derpserver.NewServer` constructor to `derpserver.New` to reduce stuttering. 3. Remove the unnecessary `derpserver.Conn` type alias. Updates #17257 Updates #cleanup Signed-off-by: Simon Law <sfllaw@tailscale.com>
		
			
				
	
	
		
			92 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright (c) Tailscale Inc & AUTHORS
 | 
						|
// SPDX-License-Identifier: BSD-3-Clause
 | 
						|
 | 
						|
//go:build linux && !android
 | 
						|
 | 
						|
package derpserver
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"crypto/tls"
 | 
						|
	"net"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"tailscale.com/net/tcpinfo"
 | 
						|
)
 | 
						|
 | 
						|
func (c *sclient) startStatsLoop(ctx context.Context) {
 | 
						|
	// Get the RTT initially to verify it's supported.
 | 
						|
	conn := c.tcpConn()
 | 
						|
	if conn == nil {
 | 
						|
		c.s.tcpRtt.Add("non-tcp", 1)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if _, err := tcpinfo.RTT(conn); err != nil {
 | 
						|
		c.logf("error fetching initial RTT: %v", err)
 | 
						|
		c.s.tcpRtt.Add("error", 1)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	const statsInterval = 10 * time.Second
 | 
						|
 | 
						|
	// Don't launch a goroutine; use a timer instead.
 | 
						|
	var gatherStats func()
 | 
						|
	gatherStats = func() {
 | 
						|
		// Do nothing if the context is finished.
 | 
						|
		if ctx.Err() != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		// Reschedule ourselves when this stats gathering is finished.
 | 
						|
		defer c.s.clock.AfterFunc(statsInterval, gatherStats)
 | 
						|
 | 
						|
		// Gather TCP RTT information.
 | 
						|
		rtt, err := tcpinfo.RTT(conn)
 | 
						|
		if err == nil {
 | 
						|
			c.s.tcpRtt.Add(durationToLabel(rtt), 1)
 | 
						|
		}
 | 
						|
 | 
						|
		// TODO(andrew): more metrics?
 | 
						|
	}
 | 
						|
 | 
						|
	// Kick off the initial timer.
 | 
						|
	c.s.clock.AfterFunc(statsInterval, gatherStats)
 | 
						|
}
 | 
						|
 | 
						|
// tcpConn attempts to get the underlying *net.TCPConn from this client's
 | 
						|
// Conn; if it cannot, then it will return nil.
 | 
						|
func (c *sclient) tcpConn() *net.TCPConn {
 | 
						|
	nc := c.nc
 | 
						|
	for {
 | 
						|
		switch v := nc.(type) {
 | 
						|
		case *net.TCPConn:
 | 
						|
			return v
 | 
						|
		case *tls.Conn:
 | 
						|
			nc = v.NetConn()
 | 
						|
		default:
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func durationToLabel(dur time.Duration) string {
 | 
						|
	switch {
 | 
						|
	case dur <= 10*time.Millisecond:
 | 
						|
		return "10ms"
 | 
						|
	case dur <= 20*time.Millisecond:
 | 
						|
		return "20ms"
 | 
						|
	case dur <= 50*time.Millisecond:
 | 
						|
		return "50ms"
 | 
						|
	case dur <= 100*time.Millisecond:
 | 
						|
		return "100ms"
 | 
						|
	case dur <= 150*time.Millisecond:
 | 
						|
		return "150ms"
 | 
						|
	case dur <= 250*time.Millisecond:
 | 
						|
		return "250ms"
 | 
						|
	case dur <= 500*time.Millisecond:
 | 
						|
		return "500ms"
 | 
						|
	default:
 | 
						|
		return "inf"
 | 
						|
	}
 | 
						|
}
 |