mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-05 14:57:49 +00:00
ipn{,/ipnlocal}: set new Notify.FilesWaiting when server has file(s)
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
0301ccd275
commit
672b9fd4bd
@ -68,6 +68,8 @@ type Notify struct {
|
||||
BackendLogID *string // public logtail id used by backend
|
||||
PingResult *ipnstate.PingResult
|
||||
|
||||
FilesWaiting *empty.Message `json:",omitempty"`
|
||||
|
||||
// LocalTCPPort, if non-nil, informs the UI frontend which
|
||||
// (non-zero) localhost TCP port it's listening on.
|
||||
// This is currently only used by Tailscale when run in the
|
||||
|
@ -107,6 +107,7 @@ type LocalBackend struct {
|
||||
authURL string
|
||||
interact bool
|
||||
prevIfState *interfaces.State
|
||||
peerAPIServer *peerAPIServer // or nil
|
||||
peerAPIListeners []*peerAPIListener
|
||||
|
||||
// statusLock must be held before calling statusChanged.Wait() or
|
||||
@ -909,15 +910,20 @@ func (b *LocalBackend) readPoller() {
|
||||
// connected, the notification is dropped without being delivered.
|
||||
func (b *LocalBackend) send(n ipn.Notify) {
|
||||
b.mu.Lock()
|
||||
notify := b.notify
|
||||
notifyFunc := b.notify
|
||||
apiSrv := b.peerAPIServer
|
||||
b.mu.Unlock()
|
||||
|
||||
if notify != nil {
|
||||
n.Version = version.Long
|
||||
notify(n)
|
||||
} else {
|
||||
if notifyFunc == nil {
|
||||
b.logf("nil notify callback; dropping %+v", n)
|
||||
return
|
||||
}
|
||||
|
||||
n.Version = version.Long
|
||||
if apiSrv != nil && apiSrv.hasFilesWaiting() {
|
||||
n.FilesWaiting = &empty.Message{}
|
||||
}
|
||||
notifyFunc(n)
|
||||
}
|
||||
|
||||
// popBrowserAuthNow shuts down the data plane and sends an auth URL
|
||||
@ -1489,6 +1495,7 @@ func (b *LocalBackend) initPeerAPIListener() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
b.peerAPIServer = nil
|
||||
for _, pln := range b.peerAPIListeners {
|
||||
pln.Close()
|
||||
}
|
||||
@ -1526,6 +1533,7 @@ func (b *LocalBackend) initPeerAPIListener() {
|
||||
tunName: tunName,
|
||||
selfNode: selfNode,
|
||||
}
|
||||
b.peerAPIServer = ps
|
||||
|
||||
isNetstack := wgengine.IsNetstack(b.e)
|
||||
for i, a := range b.netMap.Addresses {
|
||||
|
@ -22,7 +22,9 @@
|
||||
"strings"
|
||||
|
||||
"inet.af/netaddr"
|
||||
"tailscale.com/ipn"
|
||||
"tailscale.com/net/interfaces"
|
||||
"tailscale.com/syncs"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/wgengine"
|
||||
)
|
||||
@ -30,10 +32,52 @@
|
||||
var initListenConfig func(*net.ListenConfig, netaddr.IP, *interfaces.State, string) error
|
||||
|
||||
type peerAPIServer struct {
|
||||
b *LocalBackend
|
||||
rootDir string
|
||||
tunName string
|
||||
selfNode *tailcfg.Node
|
||||
b *LocalBackend
|
||||
rootDir string
|
||||
tunName string
|
||||
selfNode *tailcfg.Node
|
||||
knownEmpty syncs.AtomicBool
|
||||
}
|
||||
|
||||
const partialSuffix = ".tspartial"
|
||||
|
||||
// hasFilesWaiting reports whether any files are buffered in the
|
||||
// tailscaled daemon storage.
|
||||
func (s *peerAPIServer) hasFilesWaiting() bool {
|
||||
if s.rootDir == "" {
|
||||
return false
|
||||
}
|
||||
if s.knownEmpty.Get() {
|
||||
// Optimization: this is usually empty, so avoid opening
|
||||
// the directory and checking. We can't cache the actual
|
||||
// has-files-or-not values as the macOS/iOS client might
|
||||
// in the future use+delete the files directly. So only
|
||||
// keep this negative cache.
|
||||
return false
|
||||
}
|
||||
f, err := os.Open(s.rootDir)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
for {
|
||||
des, err := f.ReadDir(10)
|
||||
for _, de := range des {
|
||||
if strings.HasSuffix(de.Name(), partialSuffix) {
|
||||
continue
|
||||
}
|
||||
if de.Type().IsRegular() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if err == io.EOF {
|
||||
s.knownEmpty.Set(true)
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *peerAPIServer) listen(ip netaddr.IP, ifState *interfaces.State) (ln net.Listener, err error) {
|
||||
@ -221,7 +265,7 @@ func (h *peerAPIHandler) put(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
name := path.Base(r.URL.Path)
|
||||
if name == "." || name == "/" {
|
||||
if name == "." || name == "/" || strings.HasSuffix(name, partialSuffix) {
|
||||
http.Error(w, "bad filename", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
@ -258,4 +302,6 @@ func (h *peerAPIHandler) put(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO: some real response
|
||||
success = true
|
||||
io.WriteString(w, "{}\n")
|
||||
h.ps.knownEmpty.Set(false)
|
||||
h.ps.b.send(ipn.Notify{}) // it will set FilesWaiting
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user