Fix many lint warnings found by gometalinter

This commit is contained in:
Eugene Bujak
2018-09-14 16:50:56 +03:00
parent 548010e002
commit 076c9de68e
11 changed files with 359 additions and 241 deletions

View File

@@ -31,7 +31,10 @@ const defaultSafebrowsingURL = "http://%s/safebrowsing-lookup-hash.html?prefixes
const defaultParentalServer = "pctrl.adguard.com"
const defaultParentalURL = "http://%s/check-parental-control-hash?prefixes=%s&sensitivity=%d"
// ErrInvalidSyntax is returned by AddRule when rule is invalid
var ErrInvalidSyntax = errors.New("dnsfilter: invalid rule syntax")
// ErrInvalidParental is returned by EnableParental when sensitivity is not a valid value
var ErrInvalidParental = errors.New("dnsfilter: invalid parental sensitivity, must be either 3, 10, 13 or 17")
const shortcutLength = 6 // used for rule search optimization, 6 hits the sweet spot
@@ -39,16 +42,16 @@ const shortcutLength = 6 // used for rule search optimization, 6 hits the sweet
const enableFastLookup = true // flag for debugging, must be true in production for faster performance
const enableDelayedCompilation = true // flag for debugging, must be true in production for faster performance
type Config struct {
type config struct {
parentalServer string
parentalSensitivity int // must be either 3, 10, 13 or 17
parentalEnabled bool
safeSearchEnabled bool
safeBrowsingEnabled bool
safeBrowsingServer string
parentalEnabled bool
parentalServer string
parentalSensitivity int // must be either 3, 10, 13 or 17
}
type Rule struct {
type rule struct {
text string // text without @@ decorators or $ options
shortcut string // for speeding up lookup
originalText string // original text for reporting back to applications
@@ -57,9 +60,9 @@ type Rule struct {
options []string // optional options after $
// parsed options
apps []string
isWhitelist bool
isImportant bool
apps []string
// user-supplied data
listID uint32
@@ -70,6 +73,7 @@ type Rule struct {
sync.RWMutex
}
// LookupStats store stats collected during safebrowsing or parental checks
type LookupStats struct {
Requests uint64 // number of HTTP requests that were sent
CacheHits uint64 // number of lookups that didn't need HTTP requests
@@ -77,6 +81,7 @@ type LookupStats struct {
PendingMax int64 // maximum number of pending HTTP requests
}
// Stats store LookupStats for both safebrowsing and parental
type Stats struct {
Safebrowsing LookupStats
Parental LookupStats
@@ -84,7 +89,7 @@ type Stats struct {
// Dnsfilter holds added rules and performs hostname matches against the rules
type Dnsfilter struct {
storage map[string]*Rule // rule storage, not used for matching, needs to be key->value
storage map[string]*rule // rule storage, not used for matching, needs to be key->value
storageMutex sync.RWMutex
// rules are checked against these lists in the order defined here
@@ -96,12 +101,12 @@ type Dnsfilter struct {
client http.Client // handle for http client -- single instance as recommended by docs
transport *http.Transport // handle for http transport used by http client
config Config
config config
}
//go:generate stringer -type=Reason
// filtered/notfiltered reason
// Reason holds an enum detailing why it was filtered or not filtered
type Reason int
const (
@@ -125,13 +130,14 @@ var (
parentalCache = gcache.New(defaultCacheSize).LRU().Expiration(defaultCacheTime).Build()
)
// search result
// Result holds state of hostname check
type Result struct {
IsFiltered bool
Reason Reason
Rule string
}
// Matched can be used to see if any match at all was found, no matter filtered or not
func (r Reason) Matched() bool {
return r != NotFilteredNotFound
}
@@ -188,19 +194,19 @@ func (d *Dnsfilter) CheckHost(host string) (Result, error) {
//
type rulesTable struct {
rulesByShortcut map[string][]*Rule
rulesLeftovers []*Rule
rulesByShortcut map[string][]*rule
rulesLeftovers []*rule
sync.RWMutex
}
func newRulesTable() *rulesTable {
return &rulesTable{
rulesByShortcut: make(map[string][]*Rule),
rulesLeftovers: make([]*Rule, 0),
rulesByShortcut: make(map[string][]*rule),
rulesLeftovers: make([]*rule, 0),
}
}
func (r *rulesTable) Add(rule *Rule) {
func (r *rulesTable) Add(rule *rule) {
r.Lock()
if len(rule.shortcut) == shortcutLength && enableFastLookup {
r.rulesByShortcut[rule.shortcut] = append(r.rulesByShortcut[rule.shortcut], rule)
@@ -295,7 +301,7 @@ func findOptionIndex(text string) int {
return -1
}
func (rule *Rule) extractOptions() error {
func (rule *rule) extractOptions() error {
optIndex := findOptionIndex(rule.text)
if optIndex == 0 { // starts with $
return ErrInvalidSyntax
@@ -333,7 +339,7 @@ func (rule *Rule) extractOptions() error {
return nil
}
func (rule *Rule) parseOptions() error {
func (rule *rule) parseOptions() error {
err := rule.extractOptions()
if err != nil {
return err
@@ -354,7 +360,7 @@ func (rule *Rule) parseOptions() error {
return nil
}
func (rule *Rule) extractShortcut() {
func (rule *rule) extractShortcut() {
// regex rules have no shortcuts
if rule.text[0] == '/' && rule.text[len(rule.text)-1] == '/' {
return
@@ -379,7 +385,7 @@ func (rule *Rule) extractShortcut() {
rule.shortcut = strings.ToLower(longestField)
}
func (rule *Rule) compile() error {
func (rule *rule) compile() error {
rule.RLock()
isCompiled := rule.compiled != nil
rule.RUnlock()
@@ -404,7 +410,7 @@ func (rule *Rule) compile() error {
return nil
}
func (rule *Rule) match(host string) (Result, error) {
func (rule *rule) match(host string) (Result, error) {
res := Result{}
err := rule.compile()
if err != nil {
@@ -442,7 +448,7 @@ func getCachedReason(cache gcache.Cache, host string) (result Result, isFound bo
// since it can be something else, validate that it belongs to proper type
cachedValue, ok := rawValue.(Result)
if ok == false {
if !ok {
// this is not our type -- error
text := "SHOULD NOT HAPPEN: entry with invalid type was found in lookup cache"
log.Println(text)
@@ -458,7 +464,7 @@ func hostnameToHashParam(host string, addslash bool) (string, map[string]bool) {
var hashparam bytes.Buffer
hashes := map[string]bool{}
tld, icann := publicsuffix.PublicSuffix(host)
if icann == false {
if !icann {
// private suffixes like cloudfront.net
tld = ""
}
@@ -612,7 +618,10 @@ func (d *Dnsfilter) lookupCommon(host string, lookupstats *LookupStats, cache gc
switch {
case resp.StatusCode == 204:
// empty result, save cache
cache.Set(host, Result{})
err = cache.Set(host, Result{})
if err != nil {
return Result{}, err
}
return Result{}, nil
case resp.StatusCode != 200:
// error, don't save cache
@@ -625,7 +634,10 @@ func (d *Dnsfilter) lookupCommon(host string, lookupstats *LookupStats, cache gc
return Result{}, err
}
cache.Set(host, result)
err = cache.Set(host, result)
if err != nil {
return Result{}, err
}
return result, nil
}
@@ -648,7 +660,7 @@ func (d *Dnsfilter) AddRule(input string, filterListID uint32) error {
return ErrInvalidSyntax
}
rule := Rule{
rule := rule{
text: input, // will be modified
originalText: input,
listID: filterListID,
@@ -712,10 +724,11 @@ func (d *Dnsfilter) matchHost(host string) (Result, error) {
// lifecycle helper functions
//
// New creates properly initialized DNS Filter that is ready to be used
func New() *Dnsfilter {
d := new(Dnsfilter)
d.storage = make(map[string]*Rule)
d.storage = make(map[string]*rule)
d.important = newRulesTable()
d.whiteList = newRulesTable()
d.blackList = newRulesTable()
@@ -739,6 +752,8 @@ func New() *Dnsfilter {
return d
}
// Destroy is optional if you want to tidy up goroutines without waiting for them to die off
// right now it closes idle HTTP connections if there are any
func (d *Dnsfilter) Destroy() {
d.transport.CloseIdleConnections()
}
@@ -747,10 +762,12 @@ func (d *Dnsfilter) Destroy() {
// config manipulation helpers
//
// EnableSafeBrowsing turns on checking hostnames in malware/phishing database
func (d *Dnsfilter) EnableSafeBrowsing() {
d.config.safeBrowsingEnabled = true
}
// EnableParental turns on checking hostnames for containing adult content
func (d *Dnsfilter) EnableParental(sensitivity int) error {
switch sensitivity {
case 3, 10, 13, 17:
@@ -762,10 +779,13 @@ func (d *Dnsfilter) EnableParental(sensitivity int) error {
}
}
// EnableSafeSearch turns on enforcing safesearch in search engines
// only used in coredns plugin and requires caller to use SafeSearchDomain()
func (d *Dnsfilter) EnableSafeSearch() {
d.config.safeSearchEnabled = true
}
// SetSafeBrowsingServer lets you optionally change hostname of safesearch lookup
func (d *Dnsfilter) SetSafeBrowsingServer(host string) {
if len(host) == 0 {
d.config.safeBrowsingServer = defaultSafebrowsingServer
@@ -774,38 +794,35 @@ func (d *Dnsfilter) SetSafeBrowsingServer(host string) {
}
}
// SetHTTPTimeout lets you optionally change timeout during lookups
func (d *Dnsfilter) SetHTTPTimeout(t time.Duration) {
d.client.Timeout = t
}
// ResetHTTPTimeout resets lookup timeouts
func (d *Dnsfilter) ResetHTTPTimeout() {
d.client.Timeout = defaultHTTPTimeout
}
// SafeSearchDomain returns replacement address for search engine
func (d *Dnsfilter) SafeSearchDomain(host string) (string, bool) {
if d.config.safeSearchEnabled == false {
return "", false
if d.config.safeSearchEnabled {
val, ok := safeSearchDomains[host]
return val, ok
}
val, ok := safeSearchDomains[host]
return val, ok
return "", false
}
//
// stats
//
// GetStats return dns filtering stats since startup
func (d *Dnsfilter) GetStats() Stats {
return stats
}
// Count returns number of rules added to filter
func (d *Dnsfilter) Count() int {
return len(d.storage)
}
//
// cache control, right now needed only for tests
//
func purgeCaches() {
safebrowsingCache.Purge()
parentalCache.Purge()
}

View File

@@ -3,6 +3,8 @@ package dnsfilter
import (
"net/http"
"net/http/httptest"
"path"
"strings"
"testing"
"time"
@@ -217,12 +219,6 @@ func TestAddRuleFail(t *testing.T) {
d.checkAddRuleFail(t, "lkfaojewhoawehfwacoefawr$@#$@3413841384")
}
func printMemStats(r runtime.MemStats) {
fmt.Printf("Alloc: %.2f, HeapAlloc: %.2f Mb, Sys: %.2f Mb, HeapSys: %.2f Mb\n",
float64(r.Alloc)/1024.0/1024.0, float64(r.HeapAlloc)/1024.0/1024.0,
float64(r.Sys)/1024.0/1024.0, float64(r.HeapSys)/1024.0/1024.0)
}
func TestLotsOfRulesMemoryUsage(t *testing.T) {
var start, afterLoad, end runtime.MemStats
runtime.GC()
@@ -251,10 +247,10 @@ func TestLotsOfRulesMemoryUsage(t *testing.T) {
if err != nil {
t.Errorf("Error while matching host %s: %s", testcase.host, err)
}
if ret.IsFiltered == false && ret.IsFiltered != testcase.match {
if !ret.IsFiltered && ret.IsFiltered != testcase.match {
t.Errorf("Expected hostname %s to not match", testcase.host)
}
if ret.IsFiltered == true && ret.IsFiltered != testcase.match {
if ret.IsFiltered && ret.IsFiltered != testcase.match {
t.Errorf("Expected hostname %s to match", testcase.host)
}
}
@@ -642,3 +638,32 @@ func BenchmarkSafeSearchParallel(b *testing.B) {
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
//
// helper functions for debugging and testing
//
func purgeCaches() {
safebrowsingCache.Purge()
parentalCache.Purge()
}
func _Func() string {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return path.Base(f.Name())
}
func trace(format string, args ...interface{}) {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
var buf strings.Builder
buf.WriteString(fmt.Sprintf("%s(): ", path.Base(f.Name())))
text := fmt.Sprintf(format, args...)
buf.WriteString(text)
if len(text) == 0 || text[len(text)-1] != '\n' {
buf.WriteRune('\n')
}
fmt.Print(buf.String())
}

View File

@@ -1,9 +1,6 @@
package dnsfilter
import (
"fmt"
"path"
"runtime"
"strings"
"sync/atomic"
)
@@ -49,33 +46,9 @@ func updateMax(valuePtr *int64, maxPtr *int64) {
break
}
swapped := atomic.CompareAndSwapInt64(maxPtr, max, current)
if swapped == true {
if swapped {
break
}
// swapping failed because value has changed after reading, try again
}
}
//
// helper functions for debugging and testing
//
func _Func() string {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return path.Base(f.Name())
}
func trace(format string, args ...interface{}) {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
var buf strings.Builder
buf.WriteString(fmt.Sprintf("%s(): ", path.Base(f.Name())))
text := fmt.Sprintf(format, args...)
buf.WriteString(text)
if len(text) == 0 || text[len(text)-1] != '\n' {
buf.WriteRune('\n')
}
fmt.Print(buf.String())
}