frp/cmd/frps/control.go

178 lines
3.9 KiB
Go
Raw Normal View History

2016-01-27 21:24:36 +08:00
package main
import (
"encoding/json"
2016-02-03 18:46:24 +08:00
"fmt"
2016-02-05 14:18:26 +08:00
"io"
"time"
2016-01-27 21:24:36 +08:00
"github.com/fatedier/frp/models/consts"
"github.com/fatedier/frp/models/msg"
"github.com/fatedier/frp/models/server"
"github.com/fatedier/frp/utils/conn"
"github.com/fatedier/frp/utils/log"
2016-01-27 21:24:36 +08:00
)
func ProcessControlConn(l *conn.Listener) {
for {
c := l.GetConn()
log.Debug("Get one new conn, %v", c.GetRemoteAddr())
go controlWorker(c)
}
}
// connection from every client and server
2016-01-27 21:24:36 +08:00
func controlWorker(c *conn.Conn) {
// the first message is from client to server
// if error, close connection
res, err := c.ReadLine()
if err != nil {
log.Warn("Read error, %v", err)
return
}
log.Debug("get: %s", res)
clientCtlReq := &msg.ClientCtlReq{}
clientCtlRes := &msg.ClientCtlRes{}
2016-01-27 21:24:36 +08:00
if err := json.Unmarshal([]byte(res), &clientCtlReq); err != nil {
log.Warn("Parse err: %v : %s", err, res)
return
}
// check
succ, info, needRes := checkProxy(clientCtlReq, c)
2016-01-27 21:24:36 +08:00
if !succ {
clientCtlRes.Code = 1
clientCtlRes.Msg = info
2016-01-27 21:24:36 +08:00
}
2016-02-03 18:46:24 +08:00
2016-01-27 21:24:36 +08:00
if needRes {
// control conn
defer c.Close()
2016-01-27 21:24:36 +08:00
buf, _ := json.Marshal(clientCtlRes)
err = c.Write(string(buf) + "\n")
if err != nil {
log.Warn("Write error, %v", err)
2016-02-05 14:18:26 +08:00
time.Sleep(1 * time.Second)
return
2016-01-27 21:24:36 +08:00
}
} else {
2016-02-03 18:46:24 +08:00
// work conn, just return
2016-01-27 21:24:36 +08:00
return
}
// others is from server to client
2016-02-18 18:24:48 +08:00
s, ok := server.ProxyServers[clientCtlReq.ProxyName]
2016-01-27 21:24:36 +08:00
if !ok {
log.Warn("ProxyName [%s] is not exist", clientCtlReq.ProxyName)
return
}
2016-02-05 14:18:26 +08:00
// read control msg from client
2016-02-18 18:24:48 +08:00
go readControlMsgFromClient(s, c)
2016-02-05 14:18:26 +08:00
serverCtlReq := &msg.ClientCtlReq{}
serverCtlReq.Type = consts.WorkConn
2016-01-27 21:24:36 +08:00
for {
closeFlag := s.WaitUserConn()
if closeFlag {
log.Debug("ProxyName [%s], goroutine for dealing user conn is closed", s.Name)
2016-02-05 14:18:26 +08:00
break
}
2016-01-27 21:24:36 +08:00
buf, _ := json.Marshal(serverCtlReq)
err = c.Write(string(buf) + "\n")
if err != nil {
2016-02-18 18:24:48 +08:00
log.Warn("ProxyName [%s], write to client error, proxy exit", s.Name)
s.Close()
2016-01-27 21:24:36 +08:00
return
}
2016-02-18 18:24:48 +08:00
log.Debug("ProxyName [%s], write to client to add work conn success", s.Name)
2016-01-27 21:24:36 +08:00
}
log.Info("ProxyName [%s], I'm dead!", s.Name)
2016-01-27 21:24:36 +08:00
return
}
func checkProxy(req *msg.ClientCtlReq, c *conn.Conn) (succ bool, info string, needRes bool) {
2016-01-27 21:24:36 +08:00
succ = false
needRes = true
// check if proxy name exist
2016-02-18 18:24:48 +08:00
s, ok := server.ProxyServers[req.ProxyName]
2016-01-27 21:24:36 +08:00
if !ok {
info = fmt.Sprintf("ProxyName [%s] is not exist", req.ProxyName)
log.Warn(info)
2016-01-27 21:24:36 +08:00
return
}
// check password
2016-02-18 18:24:48 +08:00
if req.Passwd != s.Passwd {
info = fmt.Sprintf("ProxyName [%s], password is not correct", req.ProxyName)
log.Warn(info)
2016-01-27 21:24:36 +08:00
return
}
2016-02-03 18:46:24 +08:00
2016-01-27 21:24:36 +08:00
// control conn
if req.Type == consts.CtlConn {
2016-02-18 18:24:48 +08:00
if s.Status != consts.Idle {
info = fmt.Sprintf("ProxyName [%s], already in use", req.ProxyName)
log.Warn(info)
2016-01-27 21:24:36 +08:00
return
}
// start proxy and listen for user conn, no block
2016-02-18 18:24:48 +08:00
err := s.Start()
2016-01-27 21:24:36 +08:00
if err != nil {
info = fmt.Sprintf("ProxyName [%s], start proxy error: %v", req.ProxyName, err.Error())
log.Warn(info)
2016-01-27 21:24:36 +08:00
return
}
log.Info("ProxyName [%s], start proxy success", req.ProxyName)
} else if req.Type == consts.WorkConn {
2016-02-03 18:46:24 +08:00
// work conn
2016-01-27 21:24:36 +08:00
needRes = false
2016-02-18 18:24:48 +08:00
if s.Status != consts.Working {
2016-01-27 21:24:36 +08:00
log.Warn("ProxyName [%s], is not working when it gets one new work conn", req.ProxyName)
return
}
2016-02-18 18:24:48 +08:00
s.CliConnChan <- c
2016-01-27 21:24:36 +08:00
} else {
info = fmt.Sprintf("ProxyName [%s], type [%d] unsupport", req.ProxyName, req.Type)
log.Warn(info)
2016-01-27 21:24:36 +08:00
return
}
succ = true
return
}
2016-02-05 14:18:26 +08:00
2016-02-18 18:24:48 +08:00
func readControlMsgFromClient(s *server.ProxyServer, c *conn.Conn) {
2016-02-05 14:18:26 +08:00
isContinueRead := true
f := func() {
isContinueRead = false
c.Close()
s.Close()
2016-02-05 14:18:26 +08:00
}
2016-02-18 18:24:48 +08:00
timer := time.AfterFunc(time.Duration(server.HeartBeatTimeout)*time.Second, f)
2016-02-05 14:18:26 +08:00
defer timer.Stop()
for isContinueRead {
_, err := c.ReadLine()
2016-02-05 14:18:26 +08:00
if err != nil {
if err == io.EOF {
log.Warn("ProxyName [%s], client is dead!", s.Name)
c.Close()
s.Close()
2016-02-05 14:18:26 +08:00
break
}
log.Error("ProxyName [%s], read error: %v", s.Name, err)
2016-02-05 14:18:26 +08:00
continue
}
timer.Reset(time.Duration(server.HeartBeatTimeout) * time.Second)
2016-02-05 14:18:26 +08:00
}
}