Charlotte Brandhorst-Satzkorn 93618a3518
tailscale: update tailfs functions and vars to use drive naming ()
This change updates all tailfs functions and the majority of the tailfs
variables to use the new drive naming.

Updates 

Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>
2024-04-03 10:09:58 -07:00

116 lines
3.2 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package driveimpl
import (
"net"
"net/http"
"sync"
"github.com/tailscale/xnet/webdav"
"tailscale.com/drive/driveimpl/shared"
)
// FileServer is a standalone WebDAV server that dynamically serves up shares.
// It's typically used in a separate process from the actual Taildrive server to
// serve up files as an unprivileged user.
type FileServer struct {
l net.Listener
shareHandlers map[string]http.Handler
sharesMu sync.RWMutex
}
// NewFileServer constructs a FileServer.
//
// The server attempts to listen at a random address on 127.0.0.1.
// The listen address is available via the Addr() method.
//
// The server has to be told about shares before it can serve them. This is
// accomplished either by calling SetShares(), or locking the shares with
// LockShares(), clearing them with ClearSharesLocked(), adding them
// individually with AddShareLocked(), and finally unlocking them with
// UnlockShares().
//
// The server doesn't actually process requests until the Serve() method is
// called.
func NewFileServer() (*FileServer, error) {
// path := filepath.Join(os.TempDir(), fmt.Sprintf("%v.socket", uuid.New().String()))
// l, err := safesocket.Listen(path)
// if err != nil {
// TODO(oxtoacart): actually get safesocket working in more environments (MacOS Sandboxed, Windows, ???)
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, err
}
// }
return &FileServer{
l: l,
shareHandlers: make(map[string]http.Handler),
}, nil
}
// Addr returns the address at which this FileServer is listening.
func (s *FileServer) Addr() string {
return s.l.Addr().String()
}
// Serve() starts serving files and blocks until it encounters a fatal error.
func (s *FileServer) Serve() error {
return http.Serve(s.l, s)
}
// LockShares locks the map of shares in preparation for manipulating it.
func (s *FileServer) LockShares() {
s.sharesMu.Lock()
}
// UnlockShares unlocks the map of shares.
func (s *FileServer) UnlockShares() {
s.sharesMu.Unlock()
}
// ClearSharesLocked clears the map of shares, assuming that LockShares() has
// been called first.
func (s *FileServer) ClearSharesLocked() {
s.shareHandlers = make(map[string]http.Handler)
}
// AddShareLocked adds a share to the map of shares, assuming that LockShares()
// has been called first.
func (s *FileServer) AddShareLocked(share, path string) {
s.shareHandlers[share] = &webdav.Handler{
FileSystem: &birthTimingFS{webdav.Dir(path)},
LockSystem: webdav.NewMemLS(),
}
}
// SetShares sets the full map of shares to the new value, mapping name->path.
func (s *FileServer) SetShares(shares map[string]string) {
s.LockShares()
defer s.UnlockShares()
s.ClearSharesLocked()
for name, path := range shares {
s.AddShareLocked(name, path)
}
}
// ServeHTTP implements the http.Handler interface.
func (s *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
parts := shared.CleanAndSplit(r.URL.Path)
r.URL.Path = shared.Join(parts[1:]...)
share := parts[0]
s.sharesMu.RLock()
h, found := s.shareHandlers[share]
s.sharesMu.RUnlock()
if !found {
w.WriteHeader(http.StatusNotFound)
return
}
h.ServeHTTP(w, r)
}
func (s *FileServer) Close() error {
return s.l.Close()
}