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)