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

Last change on this file since 325 was 323, checked in by contact, 5 years ago

Add support for WebSocket connections

WebSocket connections allow web-based clients to connect to IRC. This
commit implements the WebSocket sub-protocol as specified by the pending
IRCv3 proposal [1].

WebSocket listeners can now be set up via a "wss" protocol in the
listen directive. The new http-origin directive allows the CORS
allowed origins to be configured.

[1]: https://github.com/ircv3/ircv3-specifications/pull/342

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