mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2025-05-12 21:18:03 +08:00
107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
package inbound
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
C "github.com/metacubex/mihomo/constant"
|
|
LT "github.com/metacubex/mihomo/listener/tunnel"
|
|
"github.com/metacubex/mihomo/log"
|
|
)
|
|
|
|
type TunnelOption struct {
|
|
BaseOption
|
|
Network []string `inbound:"network"`
|
|
Target string `inbound:"target"`
|
|
}
|
|
|
|
func (o TunnelOption) Equal(config C.InboundConfig) bool {
|
|
return optionToString(o) == optionToString(config)
|
|
}
|
|
|
|
type Tunnel struct {
|
|
*Base
|
|
config *TunnelOption
|
|
ttl []*LT.Listener
|
|
tul []*LT.PacketConn
|
|
}
|
|
|
|
func NewTunnel(options *TunnelOption) (*Tunnel, error) {
|
|
base, err := NewBase(&options.BaseOption)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Tunnel{
|
|
Base: base,
|
|
config: options,
|
|
}, nil
|
|
}
|
|
|
|
// Config implements constant.InboundListener
|
|
func (t *Tunnel) Config() C.InboundConfig {
|
|
return t.config
|
|
}
|
|
|
|
// Close implements constant.InboundListener
|
|
func (t *Tunnel) Close() error {
|
|
var errs []error
|
|
for _, l := range t.ttl {
|
|
err := l.Close()
|
|
if err != nil {
|
|
errs = append(errs, fmt.Errorf("close tcp listener %s err: %w", l.Address(), err))
|
|
}
|
|
}
|
|
for _, l := range t.tul {
|
|
err := l.Close()
|
|
if err != nil {
|
|
errs = append(errs, fmt.Errorf("close udp listener %s err: %w", l.Address(), err))
|
|
}
|
|
}
|
|
if len(errs) > 0 {
|
|
return errors.Join(errs...)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Address implements constant.InboundListener
|
|
func (t *Tunnel) Address() string {
|
|
var addrList []string
|
|
for _, l := range t.ttl {
|
|
addrList = append(addrList, "tcp://"+l.Address())
|
|
}
|
|
for _, l := range t.tul {
|
|
addrList = append(addrList, "udp://"+l.Address())
|
|
}
|
|
return strings.Join(addrList, ",")
|
|
}
|
|
|
|
// Listen implements constant.InboundListener
|
|
func (t *Tunnel) Listen(tunnel C.Tunnel) error {
|
|
for _, addr := range strings.Split(t.RawAddress(), ",") {
|
|
for _, network := range t.config.Network {
|
|
switch network {
|
|
case "tcp":
|
|
ttl, err := LT.New(addr, t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
t.ttl = append(t.ttl, ttl)
|
|
case "udp":
|
|
tul, err := LT.NewUDP(addr, t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
t.tul = append(t.tul, tul)
|
|
default:
|
|
log.Warnln("unknown network type: %s, passed", network)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
log.Infoln("Tunnel[%s](%s)proxy listening at: %s", t.Name(), t.config.Target, t.Address())
|
|
return nil
|
|
}
|
|
|
|
var _ C.InboundListener = (*Tunnel)(nil)
|