github.com/metacubex/mihomo@v1.18.5/listener/inbound/tunnel.go (about) 1 package inbound 2 3 import ( 4 "fmt" 5 6 C "github.com/metacubex/mihomo/constant" 7 LT "github.com/metacubex/mihomo/listener/tunnel" 8 "github.com/metacubex/mihomo/log" 9 ) 10 11 type TunnelOption struct { 12 BaseOption 13 Network []string `inbound:"network"` 14 Target string `inbound:"target"` 15 } 16 17 func (o TunnelOption) Equal(config C.InboundConfig) bool { 18 return optionToString(o) == optionToString(config) 19 } 20 21 type Tunnel struct { 22 *Base 23 config *TunnelOption 24 ttl *LT.Listener 25 tul *LT.PacketConn 26 } 27 28 func NewTunnel(options *TunnelOption) (*Tunnel, error) { 29 base, err := NewBase(&options.BaseOption) 30 if err != nil { 31 return nil, err 32 } 33 return &Tunnel{ 34 Base: base, 35 config: options, 36 }, nil 37 } 38 39 // Config implements constant.InboundListener 40 func (t *Tunnel) Config() C.InboundConfig { 41 return t.config 42 } 43 44 // Close implements constant.InboundListener 45 func (t *Tunnel) Close() error { 46 var err error 47 if t.ttl != nil { 48 if tcpErr := t.ttl.Close(); tcpErr != nil { 49 err = tcpErr 50 } 51 } 52 if t.tul != nil { 53 if udpErr := t.tul.Close(); udpErr != nil { 54 if err == nil { 55 err = udpErr 56 } else { 57 return fmt.Errorf("close tcp err: %s, close udp err: %s", err.Error(), udpErr.Error()) 58 } 59 } 60 } 61 62 return err 63 } 64 65 // Address implements constant.InboundListener 66 func (t *Tunnel) Address() string { 67 if t.ttl != nil { 68 return t.ttl.Address() 69 } 70 if t.tul != nil { 71 return t.tul.Address() 72 } 73 return "" 74 } 75 76 // Listen implements constant.InboundListener 77 func (t *Tunnel) Listen(tunnel C.Tunnel) error { 78 var err error 79 for _, network := range t.config.Network { 80 switch network { 81 case "tcp": 82 if t.ttl, err = LT.New(t.RawAddress(), t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...); err != nil { 83 return err 84 } 85 case "udp": 86 if t.tul, err = LT.NewUDP(t.RawAddress(), t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...); err != nil { 87 return err 88 } 89 default: 90 log.Warnln("unknown network type: %s, passed", network) 91 continue 92 } 93 log.Infoln("Tunnel[%s](%s/%s)proxy listening at: %s", t.Name(), network, t.config.Target, t.Address()) 94 } 95 return nil 96 } 97 98 var _ C.InboundListener = (*Tunnel)(nil)