package protocol import ( "errors" "fmt" "github.com/TransX/constant" "github.com/TransX/log" "github.com/TransX/model" "github.com/TransX/stat" "github.com/TransX/utils" "net" "os" ) var tunMng *stat.TunnelStatusManager func init() { tunMng = stat.NewTunnelStatusManager() } type TransTCP struct { } func NewTransTCP() *TransTCP { return &TransTCP{} } func (this *TransTCP) createTCPClient(ip, port string) (conn net.Conn, err error) { conn, err = net.Dial("tcp4", ip+":"+port) if err != nil { conn = nil } return } func (this *TransTCP) createTCPClientWithRetry(ip, port string, retry int) (conn net.Conn, err error) { for i := 0; i < retry; i++ { c, e := this.createTCPClient(ip, port) if e == nil { return c, e } log.Error("Create Client Error: %s", e.Error()) } //failed with retry return nil, errors.New(fmt.Sprintln("failed to create client after %d retry", retry)) } func (this *TransTCP) createTCPListener(ip, port string) (listen net.Listener, err error) { listener, _err := net.Listen("tcp4", ip+":"+port) if _err == nil { listen = listener err = nil return } else { listen = nil err = _err } return } func (this *TransTCP) Start(listenPort, destIP, destPort string, clientOrServer string) { listener, err := this.createTCPListener("0.0.0.0", listenPort) if err != nil { log.Panic("Failed to create listener. %s", err) os.Exit(0) } for { if listenerConn, err := listener.Accept(); err == nil { go func() { log.Info("Incoming %s", listenerConn.RemoteAddr().String()) //创建到目标的连接 destConn, err := this.createTCPClientWithRetry(destIP, destPort, 3) if err != nil { log.Panic("Failed to connect to destination. %s", err) os.Exit(0) } log.Info("Dial %s", destConn.RemoteAddr().String()) //tunnel model : [ -->>server ---- client -->> ](this is a tunnel) if clientOrServer == "client" { //加密方向 sendID := utils.TunnelID() ntSend := model.NewTunnel(sendID, listenerConn, destConn, constant.SEND) receiveID := utils.TunnelID() ntRev := model.NewTunnel(receiveID, destConn, listenerConn, constant.RECEIVE) printModelDetail(sendID, receiveID) tunnelPair := model.NewTunnelPair(ntSend, ntRev) tunnelPair.SetRegChan(tunMng.GetRegChan()) tunnelPair.SetUnRegChan(tunMng.GetUnregChan()) tunnelPair.Run() } if clientOrServer == "server" { receiveID := utils.TunnelID() ntRev := model.NewTunnel(receiveID, listenerConn, destConn, constant.RECEIVE) sendID := utils.TunnelID() ntSend := model.NewTunnel(sendID, destConn, listenerConn, constant.SEND) printModelDetail(sendID, receiveID) tunnelPair := model.NewTunnelPair(ntSend, ntRev) tunnelPair.SetRegChan(tunMng.GetRegChan()) tunnelPair.SetUnRegChan(tunMng.GetUnregChan()) tunnelPair.Run() } }() } else { log.Error("Failed to accept incoming connection. %s", err) } } } func printModelDetail(tunnelIDA, tunnelIDB string) { log.Info("id %s and id %s belong to a model", tunnelIDA, tunnelIDB) }