implement parsing and writing of the NEW_TOKEN frame

This commit is contained in:
Marten Seemann
2018-11-10 09:46:57 +07:00
parent c89c1f4cee
commit cf104db629
5 changed files with 115 additions and 1 deletions

View File

@@ -44,7 +44,8 @@ func parseFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (Frame
frame, err = parseStopSendingFrame(r, v)
case 0x6:
frame, err = parseCryptoFrame(r, v)
// TODO: implement the NEW_TOKEN frame
case 0x7:
frame, err = parseNewTokenFrame(r, v)
case 0x10:
frame, err = parseMaxDataFrame(r, v)
case 0x11:

View File

@@ -85,6 +85,16 @@ var _ = Describe("Frame parsing", func() {
Expect(frame).To(Equal(f))
})
It("unpacks NEW_TOKEN frames", func() {
f := &NewTokenFrame{Token: []byte("foobar")}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame).ToNot(BeNil())
Expect(frame).To(Equal(f))
})
It("unpacks STREAM frames", func() {
f := &StreamFrame{
StreamID: 0x42,

View File

@@ -0,0 +1,44 @@
package wire
import (
"bytes"
"io"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
)
// A NewTokenFrame is a NEW_TOKEN frame
type NewTokenFrame struct {
Token []byte
}
func parseNewTokenFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewTokenFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
tokenLen, err := utils.ReadVarInt(r)
if err != nil {
return nil, err
}
if uint64(r.Len()) < tokenLen {
return nil, io.EOF
}
token := make([]byte, int(tokenLen))
if _, err := io.ReadFull(r, token); err != nil {
return nil, err
}
return &NewTokenFrame{Token: token}, nil
}
func (f *NewTokenFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
b.WriteByte(0x7)
utils.WriteVarInt(b, uint64(len(f.Token)))
b.Write(f.Token)
return nil
}
// Length of a written frame
func (f *NewTokenFrame) Length(protocol.VersionNumber) protocol.ByteCount {
return 1 + utils.VarIntLen(uint64(len(f.Token))) + protocol.ByteCount(len(f.Token))
}

View File

@@ -0,0 +1,58 @@
package wire
import (
"bytes"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("NEW_TOKEN frame", func() {
Context("parsing", func() {
It("accepts a sample frame", func() {
token := "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
data := []byte{0x7}
data = append(data, encodeVarInt(uint64(len(token)))...)
data = append(data, token...)
b := bytes.NewReader(data)
f, err := parseNewTokenFrame(b, protocol.VersionWhatever)
Expect(err).ToNot(HaveOccurred())
Expect(string(f.Token)).To(Equal(token))
Expect(b.Len()).To(BeZero())
})
It("errors on EOFs", func() {
token := "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
data := []byte{0x7}
data = append(data, encodeVarInt(uint64(len(token)))...)
data = append(data, token...)
_, err := parseNewTokenFrame(bytes.NewReader(data), protocol.VersionWhatever)
Expect(err).NotTo(HaveOccurred())
for i := range data {
_, err := parseNewTokenFrame(bytes.NewReader(data[0:i]), protocol.VersionWhatever)
Expect(err).To(HaveOccurred())
}
})
})
Context("writing", func() {
It("writes a sample frame", func() {
token := "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
f := &NewTokenFrame{Token: []byte(token)}
b := &bytes.Buffer{}
Expect(f.Write(b, protocol.VersionWhatever)).To(Succeed())
expected := []byte{0x7}
expected = append(expected, encodeVarInt(uint64(len(token)))...)
expected = append(expected, token...)
Expect(b.Bytes()).To(Equal(expected))
})
It("has the correct min length", func() {
frame := &NewTokenFrame{Token: []byte("foobar")}
Expect(frame.Length(protocol.VersionWhatever)).To(Equal(1 + utils.VarIntLen(6) + 6))
})
})
})

View File

@@ -578,6 +578,7 @@ func (s *session) handleFrames(fs []wire.Frame, encLevel protocol.EncryptionLeve
case *wire.PathResponseFrame:
// since we don't send PATH_CHALLENGEs, we don't expect PATH_RESPONSEs
err = errors.New("unexpected PATH_RESPONSE frame")
case *wire.NewTokenFrame:
default:
return errors.New("Session BUG: unexpected frame type")
}