From 7b43ad4dec59494df43c73af583dadcd6a651ee2 Mon Sep 17 00:00:00 2001 From: luyuhuang Date: Sun, 20 Dec 2020 18:18:36 +0800 Subject: [PATCH] improve the rule file format --- README.md | 10 ++++++---- client/rules.go | 24 ++++++++++++++---------- client/rules_test.go | 38 +++++++++++++++++++++++++++++++++++++- subsocks.go | 2 +- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index f6e2075..8271009 100644 --- a/README.md +++ b/README.md @@ -205,15 +205,17 @@ The contents of `rules.txt` are as follows: ``` www.twitter.com P +8.8.8.8 +2001:db8::/32 + *.github.com D -8.8.8.8 P -1.0.1.0/24 D -2001:db8::/32 P +1.0.1.0/24 +# all others is automatic detection * A ``` -Each line is a rule. Address and rule are separated by several spaces. +Each line is a rule, except empty lines and comment lines(starting with `#`). Each line contains an address and an optional rule, separated by several spaces. If a line doesn't have a rule, it is the same as the previous line. ### Server configuration diff --git a/client/rules.go b/client/rules.go index 676962a..dacdaae 100644 --- a/client/rules.go +++ b/client/rules.go @@ -96,22 +96,26 @@ func NewRulesFromFile(path string) (*Rules, error) { } ln := 1 + var addr string + var rule int for s := bufio.NewScanner(f); s.Scan(); ln++ { line := strings.TrimSpace(s.Text()) if line == "" || line[0] == '#' { continue } - i := strings.IndexAny(line, " \t") - if i < 0 { - return nil, fmt.Errorf("Illegal rule in line %d", ln) - } - - addr := line[:i] - rules := strings.TrimSpace(line[i+1:]) - rule, ok := ruleString2Rule[rules] - if !ok { - return nil, fmt.Errorf("Rule in line %d got %s, want proxy|direct|auto|P|D|A", ln, rules) + if i := strings.IndexAny(line, " \t"); i < 0 { + if rule == ruleNone { + return nil, fmt.Errorf("Illegal rule in line %d", ln) + } + addr = line + } else { + addr = line[:i] + rules := strings.TrimSpace(line[i+1:]) + rule = ruleString2Rule[rules] + if rule == ruleNone { + return nil, fmt.Errorf("Rule in line %d got %s, want proxy|direct|auto|P|D|A", ln, rules) + } } if err := r.setRule(addr, rule); err != nil { diff --git a/client/rules_test.go b/client/rules_test.go index 363ab0f..c1f513b 100644 --- a/client/rules_test.go +++ b/client/rules_test.go @@ -217,7 +217,7 @@ func TestRulesIllegal(t *testing.T) { } func TestRulesFile(t *testing.T) { - path := t.TempDir() + "/" + "rules.txt" + path := fmt.Sprintf("%s%crule.txt", t.TempDir(), os.PathSeparator) f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0664) if err != nil { t.Fatalf("Create file %q failed %q", path, err) @@ -232,6 +232,8 @@ func TestRulesFile(t *testing.T) { f.WriteString(" \t# twitter\n") f.WriteString("twitter.com\t P\n") f.WriteString("facebook.com \tD\n") + f.WriteString("*.bing.com\n") + f.WriteString("*.apple.com \n") f.Close() rule, err := NewRulesFromFile(path) @@ -250,6 +252,9 @@ func TestRulesFile(t *testing.T) { {"raw.github.com", ruleDirect}, {"twitter.com", ruleProxy}, {"facebook.com", ruleDirect}, + {"bing.com", ruleDirect}, + {"cn.bing.com", ruleDirect}, + {"apple.com", ruleDirect}, } for _, c := range cases { @@ -259,6 +264,37 @@ func TestRulesFile(t *testing.T) { } } +func TestRulesFileIllegal(t *testing.T) { + path := fmt.Sprintf("%s%crule1.txt", t.TempDir(), os.PathSeparator) + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0664) + if err != nil { + t.Fatalf("Create file %q failed %q", path, err) + } + + f.WriteString("*.google.com \n") + f.WriteString("mail.google.com D\n") + f.Close() + + _, err = NewRulesFromFile(path) + if err == nil || !strings.Contains(err.Error(), "Illegal rule") { + t.Fatalf("Error %q does not contain 'Illegal rule'", err) + } + + path = fmt.Sprintf("%s%crule2.txt", t.TempDir(), os.PathSeparator) + f, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0664) + if err != nil { + t.Fatalf("Create file %q failed %q", path, err) + } + + f.WriteString("*.google.com x\n") + f.Close() + + _, err = NewRulesFromFile(path) + if err == nil || !strings.Contains(err.Error(), "want proxy|direct|auto|P|D|A") { + t.Fatalf("Error %q does not contain 'want proxy|direct|auto|P|D|A'", err) + } +} + func printIPTree(n *ipNode, k int) { fmt.Printf(strings.Repeat(" ", k)) if n == nil || len(n.bits) <= 0 { diff --git a/subsocks.go b/subsocks.go index f32efdd..1f1e25a 100644 --- a/subsocks.go +++ b/subsocks.go @@ -1,7 +1,7 @@ package main // Version of subsocks -const Version = "0.2.0" +const Version = "0.2.1" var needsTLS = map[string]bool{ "https": true,