diff --git a/engine/engine.go b/engine/engine.go index f12e04d..ca25281 100755 --- a/engine/engine.go +++ b/engine/engine.go @@ -2,6 +2,7 @@ package engine import ( "errors" + "os" "github.com/xjasonlyu/tun2socks/component/dialer" "github.com/xjasonlyu/tun2socks/core/device" @@ -11,31 +12,53 @@ import ( "github.com/xjasonlyu/tun2socks/stats" ) -type Engine struct { - mtu uint32 - iface string - stats string - token string - logLevel string - rawProxy string - rawDevice string +var _engine = &engine{} + +// Start starts the default engine up. +func Start() error { + return _engine.start() +} + +// Stop shuts the default engine down. +func Stop() error { + return _engine.stop() +} + +// Insert loads *Key to the default engine. +func Insert(k *Key) { + _engine.insert(k) +} + +type Key struct { + MTU uint32 + Proxy string + Stats string + Token string + Device string + LogLevel string + Interface string + Version bool +} + +type engine struct { + *Key stack *stack.Stack proxy proxy.Proxy device device.Device } -func New(opts ...Option) *Engine { - e := &Engine{} - - for _, opt := range opts { - opt(e) +func (e *engine) start() error { + if e.Key == nil { + return errors.New("empty key") } - return e -} -func (e *Engine) Start() error { - for _, set := range []func() error{ + if e.Version { + showVersion() + os.Exit(0) + } + + for _, f := range []func() error{ e.setLogLevel, e.setInterface, e.setStats, @@ -43,23 +66,26 @@ func (e *Engine) Start() error { e.setDevice, e.setStack, } { - if err := set(); err != nil { + if err := f(); err != nil { return err } } return nil } -func (e *Engine) Stop() { +func (e *engine) stop() error { if e.device != nil { - if err := e.device.Close(); err != nil { - log.Fatalf("%v", err) - } + return e.device.Close() } + return nil } -func (e *Engine) setLogLevel() error { - level, err := log.ParseLevel(e.logLevel) +func (e *engine) insert(k *Key) { + e.Key = k +} + +func (e *engine) setLogLevel() error { + level, err := log.ParseLevel(e.LogLevel) if err != nil { return err } @@ -67,46 +93,46 @@ func (e *Engine) setLogLevel() error { return nil } -func (e *Engine) setInterface() error { - if e.iface != "" { - if err := dialer.BindToInterface(e.iface); err != nil { +func (e *engine) setInterface() error { + if e.Interface != "" { + if err := dialer.BindToInterface(e.Interface); err != nil { return err } - log.Infof("[BOUND] bind to interface: %s", e.iface) + log.Infof("[BOUND] bind to interface: %s", e.Interface) } return nil } -func (e *Engine) setStats() error { - if e.stats != "" { +func (e *engine) setStats() error { + if e.Stats != "" { go func() { - _ = stats.Start(e.stats, e.token) + _ = stats.Start(e.Stats, e.Token) }() - log.Infof("[STATS] listen and serve at: http://%s", e.stats) + log.Infof("[STATS] stats server listen at: http://%s", e.Stats) } return nil } -func (e *Engine) setProxy() (err error) { - if e.rawProxy == "" { +func (e *engine) setProxy() (err error) { + if e.Proxy == "" { return errors.New("empty proxy") } - e.proxy, err = parseProxy(e.rawProxy) + e.proxy, err = parseProxy(e.Proxy) proxy.SetDialer(e.proxy) return } -func (e *Engine) setDevice() (err error) { - if e.rawDevice == "" { +func (e *engine) setDevice() (err error) { + if e.Device == "" { return errors.New("empty device") } - e.device, err = parseDevice(e.rawDevice, e.mtu) + e.device, err = parseDevice(e.Device, e.MTU) return } -func (e *Engine) setStack() (err error) { +func (e *engine) setStack() (err error) { defer func() { if err == nil { log.Infof( diff --git a/engine/opts.go b/engine/opts.go deleted file mode 100755 index 626b972..0000000 --- a/engine/opts.go +++ /dev/null @@ -1,40 +0,0 @@ -package engine - -type Option func(*Engine) - -func WithDevice(device string) Option { - return func(e *Engine) { - e.rawDevice = device - } -} - -func WithInterface(iface string) Option { - return func(e *Engine) { - e.iface = iface - } -} - -func WithLogLevel(level string) Option { - return func(e *Engine) { - e.logLevel = level - } -} - -func WithMTU(mtu int) Option { - return func(e *Engine) { - e.mtu = uint32(mtu) - } -} - -func WithProxy(proxy string) Option { - return func(e *Engine) { - e.rawProxy = proxy - } -} - -func WithStats(stats, token string) Option { - return func(e *Engine) { - e.stats = stats - e.token = token - } -} diff --git a/engine/version.go b/engine/version.go new file mode 100644 index 0000000..95f5a86 --- /dev/null +++ b/engine/version.go @@ -0,0 +1,22 @@ +package engine + +import ( + "fmt" + "runtime" + "strings" + + "github.com/xjasonlyu/tun2socks/constant" +) + +func showVersion() { + fmt.Print(versionString()) + fmt.Print(releaseString()) +} + +func versionString() string { + return fmt.Sprintf("%s %s\n", constant.Name, strings.TrimPrefix(constant.Version, "v")) +} + +func releaseString() string { + return fmt.Sprintf("%s/%s, %s, %s\n", runtime.GOOS, runtime.GOARCH, runtime.Version(), constant.BuildTime) +} diff --git a/main.go b/main.go index c481c8a..dcd328d 100755 --- a/main.go +++ b/main.go @@ -1,69 +1,41 @@ package main import ( - "fmt" "os" "os/signal" - "runtime" "syscall" - "github.com/xjasonlyu/tun2socks/constant" "github.com/xjasonlyu/tun2socks/engine" "github.com/xjasonlyu/tun2socks/log" flag "github.com/spf13/pflag" ) -var ( - device string - iface string - level string - proxy string - stats string - token string - mtu int - version bool -) +var key = new(engine.Key) func init() { - flag.StringVarP(&device, "device", "d", "", "Use this device [driver://]name") - flag.StringVarP(&iface, "interface", "i", "", "Use network INTERFACE (Linux and MacOS only)") - flag.StringVarP(&proxy, "proxy", "p", "", "Use this proxy [protocol://]host[:port]") - flag.StringVarP(&level, "loglevel", "l", "info", "Log level [debug|info|warn|error|silent]") - flag.StringVar(&stats, "stats", "", "HTTP statistic server listen address") - flag.StringVar(&token, "token", "", "HTTP statistic server auth token") - flag.IntVarP(&mtu, "mtu", "m", 0, "Set device maximum transmission unit (MTU)") - flag.BoolVarP(&version, "version", "v", false, "Show version information and quit") + flag.StringVarP(&key.Device, "device", "d", "", "use this device [driver://]name") + flag.StringVarP(&key.Interface, "interface", "i", "", "use network INTERFACE (Linux/MacOS only)") + flag.StringVarP(&key.Proxy, "proxy", "p", "", "use this proxy [protocol://]host[:port]") + flag.StringVarP(&key.LogLevel, "loglevel", "l", "info", "log level [debug|info|warn|error|silent]") + flag.StringVar(&key.Stats, "stats", "", "HTTP statistic server listen address") + flag.StringVar(&key.Token, "token", "", "HTTP statistic server auth token") + flag.Uint32VarP(&key.MTU, "mtu", "m", 0, "set device maximum transmission unit (MTU)") + flag.BoolVarP(&key.Version, "version", "v", false, "show version information and quit") flag.Parse() } func main() { - if version { - fmt.Printf("%s %s\n%s/%s, %s, %s\n", - constant.Name, - constant.Version, - runtime.GOOS, - runtime.GOARCH, - runtime.Version(), - constant.BuildTime, - ) - os.Exit(0) + engine.Insert(key) + + checkErr := func(msg string, f func() error) { + if err := f(); err != nil { + log.Fatalf("Failed to %s: %v", msg, err) + } } - options := []engine.Option{ - engine.WithDevice(device), - engine.WithInterface(iface), - engine.WithLogLevel(level), - engine.WithMTU(mtu), - engine.WithProxy(proxy), - engine.WithStats(stats, token), - } - - eng := engine.New(options...) - if err := eng.Start(); err != nil { - log.Fatalf("Start engine error: %v", err) - } - defer eng.Stop() + checkErr("start engine", engine.Start) + defer checkErr("stop engine", engine.Stop) sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)