From 43983a4a3b9d5b984872961be040466afbf71f57 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 1 Dec 2021 15:00:23 -0800 Subject: [PATCH] ipn/ipnlocal: run peerapi even if Taildrop storage not configured Change-Id: I77f9ecbe4617d01d13aa1127fa59c83f2aa3e1b8 Signed-off-by: Brad Fitzpatrick --- ipn/ipnlocal/local.go | 17 ++++------------- ipn/ipnlocal/peerapi.go | 30 ++++++++++++++++++++++++------ ipn/ipnlocal/peerapi_test.go | 2 +- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 01ef51f84..19ce17821 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -1284,7 +1284,7 @@ func (b *LocalBackend) send(n ipn.Notify) { return } - if apiSrv != nil && apiSrv.hasFilesWaiting() { + if apiSrv.hasFilesWaiting() { n.FilesWaiting = &empty.Message{} } @@ -2118,7 +2118,7 @@ func (b *LocalBackend) fileRootLocked(uid tailcfg.UserID) string { } varRoot := b.TailscaleVarRoot() if varRoot == "" { - b.logf("peerapi disabled; no state directory") + b.logf("Taildrop disabled; no state directory") return "" } baseDir := fmt.Sprintf("%s-uid-%d", @@ -2126,7 +2126,7 @@ func (b *LocalBackend) fileRootLocked(uid tailcfg.UserID) string { uid) dir := filepath.Join(varRoot, "files", baseDir) if err := os.MkdirAll(dir, 0700); err != nil { - b.logf("peerapi disabled; error making directory: %v", err) + b.logf("Taildrop disabled; error making directory: %v", err) return "" } return dir @@ -2189,7 +2189,7 @@ func (b *LocalBackend) initPeerAPIListener() { fileRoot := b.fileRootLocked(selfNode.User) if fileRoot == "" { - return + b.logf("peerapi starting without Taildrop directory configured") } ps := &peerAPIServer{ @@ -2783,9 +2783,6 @@ func (b *LocalBackend) WaitingFiles() ([]apitype.WaitingFile, error) { b.mu.Lock() apiSrv := b.peerAPIServer b.mu.Unlock() - if apiSrv == nil { - return nil, errors.New("peerapi disabled") - } return apiSrv.WaitingFiles() } @@ -2793,9 +2790,6 @@ func (b *LocalBackend) DeleteFile(name string) error { b.mu.Lock() apiSrv := b.peerAPIServer b.mu.Unlock() - if apiSrv == nil { - return errors.New("peerapi disabled") - } return apiSrv.DeleteFile(name) } @@ -2803,9 +2797,6 @@ func (b *LocalBackend) OpenFile(name string) (rc io.ReadCloser, size int64, err b.mu.Lock() apiSrv := b.peerAPIServer b.mu.Unlock() - if apiSrv == nil { - return nil, 0, errors.New("peerapi disabled") - } return apiSrv.OpenFile(name) } diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 2146eba38..cf9df33f7 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -48,7 +48,7 @@ var initListenConfig func(*net.ListenConfig, netaddr.IP, *interfaces.State, stri type peerAPIServer struct { b *LocalBackend - rootDir string + rootDir string // empty means file receiving unavailable selfNode *tailcfg.Node knownEmpty syncs.AtomicBool resolver *resolver.Resolver @@ -76,6 +76,10 @@ const ( deletedSuffix = ".deleted" ) +func (s *peerAPIServer) canReceiveFiles() bool { + return s != nil && s.rootDir != "" +} + func validFilenameRune(r rune) bool { switch r { case '/': @@ -122,7 +126,7 @@ func (s *peerAPIServer) diskPath(baseName string) (fullPath string, ok bool) { // hasFilesWaiting reports whether any files are buffered in the // tailscaled daemon storage. func (s *peerAPIServer) hasFilesWaiting() bool { - if s.rootDir == "" || s.directFileMode { + if s == nil || s.rootDir == "" || s.directFileMode { return false } if s.knownEmpty.Get() { @@ -182,8 +186,11 @@ func (s *peerAPIServer) hasFilesWaiting() bool { // As a side effect, it also does any lazy deletion of files as // required by Windows. func (s *peerAPIServer) WaitingFiles() (ret []apitype.WaitingFile, err error) { + if s == nil { + return nil, errNilPeerAPIServer + } if s.rootDir == "" { - return nil, errors.New("peerapi disabled; no storage configured") + return nil, errNoTaildrop } if s.directFileMode { return nil, nil @@ -247,6 +254,11 @@ func (s *peerAPIServer) WaitingFiles() (ret []apitype.WaitingFile, err error) { return ret, nil } +var ( + errNilPeerAPIServer = errors.New("peerapi unavailable; not listening") + errNoTaildrop = errors.New("Taildrop disabled; no storage directory") +) + // tryDeleteAgain tries to delete path (and path+deletedSuffix) after // it failed earlier. This happens on Windows when various anti-virus // tools hook into filesystem operations and have the file open still @@ -262,8 +274,11 @@ func tryDeleteAgain(fullPath string) { } func (s *peerAPIServer) DeleteFile(baseName string) error { + if s == nil { + return errNilPeerAPIServer + } if s.rootDir == "" { - return errors.New("peerapi disabled; no storage configured") + return errNoTaildrop } if s.directFileMode { return errors.New("deletes not allowed in direct mode") @@ -328,8 +343,11 @@ func touchFile(path string) error { } func (s *peerAPIServer) OpenFile(baseName string) (rc io.ReadCloser, size int64, err error) { + if s == nil { + return nil, 0, errNilPeerAPIServer + } if s.rootDir == "" { - return nil, 0, errors.New("peerapi disabled; no storage configured") + return nil, 0, errNoTaildrop } if s.directFileMode { return nil, 0, errors.New("opens not allowed in direct mode") @@ -607,7 +625,7 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) { return } if h.ps.rootDir == "" { - http.Error(w, "no rootdir", http.StatusInternalServerError) + http.Error(w, errNoTaildrop.Error(), http.StatusInternalServerError) return } rawPath := r.URL.EscapedPath() diff --git a/ipn/ipnlocal/peerapi_test.go b/ipn/ipnlocal/peerapi_test.go index 457001fed..18f69f999 100644 --- a/ipn/ipnlocal/peerapi_test.go +++ b/ipn/ipnlocal/peerapi_test.go @@ -179,7 +179,7 @@ func TestHandlePeerAPI(t *testing.T) { req: httptest.NewRequest("PUT", "/v0/put/foo", nil), checks: checks( httpStatus(http.StatusInternalServerError), - bodyContains("no rootdir"), + bodyContains("Taildrop disabled; no storage directory"), ), }, {