ipn/localapi: add debug (root-required) access to inject debug Notify

For testing of Windows GUI client.

Updates #6480

Change-Id: I42f7526d95723e14bed7085fb759e371b43aa9da
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/6596/head
Brad Fitzpatrick 2 years ago committed by Brad Fitzpatrick
parent 96cad35870
commit 57124e2126

@ -1820,6 +1820,13 @@ func (b *LocalBackend) pollRequestEngineStatus(ctx context.Context) {
} }
} }
// DebugNotify injects a fake notify message to clients.
//
// It should only be used via the LocalAPI's debug handler.
func (b *LocalBackend) DebugNotify(n ipn.Notify) {
b.send(n)
}
// send delivers n to the connected frontend and any API watchers from // send delivers n to the connected frontend and any API watchers from
// LocalBackend.WatchNotifications (via the LocalAPI). // LocalBackend.WatchNotifications (via the LocalAPI).
// //
@ -1828,7 +1835,9 @@ func (b *LocalBackend) pollRequestEngineStatus(ctx context.Context) {
// //
// b.mu must not be held. // b.mu must not be held.
func (b *LocalBackend) send(n ipn.Notify) { func (b *LocalBackend) send(n ipn.Notify) {
n.Version = version.Long if n.Version == "" {
n.Version = version.Long
}
b.mu.Lock() b.mu.Lock()
notifyFunc := b.notify notifyFunc := b.notify

@ -434,7 +434,16 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) {
http.Error(w, "POST required", http.StatusMethodNotAllowed) http.Error(w, "POST required", http.StatusMethodNotAllowed)
return return
} }
action := r.FormValue("action") // The action is normally in a POST form parameter, but
// some actions (like "notify") want a full JSON body, so
// permit some to have their action in a header.
var action string
switch v := r.Header.Get("Debug-Action"); v {
case "notify":
action = v
default:
action = r.FormValue("action")
}
var err error var err error
switch action { switch action {
case "rebind": case "rebind":
@ -455,6 +464,14 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) {
// client already did. A future change will remove this, so don't depend // client already did. A future change will remove this, so don't depend
// on it. // on it.
h.b.RequestEngineStatus() h.b.RequestEngineStatus()
case "notify":
var n ipn.Notify
err = json.NewDecoder(r.Body).Decode(&n)
if err != nil {
break
}
h.b.DebugNotify(n)
case "": case "":
err = fmt.Errorf("missing parameter 'action'") err = fmt.Errorf("missing parameter 'action'")
default: default:

Loading…
Cancel
Save