diff --git a/ipn/handle.go b/ipn/handle.go deleted file mode 100644 index 225f1b6ed..000000000 --- a/ipn/handle.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ipn - -import ( - "net/netip" - "sync" - "time" - - "tailscale.com/tailcfg" - "tailscale.com/types/logger" - "tailscale.com/types/netmap" -) - -type Handle struct { - b Backend - logf logger.Logf - - // Mutex protects everything below - mu sync.Mutex - xnotify func(Notify) - frontendLogID string - netmapCache *netmap.NetworkMap - engineStatusCache EngineStatus - stateCache State - prefsCache *Prefs -} - -func NewHandle(b Backend, logf logger.Logf, notify func(Notify), opts Options) (*Handle, error) { - h := &Handle{ - b: b, - logf: logf, - } - - h.SetNotifyCallback(notify) - err := h.Start(opts) - if err != nil { - return nil, err - } - - return h, nil -} - -func (h *Handle) SetNotifyCallback(notify func(Notify)) { - h.mu.Lock() - h.xnotify = notify - h.mu.Unlock() - - h.b.SetNotifyCallback(h.notify) -} - -func (h *Handle) Start(opts Options) error { - h.mu.Lock() - h.frontendLogID = opts.FrontendLogID - h.netmapCache = nil - h.engineStatusCache = EngineStatus{} - h.stateCache = NoState - if opts.Prefs != nil { - h.prefsCache = opts.Prefs.Clone() - } - h.mu.Unlock() - return h.b.Start(opts) -} - -func (h *Handle) Reset() { - st := NoState - h.notify(Notify{State: &st}) -} - -func (h *Handle) notify(n Notify) { - h.mu.Lock() - if n.BackendLogID != nil { - h.logf("Handle: logs: be:%v fe:%v", - *n.BackendLogID, h.frontendLogID) - } - if n.State != nil { - h.stateCache = *n.State - } - if n.Prefs != nil { - h.prefsCache = n.Prefs.Clone() - } - if n.NetMap != nil { - h.netmapCache = n.NetMap - } - if n.Engine != nil { - h.engineStatusCache = *n.Engine - } - h.mu.Unlock() - - if h.xnotify != nil { - // Forward onward to our parent's notifier - h.xnotify(n) - } -} - -func (h *Handle) Prefs() *Prefs { - h.mu.Lock() - defer h.mu.Unlock() - - return h.prefsCache.Clone() -} - -func (h *Handle) UpdatePrefs(updateFn func(p *Prefs)) { - h.mu.Lock() - defer h.mu.Unlock() - - new := h.prefsCache.Clone() - updateFn(new) - h.prefsCache = new - h.b.SetPrefs(new) -} - -func (h *Handle) State() State { - h.mu.Lock() - defer h.mu.Unlock() - - return h.stateCache -} - -func (h *Handle) EngineStatus() EngineStatus { - h.mu.Lock() - defer h.mu.Unlock() - - return h.engineStatusCache -} - -func (h *Handle) LocalAddrs() []netip.Prefix { - h.mu.Lock() - defer h.mu.Unlock() - - nm := h.netmapCache - if nm != nil { - return nm.Addresses - } - return []netip.Prefix{} -} - -func (h *Handle) NetMap() *netmap.NetworkMap { - h.mu.Lock() - defer h.mu.Unlock() - - return h.netmapCache -} - -func (h *Handle) Expiry() time.Time { - h.mu.Lock() - defer h.mu.Unlock() - - nm := h.netmapCache - if nm != nil { - return nm.Expiry - } - return time.Time{} -} - -func (h *Handle) AdminPageURL() string { - return h.prefsCache.AdminPageURL() -} - -func (h *Handle) StartLoginInteractive() { - h.b.StartLoginInteractive() -} - -func (h *Handle) Login(token *tailcfg.Oauth2Token) { - h.b.Login(token) -} - -func (h *Handle) Logout() { - h.b.Logout() -} - -func (h *Handle) RequestEngineStatus() { - h.b.RequestEngineStatus() -} diff --git a/ipn/message_test.go b/ipn/message_test.go index e3b3b7d12..cc95e938a 100644 --- a/ipn/message_test.go +++ b/ipn/message_test.go @@ -6,12 +6,8 @@ package ipn import ( "bytes" - "context" - "encoding/json" "testing" - "time" - "tailscale.com/tailcfg" "tailscale.com/tstest" ) @@ -61,133 +57,6 @@ func TestReadWrite(t *testing.T) { } } -func TestClientServer(t *testing.T) { - tstest.PanicOnLog() - tstest.ResourceCheck(t) - - b := &FakeBackend{} - var bs *BackendServer - var bc *BackendClient - serverToClientCh := make(chan []byte, 16) - defer close(serverToClientCh) - go func() { - for b := range serverToClientCh { - bc.GotNotifyMsg(b) - } - }() - serverToClient := func(n Notify) { - b, err := json.Marshal(n) - if err != nil { - panic(err.Error()) - } - serverToClientCh <- append([]byte{}, b...) - } - clientToServer := func(b []byte) { - bs.GotCommandMsg(context.TODO(), b) - } - slogf := func(fmt string, args ...any) { - t.Logf("s: "+fmt, args...) - } - clogf := func(fmt string, args ...any) { - t.Logf("c: "+fmt, args...) - } - bs = NewBackendServer(slogf, b, serverToClient) - // Verify that this doesn't break bs's callback: - NewBackendServer(slogf, b, nil) - bc = NewBackendClient(clogf, clientToServer) - - ch := make(chan Notify, 256) - notify := func(n Notify) { ch <- n } - h, err := NewHandle(bc, clogf, notify, Options{ - Prefs: &Prefs{ - ControlURL: "http://example.com/fake", - }, - }) - if err != nil { - t.Fatalf("NewHandle error: %v\n", err) - } - - notes := Notify{} - nn := []Notify{} - processNote := func(n Notify) { - nn = append(nn, n) - if n.State != nil { - t.Logf("state change: %v", *n.State) - notes.State = n.State - } - if n.Prefs != nil { - notes.Prefs = n.Prefs - } - if n.NetMap != nil { - notes.NetMap = n.NetMap - } - if n.Engine != nil { - notes.Engine = n.Engine - } - if n.BrowseToURL != nil { - notes.BrowseToURL = n.BrowseToURL - } - } - notesState := func() State { - if notes.State != nil { - return *notes.State - } - return NoState - } - - flushUntil := func(wantFlush State) { - t.Helper() - timer := time.NewTimer(1 * time.Second) - loop: - for { - select { - case n := <-ch: - processNote(n) - if notesState() == wantFlush { - break loop - } - case <-timer.C: - t.Fatalf("timeout waiting for state %v, got %v", wantFlush, notes.State) - } - } - timer.Stop() - loop2: - for { - select { - case n := <-ch: - processNote(n) - default: - break loop2 - } - } - if got, want := h.State(), notesState(); got != want { - t.Errorf("h.State()=%v, notes.State=%v (on flush until %v)\n", got, want, wantFlush) - } - } - - flushUntil(NeedsLogin) - - h.StartLoginInteractive() - flushUntil(Running) - if notes.NetMap == nil && h.NetMap() != nil { - t.Errorf("notes.NetMap == nil while h.NetMap != nil\nnotes:\n%v", nn) - } - - h.UpdatePrefs(func(p *Prefs) { - p.WantRunning = false - }) - flushUntil(Stopped) - - h.Logout() - flushUntil(NeedsLogin) - - h.Login(&tailcfg.Oauth2Token{ - AccessToken: "google_id_token", - TokenType: GoogleIDTokenType, - }) - flushUntil(Running) -} - func TestNilBackend(t *testing.T) { var called *Notify bs := NewBackendServer(t.Logf, nil, func(n Notify) {