diff --git a/cmd/tlstunnel/main.go b/cmd/tlstunnel/main.go index 4ca3d7f..23a0a73 100644 --- a/cmd/tlstunnel/main.go +++ b/cmd/tlstunnel/main.go @@ -4,6 +4,7 @@ import ( "flag" "log" + "git.sr.ht/~emersion/go-scfg" "git.sr.ht/~emersion/tlstunnel" "github.com/caddyserver/certmagic" ) @@ -17,7 +18,7 @@ func main() { flag.StringVar(&configPath, "config", configPath, "path to configuration file") flag.Parse() - cfg, err := tlstunnel.LoadConfig(configPath) + cfg, err := scfg.Load(configPath) if err != nil { log.Fatalf("failed to load config file: %v", err) } diff --git a/config.go b/config.go deleted file mode 100644 index fca27ec..0000000 --- a/config.go +++ /dev/null @@ -1,109 +0,0 @@ -package tlstunnel - -import ( - "bufio" - "fmt" - "io" - "os" - - "github.com/google/shlex" -) - -type Directive struct { - Name string - Params []string - Children []*Directive -} - -func (d *Directive) ParseParams(params ...*string) error { - if len(d.Params) < len(params) { - return fmt.Errorf("directive %q: want %v params, got %v", d.Name, len(params), len(d.Params)) - } - for i, ptr := range params { - if ptr == nil { - continue - } - *ptr = d.Params[i] - } - return nil -} - -func (d *Directive) ChildrenByName(name string) []*Directive { - l := make([]*Directive, 0, len(d.Children)) - for _, child := range d.Children { - if child.Name == name { - l = append(l, child) - } - } - return l -} - -func (d *Directive) ChildByName(name string) *Directive { - for _, child := range d.Children { - if child.Name == name { - return child - } - } - return nil -} - -func LoadConfig(path string) (*Directive, error) { - f, err := os.Open(path) - if err != nil { - return nil, err - } - defer f.Close() - - return ParseConfig(f) -} - -func ParseConfig(r io.Reader) (*Directive, error) { - scanner := bufio.NewScanner(r) - - var directives []*Directive - var cur *Directive - for scanner.Scan() { - l := scanner.Text() - words, err := shlex.Split(l) - if err != nil { - return nil, fmt.Errorf("failed to parse config file: %v", err) - } else if len(words) == 0 { - continue - } - - if len(words) == 1 && l[len(l)-1] == '}' { - if cur == nil { - return nil, fmt.Errorf("unexpected '}'") - } - cur = nil - continue - } - - var d *Directive - if words[len(words)-1] == "{" && l[len(l)-1] == '{' { - words = words[:len(words)-1] - - var name string - params := words - if len(words) > 0 { - name, params = words[0], words[1:] - } - - d = &Directive{Name: name, Params: params} - cur = d - directives = append(directives, d) - } else { - d = &Directive{Name: words[0], Params: words[1:]} - if cur != nil { - cur.Children = append(cur.Children, d) - } else { - directives = append(directives, d) - } - } - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("failed to read config file: %v", err) - } - - return &Directive{Children: directives}, nil -} diff --git a/directives.go b/directives.go index 43efd20..f9308c4 100644 --- a/directives.go +++ b/directives.go @@ -5,10 +5,12 @@ import ( "net" "net/url" "strings" + + "git.sr.ht/~emersion/go-scfg" ) -func parseConfig(srv *Server, cfg *Directive) error { - for _, d := range cfg.Children { +func parseConfig(srv *Server, cfg scfg.Block) error { + for _, d := range cfg { var err error switch d.Name { case "frontend": @@ -25,12 +27,12 @@ func parseConfig(srv *Server, cfg *Directive) error { return nil } -func parseFrontend(srv *Server, d *Directive) error { +func parseFrontend(srv *Server, d *scfg.Directive) error { frontend := &Frontend{Server: srv} srv.Frontends = append(srv.Frontends, frontend) // TODO: support multiple backends - backendDirective := d.ChildByName("backend") + backendDirective := d.Children.Get("backend") if backendDirective == nil { return fmt.Errorf("missing backend directive in frontend block") } @@ -60,7 +62,7 @@ func parseFrontend(srv *Server, d *Directive) error { return nil } -func parseBackend(backend *Backend, d *Directive) error { +func parseBackend(backend *Backend, d *scfg.Directive) error { var backendURI string if err := d.ParseParams(&backendURI); err != nil { return err @@ -94,7 +96,7 @@ func parseBackend(backend *Backend, d *Directive) error { return nil } -func parseTLS(srv *Server, d *Directive) error { +func parseTLS(srv *Server, d *scfg.Directive) error { for _, child := range d.Children { switch child.Name { case "acme_ca": diff --git a/go.mod b/go.mod index 87ed333..490543d 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module git.sr.ht/~emersion/tlstunnel go 1.15 require ( + git.sr.ht/~emersion/go-scfg v0.0.0-20201019141958-764b187dbd52 github.com/caddyserver/certmagic v0.12.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/klauspost/cpuid v1.3.1 // indirect diff --git a/go.sum b/go.sum index a41eaf1..29a36ba 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +git.sr.ht/~emersion/go-scfg v0.0.0-20201019141958-764b187dbd52 h1:4+M83ExDGB+goSgq+q+c1aMA43GRLsItdN23fTDjKZ4= +git.sr.ht/~emersion/go-scfg v0.0.0-20201019141958-764b187dbd52/go.mod h1:t+Ww6SR24yYnXzEWiNlOY0AFo5E9B73X++10lrSpp4U= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/caddyserver/certmagic v0.12.0 h1:1f7kxykaJkOVVpXJ8ZrC6RAO5F6+kKm9U7dBFbLNeug= diff --git a/server.go b/server.go index 4b468cf..b9c3a0d 100644 --- a/server.go +++ b/server.go @@ -9,6 +9,7 @@ import ( "net" "strings" + "git.sr.ht/~emersion/go-scfg" "github.com/caddyserver/certmagic" "github.com/pires/go-proxyproto" "github.com/pires/go-proxyproto/tlvparse" @@ -39,7 +40,7 @@ func NewServer() *Server { } } -func (srv *Server) Load(cfg *Directive) error { +func (srv *Server) Load(cfg scfg.Block) error { return parseConfig(srv, cfg) }