func (be *Backend) NewConn() (*net.TCPConn, error) { println("backend connectiing to :", be.StrAddr) conn, err := net.DialTCP("tcp", nil, be.Addr) if err != nil { log.Error("NewConn:Dial failed:", err.Error()) return nil, err } return conn, nil }
func NewBackend(strAddr string) (*Backend, error) { addr, err := net.ResolveTCPAddr("tcp", strAddr) if err != nil { log.Error("Can't resolve backend addr:", err.Error()) return nil, err } be := new(Backend) be.StrAddr = strAddr be.Addr = addr return be, nil }
func ProxyFunc(conn *net.TCPConn, be *Backend) { //connect to backend bconn, err := be.NewConn() if err != nil { log.Error("can't create new backend:", err.Error()) } //back forwarder ch_bf_data := make(chan []byte) ch_bf_status := make(chan int) go backForwarder(bconn, ch_bf_data, ch_bf_status) //back receiver ch_br_data := make(chan []byte) ch_br_st := make(chan int) go backRecvr(bconn, ch_br_data, ch_br_st) //client forwarder ch_cf_data := make(chan []byte) ch_cf_status := make(chan int) go clientForwarder(conn, ch_cf_data, ch_cf_status) //client receiver ch_cr_data := make(chan []byte) ch_cr_status := make(chan int) go clientRecvr(conn, ch_cr_data, ch_cr_status) for { select { case cr_data := <-ch_cr_data: //some data from client, forward to backend ch_bf_data <- cr_data case br_data := <-ch_br_data: //some data from backend, forward to client ch_cf_data <- br_data case _ = <-ch_cr_status: println("unhandled : status dari cr") os.Exit(1) case _ = <-ch_bf_status: println("unhandled : status dari bf") os.Exit(1) case br_st := <-ch_br_st: if br_st == ST_BE_EOF { println("unhandled : status dari br = EOF") } println("unhandled : status dari br") os.Exit(1) case _ = <-ch_cf_status: println("unhandled : status dari cf") os.Exit(1) } } }
func main() { config := jconfig.LoadConfig("conf.json") //confBE := config.GetArray("backend") backendPool := make([]*Backend, 10) for i, v := range config.GetArray("backend") { log.Info("backend %d = %s", i, v) be, _ := NewBackend(v.(string)) backendPool[i] = be } listenStr := config.GetString("listen_host") + ":" + config.GetString("listen_port") listenAddr, err := net.ResolveTCPAddr("tcp", listenStr) if err != nil { log.Error(err) } log.Info("Starting the server on %s", listenAddr) listener, err := net.ListenTCP("tcp", listenAddr) if err != nil { log.Error("error listening:%s", err.Error()) log.Close() os.Exit(1) } bc := 0 //backend counter for { conn, err := listener.AcceptTCP() if err != nil { log.Error("Error accept:%s", err.Error()) log.Close() os.Exit(1) } go ProxyFunc(conn, backendPool[bc]) bc = (bc + 1) % len(backendPool) } }
//forward all packet to client func clientForwarder(conn *net.TCPConn, ch_data chan []byte, ch_status chan int) { for { data := <-ch_data n, err := conn.Write(data) if err != nil { log.Error(err) ch_status <- ST_BE_ERR return } if n != len(data) { ch_status <- ST_BE_ERR return } } }
//forward all packet to backend func backForwarder(bconn *net.TCPConn, ch_data chan []byte, ch_status chan int) { for { data := <-ch_data println("BF get data") n, err := bconn.Write(data) if err != nil { log.Error(err) ch_status <- ST_BE_ERR return } if n != len(data) { ch_status <- ST_BE_ERR return } } }