client.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package v2raywebsocket
  2. import (
  3. "context"
  4. "net"
  5. "net/http"
  6. "net/url"
  7. "strings"
  8. "time"
  9. "github.com/sagernet/sing-box/adapter"
  10. "github.com/sagernet/sing-box/common/tls"
  11. C "github.com/sagernet/sing-box/constant"
  12. "github.com/sagernet/sing-box/option"
  13. "github.com/sagernet/sing/common/buf"
  14. "github.com/sagernet/sing/common/bufio"
  15. "github.com/sagernet/sing/common/bufio/deadline"
  16. E "github.com/sagernet/sing/common/exceptions"
  17. M "github.com/sagernet/sing/common/metadata"
  18. N "github.com/sagernet/sing/common/network"
  19. sHTTP "github.com/sagernet/sing/protocol/http"
  20. "github.com/sagernet/ws"
  21. )
  22. var _ adapter.V2RayClientTransport = (*Client)(nil)
  23. type Client struct {
  24. dialer N.Dialer
  25. serverAddr M.Socksaddr
  26. requestURL url.URL
  27. headers http.Header
  28. maxEarlyData uint32
  29. earlyDataHeaderName string
  30. }
  31. func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayWebsocketOptions, tlsConfig tls.Config) (adapter.V2RayClientTransport, error) {
  32. if tlsConfig != nil {
  33. if len(tlsConfig.NextProtos()) == 0 {
  34. tlsConfig.SetNextProtos([]string{"http/1.1"})
  35. }
  36. dialer = tls.NewDialer(dialer, tlsConfig)
  37. }
  38. var requestURL url.URL
  39. if tlsConfig == nil {
  40. requestURL.Scheme = "ws"
  41. } else {
  42. requestURL.Scheme = "wss"
  43. }
  44. requestURL.Host = serverAddr.String()
  45. requestURL.Path = options.Path
  46. err := sHTTP.URLSetPath(&requestURL, options.Path)
  47. if err != nil {
  48. return nil, E.Cause(err, "parse path")
  49. }
  50. if !strings.HasPrefix(requestURL.Path, "/") {
  51. requestURL.Path = "/" + requestURL.Path
  52. }
  53. headers := options.Headers.Build()
  54. if host := headers.Get("Host"); host != "" {
  55. headers.Del("Host")
  56. requestURL.Host = host
  57. }
  58. if headers.Get("User-Agent") == "" {
  59. headers.Set("User-Agent", "Go-http-client/1.1")
  60. }
  61. return &Client{
  62. dialer,
  63. serverAddr,
  64. requestURL,
  65. headers,
  66. options.MaxEarlyData,
  67. options.EarlyDataHeaderName,
  68. }, nil
  69. }
  70. func (c *Client) dialContext(ctx context.Context, requestURL *url.URL, headers http.Header) (*WebsocketConn, error) {
  71. conn, err := c.dialer.DialContext(ctx, N.NetworkTCP, c.serverAddr)
  72. if err != nil {
  73. return nil, err
  74. }
  75. var deadlineConn net.Conn
  76. if deadline.NeedAdditionalReadDeadline(conn) {
  77. deadlineConn = deadline.NewConn(conn)
  78. } else {
  79. deadlineConn = conn
  80. }
  81. deadlineConn.SetDeadline(time.Now().Add(C.TCPTimeout))
  82. var protocols []string
  83. if protocolHeader := headers.Get("Sec-WebSocket-Protocol"); protocolHeader != "" {
  84. protocols = []string{protocolHeader}
  85. headers.Del("Sec-WebSocket-Protocol")
  86. }
  87. reader, _, err := ws.Dialer{Header: ws.HandshakeHeaderHTTP(headers), Protocols: protocols}.Upgrade(deadlineConn, requestURL)
  88. deadlineConn.SetDeadline(time.Time{})
  89. if err != nil {
  90. return nil, err
  91. }
  92. if reader != nil {
  93. buffer := buf.NewSize(reader.Buffered())
  94. _, err = buffer.ReadFullFrom(reader, buffer.Len())
  95. if err != nil {
  96. return nil, err
  97. }
  98. conn = bufio.NewCachedConn(conn, buffer)
  99. }
  100. return NewConn(conn, nil, ws.StateClientSide), nil
  101. }
  102. func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
  103. if c.maxEarlyData <= 0 {
  104. conn, err := c.dialContext(ctx, &c.requestURL, c.headers)
  105. if err != nil {
  106. return nil, err
  107. }
  108. return conn, nil
  109. } else {
  110. return &EarlyWebsocketConn{Client: c, ctx: ctx, create: make(chan struct{})}, nil
  111. }
  112. }
  113. func (c *Client) Close() error {
  114. return nil
  115. }