diff --git a/cmd/shadowsocks-local/local.go b/cmd/shadowsocks-local/local.go index 7bfbd5e..81481f6 100644 --- a/cmd/shadowsocks-local/local.go +++ b/cmd/shadowsocks-local/local.go @@ -178,7 +178,7 @@ func run(port, password, server string) { log.Fatal(err) } encTbl := ss.GetTable(password) - log.Printf("starting server at port %v ...\n", port) + log.Printf("starting local socks5 server at port %v, remote shadowsocks server %s...\n", port, server) for { conn, err := ln.Accept() if err != nil { @@ -191,14 +191,24 @@ func run(port, password, server string) { func main() { var configFile string + var cmdConfig ss.Config + flag.StringVar(&configFile, "c", "config.json", "specify config file") + flag.StringVar(&cmdConfig.Server, "s", "", "server address") + flag.StringVar(&cmdConfig.Password, "k", "", "password") + flag.IntVar(&cmdConfig.ServerPort, "p", 0, "server port") + flag.IntVar(&cmdConfig.LocalPort, "l", 0, "local socks5 proxy port") + flag.BoolVar((*bool)(&debug), "d", false, "print debug message") + flag.Parse() config, err := ss.ParseConfig(configFile) if err != nil { return } - debug = ss.Debug + ss.UpdateConfig(config, &cmdConfig) + ss.SetDebug(debug) + run(strconv.Itoa(config.LocalPort), config.Password, config.Server+":"+strconv.Itoa(config.ServerPort)) } diff --git a/cmd/shadowsocks-server/server.go b/cmd/shadowsocks-server/server.go index c1f56f2..8f7b321 100644 --- a/cmd/shadowsocks-server/server.go +++ b/cmd/shadowsocks-server/server.go @@ -152,14 +152,23 @@ func run(port, password string) { func main() { var configFile string + var cmdConfig ss.Config + flag.StringVar(&configFile, "c", "config.json", "specify config file") + flag.StringVar(&cmdConfig.Password, "k", "", "password") + flag.IntVar(&cmdConfig.ServerPort, "p", 0, "server port") + flag.IntVar(&cmdConfig.Timeout, "t", 60, "connection timeout (in seconds)") + flag.BoolVar((*bool)(&debug), "d", false, "print debug message") + flag.Parse() config, err := ss.ParseConfig(configFile) if err != nil { return } - debug = ss.Debug + ss.UpdateConfig(config, &cmdConfig) + ss.SetDebug(debug) + if len(config.PortPassword) == 0 { run(strconv.Itoa(config.ServerPort), config.Password) } else { diff --git a/config.json b/config.json index 02a39cc..0685796 100644 --- a/config.json +++ b/config.json @@ -7,6 +7,5 @@ "8388": "barfoo!", "8387": "foobar!" }, - "timeout":60, - "debug":true + "timeout":60 } diff --git a/shadowsocks/config.go b/shadowsocks/config.go index b8a45ba..91086c1 100644 --- a/shadowsocks/config.go +++ b/shadowsocks/config.go @@ -12,6 +12,7 @@ import ( "io/ioutil" "log" "os" + "reflect" "time" ) @@ -22,7 +23,6 @@ type Config struct { Password string `json:"password"` PortPassword map[string]string `json:"port_password"` Timeout int `json:"timeout"` - Debug bool `json:"debug"` } var readTimeout time.Duration @@ -46,7 +46,40 @@ func ParseConfig(path string) (config *Config, err error) { log.Println("can not parse config:", err) return nil, err } - Debug = DebugLog(config.Debug) readTimeout = time.Duration(config.Timeout) * time.Second return } + +func SetDebug(d DebugLog) { + Debug = d +} + +// Useful for command line to override options specified in config file +// Debug is not updated. +func UpdateConfig(old, new *Config) { + // Using reflection here is not necessary, but it's a good exercise. + // For more information on reflections in Go, read "The Laws of Reflection" + // http://golang.org/doc/articles/laws_of_reflection.html + newVal := reflect.ValueOf(new).Elem() + oldVal := reflect.ValueOf(old).Elem() + + // typeOfT := newVal.Type() + for i := 0; i < newVal.NumField(); i++ { + newField := newVal.Field(i) + oldField := oldVal.Field(i) + // log.Printf("%d: %s %s = %v\n", i, + // typeOfT.Field(i).Name, newField.Type(), newField.Interface()) + switch newField.Kind() { + case reflect.String: + s := newField.String() + if s != "" { + oldField.SetString(s) + } + case reflect.Int: + i := newField.Int() + if i != 0 { + oldField.SetInt(i) + } + } + } +}