-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathredirector.go
166 lines (148 loc) · 3.76 KB
/
redirector.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package main
import (
"bufio"
"flag"
"io"
"io/ioutil"
"log"
"os"
"os/signal"
"strings"
"syscall"
)
var (
verboseFlag bool
debugFlag bool
configFlag string
)
var config *Config
var channels map[string]chan *Input
var ConsoleLogger *log.Logger
var ChangeLogger *log.Logger
var ChangeLoggerFile *os.File
var ErrorLogger *log.Logger
var ErrorLoggerFile *os.File
func init() {
flag.BoolVar(&verboseFlag, "v", false, "verbose output")
flag.BoolVar(&debugFlag, "d", true, "debug output")
flag.StringVar(&configFlag, "c", "", "config file location")
}
func handleSignals() {
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGHUP)
for {
sig := <-sigc
ErrorLogger.Println("Signal received:", sig)
switch sig {
case syscall.SIGHUP:
ErrorLogger.Println("Waiting for config")
WGConfig.Wait()
WGConfig.Add(1)
ErrorLogger.Println("Loading new configuration")
if err := load_config(true); err != nil {
ErrorLogger.Println("Failed to load new configuration")
}
WGConfig.Done()
}
}
}
func load_config(sync bool) error {
if newcfg, err := NewConfig(configFlag); err != nil {
// this will go to squid cache.log
ConsoleLogger.Printf("redirector| Failed to read config - '%v'", err)
return err
} else {
if err := setLogging(newcfg); err != nil {
// this will go to squid cache.log
ConsoleLogger.Println("redirector| Failed to set log - '%v'", err)
return err
}
newcfg.LoadFiles()
newcfg.ReloadAD(sync)
newcfg.LoadCategories(sync)
// for immediate GC old config
// oldconfig can be nil on initial config load (on start)
var oldconfig *Config
if oldconfig, config = config, newcfg; oldconfig != nil {
oldconfig.StopReloadAD()
oldconfig.AllowURLs = nil
for k, _ := range oldconfig.Categories {
oldconfig.Categories[k] = nil
}
}
config.ScheduleReloadAD(config.ADReload)
ErrorLogger.Printf("Configuration loaded")
}
return nil
}
func setLoggingFile(path string, file *os.File) (logger *log.Logger, err error) {
file.Close()
if path != "" {
if file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666); err != nil {
return nil, err
} else {
logger = log.New(file, "", log.Ldate|log.Ltime)
}
} else {
logger = log.New(ioutil.Discard, "", 0)
}
return logger, nil
}
func setLogging(cfg *Config) (err error) {
if ChangeLogger, err = setLoggingFile(cfg.change_log, ChangeLoggerFile); err != nil {
return
}
if ErrorLogger, err = setLoggingFile(cfg.error_log, ErrorLoggerFile); err != nil {
return
}
return
}
func main() {
ConsoleLogger = log.New(os.Stderr, "", 0)
flag.Parse()
if err := load_config(false); err != nil {
os.Exit(1)
}
defer ChangeLoggerFile.Close()
defer ErrorLoggerFile.Close()
// read from stdin
reader := bufio.NewReader(os.Stdin)
// sync write to stdout
writer_chan := make(chan string)
go OutWriter(writer_chan)
WGMain.Add(1)
ErrorLogger.Println("Started, ready to serve requests")
go handleSignals()
channels = make(map[string]chan *Input)
for {
if line, err := reader.ReadString('\n'); err != nil {
if err != io.EOF {
ErrorLogger.Println("Failed to read string:", err)
}
break
} else {
line = strings.Trim(line, "\n")
if input, err := ParseInput(line); err != nil {
ErrorLogger.Println("Failed to parse input:", err)
writer_chan <- line
} else {
// dynamically create separate goroutine for each squid chan-id
if _, ok := channels[input.Chanid]; !ok {
channels[input.Chanid] = make(chan *Input)
go Checker(input.Chanid, channels[input.Chanid], writer_chan)
WGMain.Add(1)
}
channels[input.Chanid] <- &input
}
}
}
close(writer_chan)
for _, ch := range channels {
close(ch)
}
config.StopReloadAD()
WGConfig.Wait()
WGAD.Wait()
WGMain.Wait()
ErrorLogger.Println("Finished")
}