add public header parser

This commit is contained in:
Lucas Clemente 2016-04-06 23:10:52 +02:00
parent afdd7c3898
commit cfccdaed9b
3 changed files with 120 additions and 0 deletions

84
public_header.go Normal file
View file

@ -0,0 +1,84 @@
package quic
import "io"
// The PublicHeader of a QUIC packet
type PublicHeader struct {
VersionFlag bool
ResetFlag bool
ConnectionIDLength uint8
ConnectionID uint64
QuicVersion uint32
PacketNumberLength uint8
PacketNumber uint64
}
// ParsePublicHeader parses a QUIC packet's public header
func ParsePublicHeader(b io.ByteReader) (*PublicHeader, error) {
header := &PublicHeader{}
// First byte
publicFlagByte, err := b.ReadByte()
if err != nil {
return nil, err
}
header.VersionFlag = publicFlagByte&0x01 > 0
header.ResetFlag = publicFlagByte&0x02 > 0
switch publicFlagByte & 0x0C {
case 0x0C:
header.ConnectionIDLength = 8
case 0x08:
header.ConnectionIDLength = 4
case 0x04:
header.ConnectionIDLength = 1
}
switch publicFlagByte & 0x30 {
case 0x30:
header.PacketNumberLength = 6
case 0x20:
header.PacketNumberLength = 4
case 0x10:
header.PacketNumberLength = 2
case 0x00:
header.PacketNumberLength = 1
}
// Connection ID
header.ConnectionID, err = readUint64(b, header.ConnectionIDLength)
if err != nil {
return nil, err
}
// Version (optional)
if header.VersionFlag {
var v uint64
v, err = readUint64(b, 4)
if err != nil {
return nil, err
}
header.QuicVersion = uint32(v)
}
// Packet number
header.PacketNumber, err = readUint64(b, header.PacketNumberLength)
if err != nil {
return nil, err
}
return header, nil
}
func readUint64(b io.ByteReader, length uint8) (uint64, error) {
var res uint64
for i := uint8(0); i < length; i++ {
bt, err := b.ReadByte()
if err != nil {
return 0, err
}
res = res<<8 + uint64(bt)
}
return res, nil
}

23
public_header_test.go Normal file
View file

@ -0,0 +1,23 @@
package quic
import (
"bytes"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Public Header", func() {
It("parses intial client header", func() {
b := bytes.NewReader([]byte{0xd, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c, 0x51, 0x30, 0x33, 0x30, 0x1})
publicHeader, err := ParsePublicHeader(b)
Expect(err).ToNot(HaveOccurred())
Expect(publicHeader.VersionFlag).To(BeTrue())
Expect(publicHeader.ResetFlag).To(BeFalse())
Expect(publicHeader.ConnectionIDLength).To(Equal(uint8(8)))
Expect(publicHeader.ConnectionID).ToNot(BeZero())
Expect(publicHeader.QuicVersion).To(Equal(uint32(0x51303330)))
Expect(publicHeader.PacketNumberLength).To(Equal(uint8(1)))
Expect(publicHeader.PacketNumber).To(Equal(uint64(1)))
})
})

13
quic_suite_test.go Normal file
View file

@ -0,0 +1,13 @@
package quic
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestQuicGo(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "QUIC Suite")
}