pmux.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // This module is used for port reuse
  2. // Distinguish client, web manager , HTTP and HTTPS according to the difference of protocol
  3. package mux
  4. import (
  5. "bufio"
  6. "bytes"
  7. "github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
  8. "github.com/pkg/errors"
  9. "io"
  10. "net"
  11. "strconv"
  12. "strings"
  13. )
  14. const (
  15. HTTP_GET = 716984
  16. HTTP_POST = 807983
  17. HTTP_HEAD = 726965
  18. HTTP_PUT = 808585
  19. HTTP_DELETE = 686976
  20. HTTP_CONNECT = 677978
  21. HTTP_OPTIONS = 798084
  22. HTTP_TRACE = 848265
  23. CLIENT = 848384
  24. )
  25. type PortMux struct {
  26. net.Listener
  27. port int
  28. isClose bool
  29. managerHost string
  30. clientConn chan *PortConn
  31. httpConn chan *PortConn
  32. httpsConn chan *PortConn
  33. managerConn chan *PortConn
  34. }
  35. func NewPortMux(port int, managerHost string) *PortMux {
  36. pMux := &PortMux{
  37. managerHost: managerHost,
  38. port: port,
  39. clientConn: make(chan *PortConn),
  40. httpConn: make(chan *PortConn),
  41. httpsConn: make(chan *PortConn),
  42. managerConn: make(chan *PortConn),
  43. }
  44. pMux.Start()
  45. return pMux
  46. }
  47. func (pMux *PortMux) Start() error {
  48. // Port multiplexing is based on TCP only
  49. tcpAddr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:"+strconv.Itoa(pMux.port))
  50. if err != nil {
  51. return err
  52. }
  53. pMux.Listener, err = net.ListenTCP("tcp", tcpAddr)
  54. if err != nil {
  55. return err
  56. }
  57. go func() {
  58. for {
  59. conn, err := pMux.Listener.Accept()
  60. if err != nil {
  61. logs.Warn(err)
  62. //close
  63. pMux.Close()
  64. }
  65. go pMux.process(conn)
  66. }
  67. }()
  68. return nil
  69. }
  70. func (pMux *PortMux) process(conn net.Conn) {
  71. // Recognition according to different signs
  72. // read 3 byte
  73. buf := make([]byte, 3)
  74. if n, err := io.ReadFull(conn, buf); err != nil || n != 3 {
  75. return
  76. }
  77. var ch chan *PortConn
  78. var rs []byte
  79. var buffer bytes.Buffer
  80. switch bytesToNum(buf) {
  81. case HTTP_CONNECT, HTTP_DELETE, HTTP_GET, HTTP_HEAD, HTTP_OPTIONS, HTTP_POST, HTTP_PUT, HTTP_TRACE: //http and manager
  82. buffer.Reset()
  83. r := bufio.NewReader(conn)
  84. buffer.Write(buf)
  85. for {
  86. b, _, err := r.ReadLine()
  87. if err != nil {
  88. logs.Warn("read line error", err.Error())
  89. conn.Close()
  90. break
  91. }
  92. buffer.Write(b)
  93. buffer.Write([]byte("\r\n"))
  94. if strings.Index(string(b), "Host:") == 0 || strings.Index(string(b), "host:") == 0 {
  95. // Remove host and space effects
  96. str := strings.Replace(string(b), "Host:", "", -1)
  97. str = strings.Replace(str, "host:", "", -1)
  98. str = strings.TrimSpace(str)
  99. // Determine whether it is the same as the manager domain name
  100. if str == pMux.managerHost {
  101. ch = pMux.managerConn
  102. } else {
  103. ch = pMux.httpConn
  104. }
  105. b, _ := r.Peek(r.Buffered())
  106. buffer.Write(b)
  107. rs = buffer.Bytes()
  108. break
  109. }
  110. }
  111. case CLIENT: // client connection
  112. ch = pMux.clientConn
  113. default: // https
  114. ch = pMux.httpsConn
  115. }
  116. if len(rs) == 0 {
  117. rs = buf
  118. }
  119. ch <- newPortConn(conn, rs)
  120. }
  121. func (pMux *PortMux) Close() error {
  122. if pMux.isClose {
  123. return errors.New("the port mux has closed")
  124. }
  125. pMux.isClose = true
  126. close(pMux.clientConn)
  127. close(pMux.httpsConn)
  128. close(pMux.httpConn)
  129. close(pMux.managerConn)
  130. return pMux.Listener.Close()
  131. }
  132. func (pMux *PortMux) GetClientListener() net.Listener {
  133. return NewPortListener(pMux.clientConn, pMux.Listener.Addr())
  134. }
  135. func (pMux *PortMux) GetHttpListener() net.Listener {
  136. return NewPortListener(pMux.httpConn, pMux.Listener.Addr())
  137. }
  138. func (pMux *PortMux) GetHttpsListener() net.Listener {
  139. return NewPortListener(pMux.httpsConn, pMux.Listener.Addr())
  140. }
  141. func (pMux *PortMux) GetManagerListener() net.Listener {
  142. return NewPortListener(pMux.managerConn, pMux.Listener.Addr())
  143. }
  144. func bytesToNum(b []byte) int {
  145. var str string
  146. for i := 0; i < len(b); i++ {
  147. str += strconv.Itoa(int(b[i]))
  148. }
  149. x, _ := strconv.Atoi(str)
  150. return int(x)
  151. }