Verified Commit 9dc0cb39 authored by onyinyang's avatar onyinyang 🔒
Browse files

Add more aggressive retry schedule for failed bridges

parent 5ef69d06
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ type TestCache struct {
	Entries map[string]*CacheEntry
	// entryTimeout determines how long a cache entry is valid for.
	entryTimeout      time.Duration
	errorEntryTimeout time.Duration
	l                 sync.Mutex
}

@@ -124,7 +125,12 @@ func (tc *TestCache) IsCached(bridgeLine string) *CacheEntry {
	now := time.Now().UTC()
	tc.l.Lock()
	for index, entry := range (*tc).Entries {
		if entry.Time.Before(now.Add(-(*tc).entryTimeout)) {
		// If the test returned an error, shorten the time it is cached
		// to errorEntryTimeout (default 1 hour) so it can be tested again
		// more quickly. This aims to prevent bridges that are temporarily
		// down due to unfortunate test timing from being marked as `gone`
		// by rdsys
		if entry.Error != "" && entry.Time.Before(now.Add(-(*tc).errorEntryTimeout)) || entry.Time.Before(now.Add(-(*tc).entryTimeout)) {
			log.Printf("Deleting cache entry: %s", index)
			delete((*tc).Entries, index)
		}
+26 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ func init() {
func NewCache() *TestCache {
	return &TestCache{
		Entries:           make(map[string]*CacheEntry),
		errorEntryTimeout: 1 * time.Hour,
		entryTimeout:      18 * time.Hour,
	}
}
@@ -57,6 +58,29 @@ func TestCacheFunctions(t *testing.T) {
	if e != nil {
		t.Errorf("Got non-nil cache entry for bogus bridge line.")
	}

	// A failed bridge should only be cached for 1 hour.
	failedBridgeLine := "obfs4 127.0.0.1:1 cert=foo iat-mode=0"
	cache.AddEntry(failedBridgeLine, nil, time.Now().UTC().Add(-(time.Second * 6000)))
	e = cache.IsCached(failedBridgeLine)
	if e == nil {
		t.Errorf("Could not retrieve existing element from cache.")
	}
	testError = fmt.Errorf("bridge is restarting at an unfortunate time")
	// Manipulate entry time to be less than 5 seconds before the 1 hour mark
	// so we can check it is cached and removed from the cache within a
	// reasonable amount of time
	cache.AddEntry(failedBridgeLine, testError, time.Now().UTC().Add(-(time.Second * 3595)))
	e = cache.IsCached(failedBridgeLine)
	if e.Error != testError.Error() {
		t.Errorf("Got test result %q but expected %q.", e.Error, testError)
	}
	time.Sleep(6 * time.Second)
	e = cache.IsCached(failedBridgeLine)
	if e != nil {
		t.Errorf("Cache is empty but marks bridge line as existing.")
	}

}

func TestCacheFracFunctional(t *testing.T) {
+3 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ func main() {
	var torBinary string
	var obfs4proxyBinary string
	var webtunnelBinary string
	var testTimeout, cacheTimeout int
	var testTimeout, cacheTimeout, errorCacheTimeout int
	var logFile string

	flag.StringVar(&addr, "addr", ":5000", "Address to listen on.")
@@ -134,6 +134,7 @@ func main() {
	flag.StringVar(&webtunnelBinary, "webtunnel", "./webtunnel", "Path to obfs4proxy executable.")
	flag.StringVar(&logFile, "log", "", "File to write logs to.")
	flag.IntVar(&testTimeout, "test-timeout", 60, "Test timeout in seconds.")
	flag.IntVar(&errorCacheTimeout, "error-cache-timeout", 1, "Test timeout in hours for tests that have errored.")
	flag.IntVar(&cacheTimeout, "cache-timeout", 18, "Cache timeout in hours.")
	flag.Parse()

@@ -188,6 +189,7 @@ func main() {
		log.Printf("Could not read cache: %s", err)
	}
	cache.entryTimeout = time.Duration(cacheTimeout) * time.Hour
	cache.errorEntryTimeout = time.Duration(errorCacheTimeout) * time.Hour
	log.Printf("Set cache timeout to %s.", cache.entryTimeout)
	if printCache {
		printPrettyCache()