mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-12 05:37:32 +00:00
ipn/ipnlocal: stay out of map poll when down
Fixes #2434 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
798b0da470
commit
6eecf3c9d1
@@ -205,6 +205,13 @@ func (lc *LogCatcher) logsString() string {
|
||||
return lc.buf.String()
|
||||
}
|
||||
|
||||
// Reset clears the buffered logs from memory.
|
||||
func (lc *LogCatcher) Reset() {
|
||||
lc.mu.Lock()
|
||||
defer lc.mu.Unlock()
|
||||
lc.buf.Reset()
|
||||
}
|
||||
|
||||
func (lc *LogCatcher) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
var body io.Reader = r.Body
|
||||
if r.Header.Get("Content-Encoding") == "zstd" {
|
||||
|
@@ -72,29 +72,9 @@ func TestOneNodeUp_NoAuth(t *testing.T) {
|
||||
|
||||
d1 := n1.StartDaemon(t)
|
||||
defer d1.Kill()
|
||||
|
||||
n1.AwaitListening(t)
|
||||
|
||||
st := n1.MustStatus(t)
|
||||
t.Logf("Status: %s", st.BackendState)
|
||||
|
||||
if err := tstest.WaitFor(20*time.Second, func() error {
|
||||
const sub = `Program starting: `
|
||||
if !env.LogCatcher.logsContains(mem.S(sub)) {
|
||||
return fmt.Errorf("log catcher didn't see %#q; got %s", sub, env.LogCatcher.logsString())
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
n1.AwaitResponding(t)
|
||||
n1.MustUp()
|
||||
|
||||
if d, _ := time.ParseDuration(os.Getenv("TS_POST_UP_SLEEP")); d > 0 {
|
||||
t.Logf("Sleeping for %v to give 'up' time to misbehave (https://github.com/tailscale/tailscale/issues/1840) ...", d)
|
||||
time.Sleep(d)
|
||||
}
|
||||
|
||||
t.Logf("Got IP: %v", n1.AwaitIP(t))
|
||||
n1.AwaitRunning(t)
|
||||
|
||||
@@ -115,22 +95,7 @@ func TestStateSavedOnStart(t *testing.T) {
|
||||
|
||||
d1 := n1.StartDaemon(t)
|
||||
defer d1.Kill()
|
||||
|
||||
n1.AwaitListening(t)
|
||||
|
||||
st := n1.MustStatus(t)
|
||||
t.Logf("Status: %s", st.BackendState)
|
||||
|
||||
if err := tstest.WaitFor(20*time.Second, func() error {
|
||||
const sub = `Program starting: `
|
||||
if !env.LogCatcher.logsContains(mem.S(sub)) {
|
||||
return fmt.Errorf("log catcher didn't see %#q; got %s", sub, env.LogCatcher.logsString())
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
n1.AwaitResponding(t)
|
||||
n1.MustUp()
|
||||
|
||||
t.Logf("Got IP: %v", n1.AwaitIP(t))
|
||||
@@ -346,6 +311,53 @@ func TestAddPingRequest(t *testing.T) {
|
||||
t.Error("all ping attempts failed")
|
||||
}
|
||||
|
||||
// Issue 2434: when "down" (WantRunning false), tailscaled shouldn't
|
||||
// be connected to control.
|
||||
func TestNoControlConnectionWhenDown(t *testing.T) {
|
||||
t.Parallel()
|
||||
bins := BuildTestBinaries(t)
|
||||
|
||||
env := newTestEnv(t, bins)
|
||||
defer env.Close()
|
||||
|
||||
n1 := newTestNode(t, env)
|
||||
|
||||
d1 := n1.StartDaemon(t)
|
||||
defer d1.Kill()
|
||||
n1.AwaitResponding(t)
|
||||
|
||||
// Come up the first time.
|
||||
n1.MustUp()
|
||||
ip1 := n1.AwaitIP(t)
|
||||
n1.AwaitRunning(t)
|
||||
|
||||
// Then bring it down and stop the daemon.
|
||||
n1.MustDown()
|
||||
d1.MustCleanShutdown(t)
|
||||
|
||||
env.LogCatcher.Reset()
|
||||
d2 := n1.StartDaemon(t)
|
||||
defer d2.Kill()
|
||||
n1.AwaitResponding(t)
|
||||
|
||||
st := n1.MustStatus(t)
|
||||
if got, want := st.BackendState, "Stopped"; got != want {
|
||||
t.Fatalf("after restart, state = %q; want %q", got, want)
|
||||
}
|
||||
|
||||
ip2 := n1.AwaitIP(t)
|
||||
if ip1 != ip2 {
|
||||
t.Errorf("IPs different: %q vs %q", ip1, ip2)
|
||||
}
|
||||
|
||||
// The real test: verify our daemon doesn't have an HTTP request open.:
|
||||
if n := env.Control.InServeMap(); n != 0 {
|
||||
t.Errorf("in serve map = %d; want 0", n)
|
||||
}
|
||||
|
||||
d2.MustCleanShutdown(t)
|
||||
}
|
||||
|
||||
// testEnv contains the test environment (set of servers) used by one
|
||||
// or more nodes.
|
||||
type testEnv struct {
|
||||
@@ -462,6 +474,26 @@ func (n *testNode) diskPrefs(t testing.TB) *ipn.Prefs {
|
||||
return p
|
||||
}
|
||||
|
||||
// AwaitResponding waits for n's tailscaled to be up enough to be
|
||||
// responding, but doesn't wait for any particular state.
|
||||
func (n *testNode) AwaitResponding(t testing.TB) {
|
||||
t.Helper()
|
||||
n.AwaitListening(t)
|
||||
|
||||
st := n.MustStatus(t)
|
||||
t.Logf("Status: %s", st.BackendState)
|
||||
|
||||
if err := tstest.WaitFor(20*time.Second, func() error {
|
||||
const sub = `Program starting: `
|
||||
if !n.env.LogCatcher.logsContains(mem.S(sub)) {
|
||||
return fmt.Errorf("log catcher didn't see %#q; got %s", sub, n.env.LogCatcher.logsString())
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// addLogLineHook registers a hook f to be called on each tailscaled
|
||||
// log line output.
|
||||
func (n *testNode) addLogLineHook(f func([]byte)) {
|
||||
@@ -654,6 +686,7 @@ func (n *testNode) AwaitIP(t testing.TB) netaddr.IP {
|
||||
return ips[0]
|
||||
}
|
||||
|
||||
// AwaitRunning waits for n to reach the IPN state "Running".
|
||||
func (n *testNode) AwaitRunning(t testing.TB) {
|
||||
t.Helper()
|
||||
if err := tstest.WaitFor(20*time.Second, func() error {
|
||||
|
@@ -51,6 +51,7 @@ type Server struct {
|
||||
mux *http.ServeMux
|
||||
|
||||
mu sync.Mutex
|
||||
inServeMap int
|
||||
cond *sync.Cond // lazily initialized by condLocked
|
||||
pubKey wgkey.Key
|
||||
privKey wgkey.Private
|
||||
@@ -509,7 +510,22 @@ func (s *Server) UpdateNode(n *tailcfg.Node) (peersToUpdate []tailcfg.NodeID) {
|
||||
return peersToUpdate
|
||||
}
|
||||
|
||||
func (s *Server) incrInServeMap(delta int) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.inServeMap += delta
|
||||
}
|
||||
|
||||
// InServeMap returns the number of clients currently in a MapRequest HTTP handler.
|
||||
func (s *Server) InServeMap() int {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.inServeMap
|
||||
}
|
||||
|
||||
func (s *Server) serveMap(w http.ResponseWriter, r *http.Request, mkey tailcfg.MachineKey) {
|
||||
s.incrInServeMap(1)
|
||||
defer s.incrInServeMap(-1)
|
||||
ctx := r.Context()
|
||||
|
||||
req := new(tailcfg.MapRequest)
|
||||
|
Reference in New Issue
Block a user