This is an automated email from the git hooks/post-receive script.
shelikhoo pushed a commit to branch main in repository pluggable-transports/snowflake.
commit 38f0e00e5d576bbb6ee78cc14ba07003c40d6091 Author: Shelikhoo xiaokangwang@outlook.com AuthorDate: Wed Mar 30 16:42:59 2022 +0100
Add Domain Name Matcher
Design difference from original vision: Skipped FQDN step to make it more generalized https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowf... --- common/namematcher/matcher.go | 26 ++++++++++++++++++ common/namematcher/matcher_test.go | 55 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+)
diff --git a/common/namematcher/matcher.go b/common/namematcher/matcher.go new file mode 100644 index 0000000..57f9c56 --- /dev/null +++ b/common/namematcher/matcher.go @@ -0,0 +1,26 @@ +package namematcher + +import "strings" + +func NewNameMatcher(rule string) NameMatcher { + return NameMatcher{suffix: strings.TrimPrefix(rule, "^"), exact: strings.HasPrefix(rule, "^")} +} + +type NameMatcher struct { + exact bool + suffix string +} + +func (m *NameMatcher) IsSupersetOf(matcher NameMatcher) bool { + if m.exact { + return matcher.exact && m.suffix == matcher.suffix + } + return strings.HasSuffix(matcher.suffix, m.suffix) +} + +func (m *NameMatcher) IsMember(s string) bool { + if m.exact { + return s == m.suffix + } + return strings.HasSuffix(s, m.suffix) +} diff --git a/common/namematcher/matcher_test.go b/common/namematcher/matcher_test.go new file mode 100644 index 0000000..8d92614 --- /dev/null +++ b/common/namematcher/matcher_test.go @@ -0,0 +1,55 @@ +package namematcher + +import "testing" + +import . "github.com/smartystreets/goconvey/convey" + +func TestMatchMember(t *testing.T) { + testingVector := []struct { + matcher string + target string + expects bool + }{ + {matcher: "", target: "", expects: true}, + {matcher: "^snowflake.torproject.net", target: "snowflake.torproject.net", expects: true}, + {matcher: "^snowflake.torproject.net", target: "faketorproject.net", expects: false}, + {matcher: "snowflake.torproject.net", target: "faketorproject.net", expects: false}, + {matcher: "snowflake.torproject.net", target: "snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "imaginary-01-snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "imaginary-aaa-snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "imaginary-aaa-snowflake.faketorproject.net", expects: false}, + } + for _, v := range testingVector { + t.Run(v.matcher+"<>"+v.target, func(t *testing.T) { + Convey("test", t, func() { + matcher := NewNameMatcher(v.matcher) + So(matcher.IsMember(v.target), ShouldEqual, v.expects) + }) + }) + } +} + +func TestMatchSubset(t *testing.T) { + testingVector := []struct { + matcher string + target string + expects bool + }{ + {matcher: "", target: "", expects: true}, + {matcher: "^snowflake.torproject.net", target: "^snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "^snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "testing-snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "^testing-snowflake.torproject.net", expects: true}, + {matcher: "snowflake.torproject.net", target: "", expects: false}, + } + for _, v := range testingVector { + t.Run(v.matcher+"<>"+v.target, func(t *testing.T) { + Convey("test", t, func() { + matcher := NewNameMatcher(v.matcher) + target := NewNameMatcher(v.target) + So(matcher.IsSupersetOf(target), ShouldEqual, v.expects) + }) + }) + } +}