tcp.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2016 fatedier, fatedier@gmail.com
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package net
  15. import (
  16. "bufio"
  17. "encoding/base64"
  18. "fmt"
  19. "net"
  20. "net/http"
  21. "net/url"
  22. "github.com/fatedier/frp/utils/log"
  23. )
  24. type TcpListener struct {
  25. net.Addr
  26. listener net.Listener
  27. accept chan Conn
  28. closeFlag bool
  29. log.Logger
  30. }
  31. func ListenTcp(bindAddr string, bindPort int) (l *TcpListener, err error) {
  32. tcpAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", bindAddr, bindPort))
  33. if err != nil {
  34. return l, err
  35. }
  36. listener, err := net.ListenTCP("tcp", tcpAddr)
  37. if err != nil {
  38. return l, err
  39. }
  40. l = &TcpListener{
  41. Addr: listener.Addr(),
  42. listener: listener,
  43. accept: make(chan Conn),
  44. closeFlag: false,
  45. Logger: log.NewPrefixLogger(""),
  46. }
  47. go func() {
  48. for {
  49. conn, err := listener.AcceptTCP()
  50. if err != nil {
  51. if l.closeFlag {
  52. close(l.accept)
  53. return
  54. }
  55. continue
  56. }
  57. c := NewTcpConn(conn)
  58. l.accept <- c
  59. }
  60. }()
  61. return l, err
  62. }
  63. // Wait util get one new connection or listener is closed
  64. // if listener is closed, err returned.
  65. func (l *TcpListener) Accept() (Conn, error) {
  66. conn, ok := <-l.accept
  67. if !ok {
  68. return conn, fmt.Errorf("channel for tcp listener closed")
  69. }
  70. return conn, nil
  71. }
  72. func (l *TcpListener) Close() error {
  73. if !l.closeFlag {
  74. l.closeFlag = true
  75. l.listener.Close()
  76. }
  77. return nil
  78. }
  79. // Wrap for TCPConn.
  80. type TcpConn struct {
  81. net.Conn
  82. log.Logger
  83. }
  84. func NewTcpConn(conn *net.TCPConn) (c *TcpConn) {
  85. c = &TcpConn{
  86. Conn: conn,
  87. Logger: log.NewPrefixLogger(""),
  88. }
  89. return
  90. }
  91. func ConnectTcpServer(addr string) (c Conn, err error) {
  92. servertAddr, err := net.ResolveTCPAddr("tcp", addr)
  93. if err != nil {
  94. return
  95. }
  96. conn, err := net.DialTCP("tcp", nil, servertAddr)
  97. if err != nil {
  98. return
  99. }
  100. c = NewTcpConn(conn)
  101. return
  102. }
  103. // ConnectTcpServerByHttpProxy try to connect remote server by http proxy.
  104. // If httpProxy is empty, it will connect server directly.
  105. func ConnectTcpServerByHttpProxy(httpProxy string, serverAddr string) (c Conn, err error) {
  106. if httpProxy == "" {
  107. return ConnectTcpServer(serverAddr)
  108. }
  109. var proxyUrl *url.URL
  110. if proxyUrl, err = url.Parse(httpProxy); err != nil {
  111. return
  112. }
  113. var proxyAuth string
  114. if proxyUrl.User != nil {
  115. username := proxyUrl.User.Username()
  116. passwd, _ := proxyUrl.User.Password()
  117. proxyAuth = "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+passwd))
  118. }
  119. if proxyUrl.Scheme != "http" {
  120. err = fmt.Errorf("Proxy URL scheme must be http, not [%s]", proxyUrl.Scheme)
  121. return
  122. }
  123. if c, err = ConnectTcpServer(proxyUrl.Host); err != nil {
  124. return
  125. }
  126. req, err := http.NewRequest("CONNECT", "http://"+serverAddr, nil)
  127. if err != nil {
  128. return
  129. }
  130. if proxyAuth != "" {
  131. req.Header.Set("Proxy-Authorization", proxyAuth)
  132. }
  133. req.Header.Set("User-Agent", "Mozilla/5.0")
  134. req.Write(c)
  135. resp, err := http.ReadResponse(bufio.NewReader(c), req)
  136. if err != nil {
  137. return
  138. }
  139. resp.Body.Close()
  140. if resp.StatusCode != 200 {
  141. err = fmt.Errorf("ConnectTcpServer using proxy error, StatusCode [%d]", resp.StatusCode)
  142. return
  143. }
  144. return
  145. }