portforwarddaemon

package
v0.0.1-dev.137 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package portforwarddaemon implements the detached daemon backing `rune port-forward -d`, plus the CLI-side RPC client and subcommands for `list` / `stop` / `logs`. See RUNE-123.

Index

Constants

View Source
const (
	CmdPing    = "ping"
	CmdAdd     = "add"
	CmdList    = "list"
	CmdStop    = "stop"
	CmdStopAll = "stop_all"
	CmdLogs    = "logs"
)

Request types accepted by the daemon over its unix socket.

Variables

View Source
var IdleShutdownAfter = 60 * time.Second

IdleShutdownAfter is how long the daemon waits with zero forwards before exiting. Tunable for tests.

Functions

func DialDaemon

func DialDaemon(socketPath string) (net.Conn, error)

DialDaemon opens a connection to the daemon socket. Returns a net.Conn the caller must Close.

func EnsureRunning

func EnsureRunning(stateDir string, daemonArgs []string) (string, error)

EnsureRunning returns the path to the daemon socket, spawning the daemon if it isn't already running. If the daemon is up, this is a fast no-op (one ping round-trip).

`daemonArgs` is the argv to pass to the spawned process; the caller supplies the path to the current binary plus the hidden subcommand (e.g. "__port-forward-daemon").

func ForwardPath

func ForwardPath(dir, id string) string

ForwardPath returns the JSON file path for a given forward id.

func IsAlive

func IsAlive(stateDir string) bool

IsAlive returns true if the pid in `daemon.pid` corresponds to a running process. Used by `list` for a quick "is the daemon up?" probe without opening a socket connection.

func LogPath

func LogPath(dir string) string

func PidPath

func PidPath(dir string) string

PidPath, SocketPath, LogPath return the canonical file paths under the state dir.

func ReadJSONLine

func ReadJSONLine(r *bufio.Reader, v interface{}) error

ReadJSONLine reads one newline-terminated JSON object from r into v.

func RemoveForward

func RemoveForward(dir, id string) error

RemoveForward removes the JSON descriptor for the given id (no-op if already gone).

func SocketPath

func SocketPath(dir string) string

func StateDir

func StateDir() (string, error)

StateDir returns the directory holding daemon state for the current user, creating it with 0700 if needed.

func WriteForward

func WriteForward(dir string, fwd *Forward) error

WriteForward persists a forward's descriptor. Atomic via tmpfile + rename so a partial write never leaves a corrupt state file behind.

func WriteJSONLine

func WriteJSONLine(w io.Writer, v interface{}) error

WriteJSONLine writes one length-prefixed JSON object to w. We use a trailing newline as the framing terminator — every Request / Response fits comfortably in well under a megabyte and pretty printers / debugging is trivial.

Types

type ClientFactory

type ClientFactory func() (*client.Client, error)

ClientFactory builds an API client for the daemon's outbound gRPC calls. Injectable for tests; production wires it to the same createAPIClient the CLI uses.

type Daemon

type Daemon struct {
	// contains filtered or unexported fields
}

Daemon owns the unix socket listener, the active set of forwards, and the idle-shutdown timer.

func New

func New(stateDir string, logger log.Logger, newClient ClientFactory) *Daemon

New constructs a Daemon bound to the given state directory.

func (*Daemon) Run

func (d *Daemon) Run(ctx context.Context) error

Run binds the unix socket, writes the pid file, then services requests until ctx is cancelled, the idle timer fires, or Stop is called. Returns once everything is torn down.

type Forward

type Forward struct {
	ID          string        `json:"id"`
	Namespace   string        `json:"namespace"`
	TargetKind  TargetKind    `json:"target_kind"`
	Target      string        `json:"target"`
	InstancePin string        `json:"instance_pin,omitempty"`
	Mappings    []PortMapping `json:"mappings"`
	Context     string        `json:"context,omitempty"`
	CreatedAt   time.Time     `json:"created_at"`
	Status      ForwardStatus `json:"status"`
	LastError   string        `json:"last_error,omitempty"`
}

Forward is the persisted descriptor for one daemonized forward. In-memory state on the daemon is authoritative; this struct is what is written to ~/.rune/forwards/<id>.json and reported via `list`.

func LoadForwards

func LoadForwards(dir string) ([]*Forward, error)

LoadForwards walks the state directory and returns every persisted descriptor, sorted by CreatedAt. Used by the daemon at startup (recovery) and as a fallback for `list` if the daemon is down.

type ForwardStatus

type ForwardStatus string

ForwardStatus mirrors the lifecycle column shown by `list`.

const (
	StatusActive          ForwardStatus = "active"
	StatusReconnecting    ForwardStatus = "reconnecting"
	StatusFailed          ForwardStatus = "failed"
	StatusUnauthenticated ForwardStatus = "unauthenticated"
)

type PortMapping

type PortMapping struct {
	Local  string `json:"local"`  // bind addr, e.g. "127.0.0.1:27017"
	Remote uint32 `json:"remote"` // remote port on the container
}

PortMapping is one [LOCAL:]REMOTE pair persisted in a forward's state file.

type Request

type Request struct {
	Cmd     string   `json:"cmd"`
	Forward *Forward `json:"forward,omitempty"` // for Add
	ID      string   `json:"id,omitempty"`      // for Stop, Logs
	Tail    int      `json:"tail,omitempty"`    // for Logs
}

Request is one CLI → daemon RPC. Exactly one of the typed fields is populated based on Cmd.

type Response

type Response struct {
	OK       bool       `json:"ok"`
	Error    string     `json:"error,omitempty"`
	Version  string     `json:"version,omitempty"`  // Ping
	Forward  *Forward   `json:"forward,omitempty"`  // Add
	Forwards []*Forward `json:"forwards,omitempty"` // List
	Stopped  int        `json:"stopped,omitempty"`  // StopAll
	Lines    []string   `json:"lines,omitempty"`    // Logs
}

Response is one daemon → CLI reply. OK is the only field guaranteed to be set; the rest are command-specific.

func Call

func Call(sockPath string, req Request) (*Response, error)

Call sends one Request to the daemon socket and returns the Response.

type TargetKind

type TargetKind string

TargetKind says whether the forward is bound to a service or a specific instance.

const (
	TargetService  TargetKind = "service"
	TargetInstance TargetKind = "instance"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL