clash/listener/tunnel/tcp.go
2022-11-16 10:43:16 +08:00

68 lines
1.2 KiB
Go

package tunnel
import (
"net"
"github.com/Dreamacro/clash/adapter/inbound"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/transport/socks5"
)
type Listener struct {
closed bool
config string
listeners []net.Listener
}
func New(config string, in chan<- C.ConnContext) (*Listener, error) {
tl := &Listener{false, config, nil}
pl := PairList{}
err := pl.Set(config)
if err != nil {
return nil, err
}
for _, p := range pl {
addr := p[0]
target := p[1]
go func() {
tgt := socks5.ParseAddr(target)
if tgt == nil {
log.Errorln("invalid target address %q", target)
return
}
l, err := inbound.Listen("tcp", addr)
if err != nil {
return
}
tl.listeners = append(tl.listeners, l)
log.Infoln("TCP tunnel %s <-> %s", l.Addr().String(), target)
for {
c, err := l.Accept()
if err != nil {
if tl.closed {
break
}
continue
}
_ = c.(*net.TCPConn).SetKeepAlive(true)
in <- inbound.NewSocket(tgt, c, C.TCPTUN)
}
}()
}
return tl, nil
}
func (l *Listener) Close() {
l.closed = true
for _, lis := range l.listeners {
_ = lis.Close()
}
}
func (l *Listener) Config() string {
return l.config
}