source: code/trunk/config/config.go@ 321

Last change on this file since 321 was 317, checked in by contact, 5 years ago

Allow multiple listeners, default to ircs

Users can now specify multiple "listen" directives in their
configuration file. If -listen is specified on the CLI, it's added to
the list of listeners.

Listeners are now parsed as URLs. If the scheme is missing "ircs" is
assumed. URLs allow to enable/disable TLS on a per-listener basis and
will be used for Unix sockets too.

The default listening address is changed from irc+insecure://:6667 to
ircs://:6697. This avoids setting up an insecure listener opened to
everybody.

File size: 2.2 KB
Line 
1package config
2
3import (
4 "bufio"
5 "fmt"
6 "io"
7 "os"
8
9 "github.com/google/shlex"
10)
11
12type TLS struct {
13 CertPath, KeyPath string
14}
15
16type Server struct {
17 Listen []string
18 Hostname string
19 TLS *TLS
20 SQLDriver string
21 SQLSource string
22 LogPath string
23}
24
25func Defaults() *Server {
26 hostname, err := os.Hostname()
27 if err != nil {
28 hostname = "localhost"
29 }
30 return &Server{
31 Hostname: hostname,
32 SQLDriver: "sqlite3",
33 SQLSource: "soju.db",
34 }
35}
36
37func Load(path string) (*Server, error) {
38 f, err := os.Open(path)
39 if err != nil {
40 return nil, err
41 }
42 defer f.Close()
43
44 return Parse(f)
45}
46
47func Parse(r io.Reader) (*Server, error) {
48 scanner := bufio.NewScanner(r)
49
50 var directives []directive
51 for scanner.Scan() {
52 words, err := shlex.Split(scanner.Text())
53 if err != nil {
54 return nil, fmt.Errorf("failed to parse config file: %v", err)
55 } else if len(words) == 0 {
56 continue
57 }
58
59 name, params := words[0], words[1:]
60 directives = append(directives, directive{name, params})
61 }
62 if err := scanner.Err(); err != nil {
63 return nil, fmt.Errorf("failed to read config file: %v", err)
64 }
65
66 srv := Defaults()
67 for _, d := range directives {
68 switch d.Name {
69 case "listen":
70 var uri string
71 if err := d.parseParams(&uri); err != nil {
72 return nil, err
73 }
74 srv.Listen = append(srv.Listen, uri)
75 case "hostname":
76 if err := d.parseParams(&srv.Hostname); err != nil {
77 return nil, err
78 }
79 case "tls":
80 tls := &TLS{}
81 if err := d.parseParams(&tls.CertPath, &tls.KeyPath); err != nil {
82 return nil, err
83 }
84 srv.TLS = tls
85 case "sql":
86 if err := d.parseParams(&srv.SQLDriver, &srv.SQLSource); err != nil {
87 return nil, err
88 }
89 case "log":
90 if err := d.parseParams(&srv.LogPath); err != nil {
91 return nil, err
92 }
93 default:
94 return nil, fmt.Errorf("unknown directive %q", d.Name)
95 }
96 }
97
98 return srv, nil
99}
100
101type directive struct {
102 Name string
103 Params []string
104}
105
106func (d *directive) parseParams(out ...*string) error {
107 if len(d.Params) != len(out) {
108 return fmt.Errorf("directive %q has wrong number of parameters: expected %v, got %v", d.Name, len(out), len(d.Params))
109 }
110 for i := range out {
111 *out[i] = d.Params[i]
112 }
113 return nil
114}
Note: See TracBrowser for help on using the repository browser.