ping.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. //go:build with_gvisor
  2. package tailscale
  3. import (
  4. "context"
  5. "net/netip"
  6. "time"
  7. "github.com/sagernet/sing-box/adapter"
  8. "github.com/sagernet/tailscale/ipn/ipnstate"
  9. "github.com/sagernet/tailscale/tailcfg"
  10. )
  11. func (t *Endpoint) StartTailscalePing(ctx context.Context, peerIP string, fn func(*adapter.TailscalePingResult)) error {
  12. ip, err := netip.ParseAddr(peerIP)
  13. if err != nil {
  14. return err
  15. }
  16. localClient, err := t.server.LocalClient()
  17. if err != nil {
  18. return err
  19. }
  20. ticker := time.NewTicker(time.Second)
  21. defer ticker.Stop()
  22. for {
  23. result, pingErr := localClient.Ping(ctx, ip, tailcfg.PingDisco)
  24. if ctx.Err() != nil {
  25. return ctx.Err()
  26. }
  27. if pingErr != nil {
  28. fn(&adapter.TailscalePingResult{
  29. Error: pingErr.Error(),
  30. })
  31. } else {
  32. fn(convertPingResult(result))
  33. }
  34. select {
  35. case <-ctx.Done():
  36. return ctx.Err()
  37. case <-ticker.C:
  38. }
  39. }
  40. }
  41. func convertPingResult(result *ipnstate.PingResult) *adapter.TailscalePingResult {
  42. return &adapter.TailscalePingResult{
  43. LatencyMs: result.LatencySeconds * 1000,
  44. IsDirect: result.Endpoint != "",
  45. Endpoint: result.Endpoint,
  46. DERPRegionID: int32(result.DERPRegionID),
  47. DERPRegionCode: result.DERPRegionCode,
  48. Error: result.Err,
  49. }
  50. }