From a5a7021fedbf52b36289e56105fdc01a3ecab8c1 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Fri, 15 Apr 2016 16:00:15 +0700 Subject: [PATCH] basic ACK frame parsing --- ack_frame.go | 86 +++++++++++++++++++++++++++++++++++++++++++++++----- session.go | 7 +++++ 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/ack_frame.go b/ack_frame.go index 4de785531..a77b84a6e 100644 --- a/ack_frame.go +++ b/ack_frame.go @@ -9,18 +9,90 @@ import ( // An AckFrame in QUIC type AckFrame struct { Entropy byte - LargestObserved uint32 // TODO: change to uint64 + LargestObserved uint64 + DelayTime uint16 // Todo: properly interpret this value as described in the specification } -// WriteAckFrame writes an ack frame. +// Write writes an ACK frame. func (f *AckFrame) Write(b *bytes.Buffer) error { typeByte := uint8(0x48) b.WriteByte(typeByte) b.WriteByte(f.Entropy) - utils.WriteUint32(b, f.LargestObserved) - utils.WriteUint16(b, 1) // TODO: Ack delay time - b.WriteByte(0x01) // Just one timestamp - b.WriteByte(0x00) // Largest observed - utils.WriteUint32(b, 0) // First timestamp + utils.WriteUint32(b, uint32(f.LargestObserved)) // TODO: send the correct length + utils.WriteUint16(b, 1) // TODO: Ack delay time + b.WriteByte(0x01) // Just one timestamp + b.WriteByte(0x00) // Largest observed + utils.WriteUint32(b, 0) // First timestamp return nil } + +// ParseAckFrame reads an ACK frame +func ParseAckFrame(r *bytes.Reader, typeByte byte) (*AckFrame, error) { + frame := &AckFrame{} + + if typeByte&0x20 == 0x20 { + panic("NACK ranges not yet implemented.") + } + if typeByte&0x10 == 0x10 { + panic("truncated ACKs not yet implemented.") + } + + var largestObservedLen uint8 = 2 * ((typeByte & 0x0C) >> 2) + if largestObservedLen == 0 { + largestObservedLen = 1 + } + + var missingSequenceNumberDeltaLen uint8 = 2 * (typeByte & 0x03) + if missingSequenceNumberDeltaLen == 0 { + missingSequenceNumberDeltaLen = 1 + } + + var err error + frame.Entropy, err = r.ReadByte() + if err != nil { + return nil, err + } + + frame.LargestObserved, err = utils.ReadUintN(r, largestObservedLen) + if err != nil { + return nil, err + } + + frame.DelayTime, err = utils.ReadUint16(r) + if err != nil { + return nil, err + } + + numTimestampByte, err := r.ReadByte() + if err != nil { + return nil, err + } + numTimestamp := uint8(numTimestampByte) + + // Delta Largest observed + _, err = r.ReadByte() + if err != nil { + return nil, err + } + + // First Timestamp + _, err = utils.ReadUint32(r) + if err != nil { + return nil, err + } + + for i := 0; i < int(numTimestamp)-1; i++ { + // Delta Largest observed + _, err = r.ReadByte() + if err != nil { + return nil, err + } + // Time Since Previous Timestamp + _, err := utils.ReadUint16(r) + if err != nil { + return nil, err + } + } + + return frame, nil +} diff --git a/session.go b/session.go index 7a146edc0..95323c7fd 100644 --- a/session.go +++ b/session.go @@ -88,6 +88,13 @@ func (s *Session) HandlePacket(addr *net.UDPAddr, publicHeaderBinary []byte, pub } } else if typeByte&0xC0 == 0x40 { // ACK fmt.Println("Detected ACK") + frame, err := ParseAckFrame(r, typeByte) + if err != nil { + return err + } + + fmt.Printf("%#v\n", frame) + continue // not yet implemented } else if typeByte&0xE0 == 0x20 { // CONGESTION_FEEDBACK fmt.Println("Detected CONGESTION_FEEDBACK")