feat: rebuild browser ssh from the ground up

This commit is contained in:
Aarnav Tale
2026-04-09 21:56:06 -04:00
parent d255098128
commit 0f19fdf0da
39 changed files with 1292 additions and 1231 deletions
+11 -69
View File
@@ -6,94 +6,36 @@ import (
"context"
"fmt"
"log"
"sync"
"tailscale.com/ipn"
"tailscale.com/ipn/ipnlocal"
)
func registerNotifyCallback(callbacks *TsWasmNetCallbacks, lb *ipnlocal.LocalBackend) {
lb.SetNotifyCallback(func(n ipn.Notify) {
// Panics should be treated with care in a JS/wasm environment.
// If a panic occurs, notify the user and either automatically reload
// or give the option to reload.
func registerNotifyCallback(callbacks *IPNCallbacks, lb *ipnlocal.LocalBackend) {
var readyOnce sync.Once
lb.SetNotifyCallback(func(n ipn.Notify) {
defer func() {
rec := recover()
if rec != nil {
callbacks.NotifyPanicRecover(fmt.Sprint(rec))
if rec := recover(); rec != nil {
callbacks.OnError(fmt.Sprint(rec))
}
}()
if n.State != nil {
callbacks.NotifyState(*n.State)
if *n.State == ipn.Running {
readyOnce.Do(callbacks.OnReady)
}
if *n.State == ipn.NeedsLogin {
// If the state is NeedsLogin, we need to force an interactive login.
go forceInteractiveLogin(lb)
}
}
if n.BrowseToURL != nil {
callbacks.NotifyBrowseToURL(*n.BrowseToURL)
}
if n.NetMap != nil {
callbacks.NotifyNetMap(n.NetMap)
}
log.Printf("NOTIFY: %+v", n)
// if nm := n.NetMap; nm != nil {
// jsNetMap := jsNetMap{
// Self: jsNetMapSelfNode{
// jsNetMapNode: jsNetMapNode{
// Name: nm.Name,
// Addresses: mapSliceView(nm.GetAddresses(), func(a netip.Prefix) string { return a.Addr().String() }),
// NodeKey: nm.NodeKey.String(),
// MachineKey: nm.MachineKey.String(),
// },
// MachineStatus: jsMachineStatus[nm.GetMachineStatus()],
// },
// Peers: mapSlice(nm.Peers, func(p tailcfg.NodeView) jsNetMapPeerNode {
// name := p.Name()
// if name == "" {
// // In practice this should only happen for Hello.
// name = p.Hostinfo().Hostname()
// }
// addrs := make([]string, p.Addresses().Len())
// for i, ap := range p.Addresses().All() {
// addrs[i] = ap.Addr().String()
// }
// return jsNetMapPeerNode{
// jsNetMapNode: jsNetMapNode{
// Name: name,
// Addresses: addrs,
// MachineKey: p.Machine().String(),
// NodeKey: p.Key().String(),
// },
// Online: p.Online().Clone(),
// TailscaleSSHEnabled: p.Hostinfo().TailscaleSSHEnabled(),
// }
// }),
// LockedOut: nm.TKAEnabled && nm.SelfNode.KeySignature().Len() == 0,
// }
// if jsonNetMap, err := json.Marshal(jsNetMap); err == nil {
// jsCallbacks.Call("notifyNetMap", string(jsonNetMap))
// } else {
// log.Printf("Could not generate JSON netmap: %v", err)
// }
// }
// if n.BrowseToURL != nil {
// jsCallbacks.Call("notifyBrowseToURL", *n.BrowseToURL)
// }
})
}
// To get auth to work, even with a pre-auth key, we need to
// force an interactive login on the NeedsLogin state.
func forceInteractiveLogin(lb *ipnlocal.LocalBackend) {
err := lb.StartLoginInteractive(context.Background())
if err != nil {
fmt.Printf("Error starting interactive login: %v\n", err)
if err := lb.StartLoginInteractive(context.Background()); err != nil {
log.Printf("Error starting interactive login: %v", err)
}
}