hysteria/app/relay/tcp.go
2022-11-24 00:22:44 -08:00

63 lines
1.3 KiB
Go

package relay
import (
"net"
"time"
"github.com/apernet/hysteria/core/cs"
"github.com/apernet/hysteria/core/utils"
)
type TCPRelay struct {
HyClient *cs.Client
ListenAddr *net.TCPAddr
Remote string
Timeout time.Duration
ConnFunc func(addr net.Addr)
ErrorFunc func(addr net.Addr, err error)
}
func NewTCPRelay(hyClient *cs.Client, listen, remote string, timeout time.Duration,
connFunc func(addr net.Addr), errorFunc func(addr net.Addr, err error),
) (*TCPRelay, error) {
tAddr, err := net.ResolveTCPAddr("tcp", listen)
if err != nil {
return nil, err
}
r := &TCPRelay{
HyClient: hyClient,
ListenAddr: tAddr,
Remote: remote,
Timeout: timeout,
ConnFunc: connFunc,
ErrorFunc: errorFunc,
}
return r, nil
}
func (r *TCPRelay) ListenAndServe() error {
listener, err := net.ListenTCP("tcp", r.ListenAddr)
if err != nil {
return err
}
defer listener.Close()
for {
c, err := listener.AcceptTCP()
if err != nil {
return err
}
go func() {
defer c.Close()
r.ConnFunc(c.RemoteAddr())
rc, err := r.HyClient.DialTCP(r.Remote)
if err != nil {
r.ErrorFunc(c.RemoteAddr(), err)
return
}
defer rc.Close()
err = utils.PipePairWithTimeout(c, rc, r.Timeout)
r.ErrorFunc(c.RemoteAddr(), err)
}()
}
}