mirror of
https://github.com/wweir/sower.git
synced 2024-04-21 12:42:15 +00:00
146 lines
3.4 KiB
Go
146 lines
3.4 KiB
Go
package conf
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/golang/glog"
|
|
toml "github.com/pelletier/go-toml"
|
|
"github.com/wweir/sower/util"
|
|
)
|
|
|
|
// Conf define the config items
|
|
var Conf = struct {
|
|
ConfigFile string
|
|
NetType string `toml:"net_type"`
|
|
Cipher string `toml:"cipher"`
|
|
Password string `toml:"password"`
|
|
|
|
ServerPort string `toml:"server_port"`
|
|
ServerAddr string `toml:"server_addr"`
|
|
HTTPProxy string `toml:"http_proxy"`
|
|
|
|
DNSServer string `toml:"dns_server"`
|
|
ClientIP string `toml:"client_ip"`
|
|
SuggestLevel string `toml:"suggest_level"`
|
|
ClearDNSCache string `toml:"clear_dns_cache"`
|
|
|
|
BlockList []string `toml:"blocklist"`
|
|
WhiteList []string `toml:"whitelist"`
|
|
Suggestions []string `toml:"suggestions"`
|
|
Verbose int `toml:"verbose"`
|
|
}{}
|
|
|
|
func init() {
|
|
initArgs()
|
|
|
|
if _, err := os.Stat(Conf.ConfigFile); os.IsNotExist(err) {
|
|
glog.Warningln("no config file has been load:", Conf.ConfigFile)
|
|
return
|
|
}
|
|
for i := range refreshFns {
|
|
if action, err := refreshFns[i](); err != nil {
|
|
glog.Fatalln(action+":", err)
|
|
}
|
|
}
|
|
|
|
go addSuggestions()
|
|
}
|
|
|
|
// refreshFns will be executed while init and write new config
|
|
var refreshFns = []func() (string, error){
|
|
func() (string, error) {
|
|
action := "load config"
|
|
f, err := os.OpenFile(Conf.ConfigFile, os.O_RDONLY, 0644)
|
|
if err != nil {
|
|
return action, err
|
|
}
|
|
defer f.Close()
|
|
|
|
//safe refresh config
|
|
file := Conf.ConfigFile
|
|
if err = toml.NewDecoder(f).Decode(&Conf); err != nil {
|
|
return action, err
|
|
}
|
|
Conf.ConfigFile = file
|
|
|
|
return action, flag.Set("v", strconv.Itoa(Conf.Verbose))
|
|
},
|
|
func() (string, error) {
|
|
action := "clear dns cache"
|
|
if Conf.ClearDNSCache != "" {
|
|
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
switch runtime.GOOS {
|
|
case "windows":
|
|
if out, err := exec.CommandContext(ctx, "cmd", "/c", Conf.ClearDNSCache).CombinedOutput(); err != nil {
|
|
return action, errors.Wrapf(err, "cmd: %s, output: %s, error", Conf.ClearDNSCache, out)
|
|
}
|
|
default:
|
|
if out, err := exec.CommandContext(ctx, "sh", "-c", Conf.ClearDNSCache).CombinedOutput(); err != nil {
|
|
return action, errors.Wrapf(err, "cmd: %s, output: %s, error", Conf.ClearDNSCache, out)
|
|
}
|
|
}
|
|
}
|
|
return action, nil
|
|
},
|
|
}
|
|
|
|
// AddRefreshFn add refreshh function for reload config
|
|
func AddRefreshFn(init bool, fn func() (string, error)) error {
|
|
if init {
|
|
if _, err := fn(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
refreshFns = append(refreshFns, fn)
|
|
return nil
|
|
}
|
|
|
|
// SuggestCh add domain into suggestios
|
|
var SuggestCh = make(chan string)
|
|
|
|
// addSuggestions add new domain into suggest rules
|
|
func addSuggestions() {
|
|
for domain := range SuggestCh {
|
|
Conf.Suggestions = append(Conf.Suggestions, domain)
|
|
Conf.Suggestions = util.NewReverseSecSlice(Conf.Suggestions).Sort().Uniq()
|
|
|
|
{ // safe write
|
|
f, err := os.OpenFile(Conf.ConfigFile+"~", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
|
if err != nil {
|
|
glog.Errorln(err)
|
|
continue
|
|
}
|
|
|
|
if err := toml.NewEncoder(f).ArraysWithOneElementPerLine(true).Encode(Conf); err != nil {
|
|
glog.Errorln(err)
|
|
f.Close()
|
|
continue
|
|
}
|
|
f.Close()
|
|
|
|
if err = os.Rename(Conf.ConfigFile+"~", Conf.ConfigFile); err != nil {
|
|
glog.Errorln(err)
|
|
continue
|
|
}
|
|
}
|
|
|
|
// reload config
|
|
for i := range refreshFns {
|
|
if action, err := refreshFns[i](); err != nil {
|
|
glog.Errorln(action+":", err)
|
|
}
|
|
}
|
|
}
|
|
}
|