-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
133 lines (112 loc) · 2.74 KB
/
main.go
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
package main
import (
"flag"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/BurntSushi/toml"
"golang.org/x/exp/inotify"
)
func main() {
configFile := flag.String("c", "config.toml", "Config file path")
flag.Parse()
findSocatBinary()
services := parseConfig(*configFile)
for _, s := range services {
if !s.Enabled {
log.Println(fmt.Sprintf("Service %s is disabled", s.Name))
} else {
s.Start()
}
}
var watch *inotify.Watcher
var err error
if watch, err = inotify.NewWatcher(); err != nil {
log.Println(fmt.Sprintf("Could not create a watcher: %s. Changes will need a restart to become effective", err))
} else {
setWatch(watch, filepath.Dir(*configFile))
}
for {
select {
case ev := <-watch.Event:
if filepath.Base(ev.Name) == *configFile {
log.Println("Change on the config file detected. Reloading services...")
unsetWatch(watch, filepath.Dir(*configFile))
for _, s := range services {
s.Stop()
}
<-time.NewTimer(time.Millisecond * 500).C
services = parseConfig(*configFile)
for _, s := range services {
if !s.Enabled {
log.Println(fmt.Sprintf("Service %s is disabled", s.Name))
} else {
s.Start()
}
}
setWatch(watch, filepath.Dir(*configFile))
}
}
}
}
func parseConfig(configFile string) map[string]*Service {
var config Services
var md toml.MetaData
var err error
if md, err = toml.DecodeFile(configFile, &config); err != nil {
log.Fatal(err)
}
services := make(map[string]*Service)
for name, serv := range config {
s := NewService()
s.Name = name
services[name] = s
for _, k := range md.Keys() {
ks := strings.Split(k.String(), ".")
if len(ks) > 1 && ks[0] == name {
switch ks[1] {
case "srcport":
s.Srcport = serv.Srcport
case "srcflags":
s.Srcflags = serv.Srcflags
case "srcproto":
s.Srcproto = serv.Srcproto
case "dsthost":
s.Dsthost = serv.Dsthost
case "dstproto":
s.Dstproto = serv.Dstproto
case "dstport":
s.Dstport = serv.Dstport
case "enabled":
s.Enabled = serv.Enabled
}
}
}
}
log.Println("Found", len(services), "services")
return services
}
func setWatch(watch *inotify.Watcher, path string) {
if err := watch.AddWatch(path, inotify.IN_MODIFY); err != nil {
log.Println(fmt.Sprintf("Error %s setting a watcher on the config file. Changes will need a restart to become effective", err))
}
}
func unsetWatch(watch *inotify.Watcher, path string) {
watch.RemoveWatch(path)
}
func findSocatBinary() {
c := exec.Command("which", "socat")
o, _ := c.Output()
err := c.Run()
if err != nil {
if _, err := os.Stat(*bin); os.IsNotExist(err) {
log.Fatalln("Couldnt find a socat binary")
}
} else {
*bin = string(o)
}
}