dialer.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. package httpupgrade
  2. import (
  3. "bufio"
  4. "context"
  5. "net/http"
  6. "strings"
  7. "github.com/v2fly/v2ray-core/v5/common"
  8. "github.com/v2fly/v2ray-core/v5/common/net"
  9. "github.com/v2fly/v2ray-core/v5/common/session"
  10. "github.com/v2fly/v2ray-core/v5/transport/internet"
  11. "github.com/v2fly/v2ray-core/v5/transport/internet/transportcommon"
  12. )
  13. func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
  14. transportConfiguration := streamSettings.ProtocolSettings.(*Config)
  15. conn, err := transportcommon.DialWithSecuritySettings(ctx, dest, streamSettings)
  16. if err != nil {
  17. return nil, newError("failed to dial request to ", dest).Base(err)
  18. }
  19. req, err := http.NewRequest("GET", transportConfiguration.GetNormalizedPath(), nil)
  20. if err != nil {
  21. return nil, err
  22. }
  23. req.Header.Set("Connection", "upgrade")
  24. req.Header.Set("Upgrade", "websocket")
  25. req.Host = transportConfiguration.Host
  26. err = req.Write(conn)
  27. if err != nil {
  28. return nil, err
  29. }
  30. // TODO The bufio usage here is unreliable
  31. resp, err := http.ReadResponse(bufio.NewReader(conn), req) // nolint:bodyclose
  32. if err != nil {
  33. return nil, err
  34. }
  35. if resp.Status == "101 Switching Protocols" &&
  36. strings.ToLower(resp.Header.Get("Upgrade")) == "websocket" &&
  37. strings.ToLower(resp.Header.Get("Connection")) == "upgrade" {
  38. return conn, nil
  39. }
  40. return nil, newError("unrecognized reply")
  41. }
  42. func dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
  43. newError("creating connection to ", dest).WriteToLog(session.ExportIDToError(ctx))
  44. conn, err := dialhttpUpgrade(ctx, dest, streamSettings)
  45. if err != nil {
  46. return nil, newError("failed to dial request to ", dest).Base(err)
  47. }
  48. return internet.Connection(conn), nil
  49. }
  50. func init() {
  51. common.Must(internet.RegisterTransportDialer(protocolName, dial))
  52. }