mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
ipn: use *Prefs rather than Prefs throughout.
Prefs has become a heavy object with non-memcpy copy semantics. We should not pass such a thing by value. Signed-off-by: David Anderson <dave@natulte.net>
This commit is contained in:
parent
0c55777fed
commit
c47f907a27
@ -77,14 +77,13 @@ func main() {
|
|||||||
|
|
||||||
// TODO(apenwarr): fix different semantics between prefs and uflags
|
// TODO(apenwarr): fix different semantics between prefs and uflags
|
||||||
// TODO(apenwarr): allow setting/using CorpDNS
|
// TODO(apenwarr): allow setting/using CorpDNS
|
||||||
prefs := ipn.Prefs{
|
prefs := ipn.NewPrefs()
|
||||||
ControlURL: *server,
|
prefs.ControlURL = *server
|
||||||
WantRunning: true,
|
prefs.WantRunning = true
|
||||||
RouteAll: *routeall,
|
prefs.RouteAll = *routeall
|
||||||
AllowSingleHosts: !*nuroutes,
|
prefs.AllowSingleHosts = !*nuroutes
|
||||||
UsePacketFilter: !*nopf,
|
prefs.UsePacketFilter = !*nopf
|
||||||
AdvertiseRoutes: adv,
|
prefs.AdvertiseRoutes = adv
|
||||||
}
|
|
||||||
|
|
||||||
c, err := safesocket.Connect(*socket, 0)
|
c, err := safesocket.Connect(*socket, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -107,7 +107,7 @@ type Backend interface {
|
|||||||
// SetPrefs install a new set of user preferences, including
|
// SetPrefs install a new set of user preferences, including
|
||||||
// WantRunning. This may cause the wireguard engine to
|
// WantRunning. This may cause the wireguard engine to
|
||||||
// reconfigure or stop.
|
// reconfigure or stop.
|
||||||
SetPrefs(new Prefs)
|
SetPrefs(new *Prefs)
|
||||||
// RequestEngineStatus polls for an update from the wireguard
|
// RequestEngineStatus polls for an update from the wireguard
|
||||||
// engine. Only needed if you want to display byte
|
// engine. Only needed if you want to display byte
|
||||||
// counts. Connection events are emitted automatically without
|
// counts. Connection events are emitted automatically without
|
||||||
|
@ -53,8 +53,12 @@ func (b *FakeBackend) Logout() {
|
|||||||
b.newState(NeedsLogin)
|
b.newState(NeedsLogin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *FakeBackend) SetPrefs(new Prefs) {
|
func (b *FakeBackend) SetPrefs(new *Prefs) {
|
||||||
b.notify(Notify{Prefs: &new})
|
if new == nil {
|
||||||
|
panic("FakeBackend.SetPrefs got nil prefs")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.notify(Notify{Prefs: new.Copy()})
|
||||||
if new.WantRunning && !b.live {
|
if new.WantRunning && !b.live {
|
||||||
b.newState(Starting)
|
b.newState(Starting)
|
||||||
b.newState(Running)
|
b.newState(Running)
|
||||||
|
@ -23,7 +23,7 @@ type Handle struct {
|
|||||||
netmapCache *NetworkMap
|
netmapCache *NetworkMap
|
||||||
engineStatusCache EngineStatus
|
engineStatusCache EngineStatus
|
||||||
stateCache State
|
stateCache State
|
||||||
prefsCache Prefs
|
prefsCache *Prefs
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandle(b Backend, logf logger.Logf, opts Options) (*Handle, error) {
|
func NewHandle(b Backend, logf logger.Logf, opts Options) (*Handle, error) {
|
||||||
@ -47,7 +47,7 @@ func (h *Handle) Start(opts Options) error {
|
|||||||
h.engineStatusCache = EngineStatus{}
|
h.engineStatusCache = EngineStatus{}
|
||||||
h.stateCache = NoState
|
h.stateCache = NoState
|
||||||
if opts.Prefs != nil {
|
if opts.Prefs != nil {
|
||||||
h.prefsCache = *opts.Prefs
|
h.prefsCache = opts.Prefs.Copy()
|
||||||
}
|
}
|
||||||
xopts := opts
|
xopts := opts
|
||||||
xopts.Notify = h.notify
|
xopts.Notify = h.notify
|
||||||
@ -69,7 +69,7 @@ func (h *Handle) notify(n Notify) {
|
|||||||
h.stateCache = *n.State
|
h.stateCache = *n.State
|
||||||
}
|
}
|
||||||
if n.Prefs != nil {
|
if n.Prefs != nil {
|
||||||
h.prefsCache = *n.Prefs
|
h.prefsCache = n.Prefs.Copy()
|
||||||
}
|
}
|
||||||
if n.NetMap != nil {
|
if n.NetMap != nil {
|
||||||
h.netmapCache = n.NetMap
|
h.netmapCache = n.NetMap
|
||||||
@ -85,18 +85,19 @@ func (h *Handle) notify(n Notify) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) Prefs() Prefs {
|
func (h *Handle) Prefs() *Prefs {
|
||||||
h.mu.Lock()
|
h.mu.Lock()
|
||||||
defer h.mu.Unlock()
|
defer h.mu.Unlock()
|
||||||
|
|
||||||
return h.prefsCache
|
return h.prefsCache.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) UpdatePrefs(updateFn func(old Prefs) (new Prefs)) {
|
func (h *Handle) UpdatePrefs(updateFn func(p *Prefs)) {
|
||||||
h.mu.Lock()
|
h.mu.Lock()
|
||||||
defer h.mu.Unlock()
|
defer h.mu.Unlock()
|
||||||
|
|
||||||
new := updateFn(h.prefsCache)
|
new := h.prefsCache.Copy()
|
||||||
|
updateFn(new)
|
||||||
h.prefsCache = new
|
h.prefsCache = new
|
||||||
h.b.SetPrefs(new)
|
h.b.SetPrefs(new)
|
||||||
}
|
}
|
||||||
|
29
ipn/local.go
29
ipn/local.go
@ -40,7 +40,7 @@ type LocalBackend struct {
|
|||||||
// The mutex protects the following elements.
|
// The mutex protects the following elements.
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
stateKey StateKey
|
stateKey StateKey
|
||||||
prefs Prefs
|
prefs *Prefs
|
||||||
state State
|
state State
|
||||||
hiCache tailcfg.Hostinfo
|
hiCache tailcfg.Hostinfo
|
||||||
netMapCache *controlclient.NetworkMap
|
netMapCache *controlclient.NetworkMap
|
||||||
@ -207,8 +207,7 @@ func (b *LocalBackend) Start(opts Options) error {
|
|||||||
b.logf("Failed to save new controlclient state: %v", err)
|
b.logf("Failed to save new controlclient state: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
np := b.prefs
|
b.send(Notify{Prefs: b.prefs.Copy()})
|
||||||
b.send(Notify{Prefs: &np})
|
|
||||||
}
|
}
|
||||||
if new.NetMap != nil {
|
if new.NetMap != nil {
|
||||||
if b.netMapCache != nil && b.cmpDiff != nil {
|
if b.netMapCache != nil && b.cmpDiff != nil {
|
||||||
@ -277,8 +276,7 @@ func (b *LocalBackend) Start(opts Options) error {
|
|||||||
blid := b.backendLogID
|
blid := b.backendLogID
|
||||||
b.logf("Backend: logs: be:%v fe:%v\n", blid, opts.FrontendLogID)
|
b.logf("Backend: logs: be:%v fe:%v\n", blid, opts.FrontendLogID)
|
||||||
b.send(Notify{BackendLogID: &blid})
|
b.send(Notify{BackendLogID: &blid})
|
||||||
nprefs := b.prefs // make a copy
|
b.send(Notify{Prefs: b.prefs.Copy()})
|
||||||
b.send(Notify{Prefs: &nprefs})
|
|
||||||
|
|
||||||
cli.Login(nil, controlclient.LoginDefault)
|
cli.Login(nil, controlclient.LoginDefault)
|
||||||
return nil
|
return nil
|
||||||
@ -368,7 +366,7 @@ func (b *LocalBackend) loadStateWithLock(key StateKey, prefs *Prefs, legacyPath
|
|||||||
if key == "" {
|
if key == "" {
|
||||||
// Frontend fully owns the state, we just need to obey it.
|
// Frontend fully owns the state, we just need to obey it.
|
||||||
b.logf("Using frontend prefs")
|
b.logf("Using frontend prefs")
|
||||||
b.prefs = *prefs
|
b.prefs = prefs.Copy()
|
||||||
b.stateKey = ""
|
b.stateKey = ""
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -387,8 +385,13 @@ func (b *LocalBackend) loadStateWithLock(key StateKey, prefs *Prefs, legacyPath
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrStateNotExist {
|
if err == ErrStateNotExist {
|
||||||
if legacyPath != "" {
|
if legacyPath != "" {
|
||||||
b.prefs = *LoadPrefs(legacyPath, true)
|
b.prefs, err = LoadPrefs(legacyPath, true)
|
||||||
b.logf("Imported state from relaynode for %q", key)
|
if err != nil {
|
||||||
|
b.logf("Failed to load legacy prefs: %v", err)
|
||||||
|
b.prefs = NewPrefs()
|
||||||
|
} else {
|
||||||
|
b.logf("Imported state from relaynode for %q", key)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
b.prefs = NewPrefs()
|
b.prefs = NewPrefs()
|
||||||
b.logf("Created empty state for %q", key)
|
b.logf("Created empty state for %q", key)
|
||||||
@ -492,14 +495,18 @@ func (b *LocalBackend) AdminPageURL() string {
|
|||||||
return b.serverURL + "/admin/machines"
|
return b.serverURL + "/admin/machines"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) Prefs() Prefs {
|
func (b *LocalBackend) Prefs() *Prefs {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
return b.prefs
|
return b.prefs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) SetPrefs(new Prefs) {
|
func (b *LocalBackend) SetPrefs(new *Prefs) {
|
||||||
|
if new == nil {
|
||||||
|
panic("SetPrefs got nil prefs")
|
||||||
|
}
|
||||||
|
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
old := b.prefs
|
old := b.prefs
|
||||||
new.Persist = old.Persist // caller isn't allowed to override this
|
new.Persist = old.Persist // caller isn't allowed to override this
|
||||||
@ -527,7 +534,7 @@ func (b *LocalBackend) SetPrefs(new Prefs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.logf("SetPrefs: %v\n", new.Pretty())
|
b.logf("SetPrefs: %v\n", new.Pretty())
|
||||||
b.send(Notify{Prefs: &new})
|
b.send(Notify{Prefs: new})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: return value may be nil, if we haven't received a netmap yet.
|
// Note: return value may be nil, if we haven't received a netmap yet.
|
||||||
|
@ -24,7 +24,7 @@ type StartArgs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SetPrefsArgs struct {
|
type SetPrefsArgs struct {
|
||||||
New Prefs
|
New *Prefs
|
||||||
}
|
}
|
||||||
|
|
||||||
type FakeExpireAfterArgs struct {
|
type FakeExpireAfterArgs struct {
|
||||||
@ -191,7 +191,7 @@ func (bc *BackendClient) Logout() {
|
|||||||
bc.send(Command{Logout: &NoArgs{}})
|
bc.send(Command{Logout: &NoArgs{}})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *BackendClient) SetPrefs(new Prefs) {
|
func (bc *BackendClient) SetPrefs(new *Prefs) {
|
||||||
bc.send(Command{SetPrefs: &SetPrefsArgs{New: new}})
|
bc.send(Command{SetPrefs: &SetPrefsArgs{New: new}})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,9 +172,8 @@ func TestClientServer(t *testing.T) {
|
|||||||
t.Errorf("notes.NetMap == nil while h.NetMap != nil\nnotes:\n%v", nn)
|
t.Errorf("notes.NetMap == nil while h.NetMap != nil\nnotes:\n%v", nn)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.UpdatePrefs(func(p Prefs) Prefs {
|
h.UpdatePrefs(func(p *Prefs) {
|
||||||
p.WantRunning = false
|
p.WantRunning = false
|
||||||
return p
|
|
||||||
})
|
})
|
||||||
flushUntil(Stopped)
|
flushUntil(Stopped)
|
||||||
|
|
||||||
|
60
ipn/prefs.go
60
ipn/prefs.go
@ -116,11 +116,11 @@ func compareIPNets(a, b []wgcfg.CIDR) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPrefs() Prefs {
|
func NewPrefs() *Prefs {
|
||||||
return Prefs{
|
return &Prefs{
|
||||||
// Provide default values for options which are normally
|
// Provide default values for options which might be missing
|
||||||
// true, but might be missing from the json data for any
|
// from the json data for any reason. The json can still
|
||||||
// reason. The json can still override them to false.
|
// override them to false.
|
||||||
ControlURL: "https://login.tailscale.com",
|
ControlURL: "https://login.tailscale.com",
|
||||||
RouteAll: true,
|
RouteAll: true,
|
||||||
AllowSingleHosts: true,
|
AllowSingleHosts: true,
|
||||||
@ -130,7 +130,10 @@ func NewPrefs() Prefs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrefsFromBytes(b []byte, enforceDefaults bool) (Prefs, error) {
|
// PrefsFromBytes deserializes Prefs from a JSON blob. If
|
||||||
|
// enforceDefaults is true, Prefs.RouteAll and Prefs.AllowSingleHosts
|
||||||
|
// are forced on.
|
||||||
|
func PrefsFromBytes(b []byte, enforceDefaults bool) (*Prefs, error) {
|
||||||
p := NewPrefs()
|
p := NewPrefs()
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return p, nil
|
return p, nil
|
||||||
@ -146,11 +149,6 @@ func PrefsFromBytes(b []byte, enforceDefaults bool) (Prefs, error) {
|
|||||||
log.Printf("Prefs parse: %v: %v\n", err, b)
|
log.Printf("Prefs parse: %v: %v\n", err, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.ControlURL == "" {
|
|
||||||
// TODO(danderson): compat shim, remove after
|
|
||||||
// Options.ServerURL has been gone for a release.
|
|
||||||
p.ControlURL = "https://login.tailscale.com"
|
|
||||||
}
|
|
||||||
if enforceDefaults {
|
if enforceDefaults {
|
||||||
p.RouteAll = true
|
p.RouteAll = true
|
||||||
p.AllowSingleHosts = true
|
p.AllowSingleHosts = true
|
||||||
@ -158,48 +156,28 @@ func PrefsFromBytes(b []byte, enforceDefaults bool) (Prefs, error) {
|
|||||||
return p, err
|
return p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep copy of p.
|
||||||
func (p *Prefs) Copy() *Prefs {
|
func (p *Prefs) Copy() *Prefs {
|
||||||
p2, err := PrefsFromBytes(p.ToBytes(), false)
|
p2, err := PrefsFromBytes(p.ToBytes(), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Prefs was uncopyable: %v\n", err)
|
log.Fatalf("Prefs was uncopyable: %v\n", err)
|
||||||
}
|
}
|
||||||
return &p2
|
return p2
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadPrefs(filename string, enforceDefaults bool) *Prefs {
|
// LoadLegacyPrefs loads a legacy relaynode config file into Prefs
|
||||||
log.Printf("Loading prefs %v\n", filename)
|
// with sensible migration defaults set. If enforceDefaults is true,
|
||||||
|
// Prefs.RouteAll and Prefs.AllowSingleHosts are forced on.
|
||||||
|
func LoadPrefs(filename string, enforceDefaults bool) (*Prefs, error) {
|
||||||
data, err := ioutil.ReadFile(filename)
|
data, err := ioutil.ReadFile(filename)
|
||||||
p := NewPrefs()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Read: %v: %v\n", filename, err)
|
return nil, fmt.Errorf("loading prefs from %q: %v", filename, err)
|
||||||
goto fail
|
|
||||||
}
|
}
|
||||||
p, err = PrefsFromBytes(data, enforceDefaults)
|
p, err := PrefsFromBytes(data, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Parse: %v: %v\n", filename, err)
|
return nil, fmt.Errorf("decoding prefs in %q: %v", filename, err)
|
||||||
goto fail
|
|
||||||
}
|
}
|
||||||
goto post
|
return p, nil
|
||||||
fail:
|
|
||||||
log.Printf("failed to load config. Generating a new one.\n")
|
|
||||||
p = NewPrefs()
|
|
||||||
p.WantRunning = true
|
|
||||||
post:
|
|
||||||
// Update: we changed our minds :)
|
|
||||||
// Versabank would like to persist the setting across reboots, for now,
|
|
||||||
// because they don't fully trust the system and want to be able to
|
|
||||||
// leave it turned off when not in use. Eventually we need to make
|
|
||||||
// all motivation for this go away.
|
|
||||||
if false {
|
|
||||||
// Usability note: we always want WantRunning = true on startup.
|
|
||||||
// That way, if someone accidentally disables their VPN and doesn't
|
|
||||||
// know how, rebooting will fix it.
|
|
||||||
// We still persist WantRunning just in case we change our minds on
|
|
||||||
// this topic.
|
|
||||||
p.WantRunning = true
|
|
||||||
}
|
|
||||||
log.Printf("Loaded prefs %v %v\n", filename, p.Pretty())
|
|
||||||
return &p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SavePrefs(filename string, p *Prefs) {
|
func SavePrefs(filename string, p *Prefs) {
|
||||||
|
@ -180,8 +180,8 @@ func TestPrefsEqual(t *testing.T) {
|
|||||||
|
|
||||||
func checkPrefs(t *testing.T, p Prefs) {
|
func checkPrefs(t *testing.T, p Prefs) {
|
||||||
var err error
|
var err error
|
||||||
var p2, p2c Prefs
|
var p2, p2c *Prefs
|
||||||
var p2b Prefs
|
var p2b *Prefs
|
||||||
|
|
||||||
pp := p.Pretty()
|
pp := p.Pretty()
|
||||||
if pp == "" {
|
if pp == "" {
|
||||||
@ -195,9 +195,9 @@ func checkPrefs(t *testing.T, p Prefs) {
|
|||||||
if !p.Equals(&p) {
|
if !p.Equals(&p) {
|
||||||
t.Fatalf("p != p\n")
|
t.Fatalf("p != p\n")
|
||||||
}
|
}
|
||||||
p2 = p
|
p2 = p.Copy()
|
||||||
p2.RouteAll = true
|
p2.RouteAll = true
|
||||||
if p.Equals(&p2) {
|
if p.Equals(p2) {
|
||||||
t.Fatalf("p == p2\n")
|
t.Fatalf("p == p2\n")
|
||||||
}
|
}
|
||||||
p2b, err = PrefsFromBytes(p2.ToBytes(), false)
|
p2b, err = PrefsFromBytes(p2.ToBytes(), false)
|
||||||
@ -210,11 +210,11 @@ func checkPrefs(t *testing.T, p Prefs) {
|
|||||||
if p2p != p2bp {
|
if p2p != p2bp {
|
||||||
t.Fatalf("p2p != p2bp\n%#v\n%#v\n", p2p, p2bp)
|
t.Fatalf("p2p != p2bp\n%#v\n%#v\n", p2p, p2bp)
|
||||||
}
|
}
|
||||||
if !p2.Equals(&p2b) {
|
if !p2.Equals(p2b) {
|
||||||
t.Fatalf("p2 != p2b\n%#v\n%#v\n", p2, p2b)
|
t.Fatalf("p2 != p2b\n%#v\n%#v\n", p2, p2b)
|
||||||
}
|
}
|
||||||
p2c = *p2.Copy()
|
p2c = p2.Copy()
|
||||||
if !p2b.Equals(&p2c) {
|
if !p2b.Equals(p2c) {
|
||||||
t.Fatalf("p2b != p2c\n")
|
t.Fatalf("p2b != p2c\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user