ping.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package burst
  2. import (
  3. "context"
  4. "net/http"
  5. "time"
  6. "github.com/v2fly/v2ray-core/v5/common/net"
  7. "github.com/v2fly/v2ray-core/v5/transport/internet/tagged"
  8. )
  9. type pingClient struct {
  10. destination string
  11. httpClient *http.Client
  12. }
  13. func newPingClient(ctx context.Context, destination string, timeout time.Duration, handler string) *pingClient {
  14. return &pingClient{
  15. destination: destination,
  16. httpClient: newHTTPClient(ctx, handler, timeout),
  17. }
  18. }
  19. func newDirectPingClient(destination string, timeout time.Duration) *pingClient {
  20. return &pingClient{
  21. destination: destination,
  22. httpClient: &http.Client{Timeout: timeout},
  23. }
  24. }
  25. func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration) *http.Client {
  26. tr := &http.Transport{
  27. DisableKeepAlives: true,
  28. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  29. dest, err := net.ParseDestination(network + ":" + addr)
  30. if err != nil {
  31. return nil, err
  32. }
  33. return tagged.Dialer(ctxv, dest, handler)
  34. },
  35. }
  36. return &http.Client{
  37. Transport: tr,
  38. Timeout: timeout,
  39. // don't follow redirect
  40. CheckRedirect: func(req *http.Request, via []*http.Request) error {
  41. return http.ErrUseLastResponse
  42. },
  43. }
  44. }
  45. // MeasureDelay returns the delay time of the request to dest
  46. func (s *pingClient) MeasureDelay() (time.Duration, error) {
  47. if s.httpClient == nil {
  48. panic("pingClient no initialized")
  49. }
  50. req, err := http.NewRequest(http.MethodHead, s.destination, nil)
  51. if err != nil {
  52. return rttFailed, err
  53. }
  54. start := time.Now()
  55. resp, err := s.httpClient.Do(req)
  56. if err != nil {
  57. return rttFailed, err
  58. }
  59. // don't wait for body
  60. resp.Body.Close()
  61. return time.Since(start), nil
  62. }