mirror of
https://github.com/rclone/rclone.git
synced 2024-12-21 11:06:55 +08:00
5d6b8141ec
As of Go 1.16, the same functionality is now provided by package io or package os, and those implementations should be preferred in new code.
101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
package docker
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
|
|
"github.com/rclone/rclone/fs"
|
|
"github.com/rclone/rclone/lib/atexit"
|
|
"github.com/rclone/rclone/lib/file"
|
|
)
|
|
|
|
// Server connects plugin with docker daemon by protocol
|
|
type Server http.Server
|
|
|
|
// NewServer creates new docker plugin server
|
|
func NewServer(drv *Driver) *Server {
|
|
return &Server{Handler: newRouter(drv)}
|
|
}
|
|
|
|
// Shutdown the server
|
|
func (s *Server) Shutdown(ctx context.Context) error {
|
|
hs := (*http.Server)(s)
|
|
return hs.Shutdown(ctx)
|
|
}
|
|
|
|
func (s *Server) serve(listener net.Listener, addr, tempFile string) error {
|
|
if tempFile != "" {
|
|
atexit.Register(func() {
|
|
// remove spec file or self-created unix socket
|
|
fs.Debugf(nil, "Removing stale file %s", tempFile)
|
|
_ = os.Remove(tempFile)
|
|
})
|
|
}
|
|
hs := (*http.Server)(s)
|
|
return hs.Serve(listener)
|
|
}
|
|
|
|
// ServeUnix makes the handler to listen for requests in a unix socket.
|
|
// It also creates the socket file in the right directory for docker to read.
|
|
func (s *Server) ServeUnix(path string, gid int) error {
|
|
listener, socketPath, err := newUnixListener(path, gid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if socketPath != "" {
|
|
path = socketPath
|
|
fs.Infof(nil, "Serving unix socket: %s", path)
|
|
} else {
|
|
fs.Infof(nil, "Serving systemd socket")
|
|
}
|
|
return s.serve(listener, path, socketPath)
|
|
}
|
|
|
|
// ServeTCP makes the handler listen for request on a given TCP address.
|
|
// It also writes the spec file in the right directory for docker to read.
|
|
func (s *Server) ServeTCP(addr, specDir string, tlsConfig *tls.Config, noSpec bool) error {
|
|
listener, err := net.Listen("tcp", addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if tlsConfig != nil {
|
|
tlsConfig.NextProtos = []string{"http/1.1"}
|
|
listener = tls.NewListener(listener, tlsConfig)
|
|
}
|
|
addr = listener.Addr().String()
|
|
specFile := ""
|
|
if !noSpec {
|
|
specFile, err = writeSpecFile(addr, "tcp", specDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
fs.Infof(nil, "Serving TCP socket: %s", addr)
|
|
return s.serve(listener, addr, specFile)
|
|
}
|
|
|
|
func writeSpecFile(addr, proto, specDir string) (string, error) {
|
|
if specDir == "" && runtime.GOOS == "windows" {
|
|
specDir = os.TempDir()
|
|
}
|
|
if specDir == "" {
|
|
specDir = defSpecDir
|
|
}
|
|
if err := file.MkdirAll(specDir, 0755); err != nil {
|
|
return "", err
|
|
}
|
|
specFile := filepath.Join(specDir, "rclone.spec")
|
|
url := fmt.Sprintf("%s://%s", proto, addr)
|
|
if err := os.WriteFile(specFile, []byte(url), 0644); err != nil {
|
|
return "", err
|
|
}
|
|
fs.Debugf(nil, "Plugin spec has been written to %s", specFile)
|
|
return specFile, nil
|
|
}
|