瀏覽代碼

SETTINGS writing.

Brad Fitzpatrick 11 年之前
父節點
當前提交
0a81e4594e
共有 3 個文件被更改,包括 57 次插入8 次删除
  1. 37 6
      frame.go
  2. 18 0
      frame_test.go
  3. 2 2
      http2.go

+ 37 - 6
frame.go

@@ -318,14 +318,12 @@ func (f *Framer) endWrite() error {
 	return err
 }
 
+func (f *Framer) writeByte(v byte)     { f.wbuf = append(f.wbuf, v) }
+func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
 func (f *Framer) writeUint32(v uint32) {
 	f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
 }
 
-func (f *Framer) writeByte(v byte) {
-	f.wbuf = append(f.wbuf, v)
-}
-
 // NewFramer returns a Framer that writes frames to w and reads them from r.
 func NewFramer(w io.Writer, r io.Reader) *Framer {
 	return &Framer{
@@ -489,15 +487,48 @@ func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
 	return 0, false
 }
 
-func (f *SettingsFrame) ForeachSetting(fn func(s SettingID, v uint32)) {
+func (f *SettingsFrame) ForeachSetting(fn func(Setting)) {
 	f.checkValid()
 	buf := f.p
 	for len(buf) > 0 {
-		fn(SettingID(binary.BigEndian.Uint16(buf[:2])), binary.BigEndian.Uint32(buf[2:4]))
+		fn(Setting{SettingID(binary.BigEndian.Uint16(buf[:2])), binary.BigEndian.Uint32(buf[2:4])})
 		buf = buf[6:]
 	}
 }
 
+// Setting is a setting parameter: which setting it is, and its value.
+type Setting struct {
+	// ID is which setting is being set.
+	// See http://http2.github.io/http2-spec/#SettingValues
+	ID SettingID
+
+	// Val is the value.
+	Val uint32
+}
+
+// WriteSettings writes a SETTINGS frame with zero or more settings
+// specified and the ACK bit not set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettings(settings ...Setting) error {
+	f.startWrite(FrameSettings, 0, 0)
+	for _, s := range settings {
+		f.writeUint16(uint16(s.ID))
+		f.writeUint32(s.Val)
+	}
+	return f.endWrite()
+}
+
+// WriteSettings writes an empty SETTINGS frame with the ACK bit set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettingsAck() error {
+	f.startWrite(FrameSettings, FlagSettingsAck, 0)
+	return f.endWrite()
+}
+
 // A PingFrame is a mechanism for measuring a minimal round trip time
 // from the sender, as well as determining whether an idle connection
 // is still functional.

+ 18 - 0
frame_test.go

@@ -314,3 +314,21 @@ func TestWritePriority(t *testing.T) {
 		}
 	}
 }
+
+func TestWriteSettings(t *testing.T) {
+	fr, buf := testFramer()
+	fr.WriteSettings(Setting{1, 2}, Setting{3, 4})
+	const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
+	if buf.String() != wantEnc {
+		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+	}
+}
+
+func TestWriteSettingsAck(t *testing.T) {
+	fr, buf := testFramer()
+	fr.WriteSettingsAck()
+	const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
+	if buf.String() != wantEnc {
+		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
+	}
+}

+ 2 - 2
http2.go

@@ -215,8 +215,8 @@ func (sc *serverConn) processFrame(f Frame) error {
 }
 
 func (sc *serverConn) processSettings(f *SettingsFrame) error {
-	f.ForeachSetting(func(s SettingID, v uint32) {
-		log.Printf("  setting %s = %v", s, v)
+	f.ForeachSetting(func(s Setting) {
+		log.Printf("  setting %s = %v", s.ID, s.Val)
 	})
 	return nil
 }