ソースを参照

Implement OSL pave offset

Enables paving starting at an offset after epoch,
which may be used to reduce the size of OSL registry
downloads and empty OSL uploads.
Rod Hynes 5 年 前
コミット
4cc7f30a6c

+ 10 - 0
psiphon/common/osl/osl.go

@@ -786,6 +786,9 @@ type PaveLogInfo struct {
 // separated. Otherwise the OSL will still be issued, but be empty (unless
 // the scheme is in omitEmptyOSLsSchemes).
 //
+// If startTime is specified and is after epoch, the pave file will contain
+// OSLs for the first period at or after startTime.
+//
 // As OSLs outside the epoch-endTime range will no longer appear in
 // the registry, Pave is intended to be used to create the full set
 // of OSLs for a distribution site; i.e., not incrementally.
@@ -793,6 +796,7 @@ type PaveLogInfo struct {
 // Automation is responsible for consistently distributing server entries
 // to OSLs in the case where OSLs are repaved in subsequent calls.
 func (config *Config) Pave(
+	startTime time.Time,
 	endTime time.Time,
 	propagationChannelID string,
 	signingPublicKey string,
@@ -820,6 +824,12 @@ func (config *Config) Pave(
 
 			oslTime := scheme.epoch
 
+			if !startTime.IsZero() && !startTime.Before(scheme.epoch) {
+				for oslTime.Before(startTime) {
+					oslTime = oslTime.Add(oslDuration)
+				}
+			}
+
 			for !oslTime.After(endTime) {
 
 				firstSLOKTime := oslTime

+ 43 - 2
psiphon/common/osl/osl_test.go

@@ -363,6 +363,21 @@ func TestOSL(t *testing.T) {
 			omitEmptyOSLsSchemes := []int{}
 
 			firstPaveFiles, err := config.Pave(
+				time.Time{},
+				endTime,
+				propagationChannelID,
+				signingPublicKey,
+				signingPrivateKey,
+				paveServerEntries,
+				omitMD5SumsSchemes,
+				omitEmptyOSLsSchemes,
+				nil)
+			if err != nil {
+				t.Fatalf("Pave failed: %s", err)
+			}
+
+			offsetPaveFiles, err := config.Pave(
+				epoch.Add(500*seedPeriod+seedPeriod/2),
 				endTime,
 				propagationChannelID,
 				signingPublicKey,
@@ -376,6 +391,7 @@ func TestOSL(t *testing.T) {
 			}
 
 			paveFiles, err := config.Pave(
+				time.Time{},
 				endTime,
 				propagationChannelID,
 				signingPublicKey,
@@ -399,10 +415,35 @@ func TestOSL(t *testing.T) {
 
 			for index, paveFile := range paveFiles {
 				if paveFile.Name != firstPaveFiles[index].Name {
-					t.Fatalf("Pave name mismatch")
+					t.Fatalf("pave name mismatch")
 				}
 				if !bytes.Equal(paveFile.Contents, firstPaveFiles[index].Contents) {
-					t.Fatalf("Pave content mismatch")
+					t.Fatalf("pave content mismatch")
+				}
+			}
+
+			// Check that the output of a pave using an unaligned offset from epoch
+			// produces a subset of OSLs with the same IDs and content: the OSL and
+			// SLOK time slots must align.
+
+			if len(offsetPaveFiles) >= len(paveFiles) {
+				t.Fatalf("unexpected pave size")
+			}
+
+			for _, offsetPaveFile := range offsetPaveFiles {
+				found := false
+				for _, paveFile := range paveFiles {
+					if offsetPaveFile.Name == paveFile.Name {
+						if offsetPaveFile.Name != GetOSLRegistryURL("") &&
+							!bytes.Equal(offsetPaveFile.Contents, paveFile.Contents) {
+							t.Fatalf("pave content mismatch")
+						}
+						found = true
+						break
+					}
+				}
+				if !found {
+					t.Fatalf("pave name missing")
 				}
 			}
 

+ 1 - 0
psiphon/common/osl/paver/main.go

@@ -213,6 +213,7 @@ func main() {
 	for propagationChannelID := range allPropagationChannelIDs {
 
 		paveFiles, err := config.Pave(
+			startTime,
 			endTime,
 			propagationChannelID,
 			signingPublicKey,