proxyport/app/proxy.go

78 lines
1.4 KiB
Go

package app
import (
"git.makemake.in/test/mycommon/mylog"
"io"
"math/rand"
"net"
"sync"
"time"
)
func Run() {
rand.Seed(time.Now().UnixNano())
for name, item := range ProxyMap {
go listenTcp(name, item)
}
select {}
}
func listenTcp(name string, item ProxyItem) {
listen, err := net.Listen("tcp", item.LocalAddr)
if err != nil {
mylog.Errorf("[%s] listen err: %s", name, err)
return
}
mylog.Infof("[%s] listen %s", name, item.LocalAddr)
for {
localConn, err := listen.Accept()
if err != nil {
mylog.Errorf("conn accept err: %s", item.LocalAddr, err)
return
}
go proxyTcp(localConn, item)
}
}
func proxyTcp(localConn net.Conn, item ProxyItem) {
randRemoteAddr := item.RemoteAddr[rand.Intn(len(item.RemoteAddr))]
remoteConn, err := net.DialTimeout("tcp", randRemoteAddr, time.Second*3)
if err != nil {
localConn.Close()
mylog.Errorf("connect remote err: %s", err)
return
}
mylog.Infof("start proxy %s -> %s", localConn.RemoteAddr(), randRemoteAddr)
wg0 := &sync.WaitGroup{}
wg0.Add(2)
go copyConn(wg0, localConn, remoteConn)
go copyConn(wg0, remoteConn, localConn)
wg0.Wait()
mylog.Infof("stop proxy %s -> %s", localConn.RemoteAddr(), randRemoteAddr)
}
func copyConn(wg0 *sync.WaitGroup, localConn, remoteConn net.Conn) {
defer func() {
wg0.Done()
localConn.Close()
remoteConn.Close()
}()
_, err := io.Copy(remoteConn, localConn)
if err != nil {
mylog.Error(err)
}
}