~bigbes/core-go

ref: d3f7b91ae41a41d56a78de7eb065f15b1a155851 core-go/config/config.go -rw-r--r-- 2.8 KiB
d3f7b91a — Drew DeVault webhooks: implement internal webhook users 1 year, 6 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package config

import (
	"fmt"
	"log"
	"net"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"git.sr.ht/~sircmpwn/getopt"
	"github.com/vaughan0/go-ini"

	"git.sr.ht/~sircmpwn/core-go/crypto"
)

var (
	Debug         bool
	Addr          string
	InternalIPNet []net.IPNet
)

// Just loads the config files
func LoadFiles() ini.File {
	var (
		config ini.File
		err    error
	)

	// Only loads from one of these locations
	for _, path := range []string{
		"config.ini",
		"../config.ini",
		"/etc/sr.ht/config.ini",
		"/etc/sr.ht/*.ini",
	} {
		matches, err_ := filepath.Glob(path)
		if err_ != nil {
			panic(err) // only happens on bad input
		}
		for _, f := range matches {
			if config == nil {
				config, err = ini.LoadFile(f)
			} else {
				err = config.LoadFile(f)
			}
			if err != nil {
				break
			} else {
				log.Printf("Loaded config from %s", f)
			}
		}
		if len(matches) > 0 {
			break
		}
	}
	if err != nil {
		log.Fatalf("Failed to load config file: %v", err)
	}
	return config
}

// Loads the application configuration, reads options from the command line,
// and initializes some internals based on these results.
func LoadConfig(defaultAddr string) ini.File {
	Addr = defaultAddr

	opts, _, err := getopt.Getopts(os.Args, "b:d")
	if err != nil {
		panic(err)
	}

	for _, opt := range opts {
		switch opt.Option {
		case 'b':
			Addr = opt.Value
		case 'd':
			Debug = true
		}
	}

	config := LoadFiles()
	crypto.InitCrypto(config)

	nets, ok := config.Get("sr.ht", "internal-ipnet")
	if !ok {
		nets = "127.0.0.0/8,192.168.0.0/16,10.0.0.0/8,::1/128,fc00::/7"
	}
	for _, n := range strings.Split(nets, ",") {
		_, net, err := net.ParseCIDR(n)
		if err != nil {
			panic(fmt.Errorf("[sr.ht]internal-ipnet: %w", err))
		}
		InternalIPNet = append(InternalIPNet, *net)
	}

	return config
}

func GetOrigin(conf ini.File, svc string, external bool) string {
	if external {
		origin, _ := conf.Get(svc, "origin")
		return origin
	}
	origin, ok := conf.Get(svc, "internal-origin")
	if ok {
		return origin
	}
	origin, _ = conf.Get(svc, "origin")
	return origin
}

const DefaultQueueSize = 512

// Returns the configured integer value for the given section and variable name.
// If nothing is configured, the default value will be returned.
// If an invalid integer is configured, this function will panic.
func GetInt(conf ini.File, section, name string, defValue int) int {
	value := defValue
	if s, ok := conf.Get(section, name); ok {
		var err error
		if value, err = strconv.Atoi(s); err != nil {
			panic(fmt.Errorf("[%s]%s: %w", section, name, err))
		}
	}
	return value
}

// Returns true if the given IP address is part of the internal networks as
// per the configuration of [sr.ht]internal-ipnet.
func IsInternalIP(ip net.IP) bool {
	for _, net := range InternalIPNet {
		if net.Contains(ip) {
			return true
		}
	}
	return false
}