uquic/public_header.go
2016-04-11 14:41:21 +02:00

90 lines
1.9 KiB
Go

package quic
import (
"bytes"
"io"
"github.com/lucas-clemente/quic-go/utils"
)
// The PublicHeader of a QUIC packet
type PublicHeader struct {
VersionFlag bool
ResetFlag bool
ConnectionID uint64
QuicVersion uint32
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
var connectionIDLen, packetNumberLen uint8
switch publicFlagByte & 0x0C {
case 0x0C:
connectionIDLen = 8
case 0x08:
connectionIDLen = 4
case 0x04:
connectionIDLen = 1
}
switch publicFlagByte & 0x30 {
case 0x30:
packetNumberLen = 6
case 0x20:
packetNumberLen = 4
case 0x10:
packetNumberLen = 2
case 0x00:
packetNumberLen = 1
}
// Connection ID
header.ConnectionID, err = utils.ReadUintN(b, connectionIDLen)
if err != nil {
return nil, err
}
// Version (optional)
if header.VersionFlag {
var b1, b2, b3, b4 uint8
if b1, err = b.ReadByte(); err != nil {
return nil, err
}
if b2, err = b.ReadByte(); err != nil {
return nil, err
}
if b3, err = b.ReadByte(); err != nil {
return nil, err
}
if b4, err = b.ReadByte(); err != nil {
return nil, err
}
header.QuicVersion = uint32(b4) + uint32(b3)<<8 + uint32(b2)<<16 + uint32(b1)<<24
}
// Packet number
header.PacketNumber, err = utils.ReadUintN(b, packetNumberLen)
if err != nil {
return nil, err
}
return header, nil
}
// WritePublicHeader writes a public header
func WritePublicHeader(b *bytes.Buffer, h *PublicHeader) {
publicFlagByte := uint8(0x0C | 0x20)
b.WriteByte(publicFlagByte)
utils.WriteUint64(b, h.ConnectionID) // TODO: Send shorter connection id if possible
utils.WriteUint32(b, uint32(h.PacketNumber)) // TODO: Send shorter packet number if possible
}