diff --git a/frames/ping_frame.go b/frames/ping_frame.go new file mode 100644 index 00000000..5cfd63f7 --- /dev/null +++ b/frames/ping_frame.go @@ -0,0 +1,33 @@ +package frames + +import ( + "bytes" + + "github.com/lucas-clemente/quic-go/protocol" +) + +// A PingFrame is a ping frame +type PingFrame struct{} + +// ParsePingFrame parses a Ping frame +func ParsePingFrame(r *bytes.Reader) (*PingFrame, error) { + frame := &PingFrame{} + + _, err := r.ReadByte() + if err != nil { + return nil, err + } + + return frame, nil +} + +func (f *PingFrame) Write(b *bytes.Buffer, packetNumber protocol.PacketNumber, packetNumberLen uint8) error { + typeByte := uint8(0x07) + b.WriteByte(typeByte) + return nil +} + +// MinLength of a written frame +func (f *PingFrame) MinLength() int { + return 1 +} diff --git a/frames/ping_frame_test.go b/frames/ping_frame_test.go new file mode 100644 index 00000000..5cec3134 --- /dev/null +++ b/frames/ping_frame_test.go @@ -0,0 +1,33 @@ +package frames + +import ( + "bytes" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("PingFrame", func() { + Context("when parsing", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x07}) + _, err := ParsePingFrame(b) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(0)) + }) + }) + + Context("when writing", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + frame := PingFrame{} + frame.Write(b, 10, 6) + Expect(b.Bytes()).To(Equal([]byte{0x07})) + }) + + It("has the correct min length", func() { + frame := PingFrame{} + Expect(frame.MinLength()).To(Equal(1)) + }) + }) +}) diff --git a/packet_unpacker.go b/packet_unpacker.go index 5fe1db34..786484f5 100644 --- a/packet_unpacker.go +++ b/packet_unpacker.go @@ -68,10 +68,7 @@ ReadLoop: case 0x06: frame, err = frames.ParseStopWaitingFrame(r, publicHeader.PacketNumber, publicHeader.PacketNumberLen) case 0x07: - // PING, do nothing - fmt.Printf("\t<- Ping Frame\n") - r.ReadByte() - continue + frame, err = frames.ParsePingFrame(r) default: err = protocol.NewQuicError(errorcodes.QUIC_INVALID_FRAME_DATA, fmt.Sprintf("unknown type byte 0x%x", typeByte)) } diff --git a/packet_unpacker_test.go b/packet_unpacker_test.go index 5cc89b31..4b2fb4de 100644 --- a/packet_unpacker_test.go +++ b/packet_unpacker_test.go @@ -152,7 +152,9 @@ var _ = Describe("Packet unpacker", func() { setReader([]byte{0x07}) 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.PingFrame{}, + })) }) It("errors on invalid type", func() { diff --git a/session.go b/session.go index 6e0491c2..a4b0dea5 100644 --- a/session.go +++ b/session.go @@ -176,6 +176,8 @@ func (s *Session) handlePacket(remoteAddr interface{}, publicHeader *PublicHeade err = s.handleWindowUpdateFrame(frame) case *frames.BlockedFrame: fmt.Printf("BLOCKED frame received for connection %x stream %d\n", s.connectionID, frame.StreamID) + case *frames.PingFrame: + fmt.Printf("\t<- %#v\n", frame) default: panic("unexpected frame type") }