Ver Fonte

add DataFrame

Brad Fitzpatrick há 11 anos atrás
pai
commit
5d62c34731
1 ficheiros alterados com 55 adições e 2 exclusões
  1. 55 2
      frame.go

+ 55 - 2
frame.go

@@ -72,7 +72,12 @@ const (
 	FlagHeadersPadded     Flags = 0x8
 	FlagHeadersPriority   Flags = 0x20
 
-	FlagContinuationEndHeaders = FlagHeadersEndHeaders
+	// Data Frame
+	FlagDataEndStream Flags = 0x1
+	FlagDataPadded    Flags = 0x8
+
+	// Continuation Frame
+	FlagContinuationEndHeaders Flags = 0x4
 )
 
 // A SettingID is an HTTP/2 setting as defined in
@@ -110,7 +115,7 @@ func (s SettingID) String() string {
 type frameParser func(fh FrameHeader, payload []byte) (Frame, error)
 
 var frameParsers = map[FrameType]frameParser{
-	FrameData:         nil, // TODO
+	FrameData:         parseDataFrame,
 	FrameHeaders:      parseHeadersFrame,
 	FramePriority:     nil, // TODO
 	FrameRSTStream:    nil, // TODO
@@ -247,6 +252,54 @@ func (fr *Framer) ReadFrame() (Frame, error) {
 	return f, nil
 }
 
+// A DataFrame conveys arbitrary, variable-length sequences of octets
+// associated with a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.1
+type DataFrame struct {
+	FrameHeader
+	data []byte
+}
+
+// Data returns the frame's data octets, not including any padding
+// size byte or padding suffix bytes.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *DataFrame) Data() []byte {
+	f.checkValid()
+	return f.data
+}
+
+func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
+	if fh.StreamID == 0 {
+		// DATA frames MUST be associated with a stream. If a
+		// DATA frame is received whose stream identifier
+		// field is 0x0, the recipient MUST respond with a
+		// connection error (Section 5.4.1) of type
+		// PROTOCOL_ERROR.
+		return nil, ConnectionError(ErrCodeProtocol)
+	}
+	f := &DataFrame{
+		FrameHeader: fh,
+	}
+	var padSize byte
+	if fh.Flags.Has(FlagDataPadded) {
+		var err error
+		payload, padSize, err = readByte(payload)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if int(padSize) > len(payload) {
+		// If the length of the padding is greater than the
+		// length of the frame payload, the recipient MUST
+		// treat this as a connection error.
+		// Filed: https://github.com/http2/http2-spec/issues/610
+		return nil, ConnectionError(ErrCodeProtocol)
+	}
+	f.data = payload[:len(payload)-int(padSize)]
+	return f, nil
+}
+
 // A SettingsFrame conveys configuration parameters that affect how
 // endpoints communicate, such as preferences and constraints on peer
 // behavior.