Skip to content

Commit

Permalink
Merge pull request #189 from fortuna/master
Browse files Browse the repository at this point in the history
Initialize saltfilter on demand
  • Loading branch information
riobard authored Oct 2, 2020
2 parents ea350a6 + 15e3c6b commit 75d4327
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 46 deletions.
6 changes: 6 additions & 0 deletions internal/bloomring.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ func NewBloomRing(slot, capacity int, falsePositiveRate float64) *BloomRing {
}

func (r *BloomRing) Add(b []byte) {
if r == nil {
return
}
r.mutex.Lock()
defer r.mutex.Unlock()
slot := r.slots[r.slotPosition]
Expand All @@ -56,6 +59,9 @@ func (r *BloomRing) Add(b []byte) {
}

func (r *BloomRing) Test(b []byte) bool {
if r == nil {
return false
}
r.mutex.RLock()
defer r.mutex.RUnlock()
for _, s := range r.slots {
Expand Down
17 changes: 17 additions & 0 deletions internal/bloomring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ func TestBloomRing_Add(t *testing.T) {
bloomRingInstance.Add(make([]byte, 16))
}

func TestBloomRing_NilAdd(t *testing.T) {
defer func() {
if any := recover(); any != nil {
t.Fatalf("Should not got panic while adding item: %v", any)
}
}()
var nilRing *internal.BloomRing
nilRing.Add(make([]byte, 16))
}

func TestBloomRing_Test(t *testing.T) {
buf := []byte("shadowsocks")
bloomRingInstance.Add(buf)
Expand All @@ -35,6 +45,13 @@ func TestBloomRing_Test(t *testing.T) {
}
}

func TestBloomRing_NilTestIsFalse(t *testing.T) {
var nilRing *internal.BloomRing
if nilRing.Test([]byte("shadowsocks")) {
t.Fatal("Test should return false for nil BloomRing")
}
}

func BenchmarkBloomRing(b *testing.B) {
// Generate test samples with different length
samples := make([][]byte, internal.DefaultSFCapacity-internal.DefaultSFSlot)
Expand Down
93 changes: 47 additions & 46 deletions internal/saltfilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"strconv"
"sync"
)

// Those suggest value are all set according to
Expand All @@ -21,60 +22,60 @@ const EnvironmentPrefix = "SHADOWSOCKS_"
// A shared instance used for checking salt repeat
var saltfilter *BloomRing

func init() {
var (
finalCapacity = DefaultSFCapacity
finalFPR = DefaultSFFPR
finalSlot = float64(DefaultSFSlot)
)
for _, opt := range []struct {
ENVName string
Target *float64
}{
{
ENVName: "CAPACITY",
Target: &finalCapacity,
},
{
ENVName: "FPR",
Target: &finalFPR,
},
{
ENVName: "SLOT",
Target: &finalSlot,
},
} {
envKey := EnvironmentPrefix + "SF_" + opt.ENVName
env := os.Getenv(envKey)
if env != "" {
p, err := strconv.ParseFloat(env, 64)
if err != nil {
panic(fmt.Sprintf("Invalid envrionment `%s` setting in saltfilter: %s", envKey, env))
// Used to initialize the saltfilter singleton only once.
var initSaltfilterOnce sync.Once

// GetSaltFilterSingleton returns the BloomRing singleton,
// initializing it on first call.
func getSaltFilterSingleton() *BloomRing {
initSaltfilterOnce.Do(func() {
var (
finalCapacity = DefaultSFCapacity
finalFPR = DefaultSFFPR
finalSlot = float64(DefaultSFSlot)
)
for _, opt := range []struct {
ENVName string
Target *float64
}{
{
ENVName: "CAPACITY",
Target: &finalCapacity,
},
{
ENVName: "FPR",
Target: &finalFPR,
},
{
ENVName: "SLOT",
Target: &finalSlot,
},
} {
envKey := EnvironmentPrefix + "SF_" + opt.ENVName
env := os.Getenv(envKey)
if env != "" {
p, err := strconv.ParseFloat(env, 64)
if err != nil {
panic(fmt.Sprintf("Invalid envrionment `%s` setting in saltfilter: %s", envKey, env))
}
*opt.Target = p
}
*opt.Target = p
}
}
// Support disable saltfilter by given a negative capacity
if finalCapacity <= 0 {
return
}
saltfilter = NewBloomRing(int(finalSlot), int(finalCapacity), finalFPR)
// Support disable saltfilter by given a negative capacity
if finalCapacity <= 0 {
return
}
saltfilter = NewBloomRing(int(finalSlot), int(finalCapacity), finalFPR)
})
return saltfilter
}

// TestSalt returns true if salt is repeated
func TestSalt(b []byte) bool {
// If nil means feature disabled, return false to bypass salt repeat detection
if saltfilter == nil {
return false
}
return saltfilter.Test(b)
return getSaltFilterSingleton().Test(b)
}

// AddSalt salt to filter
func AddSalt(b []byte) {
// If nil means feature disabled
if saltfilter == nil {
return
}
saltfilter.Add(b)
getSaltFilterSingleton().Add(b)
}

0 comments on commit 75d4327

Please sign in to comment.