mirror of
https://github.com/ginuerzh/gost.git
synced 2026-10-19 16:14:35 +00:00
add node fail filter
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Node is a proxy node, mainly used to construct a proxy chain.
|
||||
type Node struct {
|
||||
ID int
|
||||
Addr string
|
||||
IPs []string
|
||||
Host string
|
||||
Protocol string
|
||||
Transport string
|
||||
@@ -20,7 +21,9 @@ type Node struct {
|
||||
DialOptions []DialOption
|
||||
HandshakeOptions []HandshakeOption
|
||||
Client *Client
|
||||
Selector IPSelector
|
||||
group *NodeGroup
|
||||
failCount uint32
|
||||
failTime time.Time
|
||||
}
|
||||
|
||||
// ParseNode parses the node info.
|
||||
@@ -83,38 +86,89 @@ func ParseNode(s string) (node Node, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// MarkDead marks the node fail status.
|
||||
func (node *Node) MarkDead() {
|
||||
atomic.AddUint32(&node.failCount, 1)
|
||||
node.failTime = time.Now()
|
||||
|
||||
if node.group == nil {
|
||||
return
|
||||
}
|
||||
for i := range node.group.nodes {
|
||||
if node.group.nodes[i].ID == node.ID {
|
||||
atomic.AddUint32(&node.group.nodes[i].failCount, 1)
|
||||
node.group.nodes[i].failTime = time.Now()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ResetDead resets the node fail status.
|
||||
func (node *Node) ResetDead() {
|
||||
atomic.StoreUint32(&node.failCount, 0)
|
||||
node.failTime = time.Time{}
|
||||
|
||||
if node.group == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := range node.group.nodes {
|
||||
if node.group.nodes[i].ID == node.ID {
|
||||
atomic.StoreUint32(&node.group.nodes[i].failCount, 0)
|
||||
node.group.nodes[i].failTime = time.Time{}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (node *Node) String() string {
|
||||
return fmt.Sprintf("%d@%s", node.ID, node.Addr)
|
||||
}
|
||||
|
||||
// NodeGroup is a group of nodes.
|
||||
type NodeGroup struct {
|
||||
nodes []Node
|
||||
Options []SelectOption
|
||||
Selector NodeSelector
|
||||
mutex sync.Mutex
|
||||
mFails map[string]int // node -> fail count
|
||||
MaxFails int
|
||||
FailTimeout int
|
||||
Retries int
|
||||
ID int
|
||||
nodes []Node
|
||||
Options []SelectOption
|
||||
Selector NodeSelector
|
||||
}
|
||||
|
||||
// NewNodeGroup creates a node group
|
||||
func NewNodeGroup(nodes ...Node) *NodeGroup {
|
||||
return &NodeGroup{
|
||||
nodes: nodes,
|
||||
mFails: make(map[string]int),
|
||||
nodes: nodes,
|
||||
}
|
||||
}
|
||||
|
||||
// AddNode adds node or node list into group
|
||||
func (ng *NodeGroup) AddNode(node ...Node) {
|
||||
if ng == nil {
|
||||
func (group *NodeGroup) AddNode(node ...Node) {
|
||||
if group == nil {
|
||||
return
|
||||
}
|
||||
ng.nodes = append(ng.nodes, node...)
|
||||
group.nodes = append(group.nodes, node...)
|
||||
}
|
||||
|
||||
// Nodes returns node list in the group
|
||||
func (ng *NodeGroup) Nodes() []Node {
|
||||
if ng == nil {
|
||||
func (group *NodeGroup) Nodes() []Node {
|
||||
if group == nil {
|
||||
return nil
|
||||
}
|
||||
return ng.nodes
|
||||
return group.nodes
|
||||
}
|
||||
|
||||
// Next selects the next node from group.
|
||||
// It also selects IP if the IP list exists.
|
||||
func (group *NodeGroup) Next() (node Node, err error) {
|
||||
selector := group.Selector
|
||||
if selector == nil {
|
||||
selector = &defaultSelector{}
|
||||
}
|
||||
// select node from node group
|
||||
node, err = selector.Select(group.Nodes(), group.Options...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
node.group = group
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user