forked from quic-go/quic-go
split STREAM and ACK frames in seperate files
This commit is contained in:
26
ack_frame.go
Normal file
26
ack_frame.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// An AckFrame in QUIC
|
||||
type AckFrame struct {
|
||||
Entropy byte
|
||||
LargestObserved uint32 // TODO: change to uint64
|
||||
}
|
||||
|
||||
// WriteAckFrame 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
|
||||
return nil
|
||||
}
|
||||
21
ack_frame_test.go
Normal file
21
ack_frame_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("AckFrame", func() {
|
||||
Context("when writing", func() {
|
||||
It("writes simple frames", func() {
|
||||
b := &bytes.Buffer{}
|
||||
(&AckFrame{
|
||||
Entropy: 2,
|
||||
LargestObserved: 1,
|
||||
}).Write(b)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x48, 0x02, 0x01, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0}))
|
||||
})
|
||||
})
|
||||
})
|
||||
102
frame.go
102
frame.go
@@ -1,108 +1,8 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
import "bytes"
|
||||
|
||||
// A Frame in QUIC
|
||||
type Frame interface {
|
||||
Write(b *bytes.Buffer) error
|
||||
}
|
||||
|
||||
// A StreamFrame of QUIC
|
||||
type StreamFrame struct {
|
||||
FinBit bool
|
||||
StreamID uint32
|
||||
Offset uint64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// ParseStreamFrame reads a stream frame. The type byte must not have been read yet.
|
||||
func ParseStreamFrame(r *bytes.Reader, typeByte byte) (*StreamFrame, error) {
|
||||
frame := &StreamFrame{}
|
||||
|
||||
frame.FinBit = typeByte&0x40 > 0
|
||||
dataLenPresent := typeByte&0x20 > 0
|
||||
offsetLen := typeByte & 0x1C >> 2
|
||||
if offsetLen != 0 {
|
||||
offsetLen++
|
||||
}
|
||||
streamIDLen := typeByte&0x03 + 1
|
||||
|
||||
sid, err := utils.ReadUintN(r, streamIDLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.StreamID = uint32(sid)
|
||||
|
||||
frame.Offset, err = utils.ReadUintN(r, offsetLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dataLen uint16
|
||||
if dataLenPresent {
|
||||
dataLen, err = utils.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if dataLen == 0 {
|
||||
// The rest of the packet is data
|
||||
frame.Data, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
frame.Data = make([]byte, dataLen)
|
||||
if _, err := r.Read(frame.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// WriteStreamFrame writes a stream frame.
|
||||
func (f *StreamFrame) Write(b *bytes.Buffer) error {
|
||||
typeByte := uint8(0x80)
|
||||
if f.FinBit {
|
||||
typeByte ^= 0x40
|
||||
}
|
||||
typeByte ^= 0x20
|
||||
if f.Offset != 0 {
|
||||
typeByte ^= 0x1c // TODO: Send shorter offset if possible
|
||||
}
|
||||
typeByte ^= 0x03 // TODO: Send shorter stream ID if possible
|
||||
b.WriteByte(typeByte)
|
||||
utils.WriteUint32(b, f.StreamID)
|
||||
if f.Offset != 0 {
|
||||
utils.WriteUint64(b, f.Offset)
|
||||
}
|
||||
utils.WriteUint16(b, uint16(len(f.Data)))
|
||||
b.Write(f.Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// An AckFrame in QUIC
|
||||
type AckFrame struct {
|
||||
Entropy byte
|
||||
LargestObserved uint32 // TODO: change to uint64
|
||||
}
|
||||
|
||||
// WriteAckFrame 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
|
||||
return nil
|
||||
}
|
||||
|
||||
84
stream_frame.go
Normal file
84
stream_frame.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A StreamFrame of QUIC
|
||||
type StreamFrame struct {
|
||||
FinBit bool
|
||||
StreamID uint32
|
||||
Offset uint64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// ParseStreamFrame reads a stream frame. The type byte must not have been read yet.
|
||||
func ParseStreamFrame(r *bytes.Reader, typeByte byte) (*StreamFrame, error) {
|
||||
frame := &StreamFrame{}
|
||||
|
||||
frame.FinBit = typeByte&0x40 > 0
|
||||
dataLenPresent := typeByte&0x20 > 0
|
||||
offsetLen := typeByte & 0x1C >> 2
|
||||
if offsetLen != 0 {
|
||||
offsetLen++
|
||||
}
|
||||
streamIDLen := typeByte&0x03 + 1
|
||||
|
||||
sid, err := utils.ReadUintN(r, streamIDLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame.StreamID = uint32(sid)
|
||||
|
||||
frame.Offset, err = utils.ReadUintN(r, offsetLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dataLen uint16
|
||||
if dataLenPresent {
|
||||
dataLen, err = utils.ReadUint16(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if dataLen == 0 {
|
||||
// The rest of the packet is data
|
||||
frame.Data, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
frame.Data = make([]byte, dataLen)
|
||||
if _, err := r.Read(frame.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// WriteStreamFrame writes a stream frame.
|
||||
func (f *StreamFrame) Write(b *bytes.Buffer) error {
|
||||
typeByte := uint8(0x80)
|
||||
if f.FinBit {
|
||||
typeByte ^= 0x40
|
||||
}
|
||||
typeByte ^= 0x20
|
||||
if f.Offset != 0 {
|
||||
typeByte ^= 0x1c // TODO: Send shorter offset if possible
|
||||
}
|
||||
typeByte ^= 0x03 // TODO: Send shorter stream ID if possible
|
||||
b.WriteByte(typeByte)
|
||||
utils.WriteUint32(b, f.StreamID)
|
||||
if f.Offset != 0 {
|
||||
utils.WriteUint64(b, f.Offset)
|
||||
}
|
||||
utils.WriteUint16(b, uint16(len(f.Data)))
|
||||
b.Write(f.Data)
|
||||
return nil
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Frame", func() {
|
||||
var _ = Describe("StreamFrame", func() {
|
||||
Context("stream frames", func() {
|
||||
Context("when parsing", func() {
|
||||
It("accepts sample frame", func() {
|
||||
@@ -52,17 +52,4 @@ var _ = Describe("Frame", func() {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("ACK frames", func() {
|
||||
Context("when writing", func() {
|
||||
It("writes simple frames", func() {
|
||||
b := &bytes.Buffer{}
|
||||
(&AckFrame{
|
||||
Entropy: 2,
|
||||
LargestObserved: 1,
|
||||
}).Write(b)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x48, 0x02, 0x01, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0}))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user