FILE / ScuroNeko/est
internal/config/config.go
Исходный файл и его история в репозитории.
116 lines
3.3 KiB
Go
116 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 file.Close()
|
|
if _, err := toml.NewDecoder(file).Decode(&config); err != nil {
|
|
return config, err
|
|
}
|
|
return config, nil
|
|
}
|