github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/app/router/strategy_leastping.go (about)

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