From b2772127151eecd42833d6478f55bed14a21dcac Mon Sep 17 00:00:00 2001 From: mzz2017 <2017@duck.com> Date: Sat, 18 Feb 2023 21:39:46 +0800 Subject: [PATCH] optimize: memory occupation --- .../routing/domain_matcher/ahocorasick.go | 125 ----------- .../domain_matcher/ahocorasick_succinctset.go | 195 ++++++++++++++++++ .../routing/domain_matcher/benchmark_test.go | 4 +- control/routing_matcher_builder.go | 2 +- go.mod | 13 +- go.sum | 32 ++- 6 files changed, 239 insertions(+), 132 deletions(-) delete mode 100644 component/routing/domain_matcher/ahocorasick.go create mode 100644 component/routing/domain_matcher/ahocorasick_succinctset.go diff --git a/component/routing/domain_matcher/ahocorasick.go b/component/routing/domain_matcher/ahocorasick.go deleted file mode 100644 index 4060e52..0000000 --- a/component/routing/domain_matcher/ahocorasick.go +++ /dev/null @@ -1,125 +0,0 @@ -/* - * SPDX-License-Identifier: AGPL-3.0-only - * Copyright (c) 2023, v2rayA Organization - */ - -package domain_matcher - -import ( - "fmt" - "github.com/cloudflare/ahocorasick" - "github.com/v2rayA/dae/common/consts" - "regexp" - "strings" -) - -type Ahocorasick struct { - validIndexes []int - validRegexpIndexes []int - matchers []*ahocorasick.Matcher - regexp [][]*regexp.Regexp - - toBuild [][][]byte - err error -} - -func NewAhocorasick(bitLength int) *Ahocorasick { - return &Ahocorasick{ - matchers: make([]*ahocorasick.Matcher, bitLength), - toBuild: make([][][]byte, bitLength), - regexp: make([][]*regexp.Regexp, bitLength), - } -} -func (n *Ahocorasick) AddSet(bitIndex int, patterns []string, typ consts.RoutingDomainKey) { - if n.err != nil { - return - } - switch typ { - case consts.RoutingDomainKey_Full: - for _, d := range patterns { - n.toBuild[bitIndex] = append(n.toBuild[bitIndex], []byte("^"+d+"$")) - } - case consts.RoutingDomainKey_Suffix: - for _, d := range patterns { - if strings.HasPrefix(d, ".") { - // abc.example.com - n.toBuild[bitIndex] = append(n.toBuild[bitIndex], []byte(d+"$")) - } else { - // xxx.example.com - n.toBuild[bitIndex] = append(n.toBuild[bitIndex], []byte("."+d+"$")) - // example.com - n.toBuild[bitIndex] = append(n.toBuild[bitIndex], []byte("^"+d+"$")) - } - } - case consts.RoutingDomainKey_Keyword: - for _, d := range patterns { - n.toBuild[bitIndex] = append(n.toBuild[bitIndex], []byte(d)) - } - case consts.RoutingDomainKey_Regex: - for _, d := range patterns { - r, err := regexp.Compile(d) - if err != nil { - n.err = fmt.Errorf("failed to compile regex: %v", d) - return - } - n.regexp[bitIndex] = append(n.regexp[bitIndex], r) - } - default: - n.err = fmt.Errorf("unknown RoutingDomainKey: %v", typ) - return - } -} -func (n *Ahocorasick) MatchDomainBitmap(domain string) (bitmap []uint32) { - N := len(n.matchers) / 32 - if len(n.matchers)%32 != 0 { - N++ - } - bitmap = make([]uint32, N) - // Domain should not contain ^ or $. - if strings.ContainsAny(domain, "^$") { - return bitmap - } - // Add magic chars as head and tail. - domain = "^" + strings.ToLower(strings.TrimSuffix(domain, ".")) + "$" - for _, i := range n.validIndexes { - if hits := n.matchers[i].MatchThreadSafe([]byte(domain)); len(hits) > 0 { - bitmap[i/32] |= 1 << (i % 32) - } - } - // Regex matching is independent. - for _, i := range n.validRegexpIndexes { - if bitmap[i/32]&(1<<(i%32)) > 0 { - // Already matched. - continue - } - for _, r := range n.regexp[i] { - if r.MatchString(domain) { - bitmap[i/32] |= 1 << (i % 32) - break - } - } - } - return bitmap -} -func (n *Ahocorasick) Build() error { - if n.err != nil { - return n.err - } - n.validIndexes = make([]int, 0, len(n.toBuild)/8) - for i, toBuild := range n.toBuild { - if len(toBuild) == 0 { - continue - } - n.matchers[i] = ahocorasick.NewMatcher(toBuild) - n.validIndexes = append(n.validIndexes, i) - } - for i := range n.regexp { - if len(n.regexp[i]) == 0 { - continue - } - n.validRegexpIndexes = append(n.validRegexpIndexes, i) - } - // Release it. - n.toBuild = nil - return nil -} diff --git a/component/routing/domain_matcher/ahocorasick_succinctset.go b/component/routing/domain_matcher/ahocorasick_succinctset.go new file mode 100644 index 0000000..05b8009 --- /dev/null +++ b/component/routing/domain_matcher/ahocorasick_succinctset.go @@ -0,0 +1,195 @@ +/* + * SPDX-License-Identifier: AGPL-3.0-only + * Copyright (c) 2023, v2rayA Organization + */ + +package domain_matcher + +import ( + "fmt" + "github.com/openacid/slim/encode" + "github.com/openacid/slim/trie" + "github.com/v2rayA/ahocorasick-domain" + "github.com/v2rayA/dae/common/consts" + "regexp" + "sort" + "strings" +) + +type AhocorasickSuccinctset struct { + validAcIndexes []int + validTrieIndexes []int + validRegexpIndexes []int + ac []*ahocorasick.Matcher + trie []*trie.SlimTrie + regexp [][]*regexp.Regexp + + toBuildAc [][][]byte + toBuildTrie [][]string + err error +} + +func NewAhocorasickSuccinctset(bitLength int) *AhocorasickSuccinctset { + return &AhocorasickSuccinctset{ + ac: make([]*ahocorasick.Matcher, bitLength), + trie: make([]*trie.SlimTrie, bitLength), + regexp: make([][]*regexp.Regexp, bitLength), + toBuildAc: make([][][]byte, bitLength), + toBuildTrie: make([][]string, bitLength), + } +} +func (n *AhocorasickSuccinctset) AddSet(bitIndex int, patterns []string, typ consts.RoutingDomainKey) { + if n.err != nil { + return + } + switch typ { + case consts.RoutingDomainKey_Full: + for _, d := range patterns { + n.toBuildTrie[bitIndex] = append(n.toBuildTrie[bitIndex], "^"+d+"$") + } + case consts.RoutingDomainKey_Suffix: + for _, d := range patterns { + if strings.HasPrefix(d, ".") { + // abc.example.com + n.toBuildTrie[bitIndex] = append(n.toBuildTrie[bitIndex], d+"$") + // cannot match example.com + } else { + // xxx.example.com + n.toBuildTrie[bitIndex] = append(n.toBuildTrie[bitIndex], "."+d+"$") + // example.com + n.toBuildTrie[bitIndex] = append(n.toBuildTrie[bitIndex], "^"+d+"$") + // cannot match abcexample.com + } + } + case consts.RoutingDomainKey_Keyword: + // Only use ac automaton for "keyword" matching to save memory. + for _, d := range patterns { + n.toBuildAc[bitIndex] = append(n.toBuildAc[bitIndex], []byte(d)) + } + case consts.RoutingDomainKey_Regex: + for _, d := range patterns { + r, err := regexp.Compile(d) + if err != nil { + n.err = fmt.Errorf("failed to compile regex: %v", d) + return + } + n.regexp[bitIndex] = append(n.regexp[bitIndex], r) + } + default: + n.err = fmt.Errorf("unknown RoutingDomainKey: %v", typ) + return + } +} +func (n *AhocorasickSuccinctset) MatchDomainBitmap(domain string) (bitmap []uint32) { + N := len(n.ac) / 32 + if len(n.ac)%32 != 0 { + N++ + } + bitmap = make([]uint32, N) + // Add magic chars as head and tail. + domain = "^" + strings.ToLower(strings.TrimSuffix(domain, ".")) + "$" + // Domain should consist of 'a'-'z' and '.' and '-' + for _, b := range []byte(domain) { + if !ahocorasick.IsValidChar(b) { + return bitmap + } + } + // Suffix matching. + suffixTrieDomain := ToSuffixTrieString(domain) + for _, i := range n.validTrieIndexes { + if bitmap[i/32]&(1<<(i%32)) > 0 { + // Already matched. + continue + } + if _, ok := n.trie[i].Get(suffixTrieDomain); ok { + bitmap[i/32] |= 1 << (i % 32) + } + } + // Keyword matching. + for _, i := range n.validAcIndexes { + if bitmap[i/32]&(1<<(i%32)) > 0 { + // Already matched. + continue + } + if hits := n.ac[i].MatchThreadSafe([]byte(domain)); len(hits) > 0 { + bitmap[i/32] |= 1 << (i % 32) + } + } + // Regex matching. + for _, i := range n.validRegexpIndexes { + if bitmap[i/32]&(1<<(i%32)) > 0 { + // Already matched. + continue + } + for _, r := range n.regexp[i] { + if r.MatchString(domain) { + bitmap[i/32] |= 1 << (i % 32) + break + } + } + } + return bitmap +} +func ToSuffixTrieString(s string) string { + // No need for end char "$". + b := []byte(strings.TrimSuffix(s, "$")) + // Reverse. + half := len(b) / 2 + for i := 0; i < half; i++ { + b[i], b[len(b)-i-1] = b[len(b)-i-1], b[i] + } + return string(b) +} +func ToSuffixTrieStrings(s []string) []string { + to := make([]string, len(s)) + for i := range s { + to[i] = ToSuffixTrieString(s[i]) + } + return to +} +func (n *AhocorasickSuccinctset) Build() (err error) { + if n.err != nil { + return n.err + } + n.validAcIndexes = make([]int, 0, len(n.toBuildAc)/8) + n.validTrieIndexes = make([]int, 0, len(n.toBuildAc)/8) + n.validRegexpIndexes = make([]int, 0, len(n.toBuildAc)/8) + // Build AC automaton. + for i, toBuild := range n.toBuildAc { + if len(toBuild) == 0 { + continue + } + n.ac[i], err = ahocorasick.NewMatcher(toBuild) + if err != nil { + return err + } + n.validAcIndexes = append(n.validAcIndexes, i) + } + + // Build succinct trie. + for i, toBuild := range n.toBuildTrie { + if len(toBuild) == 0 { + continue + } + toBuild = ToSuffixTrieStrings(toBuild) + sort.Strings(toBuild) + n.trie[i], err = trie.NewSlimTrie(encode.I8{}, toBuild, nil) + if err != nil { + return err + } + n.validTrieIndexes = append(n.validTrieIndexes, i) + } + + // Regexp. + for i := range n.regexp { + if len(n.regexp[i]) == 0 { + continue + } + n.validRegexpIndexes = append(n.validRegexpIndexes, i) + } + + // Release unused data. + n.toBuildAc = nil + n.toBuildTrie = nil + return nil +} diff --git a/component/routing/domain_matcher/benchmark_test.go b/component/routing/domain_matcher/benchmark_test.go index 969a9c5..786dd8f 100644 --- a/component/routing/domain_matcher/benchmark_test.go +++ b/component/routing/domain_matcher/benchmark_test.go @@ -195,14 +195,14 @@ func BenchmarkGoRegexpNfa(b *testing.B) { runBenchmark(b, nfa) } -func BenchmarkAhocorasick(b *testing.B) { +func BenchmarkAhocorasickSuccinctset(b *testing.B) { b.StopTimer() logrus.SetLevel(logrus.WarnLevel) simulatedDomainSet, err := getDomain() if err != nil { b.Fatal(err) } - ahocorasick := NewAhocorasick(consts.MaxMatchSetLen) + ahocorasick := NewAhocorasickSuccinctset(consts.MaxMatchSetLen) for _, domains := range simulatedDomainSet { ahocorasick.AddSet(domains.RuleIndex, domains.Domains, domains.Key) } diff --git a/control/routing_matcher_builder.go b/control/routing_matcher_builder.go index 81b99dd..1038311 100644 --- a/control/routing_matcher_builder.go +++ b/control/routing_matcher_builder.go @@ -279,7 +279,7 @@ func (b *RoutingMatcherBuilder) BuildUserspace() (matcher *RoutingMatcher, err e m.lpms[i] = lpm } // Build domainMatcher - m.domainMatcher = domain_matcher.NewAhocorasick(consts.MaxMatchSetLen) + m.domainMatcher = domain_matcher.NewAhocorasickSuccinctset(consts.MaxMatchSetLen) for _, domains := range b.simulatedDomainSet { m.domainMatcher.AddSet(domains.RuleIndex, domains.Domains, domains.Key) } diff --git a/go.mod b/go.mod index 2f9e94e..e1478c8 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,15 @@ require ( github.com/adrg/xdg v0.4.0 github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 github.com/cilium/ebpf v0.10.0 - github.com/cloudflare/ahocorasick v0.0.0-20210425175752-730270c3e184 github.com/gorilla/websocket v1.5.0 github.com/json-iterator/go v1.1.12 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/mzz2017/softwind v0.0.0-20230217170818-542cba31602f + github.com/openacid/slim v0.5.11 github.com/safchain/ethtool v0.0.0-20230116090318-67cc41908669 github.com/sirupsen/logrus v1.9.0 github.com/spf13/cobra v1.6.1 + github.com/v2rayA/ahocorasick-domain v0.0.0-20230218133743-71484cb9a7a1 github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230201041341-1758ee5161c1 github.com/vishvananda/netlink v1.1.0 github.com/x-cray/logrus-prefixed-formatter v0.5.2 @@ -25,6 +26,8 @@ require ( ) require ( + github.com/blang/semver v3.5.1+incompatible // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d // indirect github.com/dgryski/go-idea v0.0.0-20170306091226-d2fb45a411fb // indirect github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect @@ -41,6 +44,10 @@ require ( github.com/mzz2017/disk-bloom v1.0.1 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/gomega v1.26.0 // indirect + github.com/openacid/errors v0.8.1 // indirect + github.com/openacid/low v0.1.22-0.20210130164417-01334eb50af8 // indirect + github.com/openacid/must v0.1.3 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.1 // indirect @@ -51,10 +58,12 @@ require ( golang.org/x/text v0.6.0 // indirect google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect google.golang.org/grpc v1.52.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) -//replace github.com/mzz2017/softwind => /home/mzz/goProjects/softwind +//replace github.com/mzz2017/softwind => /home/mzz/goProjects/softwind +//replace github.com/cloudflare/ahocorasick => /home/mzz/goProjects/ahocorasick //replace github.com/cilium/ebpf => /home/mzz/goProjects/ebpf //replace github.com/v2rayA/RoutingA-dist/go/routingA => /home/mzz/antlrProjects/RoutingA-antlr4/build/go/routingA //replace github.com/v2rayA/dae-config-dist/go/dae_config => /home/mzz/antlrProjects/dae-config/build/go/dae_config diff --git a/go.sum b/go.sum index 782dd0e..c4fd7d4 100644 --- a/go.sum +++ b/go.sum @@ -4,10 +4,10 @@ github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 h1:npHgfD4Tl2WJS3AJaMUi5ynGDPUBfkg3U3fCzDyXZ+4= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/cilium/ebpf v0.10.0 h1:nk5HPMeoBXtOzbkZBWym+ZWq1GIiHUsBFXxwewXAHLQ= github.com/cilium/ebpf v0.10.0/go.mod h1:DPiVdY/kT534dgc9ERmvP8mWA+9gvwgKfRvk4nNWnoE= -github.com/cloudflare/ahocorasick v0.0.0-20210425175752-730270c3e184 h1:8yL+85JpbwrIc6m+7N1iYrjn/22z68jwrTIBOJHNe4k= -github.com/cloudflare/ahocorasick v0.0.0-20210425175752-730270c3e184/go.mod h1:tGWUZLZp9ajsxUOnHmFFLnqnlKXsCn6GReG4jAD59H0= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -29,6 +29,7 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -38,6 +39,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -53,12 +55,17 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mdempsky/unconvert v0.0.0-20200228143138-95ecdbfc0b5f/go.mod h1:AmCV4WB3cDMZqgPk+OUQKumliiQS4ZYsBt3AXekyuAU= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -83,6 +90,21 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/openacid/errors v0.8.1 h1:Hrj9WENDoj5jP27ZfF60SY5LShbxei+sxKZa0EP+oDw= +github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0= +github.com/openacid/genr v0.1.1/go.mod h1:2B9wMFQKBKZnmo8AR/3JCRGnHs85r4OzeNy0RStLTiU= +github.com/openacid/low v0.1.14/go.mod h1:flqvccAtSrKeD+b5AejKgxCQVhVrsNYEWU7NlkpNCI8= +github.com/openacid/low v0.1.22-0.20210130164417-01334eb50af8 h1:3+zXRzfjDtpyHusR04m0dILUGFMwjfYS8Ejs8O0Maf8= +github.com/openacid/low v0.1.22-0.20210130164417-01334eb50af8/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0= +github.com/openacid/must v0.1.3 h1:deanGZVyVwV+ozfwNFbRU5YF7czXeQ67s8GVyZxzKW4= +github.com/openacid/must v0.1.3/go.mod h1:luPiXCuJlEo3UUFQngVQokV0MPGryeYvtCbQPs3U1+I= +github.com/openacid/slim v0.5.11 h1:LIN8ktjSV5/0h9Wai9o30jpzQPPIYZmaRExmt9nGkPU= +github.com/openacid/slim v0.5.11/go.mod h1:ddlyrp5csrPL30DlLp/SjgP4bdgCnmaCmmv4my407VI= +github.com/openacid/tablewriter v0.0.0-20190429071406-b14f71081b86/go.mod h1:iJAvCLjVGFyZOV2Oh123q4PMcoBv2qQLEvjlVIM9E2E= +github.com/openacid/testkeys v0.1.6 h1:vuQZu/NM6nJo0OKUcaFNtm76Rnv3fMIIXrjp0gFX7FM= +github.com/openacid/testkeys v0.1.6/go.mod h1:MfA7cACzBpbiwekivj8StqX0WIRmqlMsci1c37CA3Do= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= @@ -109,6 +131,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/v2rayA/ahocorasick-domain v0.0.0-20230218133743-71484cb9a7a1 h1:9rmVkH/MsdM/NLLY9r7wqCP/zNbwTijGjwCyR88PbyA= +github.com/v2rayA/ahocorasick-domain v0.0.0-20230218133743-71484cb9a7a1/go.mod h1:mWch8I826zic/bKaCyE9ZZbWtFgEW0ox3EQ0NGm5DGw= github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230201041341-1758ee5161c1 h1:Ke91ZtZItOO8/SK8nhZ1tXfXcUxj4Meq5pET/L9bHII= github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230201041341-1758ee5161c1/go.mod h1:JiTWeZybOkBfCqv/fy5jbFhXTxuLlyrI76gRNazz2sU= github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= @@ -128,6 +152,7 @@ golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -159,11 +184,13 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -183,6 +210,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=