strategy_leastping.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package router
  2. import (
  3. "context"
  4. "github.com/xtls/xray-core/app/observatory"
  5. "github.com/xtls/xray-core/common"
  6. "github.com/xtls/xray-core/common/errors"
  7. "github.com/xtls/xray-core/core"
  8. "github.com/xtls/xray-core/features/extension"
  9. )
  10. type LeastPingStrategy struct {
  11. ctx context.Context
  12. observatory extension.Observatory
  13. }
  14. func (l *LeastPingStrategy) GetPrincipleTarget(strings []string) []string {
  15. return []string{l.PickOutbound(strings)}
  16. }
  17. func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
  18. l.ctx = ctx
  19. }
  20. func (l *LeastPingStrategy) PickOutbound(strings []string) string {
  21. if l.observatory == nil {
  22. common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error {
  23. l.observatory = observatory
  24. return nil
  25. }))
  26. }
  27. observeReport, err := l.observatory.GetObservation(l.ctx)
  28. if err != nil {
  29. errors.LogInfoInner(l.ctx, err, "cannot get observe report")
  30. return ""
  31. }
  32. outboundsList := outboundList(strings)
  33. if result, ok := observeReport.(*observatory.ObservationResult); ok {
  34. status := result.Status
  35. leastPing := int64(99999999)
  36. selectedOutboundName := ""
  37. for _, v := range status {
  38. if outboundsList.contains(v.OutboundTag) && v.Alive && v.Delay < leastPing {
  39. selectedOutboundName = v.OutboundTag
  40. leastPing = v.Delay
  41. }
  42. }
  43. return selectedOutboundName
  44. }
  45. // No way to understand observeReport
  46. return ""
  47. }
  48. type outboundList []string
  49. func (o outboundList) contains(name string) bool {
  50. for _, v := range o {
  51. if v == name {
  52. return true
  53. }
  54. }
  55. return false
  56. }