mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-07 08:07:42 +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
|
BackendLogID *string // public logtail id used by backend
|
||||||
PingResult *ipnstate.PingResult
|
PingResult *ipnstate.PingResult
|
||||||
|
|
||||||
|
FilesWaiting *empty.Message `json:",omitempty"`
|
||||||
|
|
||||||
// LocalTCPPort, if non-nil, informs the UI frontend which
|
// LocalTCPPort, if non-nil, informs the UI frontend which
|
||||||
// (non-zero) localhost TCP port it's listening on.
|
// (non-zero) localhost TCP port it's listening on.
|
||||||
// This is currently only used by Tailscale when run in the
|
// This is currently only used by Tailscale when run in the
|
||||||
|
@ -107,6 +107,7 @@ type LocalBackend struct {
|
|||||||
authURL string
|
authURL string
|
||||||
interact bool
|
interact bool
|
||||||
prevIfState *interfaces.State
|
prevIfState *interfaces.State
|
||||||
|
peerAPIServer *peerAPIServer // or nil
|
||||||
peerAPIListeners []*peerAPIListener
|
peerAPIListeners []*peerAPIListener
|
||||||
|
|
||||||
// statusLock must be held before calling statusChanged.Wait() or
|
// 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.
|
// connected, the notification is dropped without being delivered.
|
||||||
func (b *LocalBackend) send(n ipn.Notify) {
|
func (b *LocalBackend) send(n ipn.Notify) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
notify := b.notify
|
notifyFunc := b.notify
|
||||||
|
apiSrv := b.peerAPIServer
|
||||||
b.mu.Unlock()
|
b.mu.Unlock()
|
||||||
|
|
||||||
if notify != nil {
|
if notifyFunc == nil {
|
||||||
n.Version = version.Long
|
|
||||||
notify(n)
|
|
||||||
} else {
|
|
||||||
b.logf("nil notify callback; dropping %+v", n)
|
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
|
// popBrowserAuthNow shuts down the data plane and sends an auth URL
|
||||||
@ -1489,6 +1495,7 @@ func (b *LocalBackend) initPeerAPIListener() {
|
|||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
|
b.peerAPIServer = nil
|
||||||
for _, pln := range b.peerAPIListeners {
|
for _, pln := range b.peerAPIListeners {
|
||||||
pln.Close()
|
pln.Close()
|
||||||
}
|
}
|
||||||
@ -1526,6 +1533,7 @@ func (b *LocalBackend) initPeerAPIListener() {
|
|||||||
tunName: tunName,
|
tunName: tunName,
|
||||||
selfNode: selfNode,
|
selfNode: selfNode,
|
||||||
}
|
}
|
||||||
|
b.peerAPIServer = ps
|
||||||
|
|
||||||
isNetstack := wgengine.IsNetstack(b.e)
|
isNetstack := wgengine.IsNetstack(b.e)
|
||||||
for i, a := range b.netMap.Addresses {
|
for i, a := range b.netMap.Addresses {
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/net/interfaces"
|
"tailscale.com/net/interfaces"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/wgengine"
|
"tailscale.com/wgengine"
|
||||||
)
|
)
|
||||||
@ -30,10 +32,52 @@
|
|||||||
var initListenConfig func(*net.ListenConfig, netaddr.IP, *interfaces.State, string) error
|
var initListenConfig func(*net.ListenConfig, netaddr.IP, *interfaces.State, string) error
|
||||||
|
|
||||||
type peerAPIServer struct {
|
type peerAPIServer struct {
|
||||||
b *LocalBackend
|
b *LocalBackend
|
||||||
rootDir string
|
rootDir string
|
||||||
tunName string
|
tunName string
|
||||||
selfNode *tailcfg.Node
|
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) {
|
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
|
return
|
||||||
}
|
}
|
||||||
name := path.Base(r.URL.Path)
|
name := path.Base(r.URL.Path)
|
||||||
if name == "." || name == "/" {
|
if name == "." || name == "/" || strings.HasSuffix(name, partialSuffix) {
|
||||||
http.Error(w, "bad filename", http.StatusForbidden)
|
http.Error(w, "bad filename", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -258,4 +302,6 @@ func (h *peerAPIHandler) put(w http.ResponseWriter, r *http.Request) {
|
|||||||
// TODO: some real response
|
// TODO: some real response
|
||||||
success = true
|
success = true
|
||||||
io.WriteString(w, "{}\n")
|
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