فهرست منبع

add least balancing strategy

Shelikhoo 4 سال پیش
والد
کامیت
5a61749328

+ 8 - 0
app/router/balancing.go

@@ -3,7 +3,10 @@
 package router
 
 import (
+	"context"
+
 	"github.com/v2fly/v2ray-core/v4/common/dice"
+	"github.com/v2fly/v2ray-core/v4/features/extension"
 	"github.com/v2fly/v2ray-core/v4/features/outbound"
 )
 
@@ -44,3 +47,8 @@ func (b *Balancer) PickOutbound() (string, error) {
 	}
 	return tag, nil
 }
+func (b *Balancer) InjectContext(ctx context.Context) {
+	if contextReceiver, ok := b.strategy.(extension.ContextReceiver); ok {
+		contextReceiver.InjectContext(ctx)
+	}
+}

+ 1 - 0
app/router/config.proto

@@ -127,6 +127,7 @@ message RoutingRule {
 message BalancingRule {
   string tag = 1;
   repeated string outbound_selector = 2;
+  string strategy = 3;
 }
 
 message Config {

+ 2 - 2
app/router/router.go

@@ -31,7 +31,7 @@ type Route struct {
 }
 
 // Init initializes the Router.
-func (r *Router) Init(config *Config, d dns.Client, ohm outbound.Manager) error {
+func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm outbound.Manager) error {
 	r.domainStrategy = config.DomainStrategy
 	r.dns = d
 
@@ -142,7 +142,7 @@ func init() {
 	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
 		r := new(Router)
 		if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager) error {
-			return r.Init(config.(*Config), d, ohm)
+			return r.Init(ctx, config.(*Config), d, ohm)
 		}); err != nil {
 			return nil, err
 		}

+ 57 - 0
app/router/strategy_leastping.go

@@ -0,0 +1,57 @@
+package router
+
+import (
+	"context"
+
+	core "github.com/v2fly/v2ray-core/v4"
+	"github.com/v2fly/v2ray-core/v4/app/observatory"
+	"github.com/v2fly/v2ray-core/v4/common"
+	"github.com/v2fly/v2ray-core/v4/features/extension"
+)
+
+type LeastPingStrategy struct {
+	ctx         context.Context
+	observatory extension.Observatory
+}
+
+func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
+	common.Must(core.RequireFeatures(ctx, func(observatory extension.Observatory) error {
+		l.observatory = observatory
+		return nil
+	}))
+	l.ctx = ctx
+}
+
+func (l *LeastPingStrategy) PickOutbound(strings []string) string {
+	observeReport, err := l.observatory.GetObservation(l.ctx)
+	if err != nil {
+		newError("cannot get observe report").Base(err).WriteToLog()
+		return ""
+	}
+	outboundsList := outboundList(strings)
+	if result, ok := observeReport.(*observatory.ObservationResult); ok {
+		status := result.Status
+		leastPing := int64(99999999)
+		selectedOutboundName := ""
+		for _, v := range status {
+			if outboundsList.contains(v.OutboundTag) && v.Alive && v.Delay < leastPing {
+				selectedOutboundName = v.OutboundTag
+			}
+		}
+		return selectedOutboundName
+	}
+
+	//No way to understand observeReport
+	return ""
+}
+
+type outboundList []string
+
+func (o outboundList) contains(name string) bool {
+	for _, v := range o {
+		if v == name {
+			return true
+		}
+	}
+	return false
+}

+ 7 - 0
features/extension/contextreceiver.go

@@ -0,0 +1,7 @@
+package extension
+
+import "context"
+
+type ContextReceiver interface {
+	InjectContext(ctx context.Context)
+}

+ 2 - 0
features/extension/observatory.go

@@ -2,7 +2,9 @@ package extension
 
 import (
 	"context"
+
 	"github.com/golang/protobuf/proto"
+
 	"github.com/v2fly/v2ray-core/v4/features"
 )