From 22a4d48cf967bffd26522d35a7b939e4d619f8ce Mon Sep 17 00:00:00 2001 From: zhengrui Date: Sun, 18 Mar 2018 10:41:55 +0800 Subject: [PATCH] #224 add fifo strategy for node selector --- cmd/gost/main.go | 4 +++- selector.go | 35 +++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/cmd/gost/main.go b/cmd/gost/main.go index 6cc244d..14f5062 100644 --- a/cmd/gost/main.go +++ b/cmd/gost/main.go @@ -488,7 +488,7 @@ func (r *route) serve() error { case "sni": handler = gost.SNIHandler(handlerOptions...) default: - // start from 2.5, if remote is not empty, then we assume that it is a forward tunnel + // start from 2.5, if remote is not empty, then we assume that it is a forward tunnel. if node.Remote != "" { handler = gost.TCPDirectForwardHandler(node.Remote, handlerOptions...) } else { @@ -696,6 +696,8 @@ func parseStrategy(s string) gost.Strategy { switch s { case "random": return &gost.RandomStrategy{} + case "fifo": + return &gost.FIFOStrategy{} case "round": fallthrough default: diff --git a/selector.go b/selector.go index 15bbe33..cadf799 100644 --- a/selector.go +++ b/selector.go @@ -9,7 +9,7 @@ import ( ) var ( - // ErrNoneAvailable indicates there is no node available + // ErrNoneAvailable indicates there is no node available. ErrNoneAvailable = errors.New("none available") ) @@ -38,10 +38,10 @@ func (s *defaultSelector) Select(nodes []Node, opts ...SelectOption) (Node, erro return sopts.Strategy.Apply(nodes), nil } -// SelectOption used when making a select call +// SelectOption is the option used when making a select call. type SelectOption func(*SelectOptions) -// SelectOptions is the options for node selection +// SelectOptions is the options for node selection. type SelectOptions struct { Filters []Filter Strategy Strategy @@ -62,18 +62,19 @@ func WithStrategy(s Strategy) SelectOption { } } -// Strategy is a selection strategy e.g random, round robin +// Strategy is a selection strategy e.g random, round-robin. type Strategy interface { Apply([]Node) Node String() string } -// RoundStrategy is a strategy for node selector +// RoundStrategy is a strategy for node selector. +// The node will be selected by round-robin algorithm. type RoundStrategy struct { count uint64 } -// Apply applies the round robin strategy for the nodes +// Apply applies the round-robin strategy for the nodes. func (s *RoundStrategy) Apply(nodes []Node) Node { if len(nodes) == 0 { return Node{} @@ -87,14 +88,15 @@ func (s *RoundStrategy) String() string { return "round" } -// RandomStrategy is a strategy for node selector +// RandomStrategy is a strategy for node selector. +// The node will be selected randomly. type RandomStrategy struct { Seed int64 rand *rand.Rand once sync.Once } -// Apply applies the random strategy for the nodes +// Apply applies the random strategy for the nodes. func (s *RandomStrategy) Apply(nodes []Node) Node { s.once.Do(func() { seed := s.Seed @@ -114,6 +116,23 @@ func (s *RandomStrategy) String() string { return "random" } +// FIFOStrategy is a strategy for node selector. +// The node will be selected from first to last, +// and will stick to the selected node until it is failed. +type FIFOStrategy struct{} + +// Apply applies the fifo strategy for the nodes. +func (s *FIFOStrategy) Apply(nodes []Node) Node { + if len(nodes) == 0 { + return Node{} + } + return nodes[0] +} + +func (s *FIFOStrategy) String() string { + return "fifo" +} + // Filter is used to filter a node during the selection process type Filter interface { Filter([]Node) []Node