jsIPN.localAPI serves localapi.Handler in-process through an httptest.ResponseRecorder, so nothing ever dialled the safesocket listener that run() opened. The other in-tree callers of safesocket.ConnectContext do not apply either: driveimpl's FileSystemForRemote is replaced by jsFileSystemForRemote in this build, and logpolicy's fallback is behind version.IsWindowsGUI. Remove the listener, and with it ipnserver, whose only remaining use was serving that listener. ipnserver.New builds a struct and SetLocalBackend stores a pointer, so dropping both leaves LocalBackend untouched. Two behaviours go with it: srv.Run's deferred lb.Shutdown, which made shutdown call lb.Shutdown twice, and its localapi.Shutdown bus subscription, which nothing in this build emits. safesocket's generated per-listener name existed so several IPNs could share one runtime. Each runtime has its own Go heap and its own memconn registry, so the fixed name never conflicted between runtimes, and there is now at most one IPN in each. Restoring the fixed name returns safesocket_js.go to its upstream contents. Co-Authored-By: claude-opus-5 <noreply@anthropic.com>
22 lines
408 B
Go
22 lines
408 B
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package safesocket
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
|
|
"github.com/akutz/memconn"
|
|
)
|
|
|
|
const memName = "Tailscale-IPN"
|
|
|
|
func listen(path string) (net.Listener, error) {
|
|
return memconn.Listen("memu", memName)
|
|
}
|
|
|
|
func connect(ctx context.Context, _ string) (net.Conn, error) {
|
|
return memconn.DialContext(ctx, "memu", memName)
|
|
}
|