Skip to content

Commit

Permalink
Improve parsing with caching and dns caching
Browse files Browse the repository at this point in the history
  • Loading branch information
NHAS committed Jan 8, 2024
1 parent bf091b9 commit df76e72
Showing 1 changed file with 66 additions and 2 deletions.
68 changes: 66 additions & 2 deletions internal/routetypes/parser.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package routetypes

import (
"crypto/sha1"
"encoding/hex"
"errors"
"fmt"
"net"
"sort"
"strconv"
"strings"
"sync"
"time"
)

const (
Expand All @@ -24,12 +29,43 @@ type Rule struct {
Values []Policy
}

var (
rwLock sync.RWMutex
globalCache = map[string][]Rule{}
)

func hash(mfa, public, deny []string) string {

sort.Strings(mfa)
sort.Strings(public)
sort.Strings(deny)

sha1.New()
sha1.Sum([]byte(strings.Join(mfa, "")))
sha1.Sum([]byte(strings.Join(public, "")))
output := sha1.Sum([]byte(strings.Join(deny, "")))

return hex.EncodeToString(output[:])
}

func ParseRules(mfa, public, deny []string) (result []Rule, err error) {

cache := map[string]int{}

parseKey := hash(mfa, public, deny)

rwLock.RLock()
if entry, ok := globalCache[parseKey]; ok {
rwLock.RUnlock()
return entry, nil

}
rwLock.RUnlock()

// Add

for _, rule := range mfa {

r, err := parseRule(0, rule)
if err != nil {
return nil, err
Expand All @@ -45,6 +81,7 @@ func ParseRules(mfa, public, deny []string) (result []Rule, err error) {
result = append(result, r)
cache[r.Keys[i].String()] = len(result) - 1
}

}

for _, rule := range public {
Expand All @@ -63,6 +100,7 @@ func ParseRules(mfa, public, deny []string) (result []Rule, err error) {
result = append(result, r)
cache[r.Keys[i].String()] = len(result) - 1
}

}

for _, rule := range deny {
Expand All @@ -81,6 +119,7 @@ func ParseRules(mfa, public, deny []string) (result []Rule, err error) {
result = append(result, r)
cache[r.Keys[i].String()] = len(result) - 1
}

}

for i := range result {
Expand All @@ -96,6 +135,9 @@ func ParseRules(mfa, public, deny []string) (result []Rule, err error) {
result[i].Values = temp[:cap(temp)]
}

rwLock.Lock()
globalCache[parseKey] = result
rwLock.Unlock()
return
}

Expand Down Expand Up @@ -169,15 +211,16 @@ func parseRule(restrictionType PolicyType, rule string) (rules Rule, err error)
}

func parseKeys(address string) (keys []Key, err error) {
resultingAddresses, err := parseAddress(address)
var resultingAddresses []net.IPNet

resultingAddresses, err = parseAddress(address)
if err != nil {
return nil, err
}

for _, ip := range resultingAddresses {

maskLength, _ := ip.Mask.Size()

keys = append(keys,
Key{
Prefixlen: uint32(maskLength),
Expand Down Expand Up @@ -301,6 +344,16 @@ func parseSinglePort(port, proto string) (Policy, error) {
return Policy{}, errors.New("unknown service: " + port + "/" + proto)
}

type cacheEntry struct {
dnsTime time.Time
addresses []net.IPNet
}

var (
dnsLock sync.RWMutex
dnsCache = map[string]cacheEntry{}
)

func parseAddress(address string) (resultAddresses []net.IPNet, err error) {

ip := net.ParseIP(address)
Expand All @@ -309,6 +362,13 @@ func parseAddress(address string) (resultAddresses []net.IPNet, err error) {
_, cidr, err := net.ParseCIDR(address)
if err != nil {

dnsLock.RLock()
if entries, ok := dnsCache[address]; ok && time.Now().Before(entries.dnsTime.Add(3*time.Second)) {
dnsLock.RUnlock()
return entries.addresses, nil
}
dnsLock.RUnlock()

//If we suspect this is a domain
addresses, err := net.LookupIP(address)
if err != nil {
Expand All @@ -331,6 +391,10 @@ func parseAddress(address string) (resultAddresses []net.IPNet, err error) {
return nil, fmt.Errorf("no addresses for domain %s were added, potentially because they were all ipv6 which is unsupported", address)
}

dnsLock.Lock()
dnsCache[address] = cacheEntry{dnsTime: time.Now(), addresses: resultAddresses}
dnsLock.Unlock()

return resultAddresses, nil
}

Expand Down

0 comments on commit df76e72

Please sign in to comment.