FILE / ScuroNeko/est

internal/config/config.go

Исходный файл и его история в репозитории.
FILE main
Files
ScuroNeko 149d20e501
Golang lint / docker-smoke (push) Successful in 15s
Golang lint / lint (push) Successful in 15s
lint fix
2026-08-06 12:50:30 +03:00

118 lines
3.3 KiB
Go

// Package config loads est tunnel configuration and command-line options.
package config
import (
"errors"
"os"
"time"
"github.com/BurntSushi/toml"
)
// ProxyDirection identifies the direction of an SSH port forward.
type ProxyDirection string
const (
// RemoteToLocal creates a local SSH forward with the -L option.
RemoteToLocal ProxyDirection = "rtl"
// LocalToRemote creates a remote SSH forward with the -R option.
LocalToRemote ProxyDirection = "ltr"
)
const (
// DefaultRetryCount is the number of reconnect attempts used when retry is
// not specified.
DefaultRetryCount = 5
// DefaultRetryDelay is the wait between reconnect attempts when retry is
// not specified.
DefaultRetryDelay = 5 * time.Second
)
var (
// ErrInvalidRetryCount is returned when retry count is less than -1.
ErrInvalidRetryCount = errors.New("retry count must be -1 or greater")
// ErrInvalidRetryDelay is returned when retry delay is invalid or not positive.
ErrInvalidRetryDelay = errors.New("retry delay must be a positive duration")
)
// RetryConfig configures tunnel reconnection behavior.
// Count is the number of attempts after the initial SSH process exits; -1
// retries indefinitely. Delay uses time.ParseDuration syntax, such as "5s".
type RetryConfig struct {
Count *int `toml:"count"`
Delay string `toml:"delay"`
}
// RetrySettings is a validated retry configuration ready for execution.
type RetrySettings struct {
Count int
Delay time.Duration
}
// Settings resolves RetryConfig fields with est's default retry values.
func (retry RetryConfig) Settings() (RetrySettings, error) {
settings := RetrySettings{Count: DefaultRetryCount, Delay: DefaultRetryDelay}
if retry.Count != nil {
settings.Count = *retry.Count
}
if settings.Count < -1 {
return RetrySettings{}, ErrInvalidRetryCount
}
if retry.Delay != "" {
delay, err := time.ParseDuration(retry.Delay)
if err != nil || delay <= 0 {
return RetrySettings{}, ErrInvalidRetryDelay
}
settings.Delay = delay
}
return settings, nil
}
// ProxyEntry defines one SSH tunnel.
type ProxyEntry struct {
Direction ProxyDirection `toml:"direction"`
RemotePort uint16 `toml:"remotePort"`
RemoteIP string `toml:"remoteIP"`
LocalPort uint16 `toml:"localPort"`
LocalIP string `toml:"localIP"`
Host string `toml:"host"`
IdentityFile string `toml:"identityFile,omitempty"`
Retry *RetryConfig `toml:"retry"`
}
// Config is the TOML configuration used by est.
type Config struct {
SSHConfig string `toml:"sshConfig"`
Retry *RetryConfig `toml:"retry"`
Entries []ProxyEntry `toml:"entry"`
}
// RetrySettings resolves the retry configuration for entry. An entry retry
// block fully overrides the top-level retry block.
func (cfg Config) RetrySettings(entry ProxyEntry) (RetrySettings, error) {
if entry.Retry != nil {
return entry.Retry.Settings()
}
if cfg.Retry != nil {
return cfg.Retry.Settings()
}
return RetryConfig{}.Settings()
}
// LoadConfig decodes a TOML configuration file from path.
func LoadConfig(path string) (Config, error) {
var config Config
file, err := os.Open(path)
if err != nil {
return config, err
}
defer func() {
_ = file.Close()
}()
if _, err := toml.NewDecoder(file).Decode(&config); err != nil {
return config, err
}
return config, nil
}