mirror of
https://github.com/bolucat/Archive.git
synced 2025-10-06 00:27:31 +08:00
86 lines
1.9 KiB
Go
86 lines
1.9 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"sync"
|
|
)
|
|
|
|
// Those suggest value are all set according to
|
|
// https://github.com/shadowsocks/shadowsocks-org/issues/44#issuecomment-281021054
|
|
// Due to this package contains various internal implementation so const named with DefaultBR prefix
|
|
const (
|
|
DefaultSFCapacity = 1e6
|
|
// FalsePositiveRate
|
|
DefaultSFFPR = 1e-6
|
|
DefaultSFSlot = 10
|
|
)
|
|
|
|
const EnvironmentPrefix = "SHADOWSOCKS_"
|
|
|
|
// A shared instance used for checking salt repeat
|
|
var saltfilter *BloomRing
|
|
|
|
// 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
|
|
}
|
|
}
|
|
// 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 {
|
|
return getSaltFilterSingleton().Test(b)
|
|
}
|
|
|
|
// AddSalt salt to filter
|
|
func AddSalt(b []byte) {
|
|
getSaltFilterSingleton().Add(b)
|
|
}
|
|
|
|
func CheckSalt(b []byte) bool {
|
|
return getSaltFilterSingleton().Test(b)
|
|
}
|