Refactor: rewrite engine

This commit is contained in:
xjasonlyu
2021-02-10 13:11:11 +08:00
parent 34fb632f38
commit ea62deb0b6
4 changed files with 104 additions and 124 deletions

View File

@@ -2,6 +2,7 @@ package engine
import ( import (
"errors" "errors"
"os"
"github.com/xjasonlyu/tun2socks/component/dialer" "github.com/xjasonlyu/tun2socks/component/dialer"
"github.com/xjasonlyu/tun2socks/core/device" "github.com/xjasonlyu/tun2socks/core/device"
@@ -11,31 +12,53 @@ import (
"github.com/xjasonlyu/tun2socks/stats" "github.com/xjasonlyu/tun2socks/stats"
) )
type Engine struct { var _engine = &engine{}
mtu uint32
iface string // Start starts the default engine up.
stats string func Start() error {
token string return _engine.start()
logLevel string }
rawProxy string
rawDevice string // 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 stack *stack.Stack
proxy proxy.Proxy proxy proxy.Proxy
device device.Device device device.Device
} }
func New(opts ...Option) *Engine { func (e *engine) start() error {
e := &Engine{} if e.Key == nil {
return errors.New("empty key")
for _, opt := range opts {
opt(e)
} }
return e
}
func (e *Engine) Start() error { if e.Version {
for _, set := range []func() error{ showVersion()
os.Exit(0)
}
for _, f := range []func() error{
e.setLogLevel, e.setLogLevel,
e.setInterface, e.setInterface,
e.setStats, e.setStats,
@@ -43,23 +66,26 @@ func (e *Engine) Start() error {
e.setDevice, e.setDevice,
e.setStack, e.setStack,
} { } {
if err := set(); err != nil { if err := f(); err != nil {
return err return err
} }
} }
return nil return nil
} }
func (e *Engine) Stop() { func (e *engine) stop() error {
if e.device != nil { if e.device != nil {
if err := e.device.Close(); err != nil { return e.device.Close()
log.Fatalf("%v", err)
}
} }
return nil
} }
func (e *Engine) setLogLevel() error { func (e *engine) insert(k *Key) {
level, err := log.ParseLevel(e.logLevel) e.Key = k
}
func (e *engine) setLogLevel() error {
level, err := log.ParseLevel(e.LogLevel)
if err != nil { if err != nil {
return err return err
} }
@@ -67,46 +93,46 @@ func (e *Engine) setLogLevel() error {
return nil return nil
} }
func (e *Engine) setInterface() error { func (e *engine) setInterface() error {
if e.iface != "" { if e.Interface != "" {
if err := dialer.BindToInterface(e.iface); err != nil { if err := dialer.BindToInterface(e.Interface); err != nil {
return err return err
} }
log.Infof("[BOUND] bind to interface: %s", e.iface) log.Infof("[BOUND] bind to interface: %s", e.Interface)
} }
return nil return nil
} }
func (e *Engine) setStats() error { func (e *engine) setStats() error {
if e.stats != "" { if e.Stats != "" {
go func() { 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 return nil
} }
func (e *Engine) setProxy() (err error) { func (e *engine) setProxy() (err error) {
if e.rawProxy == "" { if e.Proxy == "" {
return errors.New("empty proxy") return errors.New("empty proxy")
} }
e.proxy, err = parseProxy(e.rawProxy) e.proxy, err = parseProxy(e.Proxy)
proxy.SetDialer(e.proxy) proxy.SetDialer(e.proxy)
return return
} }
func (e *Engine) setDevice() (err error) { func (e *engine) setDevice() (err error) {
if e.rawDevice == "" { if e.Device == "" {
return errors.New("empty device") return errors.New("empty device")
} }
e.device, err = parseDevice(e.rawDevice, e.mtu) e.device, err = parseDevice(e.Device, e.MTU)
return return
} }
func (e *Engine) setStack() (err error) { func (e *engine) setStack() (err error) {
defer func() { defer func() {
if err == nil { if err == nil {
log.Infof( log.Infof(

View File

@@ -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
}
}

22
engine/version.go Normal file
View File

@@ -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)
}

62
main.go
View File

@@ -1,69 +1,41 @@
package main package main
import ( import (
"fmt"
"os" "os"
"os/signal" "os/signal"
"runtime"
"syscall" "syscall"
"github.com/xjasonlyu/tun2socks/constant"
"github.com/xjasonlyu/tun2socks/engine" "github.com/xjasonlyu/tun2socks/engine"
"github.com/xjasonlyu/tun2socks/log" "github.com/xjasonlyu/tun2socks/log"
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
) )
var ( var key = new(engine.Key)
device string
iface string
level string
proxy string
stats string
token string
mtu int
version bool
)
func init() { func init() {
flag.StringVarP(&device, "device", "d", "", "Use this device [driver://]name") flag.StringVarP(&key.Device, "device", "d", "", "use this device [driver://]name")
flag.StringVarP(&iface, "interface", "i", "", "Use network INTERFACE (Linux and MacOS only)") flag.StringVarP(&key.Interface, "interface", "i", "", "use network INTERFACE (Linux/MacOS only)")
flag.StringVarP(&proxy, "proxy", "p", "", "Use this proxy [protocol://]host[:port]") flag.StringVarP(&key.Proxy, "proxy", "p", "", "use this proxy [protocol://]host[:port]")
flag.StringVarP(&level, "loglevel", "l", "info", "Log level [debug|info|warn|error|silent]") flag.StringVarP(&key.LogLevel, "loglevel", "l", "info", "log level [debug|info|warn|error|silent]")
flag.StringVar(&stats, "stats", "", "HTTP statistic server listen address") flag.StringVar(&key.Stats, "stats", "", "HTTP statistic server listen address")
flag.StringVar(&token, "token", "", "HTTP statistic server auth token") flag.StringVar(&key.Token, "token", "", "HTTP statistic server auth token")
flag.IntVarP(&mtu, "mtu", "m", 0, "Set device maximum transmission unit (MTU)") flag.Uint32VarP(&key.MTU, "mtu", "m", 0, "set device maximum transmission unit (MTU)")
flag.BoolVarP(&version, "version", "v", false, "Show version information and quit") flag.BoolVarP(&key.Version, "version", "v", false, "show version information and quit")
flag.Parse() flag.Parse()
} }
func main() { func main() {
if version { engine.Insert(key)
fmt.Printf("%s %s\n%s/%s, %s, %s\n",
constant.Name, checkErr := func(msg string, f func() error) {
constant.Version, if err := f(); err != nil {
runtime.GOOS, log.Fatalf("Failed to %s: %v", msg, err)
runtime.GOARCH, }
runtime.Version(),
constant.BuildTime,
)
os.Exit(0)
} }
options := []engine.Option{ checkErr("start engine", engine.Start)
engine.WithDevice(device), defer checkErr("stop engine", engine.Stop)
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()
sigCh := make(chan os.Signal, 1) sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)