From bd67f537c9b8ae200e0b9ffc5eaac0b3fb60c7c2 Mon Sep 17 00:00:00 2001 From: Lucas Clemente Date: Wed, 27 Apr 2016 13:02:00 +0200 Subject: [PATCH] add support for receiving BLOCKED frames --- frames/blocked_frame.go | 42 ++++++++++++++++++++++++++++++++++++ frames/blocked_frame_test.go | 20 +++++++++++++++++ packet_unpacker.go | 5 +---- packet_unpacker_test.go | 8 +++++-- session.go | 5 +++++ 5 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 frames/blocked_frame.go create mode 100644 frames/blocked_frame_test.go diff --git a/frames/blocked_frame.go b/frames/blocked_frame.go new file mode 100644 index 000000000..a1a61a8c4 --- /dev/null +++ b/frames/blocked_frame.go @@ -0,0 +1,42 @@ +package frames + +import ( + "bytes" + + "github.com/lucas-clemente/quic-go/protocol" + "github.com/lucas-clemente/quic-go/utils" +) + +// A BlockedFrame in QUIC +type BlockedFrame struct { + StreamID protocol.StreamID +} + +//Write writes a RST_STREAM frame +func (f *BlockedFrame) Write(b *bytes.Buffer, packetNumber protocol.PacketNumber, packetNumberLen uint8) error { + panic("BlockedFrame: Write not yet implemented") +} + +// MinLength of a written frame +func (f *BlockedFrame) MinLength() int { + panic("BlockedFrame: Write not yet implemented") +} + +// ParseBlockedFrame parses a BLOCKED frame +func ParseBlockedFrame(r *bytes.Reader) (*BlockedFrame, error) { + frame := &BlockedFrame{} + + // read the TypeByte + _, err := r.ReadByte() + if err != nil { + return nil, err + } + + sid, err := utils.ReadUint32(r) + if err != nil { + return nil, err + } + frame.StreamID = protocol.StreamID(sid) + + return frame, nil +} diff --git a/frames/blocked_frame_test.go b/frames/blocked_frame_test.go new file mode 100644 index 000000000..b068cc8a4 --- /dev/null +++ b/frames/blocked_frame_test.go @@ -0,0 +1,20 @@ +package frames + +import ( + "bytes" + + "github.com/lucas-clemente/quic-go/protocol" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("BlockedFrame", func() { + Context("when parsing", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x05, 0xEF, 0xBE, 0xAD, 0xDE}) + frame, err := ParseBlockedFrame(b) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(0xDEADBEEF))) + }) + }) +}) diff --git a/packet_unpacker.go b/packet_unpacker.go index a5d583011..d51d2829d 100644 --- a/packet_unpacker.go +++ b/packet_unpacker.go @@ -63,10 +63,7 @@ ReadLoop: case 0x04: frame, err = frames.ParseWindowUpdateFrame(r) case 0x05: - fmt.Println("unimplemented: BLOCKED") - p := make([]byte, 1+4) - _, err = r.Read(p) - frame = nil + frame, err = frames.ParseBlockedFrame(r) case 0x06: frame, err = frames.ParseStopWaitingFrame(r, publicHeader.PacketNumber, publicHeader.PacketNumberLen) case 0x07: diff --git a/packet_unpacker_test.go b/packet_unpacker_test.go index a11bb6419..3761af7e0 100644 --- a/packet_unpacker_test.go +++ b/packet_unpacker_test.go @@ -138,10 +138,14 @@ var _ = Describe("Packet unpacker", func() { }) It("accepts BLOCKED frames", func() { - setReader([]byte{0x05, 0, 0, 0, 0}) + setReader([]byte{0x05, 0xEF, 0xBE, 0xAD, 0xDE}) packet, err := unpacker.Unpack(hdrBin, hdr, r) Expect(err).ToNot(HaveOccurred()) - Expect(packet.frames).To(HaveLen(0)) + Expect(packet.frames).To(Equal([]frames.Frame{ + &frames.BlockedFrame{ + StreamID: 0xDEADBEEF, + }, + })) }) It("unpacks STOP_WAITING frames", func() { diff --git a/session.go b/session.go index b42968730..ea30aa3d2 100644 --- a/session.go +++ b/session.go @@ -30,6 +30,8 @@ type StreamCallback func(*Session, utils.Stream) // A Session is a QUIC session type Session struct { + connectionID protocol.ConnectionID + streamCallback StreamCallback conn connection @@ -54,6 +56,7 @@ type Session struct { // NewSession makes a new session func NewSession(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, streamCallback StreamCallback) PacketHandler { session := &Session{ + connectionID: connectionID, conn: conn, streamCallback: streamCallback, streams: make(map[protocol.StreamID]*stream), @@ -146,6 +149,8 @@ func (s *Session) handlePacket(remoteAddr interface{}, publicHeader *PublicHeade err = s.handleRstStreamFrame(frame) case *frames.WindowUpdateFrame: fmt.Printf("%#v\n", frame) + case *frames.BlockedFrame: + fmt.Printf("BLOCKED frame received for connection %d stream %d\n", s.connectionID, frame.StreamID) default: panic("unexpected frame type") }