introduce an utils.LittleEndian

This commit is contained in:
Marten Seemann
2017-08-02 14:23:18 +07:00
parent 3bb4662cfc
commit 2330ac0497
25 changed files with 195 additions and 155 deletions

View File

@@ -51,10 +51,10 @@ func compressChain(chain [][]byte, pCommonSetHashes, pCachedHashes []byte) ([]by
res.WriteByte(uint8(e.t))
switch e.t {
case entryCached:
utils.WriteUint64(res, e.h)
utils.LittleEndian.WriteUint64(res, e.h)
case entryCommon:
utils.WriteUint64(res, e.h)
utils.WriteUint32(res, e.i)
utils.LittleEndian.WriteUint64(res, e.h)
utils.LittleEndian.WriteUint32(res, e.i)
case entryCompressed:
totalUncompressedLen += 4 + len(chain[i])
}
@@ -67,7 +67,7 @@ func compressChain(chain [][]byte, pCommonSetHashes, pCachedHashes []byte) ([]by
return nil, fmt.Errorf("cert compression failed: %s", err.Error())
}
utils.WriteUint32(res, uint32(totalUncompressedLen))
utils.LittleEndian.WriteUint32(res, uint32(totalUncompressedLen))
for i, e := range entries {
if e.t != entryCompressed {
@@ -115,11 +115,11 @@ func decompressChain(data []byte) ([][]byte, error) {
return nil, errors.New("unexpected cached certificate")
case entryCommon:
e := entry{t: entryCommon}
e.h, err = utils.ReadUint64(r)
e.h, err = utils.LittleEndian.ReadUint64(r)
if err != nil {
return nil, err
}
e.i, err = utils.ReadUint32(r)
e.i, err = utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}
@@ -146,7 +146,7 @@ func decompressChain(data []byte) ([][]byte, error) {
}
if hasCompressedCerts {
uncompressedLength, err := utils.ReadUint32(r)
uncompressedLength, err := utils.LittleEndian.ReadUint32(r)
if err != nil {
fmt.Println(4)
return nil, err

View File

@@ -42,7 +42,7 @@ func deriveKeys(forwardSecure bool, sharedSecret, nonces []byte, connID protocol
} else {
info.Write([]byte("QUIC key expansion\x00"))
}
utils.WriteUint64(&info, uint64(connID))
utils.LittleEndian.WriteUint64(&info, uint64(connID))
info.Write(chlo)
info.Write(scfg)
info.Write(cert)

View File

@@ -57,13 +57,13 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
missingSequenceNumberDeltaLen = 1
}
largestAcked, err := utils.ReadUintN(r, largestAckedLen)
largestAcked, err := utils.LittleEndian.ReadUintN(r, largestAckedLen)
if err != nil {
return nil, err
}
frame.LargestAcked = protocol.PacketNumber(largestAcked)
delay, err := utils.ReadUfloat16(r)
delay, err := utils.LittleEndian.ReadUfloat16(r)
if err != nil {
return nil, err
}
@@ -81,7 +81,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
return nil, ErrInvalidAckRanges
}
ackBlockLength, err := utils.ReadUintN(r, missingSequenceNumberDeltaLen)
ackBlockLength, err := utils.LittleEndian.ReadUintN(r, missingSequenceNumberDeltaLen)
if err != nil {
return nil, err
}
@@ -109,7 +109,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
return nil, err
}
ackBlockLength, err = utils.ReadUintN(r, missingSequenceNumberDeltaLen)
ackBlockLength, err = utils.LittleEndian.ReadUintN(r, missingSequenceNumberDeltaLen)
if err != nil {
return nil, err
}
@@ -167,7 +167,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
return nil, err
}
// First Timestamp
_, err = utils.ReadUint32(r)
_, err = utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}
@@ -180,7 +180,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
}
// Time Since Previous Timestamp
_, err = utils.ReadUint16(r)
_, err = utils.LittleEndian.ReadUint16(r)
if err != nil {
return nil, err
}
@@ -215,15 +215,15 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
case protocol.PacketNumberLen1:
b.WriteByte(uint8(f.LargestAcked))
case protocol.PacketNumberLen2:
utils.WriteUint16(b, uint16(f.LargestAcked))
utils.LittleEndian.WriteUint16(b, uint16(f.LargestAcked))
case protocol.PacketNumberLen4:
utils.WriteUint32(b, uint32(f.LargestAcked))
utils.LittleEndian.WriteUint32(b, uint32(f.LargestAcked))
case protocol.PacketNumberLen6:
utils.WriteUint48(b, uint64(f.LargestAcked))
utils.LittleEndian.WriteUint48(b, uint64(f.LargestAcked))
}
f.DelayTime = time.Since(f.PacketReceivedTime)
utils.WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond))
utils.LittleEndian.WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond))
var numRanges uint64
var numRangesWritten uint64
@@ -253,11 +253,11 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
case protocol.PacketNumberLen1:
b.WriteByte(uint8(firstAckBlockLength))
case protocol.PacketNumberLen2:
utils.WriteUint16(b, uint16(firstAckBlockLength))
utils.LittleEndian.WriteUint16(b, uint16(firstAckBlockLength))
case protocol.PacketNumberLen4:
utils.WriteUint32(b, uint32(firstAckBlockLength))
utils.LittleEndian.WriteUint32(b, uint32(firstAckBlockLength))
case protocol.PacketNumberLen6:
utils.WriteUint48(b, uint64(firstAckBlockLength))
utils.LittleEndian.WriteUint48(b, uint64(firstAckBlockLength))
}
for i, ackRange := range f.AckRanges {
@@ -279,11 +279,11 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
case protocol.PacketNumberLen1:
b.WriteByte(uint8(length))
case protocol.PacketNumberLen2:
utils.WriteUint16(b, uint16(length))
utils.LittleEndian.WriteUint16(b, uint16(length))
case protocol.PacketNumberLen4:
utils.WriteUint32(b, uint32(length))
utils.LittleEndian.WriteUint32(b, uint32(length))
case protocol.PacketNumberLen6:
utils.WriteUint48(b, uint64(length))
utils.LittleEndian.WriteUint48(b, uint64(length))
}
numRangesWritten++
} else {
@@ -304,11 +304,11 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
case protocol.PacketNumberLen1:
b.WriteByte(uint8(lengthWritten))
case protocol.PacketNumberLen2:
utils.WriteUint16(b, uint16(lengthWritten))
utils.LittleEndian.WriteUint16(b, uint16(lengthWritten))
case protocol.PacketNumberLen4:
utils.WriteUint32(b, uint32(lengthWritten))
utils.LittleEndian.WriteUint32(b, uint32(lengthWritten))
case protocol.PacketNumberLen6:
utils.WriteUint48(b, lengthWritten)
utils.LittleEndian.WriteUint48(b, lengthWritten)
}
numRangesWritten++

View File

@@ -15,7 +15,7 @@ type BlockedFrame struct {
//Write writes a BlockedFrame frame
func (f *BlockedFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
b.WriteByte(0x05)
utils.WriteUint32(b, uint32(f.StreamID))
utils.LittleEndian.WriteUint32(b, uint32(f.StreamID))
return nil
}
@@ -34,7 +34,7 @@ func ParseBlockedFrame(r *bytes.Reader) (*BlockedFrame, error) {
return nil, err
}
sid, err := utils.ReadUint32(r)
sid, err := utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}

View File

@@ -27,13 +27,13 @@ func ParseConnectionCloseFrame(r *bytes.Reader) (*ConnectionCloseFrame, error) {
return nil, err
}
errorCode, err := utils.ReadUint32(r)
errorCode, err := utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}
frame.ErrorCode = qerr.ErrorCode(errorCode)
reasonPhraseLen, err := utils.ReadUint16(r)
reasonPhraseLen, err := utils.LittleEndian.ReadUint16(r)
if err != nil {
return nil, err
}
@@ -59,14 +59,14 @@ func (f *ConnectionCloseFrame) MinLength(version protocol.VersionNumber) (protoc
// Write writes an CONNECTION_CLOSE frame.
func (f *ConnectionCloseFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
b.WriteByte(0x02)
utils.WriteUint32(b, uint32(f.ErrorCode))
utils.LittleEndian.WriteUint32(b, uint32(f.ErrorCode))
if len(f.ReasonPhrase) > math.MaxUint16 {
return errors.New("ConnectionFrame: ReasonPhrase too long")
}
reasonPhraseLen := uint16(len(f.ReasonPhrase))
utils.WriteUint16(b, reasonPhraseLen)
utils.LittleEndian.WriteUint16(b, reasonPhraseLen)
b.WriteString(f.ReasonPhrase)
return nil

View File

@@ -25,19 +25,19 @@ func ParseGoawayFrame(r *bytes.Reader) (*GoawayFrame, error) {
return nil, err
}
errorCode, err := utils.ReadUint32(r)
errorCode, err := utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}
frame.ErrorCode = qerr.ErrorCode(errorCode)
lastGoodStream, err := utils.ReadUint32(r)
lastGoodStream, err := utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}
frame.LastGoodStream = protocol.StreamID(lastGoodStream)
reasonPhraseLen, err := utils.ReadUint16(r)
reasonPhraseLen, err := utils.LittleEndian.ReadUint16(r)
if err != nil {
return nil, err
}
@@ -59,9 +59,9 @@ func (f *GoawayFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) err
typeByte := uint8(0x03)
b.WriteByte(typeByte)
utils.WriteUint32(b, uint32(f.ErrorCode))
utils.WriteUint32(b, uint32(f.LastGoodStream))
utils.WriteUint16(b, uint16(len(f.ReasonPhrase)))
utils.LittleEndian.WriteUint32(b, uint32(f.ErrorCode))
utils.LittleEndian.WriteUint32(b, uint32(f.LastGoodStream))
utils.LittleEndian.WriteUint16(b, uint16(len(f.ReasonPhrase)))
b.WriteString(f.ReasonPhrase)
return nil

View File

@@ -17,9 +17,9 @@ type RstStreamFrame struct {
//Write writes a RST_STREAM frame
func (f *RstStreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error {
b.WriteByte(0x01)
utils.WriteUint32(b, uint32(f.StreamID))
utils.WriteUint64(b, uint64(f.ByteOffset))
utils.WriteUint32(b, f.ErrorCode)
utils.LittleEndian.WriteUint32(b, uint32(f.StreamID))
utils.LittleEndian.WriteUint64(b, uint64(f.ByteOffset))
utils.LittleEndian.WriteUint32(b, f.ErrorCode)
return nil
}
@@ -38,19 +38,19 @@ func ParseRstStreamFrame(r *bytes.Reader) (*RstStreamFrame, error) {
return nil, err
}
sid, err := utils.ReadUint32(r)
sid, err := utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}
frame.StreamID = protocol.StreamID(sid)
byteOffset, err := utils.ReadUint64(r)
byteOffset, err := utils.LittleEndian.ReadUint64(r)
if err != nil {
return nil, err
}
frame.ByteOffset = protocol.ByteCount(byteOffset)
frame.ErrorCode, err = utils.ReadUint32(r)
frame.ErrorCode, err = utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}

View File

@@ -42,11 +42,11 @@ func (f *StopWaitingFrame) Write(b *bytes.Buffer, version protocol.VersionNumber
case protocol.PacketNumberLen1:
b.WriteByte(uint8(leastUnackedDelta))
case protocol.PacketNumberLen2:
utils.WriteUint16(b, uint16(leastUnackedDelta))
utils.LittleEndian.WriteUint16(b, uint16(leastUnackedDelta))
case protocol.PacketNumberLen4:
utils.WriteUint32(b, uint32(leastUnackedDelta))
utils.LittleEndian.WriteUint32(b, uint32(leastUnackedDelta))
case protocol.PacketNumberLen6:
utils.WriteUint48(b, leastUnackedDelta)
utils.LittleEndian.WriteUint48(b, leastUnackedDelta)
default:
return errPacketNumberLenNotSet
}
@@ -76,7 +76,7 @@ func ParseStopWaitingFrame(r *bytes.Reader, packetNumber protocol.PacketNumber,
return nil, err
}
leastUnackedDelta, err := utils.ReadUintN(r, uint8(packetNumberLen))
leastUnackedDelta, err := utils.LittleEndian.ReadUintN(r, uint8(packetNumberLen))
if err != nil {
return nil, err
}

View File

@@ -41,13 +41,13 @@ func ParseStreamFrame(r *bytes.Reader) (*StreamFrame, error) {
}
streamIDLen := typeByte&0x03 + 1
sid, err := utils.ReadUintN(r, streamIDLen)
sid, err := utils.LittleEndian.ReadUintN(r, streamIDLen)
if err != nil {
return nil, err
}
frame.StreamID = protocol.StreamID(sid)
offset, err := utils.ReadUintN(r, offsetLen)
offset, err := utils.LittleEndian.ReadUintN(r, offsetLen)
if err != nil {
return nil, err
}
@@ -55,7 +55,7 @@ func ParseStreamFrame(r *bytes.Reader) (*StreamFrame, error) {
var dataLen uint16
if frame.DataLenPresent {
dataLen, err = utils.ReadUint16(r)
dataLen, err = utils.LittleEndian.ReadUint16(r)
if err != nil {
return nil, err
}
@@ -118,11 +118,11 @@ func (f *StreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) err
case 1:
b.WriteByte(uint8(f.StreamID))
case 2:
utils.WriteUint16(b, uint16(f.StreamID))
utils.LittleEndian.WriteUint16(b, uint16(f.StreamID))
case 3:
utils.WriteUint24(b, uint32(f.StreamID))
utils.LittleEndian.WriteUint24(b, uint32(f.StreamID))
case 4:
utils.WriteUint32(b, uint32(f.StreamID))
utils.LittleEndian.WriteUint32(b, uint32(f.StreamID))
default:
return errInvalidStreamIDLen
}
@@ -130,25 +130,25 @@ func (f *StreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) err
switch offsetLength {
case 0:
case 2:
utils.WriteUint16(b, uint16(f.Offset))
utils.LittleEndian.WriteUint16(b, uint16(f.Offset))
case 3:
utils.WriteUint24(b, uint32(f.Offset))
utils.LittleEndian.WriteUint24(b, uint32(f.Offset))
case 4:
utils.WriteUint32(b, uint32(f.Offset))
utils.LittleEndian.WriteUint32(b, uint32(f.Offset))
case 5:
utils.WriteUint40(b, uint64(f.Offset))
utils.LittleEndian.WriteUint40(b, uint64(f.Offset))
case 6:
utils.WriteUint48(b, uint64(f.Offset))
utils.LittleEndian.WriteUint48(b, uint64(f.Offset))
case 7:
utils.WriteUint56(b, uint64(f.Offset))
utils.LittleEndian.WriteUint56(b, uint64(f.Offset))
case 8:
utils.WriteUint64(b, uint64(f.Offset))
utils.LittleEndian.WriteUint64(b, uint64(f.Offset))
default:
return errInvalidOffsetLen
}
if f.DataLenPresent {
utils.WriteUint16(b, uint16(len(f.Data)))
utils.LittleEndian.WriteUint16(b, uint16(len(f.Data)))
}
b.Write(f.Data)

View File

@@ -18,8 +18,8 @@ func (f *WindowUpdateFrame) Write(b *bytes.Buffer, version protocol.VersionNumbe
typeByte := uint8(0x04)
b.WriteByte(typeByte)
utils.WriteUint32(b, uint32(f.StreamID))
utils.WriteUint64(b, uint64(f.ByteOffset))
utils.LittleEndian.WriteUint32(b, uint32(f.StreamID))
utils.LittleEndian.WriteUint64(b, uint64(f.ByteOffset))
return nil
}
@@ -38,13 +38,13 @@ func ParseWindowUpdateFrame(r *bytes.Reader) (*WindowUpdateFrame, error) {
return nil, err
}
sid, err := utils.ReadUint32(r)
sid, err := utils.LittleEndian.ReadUint32(r)
if err != nil {
return nil, err
}
frame.StreamID = protocol.StreamID(sid)
byteOffset, err := utils.ReadUint64(r)
byteOffset, err := utils.LittleEndian.ReadUint64(r)
if err != nil {
return nil, err
}

View File

@@ -97,28 +97,28 @@ func (h *connectionParametersManager) SetFromMap(params map[Tag][]byte) error {
defer h.mutex.Unlock()
if value, ok := params[TagTCID]; ok && h.perspective == protocol.PerspectiveServer {
clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.truncateConnectionID = (clientValue == 0)
}
if value, ok := params[TagMSPC]; ok {
clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.maxStreamsPerConnection = h.negotiateMaxStreamsPerConnection(clientValue)
}
if value, ok := params[TagMIDS]; ok {
clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
h.maxIncomingDynamicStreamsPerConnection = h.negotiateMaxIncomingDynamicStreamsPerConnection(clientValue)
}
if value, ok := params[TagICSL]; ok {
clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
clientValue, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
@@ -128,7 +128,7 @@ func (h *connectionParametersManager) SetFromMap(params map[Tag][]byte) error {
if h.flowControlNegotiated {
return ErrFlowControlRenegotiationNotSupported
}
sendStreamFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value))
sendStreamFlowControlWindow, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
@@ -138,7 +138,7 @@ func (h *connectionParametersManager) SetFromMap(params map[Tag][]byte) error {
if h.flowControlNegotiated {
return ErrFlowControlRenegotiationNotSupported
}
sendConnectionFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value))
sendConnectionFlowControlWindow, err := utils.LittleEndian.ReadUint32(bytes.NewBuffer(value))
if err != nil {
return ErrMalformedTag
}
@@ -172,15 +172,15 @@ func (h *connectionParametersManager) negotiateIdleConnectionStateLifetime(clien
// GetHelloMap gets all parameters needed for the Hello message
func (h *connectionParametersManager) GetHelloMap() (map[Tag][]byte, error) {
sfcw := bytes.NewBuffer([]byte{})
utils.WriteUint32(sfcw, uint32(h.GetReceiveStreamFlowControlWindow()))
utils.LittleEndian.WriteUint32(sfcw, uint32(h.GetReceiveStreamFlowControlWindow()))
cfcw := bytes.NewBuffer([]byte{})
utils.WriteUint32(cfcw, uint32(h.GetReceiveConnectionFlowControlWindow()))
utils.LittleEndian.WriteUint32(cfcw, uint32(h.GetReceiveConnectionFlowControlWindow()))
mspc := bytes.NewBuffer([]byte{})
utils.WriteUint32(mspc, h.maxStreamsPerConnection)
utils.LittleEndian.WriteUint32(mspc, h.maxStreamsPerConnection)
mids := bytes.NewBuffer([]byte{})
utils.WriteUint32(mids, protocol.MaxIncomingDynamicStreamsPerConnection)
utils.LittleEndian.WriteUint32(mids, protocol.MaxIncomingDynamicStreamsPerConnection)
icsl := bytes.NewBuffer([]byte{})
utils.WriteUint32(icsl, uint32(h.GetIdleConnectionStateLifetime()/time.Second))
utils.LittleEndian.WriteUint32(icsl, uint32(h.GetIdleConnectionStateLifetime()/time.Second))
return map[Tag][]byte{
TagICSL: icsl.Bytes(),

View File

@@ -285,7 +285,7 @@ func (h *cryptoSetupClient) validateVersionList(verTags []byte) bool {
b := bytes.NewReader(verTags)
for _, negotiatedVersion := range h.negotiatedVersions {
verTag, err := utils.ReadUint32(b)
verTag, err := utils.LittleEndian.ReadUint32(b)
if err != nil { // should never occur, since the length was already checked
return false
}

View File

@@ -198,7 +198,7 @@ var _ = Describe("Client Crypto Setup", func() {
It("detects a downgrade attack", func() {
cs.negotiatedVersions = []protocol.VersionNumber{protocol.Version36}
b := &bytes.Buffer{}
utils.WriteUint32(b, protocol.VersionNumberToTag(protocol.Version35))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(protocol.Version35))
Expect(cs.validateVersionList(b.Bytes())).To(BeFalse())
})
@@ -211,7 +211,7 @@ var _ = Describe("Client Crypto Setup", func() {
cs.negotiatedVersions = []protocol.VersionNumber{protocol.VersionUnsupported, protocol.Version36, protocol.VersionUnsupported}
b := &bytes.Buffer{}
b.Write([]byte{0, 0, 0, 0})
utils.WriteUint32(b, protocol.VersionNumberToTag(protocol.Version36))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(protocol.Version36))
b.Write([]byte{0x13, 0x37, 0x13, 0x37})
Expect(cs.validateVersionList(b.Bytes())).To(BeTrue())
})
@@ -406,7 +406,7 @@ var _ = Describe("Client Crypto Setup", func() {
cs.negotiatedVersions = []protocol.VersionNumber{protocol.Version36}
cs.receivedSecurePacket = true
b := &bytes.Buffer{}
utils.WriteUint32(b, protocol.VersionNumberToTag(protocol.Version36))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(protocol.Version36))
shloMap[TagVER] = b.Bytes()
err := cs.handleSHLOMessage(shloMap)
Expect(err).ToNot(HaveOccurred())

View File

@@ -437,7 +437,7 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T
// add crypto parameters
verTag := &bytes.Buffer{}
for _, v := range h.supportedVersions {
utils.WriteUint32(verTag, protocol.VersionNumberToTag(v))
utils.LittleEndian.WriteUint32(verTag, protocol.VersionNumberToTag(v))
}
replyMap[TagPUBS] = ephermalKex.PublicKey()
replyMap[TagSNO] = serverNonce

View File

@@ -322,7 +322,7 @@ var _ = Describe("Server Crypto Setup", func() {
Expect(response).To(ContainSubstring("SNO\x00"))
for _, v := range supportedVersions {
b := &bytes.Buffer{}
utils.WriteUint32(b, protocol.VersionNumberToTag(v))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(v))
Expect(response).To(ContainSubstring(string(b.Bytes())))
}
Expect(cs.secureAEAD).ToNot(BeNil())

View File

@@ -72,9 +72,9 @@ func ParseHandshakeMessage(r io.Reader) (HandshakeMessage, error) {
// Write writes a crypto message
func (h HandshakeMessage) Write(b *bytes.Buffer) {
data := h.Data
utils.WriteUint32(b, uint32(h.Tag))
utils.WriteUint16(b, uint16(len(data)))
utils.WriteUint16(b, 0)
utils.LittleEndian.WriteUint32(b, uint32(h.Tag))
utils.LittleEndian.WriteUint16(b, uint16(len(data)))
utils.LittleEndian.WriteUint16(b, 0)
// Save current position in the buffer, so that we can update the index in-place later
indexStart := b.Len()

View File

@@ -0,0 +1,25 @@
package utils
import (
"bytes"
"io"
)
// A ByteOrder specifies how to convert byte sequences into 16-, 32-, or 64-bit unsigned integers.
type ByteOrder interface {
ReadUintN(b io.ByteReader, length uint8) (uint64, error)
ReadUint64(io.ByteReader) (uint64, error)
ReadUint32(io.ByteReader) (uint32, error)
ReadUint16(io.ByteReader) (uint16, error)
WriteUint64(*bytes.Buffer, uint64)
WriteUint56(*bytes.Buffer, uint64)
WriteUint48(*bytes.Buffer, uint64)
WriteUint40(*bytes.Buffer, uint64)
WriteUint32(*bytes.Buffer, uint32)
WriteUint24(*bytes.Buffer, uint32)
WriteUint16(*bytes.Buffer, uint16)
ReadUfloat16(io.ByteReader) (uint64, error)
WriteUfloat16(*bytes.Buffer, uint64)
}

View File

@@ -5,8 +5,15 @@ import (
"io"
)
// LittleEndian is the little-endian implementation of ByteOrder.
var LittleEndian ByteOrder = littleEndian{}
type littleEndian struct{}
var _ ByteOrder = &littleEndian{}
// ReadUintN reads N bytes
func ReadUintN(b io.ByteReader, length uint8) (uint64, error) {
func (littleEndian) ReadUintN(b io.ByteReader, length uint8) (uint64, error) {
var res uint64
for i := uint8(0); i < length; i++ {
bt, err := b.ReadByte()
@@ -19,7 +26,7 @@ func ReadUintN(b io.ByteReader, length uint8) (uint64, error) {
}
// ReadUint64 reads a uint64
func ReadUint64(b io.ByteReader) (uint64, error) {
func (littleEndian) ReadUint64(b io.ByteReader) (uint64, error) {
var b1, b2, b3, b4, b5, b6, b7, b8 uint8
var err error
if b1, err = b.ReadByte(); err != nil {
@@ -50,7 +57,7 @@ func ReadUint64(b io.ByteReader) (uint64, error) {
}
// ReadUint32 reads a uint32
func ReadUint32(b io.ByteReader) (uint32, error) {
func (littleEndian) ReadUint32(b io.ByteReader) (uint32, error) {
var b1, b2, b3, b4 uint8
var err error
if b1, err = b.ReadByte(); err != nil {
@@ -69,7 +76,7 @@ func ReadUint32(b io.ByteReader) (uint32, error) {
}
// ReadUint16 reads a uint16
func ReadUint16(b io.ByteReader) (uint16, error) {
func (littleEndian) ReadUint16(b io.ByteReader) (uint16, error) {
var b1, b2 uint8
var err error
if b1, err = b.ReadByte(); err != nil {
@@ -82,7 +89,7 @@ func ReadUint16(b io.ByteReader) (uint16, error) {
}
// WriteUint64 writes a uint64
func WriteUint64(b *bytes.Buffer, i uint64) {
func (littleEndian) WriteUint64(b *bytes.Buffer, i uint64) {
b.Write([]byte{
uint8(i), uint8(i >> 8), uint8(i >> 16), uint8(i >> 24),
uint8(i >> 32), uint8(i >> 40), uint8(i >> 48), uint8(i >> 56),
@@ -90,7 +97,7 @@ func WriteUint64(b *bytes.Buffer, i uint64) {
}
// WriteUint56 writes 56 bit of a uint64
func WriteUint56(b *bytes.Buffer, i uint64) {
func (littleEndian) WriteUint56(b *bytes.Buffer, i uint64) {
b.Write([]byte{
uint8(i), uint8(i >> 8), uint8(i >> 16), uint8(i >> 24),
uint8(i >> 32), uint8(i >> 40), uint8(i >> 48),
@@ -98,7 +105,7 @@ func WriteUint56(b *bytes.Buffer, i uint64) {
}
// WriteUint48 writes 48 bit of a uint64
func WriteUint48(b *bytes.Buffer, i uint64) {
func (littleEndian) WriteUint48(b *bytes.Buffer, i uint64) {
b.Write([]byte{
uint8(i), uint8(i >> 8), uint8(i >> 16), uint8(i >> 24),
uint8(i >> 32), uint8(i >> 40),
@@ -106,7 +113,7 @@ func WriteUint48(b *bytes.Buffer, i uint64) {
}
// WriteUint40 writes 40 bit of a uint64
func WriteUint40(b *bytes.Buffer, i uint64) {
func (littleEndian) WriteUint40(b *bytes.Buffer, i uint64) {
b.Write([]byte{
uint8(i), uint8(i >> 8), uint8(i >> 16),
uint8(i >> 24), uint8(i >> 32),
@@ -114,16 +121,24 @@ func WriteUint40(b *bytes.Buffer, i uint64) {
}
// WriteUint32 writes a uint32
func WriteUint32(b *bytes.Buffer, i uint32) {
func (littleEndian) WriteUint32(b *bytes.Buffer, i uint32) {
b.Write([]byte{uint8(i), uint8(i >> 8), uint8(i >> 16), uint8(i >> 24)})
}
// WriteUint24 writes 24 bit of a uint32
func WriteUint24(b *bytes.Buffer, i uint32) {
func (littleEndian) WriteUint24(b *bytes.Buffer, i uint32) {
b.Write([]byte{uint8(i), uint8(i >> 8), uint8(i >> 16)})
}
// WriteUint16 writes a uint16
func WriteUint16(b *bytes.Buffer, i uint16) {
func (littleEndian) WriteUint16(b *bytes.Buffer, i uint16) {
b.Write([]byte{uint8(i), uint8(i >> 8)})
}
func (l littleEndian) ReadUfloat16(b io.ByteReader) (uint64, error) {
return readUfloat16(b, l)
}
func (l littleEndian) WriteUfloat16(b *bytes.Buffer, val uint64) {
writeUfloat16(b, l, val)
}

View File

@@ -8,11 +8,11 @@ import (
. "github.com/onsi/gomega"
)
var _ = Describe("Utils", func() {
var _ = Describe("Little Endian encoding / decoding", func() {
Context("ReadUint16", func() {
It("reads a little endian", func() {
b := []byte{0x13, 0xEF}
val, err := ReadUint16(bytes.NewReader(b))
val, err := LittleEndian.ReadUint16(bytes.NewReader(b))
Expect(err).ToNot(HaveOccurred())
Expect(val).To(Equal(uint16(0xEF13)))
})
@@ -20,7 +20,7 @@ var _ = Describe("Utils", func() {
It("throws an error if less than 2 bytes are passed", func() {
b := []byte{0x13, 0xEF}
for i := 0; i < len(b); i++ {
_, err := ReadUint16(bytes.NewReader(b[:i]))
_, err := LittleEndian.ReadUint16(bytes.NewReader(b[:i]))
Expect(err).To(MatchError(io.EOF))
}
})
@@ -29,7 +29,7 @@ var _ = Describe("Utils", func() {
Context("ReadUint32", func() {
It("reads a little endian", func() {
b := []byte{0x12, 0x35, 0xAB, 0xFF}
val, err := ReadUint32(bytes.NewReader(b))
val, err := LittleEndian.ReadUint32(bytes.NewReader(b))
Expect(err).ToNot(HaveOccurred())
Expect(val).To(Equal(uint32(0xFFAB3512)))
})
@@ -37,7 +37,7 @@ var _ = Describe("Utils", func() {
It("throws an error if less than 4 bytes are passed", func() {
b := []byte{0x12, 0x35, 0xAB, 0xFF}
for i := 0; i < len(b); i++ {
_, err := ReadUint32(bytes.NewReader(b[:i]))
_, err := LittleEndian.ReadUint32(bytes.NewReader(b[:i]))
Expect(err).To(MatchError(io.EOF))
}
})
@@ -46,7 +46,7 @@ var _ = Describe("Utils", func() {
Context("ReadUint64", func() {
It("reads a little endian", func() {
b := []byte{0x12, 0x35, 0xAB, 0xFF, 0xEF, 0xBE, 0xAD, 0xDE}
val, err := ReadUint64(bytes.NewReader(b))
val, err := LittleEndian.ReadUint64(bytes.NewReader(b))
Expect(err).ToNot(HaveOccurred())
Expect(val).To(Equal(uint64(0xDEADBEEFFFAB3512)))
})
@@ -54,7 +54,7 @@ var _ = Describe("Utils", func() {
It("throws an error if less than 8 bytes are passed", func() {
b := []byte{0x12, 0x35, 0xAB, 0xFF, 0xEF, 0xBE, 0xAD, 0xDE}
for i := 0; i < len(b); i++ {
_, err := ReadUint64(bytes.NewReader(b[:i]))
_, err := LittleEndian.ReadUint64(bytes.NewReader(b[:i]))
Expect(err).To(MatchError(io.EOF))
}
})
@@ -63,14 +63,14 @@ var _ = Describe("Utils", func() {
Context("WriteUint16", func() {
It("outputs 2 bytes", func() {
b := &bytes.Buffer{}
WriteUint16(b, uint16(1))
LittleEndian.WriteUint16(b, uint16(1))
Expect(b.Len()).To(Equal(2))
})
It("outputs a little endian", func() {
num := uint16(0xFF11)
b := &bytes.Buffer{}
WriteUint16(b, num)
LittleEndian.WriteUint16(b, num)
Expect(b.Bytes()).To(Equal([]byte{0x11, 0xFF}))
})
})
@@ -78,14 +78,14 @@ var _ = Describe("Utils", func() {
Context("WriteUint24", func() {
It("outputs 3 bytes", func() {
b := &bytes.Buffer{}
WriteUint24(b, uint32(1))
LittleEndian.WriteUint24(b, uint32(1))
Expect(b.Len()).To(Equal(3))
})
It("outputs a little endian", func() {
num := uint32(0xEFAC3512)
b := &bytes.Buffer{}
WriteUint24(b, num)
LittleEndian.WriteUint24(b, num)
Expect(b.Bytes()).To(Equal([]byte{0x12, 0x35, 0xAC}))
})
})
@@ -93,14 +93,14 @@ var _ = Describe("Utils", func() {
Context("WriteUint32", func() {
It("outputs 4 bytes", func() {
b := &bytes.Buffer{}
WriteUint32(b, uint32(1))
LittleEndian.WriteUint32(b, uint32(1))
Expect(b.Len()).To(Equal(4))
})
It("outputs a little endian", func() {
num := uint32(0xEFAC3512)
b := &bytes.Buffer{}
WriteUint32(b, num)
LittleEndian.WriteUint32(b, num)
Expect(b.Bytes()).To(Equal([]byte{0x12, 0x35, 0xAC, 0xEF}))
})
})
@@ -108,14 +108,14 @@ var _ = Describe("Utils", func() {
Context("WriteUint40", func() {
It("outputs 5 bytes", func() {
b := &bytes.Buffer{}
WriteUint40(b, uint64(1))
LittleEndian.WriteUint40(b, uint64(1))
Expect(b.Len()).To(Equal(5))
})
It("outputs a little endian", func() {
num := uint64(0xDEADBEEFCAFE)
b := &bytes.Buffer{}
WriteUint40(b, num)
LittleEndian.WriteUint40(b, num)
Expect(b.Bytes()).To(Equal([]byte{0xFE, 0xCA, 0xEF, 0xBE, 0xAD}))
})
})
@@ -123,21 +123,21 @@ var _ = Describe("Utils", func() {
Context("WriteUint48", func() {
It("outputs 6 bytes", func() {
b := &bytes.Buffer{}
WriteUint48(b, uint64(1))
LittleEndian.WriteUint48(b, uint64(1))
Expect(b.Len()).To(Equal(6))
})
It("outputs a little endian", func() {
num := uint64(0xDEADBEEFCAFE)
b := &bytes.Buffer{}
WriteUint48(b, num)
LittleEndian.WriteUint48(b, num)
Expect(b.Bytes()).To(Equal([]byte{0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE}))
})
It("doesn't care about the two higher order bytes", func() {
num := uint64(0x1337DEADBEEFCAFE)
b := &bytes.Buffer{}
WriteUint48(b, num)
LittleEndian.WriteUint48(b, num)
Expect(b.Len()).To(Equal(6))
Expect(b.Bytes()).To(Equal([]byte{0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE}))
})
@@ -146,14 +146,14 @@ var _ = Describe("Utils", func() {
Context("WriteUint56", func() {
It("outputs 7 bytes", func() {
b := &bytes.Buffer{}
WriteUint56(b, uint64(1))
LittleEndian.WriteUint56(b, uint64(1))
Expect(b.Len()).To(Equal(7))
})
It("outputs a little endian", func() {
num := uint64(0xFFEEDDCCBBAA9988)
b := &bytes.Buffer{}
WriteUint56(b, num)
LittleEndian.WriteUint56(b, num)
Expect(b.Bytes()).To(Equal([]byte{0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE}))
})
})
@@ -161,14 +161,14 @@ var _ = Describe("Utils", func() {
Context("WriteUint64", func() {
It("outputs 8 bytes", func() {
b := &bytes.Buffer{}
WriteUint64(b, uint64(1))
LittleEndian.WriteUint64(b, uint64(1))
Expect(b.Len()).To(Equal(8))
})
It("outputs a little endian", func() {
num := uint64(0xFFEEDDCCBBAA9988)
b := &bytes.Buffer{}
WriteUint64(b, num)
LittleEndian.WriteUint64(b, num)
Expect(b.Bytes()).To(Equal([]byte{0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}))
})
})
@@ -181,7 +181,7 @@ var _ = Describe("Utils", func() {
}
for n, expected := range m {
b := bytes.NewReader([]byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8})
i, err := ReadUintN(b, n)
i, err := LittleEndian.ReadUintN(b, n)
Expect(err).ToNot(HaveOccurred())
Expect(i).To(Equal(expected))
}
@@ -189,7 +189,7 @@ var _ = Describe("Utils", func() {
It("errors", func() {
b := bytes.NewReader([]byte{0x1, 0x2})
_, err := ReadUintN(b, 3)
_, err := LittleEndian.ReadUintN(b, 3)
Expect(err).To(HaveOccurred())
})
})

View File

@@ -21,9 +21,9 @@ const uFloat16MantissaBits = 16 - uFloat16ExponentBits
const uFloat16MantissaEffectiveBits = uFloat16MantissaBits + 1 // 12
const uFloat16MaxValue = ((uint64(1) << uFloat16MantissaEffectiveBits) - 1) << uFloat16MaxExponent // 0x3FFC0000000
// ReadUfloat16 reads a float in the QUIC-float16 format and returns its uint64 representation
func ReadUfloat16(b io.ByteReader) (uint64, error) {
val, err := ReadUint16(b)
// readUfloat16 reads a float in the QUIC-float16 format and returns its uint64 representation
func readUfloat16(b io.ByteReader, byteOrder ByteOrder) (uint64, error) {
val, err := byteOrder.ReadUint16(b)
if err != nil {
return 0, err
}
@@ -50,8 +50,8 @@ func ReadUfloat16(b io.ByteReader) (uint64, error) {
return res, nil
}
// WriteUfloat16 writes a float in the QUIC-float16 format from its uint64 representation
func WriteUfloat16(b *bytes.Buffer, value uint64) {
// writeUfloat16 writes a float in the QUIC-float16 format from its uint64 representation
func writeUfloat16(b *bytes.Buffer, byteOrder ByteOrder, value uint64) {
var result uint16
if value < (uint64(1) << uFloat16MantissaEffectiveBits) {
// Fast path: either the value is denormalized, or has exponent zero.
@@ -82,5 +82,5 @@ func WriteUfloat16(b *bytes.Buffer, value uint64) {
result = (uint16(value) + (exponent << uFloat16MantissaBits))
}
WriteUint16(b, result)
byteOrder.WriteUint16(b, result)
}

View File

@@ -60,15 +60,15 @@ var _ = Describe("float16", func() {
}
for _, testcase := range testcases {
b := &bytes.Buffer{}
WriteUint16(b, testcase.binary)
val, err := ReadUfloat16(b)
LittleEndian.WriteUint16(b, testcase.binary)
val, err := LittleEndian.ReadUfloat16(b)
Expect(err).NotTo(HaveOccurred())
Expect(val).To(Equal(testcase.expected))
}
})
It("errors on eof", func() {
_, err := ReadUfloat16(&bytes.Buffer{})
_, err := LittleEndian.ReadUfloat16(&bytes.Buffer{})
Expect(err).To(MatchError(io.EOF))
})
@@ -141,8 +141,8 @@ var _ = Describe("float16", func() {
}
for _, testcase := range testcases {
b := &bytes.Buffer{}
WriteUfloat16(b, testcase.decoded)
val, err := ReadUint16(b)
LittleEndian.WriteUfloat16(b, testcase.decoded)
val, err := LittleEndian.ReadUint16(b)
Expect(err).NotTo(HaveOccurred())
Expect(val).To(Equal(testcase.encoded))
}

View File

@@ -74,11 +74,11 @@ func (h *PublicHeader) Write(b *bytes.Buffer, version protocol.VersionNumber, pe
b.WriteByte(publicFlagByte)
if !h.TruncateConnectionID {
utils.WriteUint64(b, uint64(h.ConnectionID))
utils.LittleEndian.WriteUint64(b, uint64(h.ConnectionID))
}
if h.VersionFlag && pers == protocol.PerspectiveClient {
utils.WriteUint32(b, protocol.VersionNumberToTag(h.VersionNumber))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(h.VersionNumber))
}
if len(h.DiversificationNonce) > 0 {
@@ -98,11 +98,11 @@ func (h *PublicHeader) Write(b *bytes.Buffer, version protocol.VersionNumber, pe
case protocol.PacketNumberLen1:
b.WriteByte(uint8(h.PacketNumber))
case protocol.PacketNumberLen2:
utils.WriteUint16(b, uint16(h.PacketNumber))
utils.LittleEndian.WriteUint16(b, uint16(h.PacketNumber))
case protocol.PacketNumberLen4:
utils.WriteUint32(b, uint32(h.PacketNumber))
utils.LittleEndian.WriteUint32(b, uint32(h.PacketNumber))
case protocol.PacketNumberLen6:
utils.WriteUint48(b, uint64(h.PacketNumber))
utils.LittleEndian.WriteUint48(b, uint64(h.PacketNumber))
default:
return errPacketNumberLenNotSet
}
@@ -151,7 +151,7 @@ func ParsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Pub
// Connection ID
if !header.TruncateConnectionID {
var connID uint64
connID, err = utils.ReadUint64(b)
connID, err = utils.LittleEndian.ReadUint64(b)
if err != nil {
return nil, err
}
@@ -178,7 +178,7 @@ func ParsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Pub
if header.VersionFlag {
if packetSentBy == protocol.PerspectiveClient {
var versionTag uint32
versionTag, err = utils.ReadUint32(b)
versionTag, err = utils.LittleEndian.ReadUint32(b)
if err != nil {
return nil, err
}
@@ -190,7 +190,7 @@ func ParsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Pub
header.SupportedVersions = make([]protocol.VersionNumber, 0)
for {
var versionTag uint32
versionTag, err = utils.ReadUint32(b)
versionTag, err = utils.LittleEndian.ReadUint32(b)
if err != nil {
break
}
@@ -203,7 +203,7 @@ func ParsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Pub
// Packet number
if header.hasPacketNumber(packetSentBy) {
packetNumber, err := utils.ReadUintN(b, uint8(header.PacketNumberLen))
packetNumber, err := utils.LittleEndian.ReadUintN(b, uint8(header.PacketNumberLen))
if err != nil {
return nil, err
}

View File

@@ -18,15 +18,15 @@ type publicReset struct {
func writePublicReset(connectionID protocol.ConnectionID, rejectedPacketNumber protocol.PacketNumber, nonceProof uint64) []byte {
b := &bytes.Buffer{}
b.WriteByte(0x0a)
utils.WriteUint64(b, uint64(connectionID))
utils.WriteUint32(b, uint32(handshake.TagPRST))
utils.WriteUint32(b, 2)
utils.WriteUint32(b, uint32(handshake.TagRNON))
utils.WriteUint32(b, 8)
utils.WriteUint32(b, uint32(handshake.TagRSEQ))
utils.WriteUint32(b, 16)
utils.WriteUint64(b, nonceProof)
utils.WriteUint64(b, uint64(rejectedPacketNumber))
utils.LittleEndian.WriteUint64(b, uint64(connectionID))
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagPRST))
utils.LittleEndian.WriteUint32(b, 2)
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagRNON))
utils.LittleEndian.WriteUint32(b, 8)
utils.LittleEndian.WriteUint32(b, uint32(handshake.TagRSEQ))
utils.LittleEndian.WriteUint32(b, 16)
utils.LittleEndian.WriteUint64(b, nonceProof)
utils.LittleEndian.WriteUint64(b, uint64(rejectedPacketNumber))
return b.Bytes()
}

View File

@@ -332,7 +332,7 @@ func composeVersionNegotiation(connectionID protocol.ConnectionID, versions []pr
utils.Errorf("error composing version negotiation packet: %s", err.Error())
}
for _, v := range versions {
utils.WriteUint32(fullReply, protocol.VersionNumberToTag(v))
utils.LittleEndian.WriteUint32(fullReply, protocol.VersionNumberToTag(v))
}
return fullReply.Bytes()
}

View File

@@ -114,7 +114,7 @@ var _ = Describe("Server", func() {
errorChan: make(chan struct{}),
}
b := &bytes.Buffer{}
utils.WriteUint32(b, protocol.VersionNumberToTag(protocol.SupportedVersions[0]))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(protocol.SupportedVersions[0]))
firstPacket = []byte{0x09, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c}
firstPacket = append(append(firstPacket, b.Bytes()...), 0x01)
})
@@ -288,7 +288,7 @@ var _ = Describe("Server", func() {
Expect(serv.sessions[connID].(*mockSession).packetCount).To(Equal(1))
b := &bytes.Buffer{}
// add an unsupported version
utils.WriteUint32(b, protocol.VersionNumberToTag(protocol.SupportedVersions[0]+1))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(protocol.SupportedVersions[0]+1))
data := []byte{0x09, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c}
data = append(append(data, b.Bytes()...), 0x01)
err = serv.handlePacket(nil, nil, data)
@@ -420,7 +420,7 @@ var _ = Describe("Server", func() {
Eventually(func() int { return conn.dataWritten.Len() }).ShouldNot(BeZero())
Expect(conn.dataWrittenTo).To(Equal(udpAddr))
b = &bytes.Buffer{}
utils.WriteUint32(b, protocol.VersionNumberToTag(99))
utils.LittleEndian.WriteUint32(b, protocol.VersionNumberToTag(99))
expected := append(
[]byte{0x9, 0x37, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
b.Bytes()...,