diff --git a/cmd/verysimple/gui.go b/cmd/verysimple/gui.go index c72f979..911847d 100644 --- a/cmd/verysimple/gui.go +++ b/cmd/verysimple/gui.go @@ -11,10 +11,15 @@ import ( "go.uber.org/zap" ) +var testFunc func() + func init() { gui_mode = true runGui = func() { ui.Main(setupUI) + testFunc = func() { + + } } } @@ -41,6 +46,9 @@ func makeBasicControlsPage() ui.Control { toggleCheckbox.SetChecked(defaultMachine.IsRunning()) defaultMachine.AddToggleCallback(func(i int) { + if mainwin == nil { + return + } ok := i == 1 toggleCheckbox.SetChecked(ok) //SetChecked不会触发OnToggled if ok { @@ -67,6 +75,7 @@ func makeBasicControlsPage() ui.Control { startBtn.OnClicked(func(b *ui.Button) { defaultMachine.Start() }) + } vbox.Append(ui.NewLabel("This is a label. Right now, labels can only span one line."), false) @@ -92,56 +101,76 @@ func makeBasicControlsPage() ui.Control { return vbox } -func makeNumbersPage() ui.Control { - hbox := ui.NewHorizontalBox() - hbox.SetPadded(true) - +func makeConfPage() ui.Control { + result := ui.NewHorizontalBox() group := ui.NewGroup("Numbers") + group2 := ui.NewGroup("Lists") + + result.Append(group, true) + result.Append(group2, true) + + result.SetPadded(true) group.SetMargined(true) - hbox.Append(group, true) + group2.SetMargined(true) + + { + vbox := ui.NewVerticalBox() + vbox.SetPadded(true) + group.SetChild(vbox) + + spinbox := ui.NewSpinbox(0, 100) + slider := ui.NewSlider(0, 100) + pbar := ui.NewProgressBar() + spinbox.OnChanged(func(*ui.Spinbox) { + slider.SetValue(spinbox.Value()) + pbar.SetValue(spinbox.Value()) + }) + slider.OnChanged(func(*ui.Slider) { + spinbox.SetValue(slider.Value()) + pbar.SetValue(slider.Value()) + }) + vbox.Append(spinbox, false) + vbox.Append(slider, false) + vbox.Append(pbar, false) + + ip := ui.NewProgressBar() + ip.SetValue(-1) + vbox.Append(ip, false) + } vbox := ui.NewVerticalBox() + group2.SetChild(vbox) + vbox.SetPadded(true) - group.SetChild(vbox) - spinbox := ui.NewSpinbox(0, 100) - slider := ui.NewSlider(0, 100) - pbar := ui.NewProgressBar() - spinbox.OnChanged(func(*ui.Spinbox) { - slider.SetValue(spinbox.Value()) - pbar.SetValue(spinbox.Value()) - }) - slider.OnChanged(func(*ui.Slider) { - spinbox.SetValue(slider.Value()) - pbar.SetValue(slider.Value()) - }) - vbox.Append(spinbox, false) - vbox.Append(slider, false) - vbox.Append(pbar, false) + hbox2 := ui.NewHorizontalBox() + vbox.Append(hbox2, false) - ip := ui.NewProgressBar() - ip.SetValue(-1) - vbox.Append(ip, false) - - group = ui.NewGroup("Lists") - group.SetMargined(true) - hbox.Append(group, true) - - vbox = ui.NewVerticalBox() - vbox.SetPadded(true) - group.SetChild(vbox) + hbox2.Append(ui.NewLabel("Listen"), false) cbox := ui.NewCombobox() - cbox.Append("Combobox Item 1") - cbox.Append("Combobox Item 2") - cbox.Append("Combobox Item 3") - vbox.Append(cbox, false) + + hbox2.Append(cbox, true) + + // cbox.Append("Combobox Item 1") + // cbox.Append("Combobox Item 2") + // cbox.Append("Combobox Item 3") + + hbox2 = ui.NewHorizontalBox() + vbox.Append(hbox2, false) + + hbox2.Append(ui.NewLabel("Dial"), false) + + cbox = ui.NewCombobox() + + hbox2.Append(cbox, true) ecbox := ui.NewEditableCombobox() + vbox.Append(ecbox, false) + ecbox.Append("Editable Item 1") ecbox.Append("Editable Item 2") ecbox.Append("Editable Item 3") - vbox.Append(ecbox, false) rb := ui.NewRadioButtons() rb.Append("Radio Button 1") @@ -149,7 +178,7 @@ func makeNumbersPage() ui.Control { rb.Append("Radio Button 3") vbox.Append(rb, false) - return hbox + return result } func makeDataChoosersPage() ui.Control { @@ -265,8 +294,12 @@ func setupUI() { filesM.AppendItem("Open github").OnClicked(openUrlFunc(weblink)) filesM.AppendItem("Check github releases").OnClicked(openUrlFunc(weblink + "releases")) - //var y = ui.NewMenu("Menu2") - //y.AppendItem("verysimple") + var y = ui.NewMenu("Debug") + y.AppendItem("test").OnClicked(func(mi *ui.MenuItem, w *ui.Window) { + if testFunc != nil { + testFunc() + } + }) } mainwin = ui.NewWindow("verysimple", 640, 480, true) //must create after menu; or it will panic @@ -274,10 +307,11 @@ func setupUI() { { mainwin.OnClosing(func(*ui.Window) bool { ui.Quit() + mainwin = nil return true }) ui.OnShouldQuit(func() bool { - mainwin.Destroy() + mainwin = nil return true }) } @@ -286,14 +320,13 @@ func setupUI() { mainwin.SetChild(tab) mainwin.SetMargined(true) - tab.Append("Basic Controls", makeBasicControlsPage()) - tab.Append("Numbers and Lists", makeNumbersPage()) + tab.Append("基础控制", makeBasicControlsPage()) + tab.Append("配置控制", makeConfPage()) tab.Append("Data Choosers", makeDataChoosersPage()) for i := 0; i < tab.NumPages(); i++ { tab.SetMargined(i, true) } - mainwin.Show() } diff --git a/cmd/verysimple/main.go b/cmd/verysimple/main.go index 37b08a2..5d53e90 100644 --- a/cmd/verysimple/main.go +++ b/cmd/verysimple/main.go @@ -340,6 +340,7 @@ func mainFunc() (result int) { if runGui != nil { runGui() gui_mode = false + utils.Info("gui mode exited") } } diff --git a/go.mod b/go.mod index 8455e1b..fb4b988 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/biter777/countries v1.5.6 github.com/e1732a364fed/ui v0.0.1-alpha.5 + github.com/eycorsican/go-tun2socks v1.16.11 github.com/gobwas/ws v1.1.0 github.com/lucas-clemente/quic-go v0.0.0-00010101000000-000000000000 github.com/manifoldco/promptui v0.9.0 @@ -37,6 +38,7 @@ require ( github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect github.com/onsi/ginkgo/v2 v2.2.0 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect + github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b // indirect ) require ( diff --git a/go.sum b/go.sum index c18a90b..66da718 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/e1732a364fed/ui v0.0.1-alpha.5 h1:4SR/7DvZ65ZTK7zO7ITdus2oI0XtjCA0uAcOQdifyaw= github.com/e1732a364fed/ui v0.0.1-alpha.5/go.mod h1:uK9ryjwA0+3KdICbeXm5IjhKZ+1ZooMVDdTuLaQHpwM= +github.com/eycorsican/go-tun2socks v1.16.11 h1:+hJDNgisrYaGEqoSxhdikMgMJ4Ilfwm/IZDrWRrbaH8= +github.com/eycorsican/go-tun2socks v1.16.11/go.mod h1:wgB2BFT8ZaPKyKOQ/5dljMG/YIow+AIXyq4KBwJ5sGQ= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= @@ -73,6 +75,8 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/shadowsocks/go-shadowsocks2 v0.1.5 h1:PDSQv9y2S85Fl7VBeOMF9StzeXZyK1HakRm86CUbr28= github.com/shadowsocks/go-shadowsocks2 v0.1.5/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM= +github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b h1:+y4hCMc/WKsDbAPsOQZgBSaSZ26uh2afyaWeVg/3s/c= +github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -109,6 +113,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= diff --git a/machine/callback.go b/machine/callback.go index 9b3d1e0..42f854f 100644 --- a/machine/callback.go +++ b/machine/callback.go @@ -1,7 +1,9 @@ package machine type callbacks struct { - toggle []func(int) + toggle []func(int) //开关代理 + + updated []func() //运行中的配置发生了变更 } func (m *M) AddToggleCallback(f func(int)) { @@ -14,3 +16,14 @@ func (m *M) callToggleFallback(e int) { } } } + +func (m *M) AddUpdatedCallback(f func()) { + m.updated = append(m.updated, f) +} +func (m *M) callUpdatedFallback() { + if len(m.updated) > 0 { + for _, f := range m.updated { + f() + } + } +} diff --git a/main.go b/main.go index 37aa5f0..c8f4e33 100644 --- a/main.go +++ b/main.go @@ -77,11 +77,11 @@ func ListenSer(inServer proxy.Server, defaultOutClient proxy.Client, env *proxy. var is, tcp, udp bool //tproxy 和 shadowsocks 都用到了 SelfListen if is, tcp, udp = inServer.SelfListen(); is { - var chantcp chan proxy.TCPRequestInfo - var chanudp chan proxy.UDPRequestInfo + var chantcp chan netLayer.TCPRequestInfo + var chanudp chan netLayer.UDPRequestInfo if tcp { - chantcp = make(chan proxy.TCPRequestInfo, 2) + chantcp = make(chan netLayer.TCPRequestInfo, 2) go func() { for tcpInfo := range chantcp { go passToOutClient(incomingInserverConnState{ @@ -97,7 +97,7 @@ func ListenSer(inServer proxy.Server, defaultOutClient proxy.Client, env *proxy. } if udp { - chanudp = make(chan proxy.UDPRequestInfo, 2) + chanudp = make(chan netLayer.UDPRequestInfo, 2) go func() { for udpInfo := range chanudp { diff --git a/netLayer/netlayer.go b/netLayer/netlayer.go index 07d0849..264c11c 100644 --- a/netLayer/netlayer.go +++ b/netLayer/netlayer.go @@ -5,12 +5,11 @@ Package netLayer contains definitions in network layer AND transport layer. 以后如果要添加 kcp 或 raw socket 等底层协议时,也要在此包 或子包里实现. -Tags +# Tags 本包提供 embed_geoip 这个 build tag。 若给出 embed_geoip,则会尝试内嵌 GeoLite2-Country.mmdb.tgz 文件;默认不内嵌。 - */ package netLayer @@ -36,12 +35,12 @@ var ( ErrTimeout = errors.New("timeout") ) -//做一些网络层的资料准备工作, 可以优化本包其它函数的调用。 +// 做一些网络层的资料准备工作, 可以优化本包其它函数的调用。 func PrepareInterfaces() { //weKnowThatWeDontHaveIPV6 = !HasIpv6Interface() } -//c.SetDeadline(time.Time{}) +// c.SetDeadline(time.Time{}) func PersistConn(c net.Conn) { c.SetDeadline(time.Time{}) } @@ -54,7 +53,7 @@ func IsTCP(r any) *net.TCPConn { return nil } -//net.IPConn, net.TCPConn, net.UDPConn, net.UnixConn +// net.IPConn, net.TCPConn, net.UDPConn, net.UnixConn func IsBasicConn(r interface{}) bool { if _, ok := r.(syscall.Conn); ok { return true @@ -79,7 +78,7 @@ func GetRawConn(reader io.Reader) syscall.RawConn { return nil } -//"udp", "udp4", "udp6" +// "udp", "udp4", "udp6" func IsStrUDP_network(s string) bool { switch s { case "udp", "udp4", "udp6": @@ -117,7 +116,7 @@ type NetDeadliner interface { SetWriteDeadline(t time.Time) error } -//实现 NetAddresser +// 实现 NetAddresser type EasyNetAddresser struct { LA, RA net.Addr } @@ -159,8 +158,18 @@ func HasIpv6Interface() bool { return false } -//用于定义拒绝响应的行为;可参考 httpLayer.RejectConn +// 用于定义拒绝响应的行为;可参考 httpLayer.RejectConn type RejectConn interface { RejectBehaviorDefined() bool //若为false,则只能直接Close Reject() } + +type TCPRequestInfo struct { + net.Conn + Target Addr +} + +type UDPRequestInfo struct { + MsgConn + Target Addr +} diff --git a/netLayer/tun/tun.go b/netLayer/tun/tun.go new file mode 100644 index 0000000..bf88f3b --- /dev/null +++ b/netLayer/tun/tun.go @@ -0,0 +1,91 @@ +package tun + +import ( + "io" + "log" + "net" + + "github.com/e1732a364fed/v2ray_simple/netLayer" + "github.com/e1732a364fed/v2ray_simple/utils" + "github.com/eycorsican/go-tun2socks/core" + "github.com/eycorsican/go-tun2socks/tun" +) + +type coreConnAdapter struct { + core.UDPConn + netLayer.EasyDeadline +} + +func (h *coreConnAdapter) ReadMsgFrom() ([]byte, netLayer.Addr, error) { + + return nil, netLayer.Addr{}, nil +} +func (h *coreConnAdapter) WriteMsgTo([]byte, netLayer.Addr) error { + return nil +} +func (h *coreConnAdapter) CloseConnWithRaddr(raddr netLayer.Addr) error { + + return nil +} +func (h *coreConnAdapter) Fullcone() bool { + return true +} + +type handler struct { + tcpChan chan netLayer.TCPRequestInfo + udpChan chan netLayer.UDPRequestInfo +} + +func newHandler() *handler { + return &handler{ + tcpChan: make(chan netLayer.TCPRequestInfo), + udpChan: make(chan netLayer.UDPRequestInfo), + } +} + +func (h *handler) Handle(conn net.Conn, target *net.TCPAddr) error { + tad := netLayer.NewAddrFromTCPAddr(target) + h.tcpChan <- netLayer.TCPRequestInfo{Target: tad, Conn: conn} + return nil +} + +func (h *handler) Connect(conn core.UDPConn, target *net.UDPAddr) error { + uad := netLayer.NewAddrFromUDPAddr(target) + adapter := &coreConnAdapter{UDPConn: conn} + adapter.InitEasyDeadline() + + h.udpChan <- netLayer.UDPRequestInfo{Target: uad, MsgConn: adapter} + return nil +} + +func (h *handler) ReceiveTo(conn core.UDPConn, data []byte, addr *net.UDPAddr) error { + log.Println("ReceiveTo called") + return nil +} + +func ListenTun() (tunDev io.ReadWriteCloser, err error) { + + //macos 上无法指定tun名称 + tunDev, err = tun.OpenTunDevice("", "10.1.0.10", "10.1.0.20", "255.255.255.0", nil, false) + + return +} + +func HandleTun(tunDev io.ReadWriteCloser) (tcpChan chan netLayer.TCPRequestInfo, udpChan chan netLayer.UDPRequestInfo) { + lwipWriter := core.NewLWIPStack().(io.Writer) + core.RegisterOutputFn(func(data []byte) (int, error) { + return tunDev.Write(data) + }) + nh := newHandler() + core.RegisterTCPConnHandler(nh) + core.RegisterUDPConnHandler(nh) + go func() { + _, err := io.CopyBuffer(lwipWriter, tunDev, make([]byte, utils.MTU)) + if err != nil { + log.Fatalf("tun copying from tunDev to lwip failed: %v", err) + } + }() + tcpChan = nh.tcpChan + udpChan = nh.udpChan + return +} diff --git a/proxy/proxy.go b/proxy/proxy.go index 8617bfd..bfbbc7b 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -94,19 +94,9 @@ type Server interface { SelfListen() (is, tcp, udp bool) } -type TCPRequestInfo struct { - net.Conn - Target netLayer.Addr -} - -type UDPRequestInfo struct { - netLayer.MsgConn - Target netLayer.Addr -} - type ListenerServer interface { Server - StartListen(chan<- TCPRequestInfo, chan<- UDPRequestInfo) io.Closer + StartListen(chan<- netLayer.TCPRequestInfo, chan<- netLayer.UDPRequestInfo) io.Closer } type UserServer interface { diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index 5f8aef4..126e435 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -162,7 +162,7 @@ func (m *Server) removeUDPByHash(hash netLayer.HashableAddr) { m.Unlock() } -func (s *Server) StartListen(_ chan<- proxy.TCPRequestInfo, udpInfoChan chan<- proxy.UDPRequestInfo) io.Closer { +func (s *Server) StartListen(_ chan<- netLayer.TCPRequestInfo, udpInfoChan chan<- netLayer.UDPRequestInfo) io.Closer { uc, err := net.ListenUDP("udp", s.LUA) if err != nil { log.Panicln("shadowsocks listen udp failed", err) @@ -226,7 +226,7 @@ func (s *Server) StartListen(_ chan<- proxy.TCPRequestInfo, udpInfoChan chan<- p conn.readChan <- netLayer.AddrData{Data: readbuf.Bytes(), Addr: destAddr} if !found { - udpInfoChan <- proxy.UDPRequestInfo{ + udpInfoChan <- netLayer.UDPRequestInfo{ MsgConn: conn, Target: destAddr, } } diff --git a/proxy/tproxy/server_linux.go b/proxy/tproxy/server_linux.go index 833c37a..e218ba3 100644 --- a/proxy/tproxy/server_linux.go +++ b/proxy/tproxy/server_linux.go @@ -60,8 +60,8 @@ type Server struct { shouldSetIPTable bool - infoChan chan<- proxy.TCPRequestInfo - udpInfoChan chan<- proxy.UDPRequestInfo + infoChan chan<- netLayer.TCPRequestInfo + udpInfoChan chan<- netLayer.UDPRequestInfo tm *tproxy.Machine sync.Once } @@ -109,7 +109,7 @@ func (s *Server) Stop() { } -func (s *Server) StartListen(infoChan chan<- proxy.TCPRequestInfo, udpInfoChan chan<- proxy.UDPRequestInfo) io.Closer { +func (s *Server) StartListen(infoChan chan<- netLayer.TCPRequestInfo, udpInfoChan chan<- netLayer.UDPRequestInfo) io.Closer { tm := new(tproxy.Machine) @@ -122,7 +122,7 @@ func (s *Server) StartListen(infoChan chan<- proxy.TCPRequestInfo, udpInfoChan c tcpconn := conn.(*net.TCPConn) targetAddr := tproxy.HandshakeTCP(tcpconn) - info := proxy.TCPRequestInfo{ + info := netLayer.TCPRequestInfo{ Conn: tcpconn, Target: targetAddr, } @@ -184,7 +184,7 @@ func (s *Server) StartListen(infoChan chan<- proxy.TCPRequestInfo, udpInfoChan c return } - udpInfoChan <- proxy.UDPRequestInfo{MsgConn: msgConn, Target: raddr} + udpInfoChan <- netLayer.UDPRequestInfo{MsgConn: msgConn, Target: raddr} } }() diff --git a/proxy/tun/tun.go b/proxy/tun/tun.go new file mode 100644 index 0000000..583a5a0 --- /dev/null +++ b/proxy/tun/tun.go @@ -0,0 +1,90 @@ +package tun + +import ( + "io" + "net" + "net/url" + + "github.com/e1732a364fed/v2ray_simple/netLayer" + "github.com/e1732a364fed/v2ray_simple/netLayer/tun" + "github.com/e1732a364fed/v2ray_simple/proxy" + "github.com/e1732a364fed/v2ray_simple/utils" + "go.uber.org/zap" +) + +const name = "tun" + +type ServerCreator struct{ proxy.CreatorCommonStruct } + +func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format int) (*proxy.ListenConf, error) { + if lc == nil { + return nil, utils.ErrNilParameter + } + + return lc, nil +} + +func (ServerCreator) NewServer(lc *proxy.ListenConf) (proxy.Server, error) { + + s := &Server{} + + return s, nil +} + +type Server struct { + proxy.Base + + stopped bool + + infoChan chan<- netLayer.TCPRequestInfo +} + +func (*Server) Name() string { return name } + +func (s *Server) SelfListen() (is, tcp, udp bool) { + is = true + tcp = true + udp = true + return +} + +func (s *Server) Close() error { + s.Stop() + return nil +} + +func (s *Server) Stop() { + if !s.stopped { + s.stopped = true + close(s.infoChan) + } + +} + +func (s *Server) StartListen(infoChan chan<- netLayer.TCPRequestInfo, udpInfoChan chan<- netLayer.UDPRequestInfo) io.Closer { + tunDev, err := tun.ListenTun() + if err != nil { + if ce := utils.CanLogErr("tun listen failed"); ce != nil { + ce.Write(zap.Error(err)) + } + return nil + } + s.infoChan = infoChan + + tchan, _ := tun.HandleTun(tunDev) + go func() { + for tr := range tchan { + if s.stopped { + return + } + infoChan <- tr + + } + }() + + return s +} + +func (s *Server) Handshake(underlay net.Conn) (net.Conn, netLayer.MsgConn, netLayer.Addr, error) { + return nil, nil, netLayer.Addr{}, utils.ErrUnImplemented +}