7
7
"fmt"
8
8
"net/http"
9
9
"os"
10
+ "sync"
11
+ "strings"
10
12
"runtime"
11
13
12
14
_ "net/http/pprof"
@@ -16,56 +18,148 @@ import (
16
18
)
17
19
18
20
var (
19
- configureFile string
20
- baseCfg = & baseConfig {}
21
- pprofAddr string
22
21
pprofEnabled = os .Getenv ("PROFILING" ) != ""
23
22
)
24
23
25
24
func init () {
26
25
gost .SetLogger (& gost.LogLogger {})
27
26
27
+ // TODO - Generate different certificates for each worker
28
+ generateTLSCertificate ()
29
+ }
30
+
31
+ func main () {
32
+ var wg sync.WaitGroup
33
+ wg .Add (1 ) // Gost must exit if any of the workers exit
34
+
35
+ // Split os.Args using -- and create a worker with each slice
36
+ args := strings .Split (" " + strings .Join (os .Args [1 :], " " ) + " " , " -- " )
37
+ if strings .Join (args , "" ) == "" {
38
+ // Fix to show gost help if the resulting array is empty
39
+ args [0 ] = " "
40
+ }
41
+ for wid , wargs := range args {
42
+ if wargs != "" {
43
+ go worker (wid , wargs , & wg )
44
+ }
45
+ }
46
+ wg .Wait ()
47
+ }
48
+
49
+ func worker (id int , args string , wg * sync.WaitGroup ) {
50
+ defer wg .Done ()
51
+
28
52
var (
29
- printVersion bool
53
+ configureFile string
54
+ baseCfg = & baseConfig {}
55
+ pprofAddr string
30
56
)
31
57
32
- flag .Var (& baseCfg .route .ChainNodes , "F" , "forward address, can make a forward chain" )
33
- flag .Var (& baseCfg .route .ServeNodes , "L" , "listen address, can listen on multiple ports (required)" )
34
- flag .StringVar (& configureFile , "C" , "" , "configure file" )
35
- flag .BoolVar (& baseCfg .Debug , "D" , false , "enable debug log" )
36
- flag .BoolVar (& printVersion , "V" , false , "print version" )
37
- if pprofEnabled {
38
- flag .StringVar (& pprofAddr , "P" , ":6060" , "profiling HTTP server address" )
39
- }
40
- flag .Parse ()
58
+ init := func () error {
59
+ var printVersion bool
60
+
61
+ wf := flag .NewFlagSet (os .Args [0 ], flag .ExitOnError )
62
+
63
+ wf .Var (& baseCfg .route .ChainNodes , "F" , "forward address, can make a forward chain" )
64
+ wf .Var (& baseCfg .route .ServeNodes , "L" , "listen address, can listen on multiple ports (required)" )
65
+ wf .StringVar (& configureFile , "C" , "" , "configure file" )
66
+ wf .BoolVar (& baseCfg .Debug , "D" , false , "enable debug log" )
67
+ wf .BoolVar (& printVersion , "V" , false , "print version" )
68
+
69
+ if pprofEnabled {
70
+ // Every worker uses a different profiling server by default
71
+ wf .StringVar (& pprofAddr , "P" , fmt .Sprintf (":606%d" , id ), "profiling HTTP server address" )
72
+ }
73
+
74
+ wf .Parse (strings .Fields (args ))
75
+
76
+ if printVersion {
77
+ fmt .Fprintf (os .Stdout , "gost %s (%s %s/%s)\n " , gost .Version , runtime .Version (), runtime .GOOS , runtime .GOARCH )
78
+ os .Exit (0 )
79
+ } else if wf .NFlag () == 0 {
80
+ wf .Usage ()
81
+ os .Exit (0 )
82
+ } else if configureFile != "" {
83
+ err := parseBaseConfig (configureFile , baseCfg )
84
+ if err != nil {
85
+ return err
86
+ }
87
+ }
41
88
42
- if printVersion {
43
- fmt .Fprintf (os .Stdout , "gost %s (%s %s/%s)\n " ,
44
- gost .Version , runtime .Version (), runtime .GOOS , runtime .GOARCH )
45
- os .Exit (0 )
89
+ if baseCfg .route .ServeNodes .String () == "[]" {
90
+ configErrMsg := ""
91
+ if configureFile != "" {
92
+ configErrMsg = " or ServeNodes inside config file (-C)"
93
+ }
94
+ fmt .Fprintf (os .Stderr , "\n [!] Error: Missing -L flag%s\n \n " , configErrMsg )
95
+ wf .Usage ()
96
+ os .Exit (1 )
97
+ }
98
+
99
+ return nil
46
100
}
47
101
48
- if configureFile != "" {
49
- _ , err := parseBaseConfig (configureFile )
102
+ start := func () error {
103
+ // TODO - Make debug worker independent
104
+ if ! gost .Debug {
105
+ gost .Debug = baseCfg .Debug
106
+ }
107
+
108
+ var routers []router
109
+ rts , err := baseCfg .route .GenRouters ()
50
110
if err != nil {
51
- log .Log (err )
52
- os .Exit (1 )
111
+ return err
112
+ }
113
+ routers = append (routers , rts ... )
114
+
115
+ for _ , route := range baseCfg .Routes {
116
+ rts , err := route .GenRouters ()
117
+ if err != nil {
118
+ return err
119
+ }
120
+ routers = append (routers , rts ... )
121
+ }
122
+
123
+ if len (routers ) == 0 {
124
+ return errors .New ("invalid config" )
53
125
}
126
+ for i := range routers {
127
+ go routers [i ].Serve ()
128
+ }
129
+
130
+ return nil
54
131
}
55
- if flag .NFlag () == 0 {
56
- flag .PrintDefaults ()
57
- os .Exit (0 )
132
+
133
+ main := func () error {
134
+ if pprofEnabled {
135
+ go func () {
136
+ log .Log ("profiling server on" , pprofAddr )
137
+ log .Log (http .ListenAndServe (pprofAddr , nil ))
138
+ }()
139
+ }
140
+
141
+ err := start ()
142
+ return err
58
143
}
59
- }
60
144
61
- func main () {
62
- if pprofEnabled {
63
- go func () {
64
- log .Log ("profiling server on" , pprofAddr )
65
- log .Log (http .ListenAndServe (pprofAddr , nil ))
66
- }()
145
+ if err := init (); err != nil {
146
+ log .Log (err )
147
+ return
148
+ }
149
+ if err := main (); err != nil {
150
+ log .Log (err )
151
+ return
67
152
}
68
153
154
+ // Allow local functions to be garbage-collected
155
+ init = nil
156
+ main = nil
157
+ start = nil
158
+
159
+ select {}
160
+ }
161
+
162
+ func generateTLSCertificate () {
69
163
// NOTE: as of 2.6, you can use custom cert/key files to initialize the default certificate.
70
164
tlsConfig , err := tlsConfig (defaultCertFile , defaultKeyFile , "" )
71
165
if err != nil {
@@ -81,41 +175,5 @@ func main() {
81
175
} else {
82
176
log .Log ("load TLS certificate files OK" )
83
177
}
84
-
85
178
gost .DefaultTLSConfig = tlsConfig
86
-
87
- if err := start (); err != nil {
88
- log .Log (err )
89
- os .Exit (1 )
90
- }
91
-
92
- select {}
93
- }
94
-
95
- func start () error {
96
- gost .Debug = baseCfg .Debug
97
-
98
- var routers []router
99
- rts , err := baseCfg .route .GenRouters ()
100
- if err != nil {
101
- return err
102
- }
103
- routers = append (routers , rts ... )
104
-
105
- for _ , route := range baseCfg .Routes {
106
- rts , err := route .GenRouters ()
107
- if err != nil {
108
- return err
109
- }
110
- routers = append (routers , rts ... )
111
- }
112
-
113
- if len (routers ) == 0 {
114
- return errors .New ("invalid config" )
115
- }
116
- for i := range routers {
117
- go routers [i ].Serve ()
118
- }
119
-
120
- return nil
121
179
}
0 commit comments