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