server.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package models
  2. import (
  3. "container/list"
  4. "sync"
  5. "github.com/fatedier/frp/pkg/utils/conn"
  6. "github.com/fatedier/frp/pkg/utils/log"
  7. )
  8. const (
  9. Idle = iota
  10. Working
  11. )
  12. type ProxyServer struct {
  13. Name string
  14. Passwd string
  15. BindAddr string
  16. ListenPort int64
  17. Status int64
  18. Listener *conn.Listener // accept new connection from remote users
  19. CtlMsgChan chan int64 // every time accept a new user conn, put "1" to the channel
  20. CliConnChan chan *conn.Conn // get client conns from control goroutine
  21. UserConnList *list.List // store user conns
  22. Mutex sync.Mutex
  23. }
  24. func (p *ProxyServer) Init() {
  25. p.Status = Idle
  26. p.CtlMsgChan = make(chan int64)
  27. p.CliConnChan = make(chan *conn.Conn)
  28. p.UserConnList = list.New()
  29. }
  30. func (p *ProxyServer) Lock() {
  31. p.Mutex.Lock()
  32. }
  33. func (p *ProxyServer) Unlock() {
  34. p.Mutex.Unlock()
  35. }
  36. // start listening for user conns
  37. func (p *ProxyServer) Start() (err error) {
  38. p.Listener, err = conn.Listen(p.BindAddr, p.ListenPort)
  39. if err != nil {
  40. return err
  41. }
  42. p.Status = Working
  43. // start a goroutine for listener
  44. go func() {
  45. for {
  46. // block
  47. c := p.Listener.GetConn()
  48. log.Debug("ProxyName [%s], get one new user conn [%s]", p.Name, c.GetRemoteAddr())
  49. // put to list
  50. p.Lock()
  51. if p.Status != Working {
  52. log.Debug("ProxyName [%s] is not working, new user conn close", p.Name)
  53. c.Close()
  54. p.Unlock()
  55. return
  56. }
  57. p.UserConnList.PushBack(c)
  58. p.Unlock()
  59. // put msg to control conn
  60. p.CtlMsgChan <- 1
  61. }
  62. }()
  63. // start another goroutine for join two conns from client and user
  64. go func() {
  65. for {
  66. cliConn := <-p.CliConnChan
  67. p.Lock()
  68. element := p.UserConnList.Front()
  69. var userConn *conn.Conn
  70. if element != nil {
  71. userConn = element.Value.(*conn.Conn)
  72. p.UserConnList.Remove(element)
  73. } else {
  74. cliConn.Close()
  75. continue
  76. }
  77. p.Unlock()
  78. // msg will transfer to another without modifying
  79. log.Debug("Join two conns, (l[%s] r[%s]) (l[%s] r[%s])", cliConn.GetLocalAddr(), cliConn.GetRemoteAddr(),
  80. userConn.GetLocalAddr(), userConn.GetRemoteAddr())
  81. go conn.Join(cliConn, userConn)
  82. }
  83. }()
  84. return nil
  85. }
  86. func (p *ProxyServer) Close() {
  87. p.Lock()
  88. p.Status = Idle
  89. p.CtlMsgChan = make(chan int64)
  90. p.CliConnChan = make(chan *conn.Conn)
  91. p.UserConnList = list.New()
  92. p.Unlock()
  93. }
  94. func (p *ProxyServer) WaitUserConn() (res int64) {
  95. res = <-p.CtlMsgChan
  96. return
  97. }