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 { func NewProxy(adapter C.ProxyAdapter) *Proxy {
return &Proxy{adapter, queue.New(10), true} 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 // 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 return nil, err
} }

View File

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