mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-03 07:56:42 -05:00
Fix DNS servers with same tag wrongly merged
This commit is contained in:
parent
54c2c6d537
commit
7243392af2
@ -194,6 +194,108 @@ func TestMergeTagDeep(t *testing.T) {
|
||||
assertResult(t, m, expected)
|
||||
}
|
||||
|
||||
func TestNoMergeDnsServers(t *testing.T) {
|
||||
json1 := `
|
||||
{
|
||||
"dns": {
|
||||
"queryStrategy": "UseIPv4",
|
||||
"fallbackStrategy": "disabled-if-any-match",
|
||||
"domainMatcher": "mph",
|
||||
"servers": [
|
||||
{
|
||||
"address": "aaa.bbb.ccc.ddd",
|
||||
"port": 53,
|
||||
"domains": [
|
||||
"geosite:cn"
|
||||
],
|
||||
"tag": "dns-domestic"
|
||||
},
|
||||
{
|
||||
"address": "114.114.114.114",
|
||||
"port": 53,
|
||||
"domains": [
|
||||
"geosite:cn"
|
||||
],
|
||||
"tag": "dns-domestic"
|
||||
},
|
||||
{
|
||||
"address": "https://1.1.1.1/dns-query",
|
||||
"tag": "dns-international"
|
||||
}
|
||||
]
|
||||
},
|
||||
"routing": {
|
||||
"domainStrategy": "IPIfNonMatch",
|
||||
"domainMatcher": "mph",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": "dns-domestic",
|
||||
"outboundTag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": "dns-international",
|
||||
"outboundTag": "proxy"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`
|
||||
expected := `
|
||||
{
|
||||
"dns": {
|
||||
"queryStrategy": "UseIPv4",
|
||||
"fallbackStrategy": "disabled-if-any-match",
|
||||
"domainMatcher": "mph",
|
||||
"servers": [
|
||||
{
|
||||
"address": "aaa.bbb.ccc.ddd",
|
||||
"port": 53,
|
||||
"domains": [
|
||||
"geosite:cn"
|
||||
],
|
||||
"tag": "dns-domestic"
|
||||
},
|
||||
{
|
||||
"address": "114.114.114.114",
|
||||
"port": 53,
|
||||
"domains": [
|
||||
"geosite:cn"
|
||||
],
|
||||
"tag": "dns-domestic"
|
||||
},
|
||||
{
|
||||
"address": "https://1.1.1.1/dns-query",
|
||||
"tag": "dns-international"
|
||||
}
|
||||
]
|
||||
},
|
||||
"routing": {
|
||||
"domainStrategy": "IPIfNonMatch",
|
||||
"domainMatcher": "mph",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": "dns-domestic",
|
||||
"outboundTag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": "dns-international",
|
||||
"outboundTag": "proxy"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`
|
||||
m, err := merge.JSONs([][]byte{[]byte(json1)})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assertResult(t, m, expected)
|
||||
}
|
||||
|
||||
func assertResult(t *testing.T, value []byte, expected string) {
|
||||
v := make(map[string]interface{})
|
||||
err := serial.DecodeJSON(bytes.NewReader(value), &v)
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package merge
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
priorityKey string = "_priority"
|
||||
tagKey string = "_tag"
|
||||
@ -11,7 +13,7 @@ const (
|
||||
|
||||
// ApplyRules applies merge rules according to _tag, _priority fields, and remove them
|
||||
func ApplyRules(m map[string]interface{}) error {
|
||||
err := sortMergeSlices(m)
|
||||
err := sortMergeSlices(m, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -20,22 +22,22 @@ func ApplyRules(m map[string]interface{}) error {
|
||||
}
|
||||
|
||||
// sortMergeSlices enumerates all slices in a map, to sort by priority and merge by tag
|
||||
func sortMergeSlices(target map[string]interface{}) error {
|
||||
func sortMergeSlices(target map[string]interface{}, path string) error {
|
||||
for key, value := range target {
|
||||
if slice, ok := value.([]interface{}); ok {
|
||||
sortByPriority(slice)
|
||||
s, err := mergeSameTag(slice)
|
||||
s, err := mergeSameTag(slice, fmt.Sprintf("%s.%s", path, key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
target[key] = s
|
||||
for _, item := range s {
|
||||
for i, item := range s {
|
||||
if m, ok := item.(map[string]interface{}); ok {
|
||||
sortMergeSlices(m)
|
||||
sortMergeSlices(m, fmt.Sprintf("%s.%s.%d", path, key, i))
|
||||
}
|
||||
}
|
||||
} else if field, ok := value.(map[string]interface{}); ok {
|
||||
sortMergeSlices(field)
|
||||
sortMergeSlices(field, fmt.Sprintf("%s.%s", path, key))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -4,12 +4,18 @@
|
||||
|
||||
package merge
|
||||
|
||||
func getTag(v map[string]interface{}) string {
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getTag(v map[string]interface{}, tagKeyOnly bool) string {
|
||||
if !tagKeyOnly {
|
||||
if field, ok := v["tag"]; ok {
|
||||
if t, ok := field.(string); ok {
|
||||
return t
|
||||
}
|
||||
}
|
||||
}
|
||||
if field, ok := v[tagKey]; ok {
|
||||
if t, ok := field.(string); ok {
|
||||
return t
|
||||
@ -18,16 +24,21 @@ func getTag(v map[string]interface{}) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func mergeSameTag(s []interface{}) ([]interface{}, error) {
|
||||
func mergeSameTag(s []interface{}, path string) ([]interface{}, error) {
|
||||
// from: [a,"",b,"",a,"",b,""]
|
||||
// to: [a,"",b,"",merged,"",merged,""]
|
||||
merged := &struct{}{}
|
||||
tagKeyOnly := false
|
||||
// See https://github.com/v2fly/v2ray-core/issues/2981
|
||||
if strings.HasPrefix(path, ".dns.servers") {
|
||||
tagKeyOnly = true
|
||||
}
|
||||
for i, item1 := range s {
|
||||
map1, ok := item1.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
tag1 := getTag(map1)
|
||||
tag1 := getTag(map1, tagKeyOnly)
|
||||
if tag1 == "" {
|
||||
continue
|
||||
}
|
||||
@ -36,7 +47,7 @@ func mergeSameTag(s []interface{}) ([]interface{}, error) {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
tag2 := getTag(map2)
|
||||
tag2 := getTag(map2, tagKeyOnly)
|
||||
if tag1 == tag2 {
|
||||
s[j] = merged
|
||||
err := mergeMaps(map1, map2)
|
||||
|
Loading…
Reference in New Issue
Block a user