Files
tun2socks/engine/engine.go
2021-02-07 10:38:07 +08:00

128 lines
2.2 KiB
Go
Executable File

package engine
import (
"errors"
"github.com/xjasonlyu/tun2socks/component/dialer"
"github.com/xjasonlyu/tun2socks/device"
"github.com/xjasonlyu/tun2socks/log"
"github.com/xjasonlyu/tun2socks/proxy"
"github.com/xjasonlyu/tun2socks/stack"
"github.com/xjasonlyu/tun2socks/stats"
)
type Engine struct {
mtu uint32
iface string
stats string
token string
logLevel string
rawProxy string
rawDevice string
proxy proxy.Proxy
device device.Device
}
func New(opts ...Option) *Engine {
e := &Engine{}
for _, opt := range opts {
opt(e)
}
return e
}
func (e *Engine) Start() error {
for _, set := range []func() error{
e.setLogLevel,
e.setInterface,
e.setStats,
e.setProxy,
e.setDevice,
e.setStack,
} {
if err := set(); err != nil {
return err
}
}
return nil
}
func (e *Engine) Stop() {
if e.device != nil {
if err := e.device.Close(); err != nil {
log.Fatalf("%v", err)
}
}
}
func (e *Engine) setLogLevel() error {
level, err := log.ParseLevel(e.logLevel)
if err != nil {
return err
}
log.SetLevel(level)
return nil
}
func (e *Engine) setInterface() error {
if e.iface != "" {
if err := dialer.BindToInterface(e.iface); err != nil {
return err
}
log.Infof("[BOUND] bind to interface: %s", e.iface)
}
return nil
}
func (e *Engine) setStats() error {
if e.stats != "" {
go func() {
_ = stats.Start(e.stats, e.token)
}()
log.Infof("[STATS] listen and serve at: http://%s", e.stats)
}
return nil
}
func (e *Engine) setProxy() error {
if e.rawProxy == "" {
return errors.New("empty proxy")
}
p, err := parseProxy(e.rawProxy)
if err != nil {
return err
}
e.proxy = p
proxy.SetDialer(p)
return nil
}
func (e *Engine) setDevice() error {
if e.rawDevice == "" {
return errors.New("empty device")
}
d, err := parseDevice(e.rawDevice, e.mtu)
if err != nil {
return err
}
e.device = d
return nil
}
func (e *Engine) setStack() error {
handler := &fakeTunnel{}
if _, err := stack.New(e.device, handler, stack.WithDefault()); err != nil {
return err
}
log.Infof(
"[STACK] %s://%s <-> %s://%s",
e.device.Type(), e.device.Name(),
e.proxy.Proto(), e.proxy.Addr(),
)
return nil
}