control.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "sync"
  7. "time"
  8. "github.com/fatedier/frp/models/client"
  9. "github.com/fatedier/frp/models/consts"
  10. "github.com/fatedier/frp/models/msg"
  11. "github.com/fatedier/frp/utils/conn"
  12. "github.com/fatedier/frp/utils/log"
  13. )
  14. func ControlProcess(cli *client.ProxyClient, wait *sync.WaitGroup) {
  15. defer wait.Done()
  16. c, err := loginToServer(cli)
  17. if err != nil {
  18. log.Error("ProxyName [%s], connect to server failed!", cli.Name)
  19. return
  20. }
  21. defer c.Close()
  22. for {
  23. // ignore response content now
  24. _, err := c.ReadLine()
  25. if err == io.EOF {
  26. log.Debug("ProxyName [%s], server close this control conn", cli.Name)
  27. var sleepTime time.Duration = 1
  28. // loop until connect to server
  29. for {
  30. log.Debug("ProxyName [%s], try to reconnect to server[%s:%d]...", cli.Name, client.ServerAddr, client.ServerPort)
  31. tmpConn, err := loginToServer(cli)
  32. if err == nil {
  33. c.Close()
  34. c = tmpConn
  35. break
  36. }
  37. if sleepTime < 60 {
  38. sleepTime = sleepTime * 2
  39. }
  40. time.Sleep(sleepTime * time.Second)
  41. }
  42. continue
  43. } else if err != nil {
  44. log.Warn("ProxyName [%s], read from server error, %v", cli.Name, err)
  45. continue
  46. }
  47. cli.StartTunnel(client.ServerAddr, client.ServerPort)
  48. }
  49. }
  50. func loginToServer(cli *client.ProxyClient) (c *conn.Conn, err error) {
  51. c, err = conn.ConnectServer(client.ServerAddr, client.ServerPort)
  52. if err != nil {
  53. log.Error("ProxyName [%s], connect to server [%s:%d] error, %v", cli.Name, client.ServerAddr, client.ServerPort, err)
  54. return
  55. }
  56. req := &msg.ClientCtlReq{
  57. Type: consts.CtlConn,
  58. ProxyName: cli.Name,
  59. Passwd: cli.Passwd,
  60. }
  61. buf, _ := json.Marshal(req)
  62. err = c.Write(string(buf) + "\n")
  63. if err != nil {
  64. log.Error("ProxyName [%s], write to server error, %v", cli.Name, err)
  65. return
  66. }
  67. res, err := c.ReadLine()
  68. if err != nil {
  69. log.Error("ProxyName [%s], read from server error, %v", cli.Name, err)
  70. return
  71. }
  72. log.Debug("ProxyName [%s], read [%s]", cli.Name, res)
  73. clientCtlRes := &msg.ClientCtlRes{}
  74. if err = json.Unmarshal([]byte(res), &clientCtlRes); err != nil {
  75. log.Error("ProxyName [%s], format server response error, %v", cli.Name, err)
  76. return
  77. }
  78. if clientCtlRes.Code != 0 {
  79. log.Error("ProxyName [%s], start proxy error, %s", cli.Name, clientCtlRes.Msg)
  80. return c, fmt.Errorf("%s", clientCtlRes.Msg)
  81. }
  82. go startHeartBeat(c)
  83. log.Debug("ProxyName [%s], connect to server[%s:%d] success!", cli.Name, client.ServerAddr, client.ServerPort)
  84. return
  85. }
  86. func startHeartBeat(c *conn.Conn) {
  87. log.Debug("Start to send heartbeat")
  88. for {
  89. time.Sleep(time.Duration(client.HeartBeatInterval) * time.Second)
  90. if !c.IsClosed() {
  91. err := c.Write("\n")
  92. if err != nil {
  93. log.Error("Send hearbeat to server failed! Err:%s", err.Error())
  94. continue
  95. }
  96. } else {
  97. break
  98. }
  99. }
  100. log.Debug("heartbeat exit")
  101. }