Brad Fitzpatrick 11 лет назад
Родитель
Сommit
825606855b
2 измененных файлов с 44 добавлено и 4 удалено
  1. 15 3
      hpack/hpack.go
  2. 29 1
      hpack/hpack_test.go

+ 15 - 3
hpack/hpack.go

@@ -66,8 +66,8 @@ type dynamicTable struct {
 }
 }
 
 
 func (dt *dynamicTable) setMaxSize(v uint32) {
 func (dt *dynamicTable) setMaxSize(v uint32) {
-	// TODO: evictions
 	dt.maxSize = v
 	dt.maxSize = v
+	dt.evict()
 }
 }
 
 
 // TODO: change dynamicTable to be a struct with a slice and a size int field,
 // TODO: change dynamicTable to be a struct with a slice and a size int field,
@@ -82,9 +82,21 @@ func (dt *dynamicTable) setMaxSize(v uint32) {
 func (dt *dynamicTable) add(f HeaderField) {
 func (dt *dynamicTable) add(f HeaderField) {
 	dt.s = append(dt.s, f)
 	dt.s = append(dt.s, f)
 	dt.size += f.size()
 	dt.size += f.size()
+	dt.evict()
+}
+
+// If we're too big, evict old stuff (front of the slice)
+func (dt *dynamicTable) evict() {
+	base := dt.s // keep base pointer of slice
 	for dt.size > dt.maxSize {
 	for dt.size > dt.maxSize {
-		// TODO: evict
-		break
+		dt.size -= dt.s[0].size()
+		dt.s = dt.s[1:]
+	}
+
+	// Shift slice contents down if we evicted things.
+	if len(dt.s) != len(base) {
+		copy(base, dt.s)
+		dt.s = base[:len(dt.s)]
 	}
 	}
 }
 }
 
 

+ 29 - 1
hpack/hpack_test.go

@@ -113,8 +113,9 @@ func TestStaticTable(t *testing.T) {
 	}
 	}
 }
 }
 
 
-func TestHeaderTableAt(t *testing.T) {
+func TestDynamicTableAt(t *testing.T) {
 	var dt dynamicTable
 	var dt dynamicTable
+	dt.setMaxSize(4 << 10)
 	if got, want := dt.at(2), (HeaderField{":method", "GET"}); got != want {
 	if got, want := dt.at(2), (HeaderField{":method", "GET"}); got != want {
 		t.Errorf("at(2) = %q; want %q", got, want)
 		t.Errorf("at(2) = %q; want %q", got, want)
 	}
 	}
@@ -131,6 +132,33 @@ func TestHeaderTableAt(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestDynamicTableSizeEvict(t *testing.T) {
+	var dt dynamicTable
+	dt.setMaxSize(4 << 10)
+	if want := uint32(0); dt.size != want {
+		t.Fatalf("size = %d; want %d", dt.size, want)
+	}
+	dt.add(HeaderField{"blake", "eats pizza"})
+	if want := uint32(15 + 32); dt.size != want {
+		t.Fatalf("after pizza, size = %d; want %d", dt.size, want)
+	}
+	dt.add(HeaderField{"foo", "bar"})
+	if want := uint32(15 + 32 + 6 + 32); dt.size != want {
+		t.Fatalf("after foo bar, size = %d; want %d", dt.size, want)
+	}
+	dt.setMaxSize(15 + 32 + 1 /* slop */)
+	if want := uint32(6 + 32); dt.size != want {
+		t.Fatalf("after setMaxSize, size = %d; want %d", dt.size, want)
+	}
+	if got, want := dt.at(len(staticTable)+1), (HeaderField{"foo", "bar"}); got != want {
+		t.Errorf("at(dyn 1) = %q; want %q", got, want)
+	}
+	dt.add(HeaderField{"long", strings.Repeat("x", 500)})
+	if want := uint32(0); dt.size != want {
+		t.Fatalf("after big one, size = %d; want %d", dt.size, want)
+	}
+}
+
 func TestHuffmanDecode(t *testing.T) {
 func TestHuffmanDecode(t *testing.T) {
 	tests := []struct {
 	tests := []struct {
 		inHex, want string
 		inHex, want string