control/controlclient, ipn/ipnlocal, tailcfg: add MapResponse.PopBrowserURL
Updates #3802 Change-Id: I89481fc5782a0cc8084354706f8f28d94f197325 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>pull/4257/head
parent
3ea6ddbb5f
commit
f3b13604b3
|
@ -69,6 +69,7 @@ type Direct struct {
|
||||||
keepSharerAndUserSplit bool
|
keepSharerAndUserSplit bool
|
||||||
skipIPForwardingCheck bool
|
skipIPForwardingCheck bool
|
||||||
pinger Pinger
|
pinger Pinger
|
||||||
|
popBrowser func(url string) // or nil
|
||||||
|
|
||||||
mu sync.Mutex // mutex guards the following fields
|
mu sync.Mutex // mutex guards the following fields
|
||||||
serverKey key.MachinePublic // original ("legacy") nacl crypto_box-based public key
|
serverKey key.MachinePublic // original ("legacy") nacl crypto_box-based public key
|
||||||
|
@ -103,6 +104,7 @@ type Options struct {
|
||||||
HTTPTestClient *http.Client // optional HTTP client to use (for tests only)
|
HTTPTestClient *http.Client // optional HTTP client to use (for tests only)
|
||||||
DebugFlags []string // debug settings to send to control
|
DebugFlags []string // debug settings to send to control
|
||||||
LinkMonitor *monitor.Mon // optional link monitor
|
LinkMonitor *monitor.Mon // optional link monitor
|
||||||
|
PopBrowserURL func(url string) // optional func to open browser
|
||||||
|
|
||||||
// KeepSharerAndUserSplit controls whether the client
|
// KeepSharerAndUserSplit controls whether the client
|
||||||
// understands Node.Sharer. If false, the Sharer is mapped to the User.
|
// understands Node.Sharer. If false, the Sharer is mapped to the User.
|
||||||
|
@ -198,6 +200,7 @@ func NewDirect(opts Options) (*Direct, error) {
|
||||||
linkMon: opts.LinkMonitor,
|
linkMon: opts.LinkMonitor,
|
||||||
skipIPForwardingCheck: opts.SkipIPForwardingCheck,
|
skipIPForwardingCheck: opts.SkipIPForwardingCheck,
|
||||||
pinger: opts.Pinger,
|
pinger: opts.Pinger,
|
||||||
|
popBrowser: opts.PopBrowserURL,
|
||||||
}
|
}
|
||||||
if opts.Hostinfo == nil {
|
if opts.Hostinfo == nil {
|
||||||
c.SetHostinfo(hostinfo.New())
|
c.SetHostinfo(hostinfo.New())
|
||||||
|
@ -849,7 +852,15 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
|
||||||
metricMapResponsePings.Add(1)
|
metricMapResponsePings.Add(1)
|
||||||
go answerPing(c.logf, c.httpc, pr)
|
go answerPing(c.logf, c.httpc, pr)
|
||||||
}
|
}
|
||||||
|
if u := resp.PopBrowserURL; u != "" && u != sess.lastPopBrowserURL {
|
||||||
|
sess.lastPopBrowserURL = u
|
||||||
|
if c.popBrowser != nil {
|
||||||
|
c.logf("netmap: control says to open URL %v; opening...", u)
|
||||||
|
c.popBrowser(u)
|
||||||
|
} else {
|
||||||
|
c.logf("netmap: control says to open URL %v; no popBrowser func", u)
|
||||||
|
}
|
||||||
|
}
|
||||||
if resp.ControlTime != nil && !resp.ControlTime.IsZero() {
|
if resp.ControlTime != nil && !resp.ControlTime.IsZero() {
|
||||||
c.logf.JSON(1, "controltime", resp.ControlTime.UTC())
|
c.logf.JSON(1, "controltime", resp.ControlTime.UTC())
|
||||||
}
|
}
|
||||||
|
@ -858,6 +869,7 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
|
||||||
} else {
|
} else {
|
||||||
vlogf("netmap: got new map")
|
vlogf("netmap: got new map")
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case timeoutReset <- struct{}{}:
|
case timeoutReset <- struct{}{}:
|
||||||
vlogf("netmap: sent timer reset")
|
vlogf("netmap: sent timer reset")
|
||||||
|
|
|
@ -44,6 +44,7 @@ type mapSession struct {
|
||||||
previousPeers []*tailcfg.Node // for delta-purposes
|
previousPeers []*tailcfg.Node // for delta-purposes
|
||||||
lastDomain string
|
lastDomain string
|
||||||
lastHealth []string
|
lastHealth []string
|
||||||
|
lastPopBrowserURL string
|
||||||
|
|
||||||
// netMapBuilding is non-nil during a netmapForResponse call,
|
// netMapBuilding is non-nil during a netmapForResponse call,
|
||||||
// containing the value to be returned, once fully populated.
|
// containing the value to be returned, once fully populated.
|
||||||
|
|
|
@ -973,6 +973,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error {
|
||||||
DebugFlags: debugFlags,
|
DebugFlags: debugFlags,
|
||||||
LinkMonitor: b.e.GetLinkMonitor(),
|
LinkMonitor: b.e.GetLinkMonitor(),
|
||||||
Pinger: b.e,
|
Pinger: b.e,
|
||||||
|
PopBrowserURL: b.tellClientToBrowseToURL,
|
||||||
|
|
||||||
// Don't warn about broken Linux IP forwarding when
|
// Don't warn about broken Linux IP forwarding when
|
||||||
// netstack is being used.
|
// netstack is being used.
|
||||||
|
@ -1370,12 +1371,18 @@ func (b *LocalBackend) popBrowserAuthNow() {
|
||||||
|
|
||||||
b.blockEngineUpdates(true)
|
b.blockEngineUpdates(true)
|
||||||
b.stopEngineAndWait()
|
b.stopEngineAndWait()
|
||||||
b.send(ipn.Notify{BrowseToURL: &url})
|
b.tellClientToBrowseToURL(url)
|
||||||
if b.State() == ipn.Running {
|
if b.State() == ipn.Running {
|
||||||
b.enterState(ipn.Starting)
|
b.enterState(ipn.Starting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LocalBackend) tellClientToBrowseToURL(url string) {
|
||||||
|
if url != "" {
|
||||||
|
b.send(ipn.Notify{BrowseToURL: &url})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For testing lazy machine key generation.
|
// For testing lazy machine key generation.
|
||||||
var panicOnMachineKeyGeneration = envknob.Bool("TS_DEBUG_PANIC_MACHINE_KEY")
|
var panicOnMachineKeyGeneration = envknob.Bool("TS_DEBUG_PANIC_MACHINE_KEY")
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,8 @@ type CapabilityVersion int
|
||||||
// 26: 2022-01-12: (nothing, just bumping for 1.20.0)
|
// 26: 2022-01-12: (nothing, just bumping for 1.20.0)
|
||||||
// 27: 2022-02-18: start of SSHPolicy being respected
|
// 27: 2022-02-18: start of SSHPolicy being respected
|
||||||
// 28: 2022-03-09: client can communicate over Noise.
|
// 28: 2022-03-09: client can communicate over Noise.
|
||||||
const CurrentCapabilityVersion CapabilityVersion = 28
|
// 29: 2022-03-09: MapResponse.PopBrowserURL
|
||||||
|
const CurrentCapabilityVersion CapabilityVersion = 29
|
||||||
|
|
||||||
type StableID string
|
type StableID string
|
||||||
|
|
||||||
|
@ -1221,7 +1222,7 @@ type PingRequest struct {
|
||||||
type MapResponse struct {
|
type MapResponse struct {
|
||||||
// KeepAlive, if set, represents an empty message just to keep
|
// KeepAlive, if set, represents an empty message just to keep
|
||||||
// the connection alive. When true, all other fields except
|
// the connection alive. When true, all other fields except
|
||||||
// PingRequest are ignored.
|
// PingRequest, ControlTime, and PopBrowserURL are ignored.
|
||||||
KeepAlive bool `json:",omitempty"`
|
KeepAlive bool `json:",omitempty"`
|
||||||
|
|
||||||
// PingRequest, if non-empty, is a request to the client to
|
// PingRequest, if non-empty, is a request to the client to
|
||||||
|
@ -1231,6 +1232,11 @@ type MapResponse struct {
|
||||||
// KeepAlive true or false).
|
// KeepAlive true or false).
|
||||||
PingRequest *PingRequest `json:",omitempty"`
|
PingRequest *PingRequest `json:",omitempty"`
|
||||||
|
|
||||||
|
// PopBrowserURL, if non-empty, is a URL for the client to
|
||||||
|
// open to complete an action. The client should dup suppress
|
||||||
|
// identical URLs and only open it once for the same URL.
|
||||||
|
PopBrowserURL string
|
||||||
|
|
||||||
// Networking
|
// Networking
|
||||||
|
|
||||||
// Node describes the node making the map request.
|
// Node describes the node making the map request.
|
||||||
|
|
Loading…
Reference in New Issue