Fix: parse error in proxyGroupsDagSort (#298)

This commit is contained in:
Comzyh 2019-09-13 15:04:51 +08:00 committed by Dreamacro
parent 112b3e5a6c
commit b3e10c05e6
3 changed files with 23 additions and 16 deletions

View File

@ -193,3 +193,9 @@ func (p *Proxy) URLTest(ctx context.Context, url string) (t uint16, err error) {
func NewProxy(adapter C.ProxyAdapter) *Proxy {
return &Proxy{adapter, queue.New(10), true}
}
// ProxyGroupOption contain the common options for all kind of ProxyGroup
type ProxyGroupOption struct {
Name string `proxy:"name"`
Proxies []string `proxy:"proxies"`
}

View File

@ -302,7 +302,7 @@ func parseProxies(cfg *rawConfig) (map[string]C.Proxy, error) {
}
// check if any loop exists and sort the ProxyGroups
if err := proxyGroupsDagSort(groupsConfig); err != nil {
if err := proxyGroupsDagSort(groupsConfig, decoder); err != nil {
return nil, err
}

View File

@ -4,6 +4,8 @@ import (
"fmt"
"strings"
adapters "github.com/Dreamacro/clash/adapters/outbound"
"github.com/Dreamacro/clash/common/structure"
C "github.com/Dreamacro/clash/constant"
)
@ -38,9 +40,9 @@ func or(pointers ...*int) *int {
// Check if ProxyGroups form DAG(Directed Acyclic Graph), and sort all ProxyGroups by dependency order.
// Meanwhile, record the original index in the config file.
// If loop is detected, return an error with location of loop.
func proxyGroupsDagSort(groupsConfig []map[string]interface{}) error {
func proxyGroupsDagSort(groupsConfig []map[string]interface{}, decoder *structure.Decoder) error {
type Node struct {
type graphNode struct {
indegree int
// topological order
topo int
@ -51,32 +53,31 @@ func proxyGroupsDagSort(groupsConfig []map[string]interface{}) error {
from []string
}
graph := make(map[string]*Node)
graph := make(map[string]*graphNode)
// Step 1.1 build dependency graph
for idx, mapping := range groupsConfig {
groupName, existName := mapping["name"].(string)
if !existName {
return fmt.Errorf("ProxyGroup %d: missing name", idx)
for _, mapping := range groupsConfig {
option := &adapters.ProxyGroupOption{}
err := decoder.Decode(mapping, option)
groupName := option.Name
if err != nil {
return fmt.Errorf("ProxyGroup %s: %s", groupName, err.Error())
}
if node, ok := graph[groupName]; ok {
if node.data != nil {
return fmt.Errorf("ProxyGroup %s: duplicate group name", groupName)
}
node.data = mapping
} else {
graph[groupName] = &Node{0, -1, mapping, 0, nil}
graph[groupName] = &graphNode{0, -1, mapping, 0, nil}
}
proxies, existProxies := mapping["proxies"]
if !existProxies {
return fmt.Errorf("ProxyGroup %s: the `proxies` field is requried", groupName)
}
for _, proxy := range proxies.([]interface{}) {
proxy := proxy.(string)
for _, proxy := range option.Proxies {
if node, ex := graph[proxy]; ex {
node.indegree++
} else {
graph[proxy] = &Node{1, -1, nil, 0, nil}
graph[proxy] = &graphNode{1, -1, nil, 0, nil}
}
}
}