Files
orchard/internal/worker/socketalias/socketalias.go
T

68 lines
2.0 KiB
Go

package socketalias
import (
"context"
"errors"
"net"
"os"
"path/filepath"
)
// baseDirectory is the parent directory for transient socket aliases.
//
// To keep the Unix socket path short enough and fit the platform limit,
// we're specifically requesting "/var/tmp" instead of "/var/folders/.../T/".
const baseDirectory = "/var/tmp"
// Create creates a short Unix socket alias in runtimeDir that points to socketPath.
//
// The alias remains valid until runtimeDir is removed.
func Create(runtimeDir string, socketPath string) (string, error) {
// Make the symlink target absolute because a relative TART_HOME would
// otherwise be resolved from runtimeDir, breaking the symlink
absoluteSocketPath, err := filepath.Abs(socketPath)
if err != nil {
return "", err
}
// Place the VM's control socket alias in the runtime directory
aliasSocketPath := filepath.Join(runtimeDir, "vm.sock")
if err := os.Symlink(absoluteSocketPath, aliasSocketPath); err != nil {
return "", err
}
return aliasSocketPath, nil
}
// DialContext connects to socketPath through a short transient alias.
func DialContext(ctx context.Context, socketPath string) (net.Conn, error) {
// Create a directory where the transient Unix socket alias will live
runtimeDir, err := os.MkdirTemp(baseDirectory, "orchard-socket-")
if err != nil {
return nil, err
}
// Route the socket through the short runtime directory
aliasSocketPath, err := Create(runtimeDir, socketPath)
if err != nil {
return nil, errors.Join(err, os.RemoveAll(runtimeDir))
}
// Connect through the short alias
var dialer net.Dialer
conn, err := dialer.DialContext(ctx, "unix", aliasSocketPath)
// Remove the transient alias after the connection attempt
cleanupErr := os.RemoveAll(runtimeDir)
if err != nil {
return nil, errors.Join(err, cleanupErr)
}
// Avoid returning a live connection when its alias cannot be removed
if cleanupErr != nil {
return nil, errors.Join(cleanupErr, conn.Close())
}
return conn, nil
}