mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-06 13:47:35 +03:00
make stream private
This commit is contained in:
parent
a79f7c4dc6
commit
23a1e08e90
7 changed files with 155 additions and 146 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
|
"github.com/lucas-clemente/quic-go/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var supportedVersions = map[protocol.VersionNumber]bool{
|
var supportedVersions = map[protocol.VersionNumber]bool{
|
||||||
|
@ -40,8 +41,8 @@ func main() {
|
||||||
type responseWriter struct {
|
type responseWriter struct {
|
||||||
session *quic.Session
|
session *quic.Session
|
||||||
dataStreamID protocol.StreamID
|
dataStreamID protocol.StreamID
|
||||||
headerStream *quic.Stream
|
headerStream utils.Stream
|
||||||
dataStream *quic.Stream
|
dataStream utils.Stream
|
||||||
|
|
||||||
header http.Header
|
header http.Header
|
||||||
headerWritten bool
|
headerWritten bool
|
||||||
|
@ -105,7 +106,7 @@ func (w *responseWriter) Write(p []byte) (int, error) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleStream(session *quic.Session, headerStream *quic.Stream) {
|
func handleStream(session *quic.Session, headerStream utils.Stream) {
|
||||||
hpackDecoder := hpack.NewDecoder(4096, nil)
|
hpackDecoder := hpack.NewDecoder(4096, nil)
|
||||||
h2framer := http2.NewFramer(nil, headerStream)
|
h2framer := http2.NewFramer(nil, headerStream)
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,10 @@ func (s *mockStream) Write(p []byte) (int, error) {
|
||||||
return s.dataWritten.Write(p)
|
return s.dataWritten.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *mockStream) Close() error {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
var _ = Describe("Crypto setup", func() {
|
var _ = Describe("Crypto setup", func() {
|
||||||
var (
|
var (
|
||||||
kex *mockKEX
|
kex *mockKEX
|
||||||
|
|
28
session.go
28
session.go
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/lucas-clemente/quic-go/frames"
|
"github.com/lucas-clemente/quic-go/frames"
|
||||||
"github.com/lucas-clemente/quic-go/handshake"
|
"github.com/lucas-clemente/quic-go/handshake"
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
|
"github.com/lucas-clemente/quic-go/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type receivedPacket struct {
|
type receivedPacket struct {
|
||||||
|
@ -21,7 +22,7 @@ type receivedPacket struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// StreamCallback gets a stream frame and returns a reply frame
|
// StreamCallback gets a stream frame and returns a reply frame
|
||||||
type StreamCallback func(*Session, *Stream)
|
type StreamCallback func(*Session, utils.Stream)
|
||||||
|
|
||||||
// A Session is a QUIC session
|
// A Session is a QUIC session
|
||||||
type Session struct {
|
type Session struct {
|
||||||
|
@ -30,7 +31,7 @@ type Session struct {
|
||||||
connection *net.UDPConn
|
connection *net.UDPConn
|
||||||
currentRemoteAddr *net.UDPAddr
|
currentRemoteAddr *net.UDPAddr
|
||||||
|
|
||||||
streams map[protocol.StreamID]*Stream
|
streams map[protocol.StreamID]*stream
|
||||||
streamsMutex sync.RWMutex
|
streamsMutex sync.RWMutex
|
||||||
|
|
||||||
outgoingAckHandler ackhandler.OutgoingPacketAckHandler
|
outgoingAckHandler ackhandler.OutgoingPacketAckHandler
|
||||||
|
@ -47,7 +48,7 @@ func NewSession(conn *net.UDPConn, v protocol.VersionNumber, connectionID protoc
|
||||||
session := &Session{
|
session := &Session{
|
||||||
connection: conn,
|
connection: conn,
|
||||||
streamCallback: streamCallback,
|
streamCallback: streamCallback,
|
||||||
streams: make(map[protocol.StreamID]*Stream),
|
streams: make(map[protocol.StreamID]*stream),
|
||||||
outgoingAckHandler: ackhandler.NewOutgoingPacketAckHandler(),
|
outgoingAckHandler: ackhandler.NewOutgoingPacketAckHandler(),
|
||||||
incomingAckHandler: ackhandler.NewIncomingPacketAckHandler(),
|
incomingAckHandler: ackhandler.NewIncomingPacketAckHandler(),
|
||||||
receivedPackets: make(chan receivedPacket),
|
receivedPackets: make(chan receivedPacket),
|
||||||
|
@ -133,21 +134,22 @@ func (s *Session) handleStreamFrame(frame *frames.StreamFrame) error {
|
||||||
return errors.New("Session: 0 is not a valid Stream ID")
|
return errors.New("Session: 0 is not a valid Stream ID")
|
||||||
}
|
}
|
||||||
s.streamsMutex.RLock()
|
s.streamsMutex.RLock()
|
||||||
stream, existingStream := s.streams[frame.StreamID]
|
str, streamExists := s.streams[frame.StreamID]
|
||||||
s.streamsMutex.RUnlock()
|
s.streamsMutex.RUnlock()
|
||||||
|
|
||||||
if !existingStream {
|
if !streamExists {
|
||||||
stream, _ = s.NewStream(frame.StreamID)
|
ss, _ := s.NewStream(frame.StreamID)
|
||||||
|
str = ss.(*stream)
|
||||||
}
|
}
|
||||||
if stream == nil {
|
if str == nil {
|
||||||
return errors.New("Session: reopening streams is not allowed")
|
return errors.New("Session: reopening streams is not allowed")
|
||||||
}
|
}
|
||||||
err := stream.AddStreamFrame(frame)
|
err := str.AddStreamFrame(frame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !existingStream {
|
if !streamExists {
|
||||||
s.streamCallback(s, stream)
|
s.streamCallback(s, str)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -193,11 +195,11 @@ func (s *Session) QueueFrame(frame frames.Frame) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStream creates a new strean open for reading and writing
|
// NewStream creates a new stream open for reading and writing
|
||||||
func (s *Session) NewStream(id protocol.StreamID) (*Stream, error) {
|
func (s *Session) NewStream(id protocol.StreamID) (utils.Stream, error) {
|
||||||
s.streamsMutex.Lock()
|
s.streamsMutex.Lock()
|
||||||
defer s.streamsMutex.Unlock()
|
defer s.streamsMutex.Unlock()
|
||||||
stream := NewStream(s, id)
|
stream := newStream(s, id)
|
||||||
if s.streams[id] != nil {
|
if s.streams[id] != nil {
|
||||||
return nil, fmt.Errorf("Session: stream with ID %d already exists", id)
|
return nil, fmt.Errorf("Session: stream with ID %d already exists", id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/frames"
|
"github.com/lucas-clemente/quic-go/frames"
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
|
"github.com/lucas-clemente/quic-go/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Session", func() {
|
var _ = Describe("Session", func() {
|
||||||
|
@ -19,8 +20,8 @@ var _ = Describe("Session", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
callbackCalled = false
|
callbackCalled = false
|
||||||
session = &Session{
|
session = &Session{
|
||||||
streams: make(map[protocol.StreamID]*Stream),
|
streams: make(map[protocol.StreamID]*stream),
|
||||||
streamCallback: func(*Session, *Stream) { callbackCalled = true },
|
streamCallback: func(*Session, utils.Stream) { callbackCalled = true },
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
104
stream.go
104
stream.go
|
@ -15,66 +15,66 @@ type streamHandler interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
|
// A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
|
||||||
type Stream struct {
|
type stream struct {
|
||||||
Session streamHandler
|
session streamHandler
|
||||||
StreamID protocol.StreamID
|
streamID protocol.StreamID
|
||||||
StreamFrames chan *frames.StreamFrame
|
streamFrames chan *frames.StreamFrame
|
||||||
CurrentFrame *frames.StreamFrame
|
currentFrame *frames.StreamFrame
|
||||||
ReadPosInFrame int
|
readPosInFrame int
|
||||||
WriteOffset uint64
|
writeOffset uint64
|
||||||
ReadOffset uint64
|
readOffset uint64
|
||||||
frameQueue []*frames.StreamFrame // TODO: replace with heap
|
frameQueue []*frames.StreamFrame // TODO: replace with heap
|
||||||
currentErr error
|
currentErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStream creates a new Stream
|
// newStream creates a new Stream
|
||||||
func NewStream(session streamHandler, StreamID protocol.StreamID) *Stream {
|
func newStream(session streamHandler, StreamID protocol.StreamID) *stream {
|
||||||
return &Stream{
|
return &stream{
|
||||||
Session: session,
|
session: session,
|
||||||
StreamID: StreamID,
|
streamID: StreamID,
|
||||||
StreamFrames: make(chan *frames.StreamFrame, 8), // ToDo: add config option for this number
|
streamFrames: make(chan *frames.StreamFrame, 8), // ToDo: add config option for this number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads data
|
// Read reads data
|
||||||
func (s *Stream) Read(p []byte) (int, error) {
|
func (s *stream) Read(p []byte) (int, error) {
|
||||||
bytesRead := 0
|
bytesRead := 0
|
||||||
for bytesRead < len(p) {
|
for bytesRead < len(p) {
|
||||||
if s.CurrentFrame == nil {
|
if s.currentFrame == nil {
|
||||||
var err error
|
var err error
|
||||||
s.CurrentFrame, err = s.getNextFrameInOrder(bytesRead == 0)
|
s.currentFrame, err = s.getNextFrameInOrder(bytesRead == 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return bytesRead, err
|
return bytesRead, err
|
||||||
}
|
}
|
||||||
if s.CurrentFrame == nil {
|
if s.currentFrame == nil {
|
||||||
return bytesRead, nil
|
return bytesRead, nil
|
||||||
}
|
}
|
||||||
s.ReadPosInFrame = 0
|
s.readPosInFrame = 0
|
||||||
}
|
}
|
||||||
m := utils.Min(len(p)-bytesRead, len(s.CurrentFrame.Data)-s.ReadPosInFrame)
|
m := utils.Min(len(p)-bytesRead, len(s.currentFrame.Data)-s.readPosInFrame)
|
||||||
copy(p[bytesRead:], s.CurrentFrame.Data[s.ReadPosInFrame:])
|
copy(p[bytesRead:], s.currentFrame.Data[s.readPosInFrame:])
|
||||||
s.ReadPosInFrame += m
|
s.readPosInFrame += m
|
||||||
bytesRead += m
|
bytesRead += m
|
||||||
s.ReadOffset += uint64(m)
|
s.readOffset += uint64(m)
|
||||||
if s.ReadPosInFrame >= len(s.CurrentFrame.Data) {
|
if s.readPosInFrame >= len(s.currentFrame.Data) {
|
||||||
if s.CurrentFrame.FinBit {
|
if s.currentFrame.FinBit {
|
||||||
s.currentErr = io.EOF
|
s.currentErr = io.EOF
|
||||||
close(s.StreamFrames)
|
close(s.streamFrames)
|
||||||
s.CurrentFrame = nil
|
s.currentFrame = nil
|
||||||
s.Session.closeStream(s.StreamID)
|
s.session.closeStream(s.streamID)
|
||||||
return bytesRead, io.EOF
|
return bytesRead, io.EOF
|
||||||
}
|
}
|
||||||
s.CurrentFrame = nil
|
s.currentFrame = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytesRead, nil
|
return bytesRead, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) getNextFrameInOrder(wait bool) (*frames.StreamFrame, error) {
|
func (s *stream) getNextFrameInOrder(wait bool) (*frames.StreamFrame, error) {
|
||||||
// First, check the queue
|
// First, check the queue
|
||||||
for i, f := range s.frameQueue {
|
for i, f := range s.frameQueue {
|
||||||
if f.Offset == s.ReadOffset {
|
if f.Offset == s.readOffset {
|
||||||
// Move last element into position i
|
// Move last element into position i
|
||||||
s.frameQueue[i] = s.frameQueue[len(s.frameQueue)-1]
|
s.frameQueue[i] = s.frameQueue[len(s.frameQueue)-1]
|
||||||
s.frameQueue = s.frameQueue[:len(s.frameQueue)-1]
|
s.frameQueue = s.frameQueue[:len(s.frameQueue)-1]
|
||||||
|
@ -91,12 +91,12 @@ func (s *Stream) getNextFrameInOrder(wait bool) (*frames.StreamFrame, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if nextFrameFromChannel.Offset == s.ReadOffset {
|
if nextFrameFromChannel.Offset == s.readOffset {
|
||||||
return nextFrameFromChannel, nil
|
return nextFrameFromChannel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard if we already know it
|
// Discard if we already know it
|
||||||
if nextFrameFromChannel.Offset < s.ReadOffset {
|
if nextFrameFromChannel.Offset < s.readOffset {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,15 +105,15 @@ func (s *Stream) getNextFrameInOrder(wait bool) (*frames.StreamFrame, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) nextFrameInChan(blocking bool) (f *frames.StreamFrame, err error) {
|
func (s *stream) nextFrameInChan(blocking bool) (f *frames.StreamFrame, err error) {
|
||||||
var ok bool
|
var ok bool
|
||||||
if blocking {
|
if blocking {
|
||||||
select {
|
select {
|
||||||
case f, ok = <-s.StreamFrames:
|
case f, ok = <-s.streamFrames:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
select {
|
select {
|
||||||
case f, ok = <-s.StreamFrames:
|
case f, ok = <-s.streamFrames:
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,48 +124,48 @@ func (s *Stream) nextFrameInChan(blocking bool) (f *frames.StreamFrame, err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadByte implements io.ByteReader
|
// ReadByte implements io.ByteReader
|
||||||
func (s *Stream) ReadByte() (byte, error) {
|
func (s *stream) ReadByte() (byte, error) {
|
||||||
// TODO: Optimize
|
// TODO: Optimize
|
||||||
p := make([]byte, 1)
|
p := make([]byte, 1)
|
||||||
_, err := io.ReadFull(s, p)
|
_, err := io.ReadFull(s, p)
|
||||||
return p[0], err
|
return p[0], err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) Write(p []byte) (int, error) {
|
func (s *stream) Write(p []byte) (int, error) {
|
||||||
data := make([]byte, len(p))
|
data := make([]byte, len(p))
|
||||||
copy(data, p)
|
copy(data, p)
|
||||||
err := s.Session.QueueFrame(&frames.StreamFrame{
|
err := s.session.QueueFrame(&frames.StreamFrame{
|
||||||
StreamID: s.StreamID,
|
StreamID: s.streamID,
|
||||||
Offset: s.WriteOffset,
|
Offset: s.writeOffset,
|
||||||
Data: data,
|
Data: data,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
s.WriteOffset += uint64(len(p))
|
s.writeOffset += uint64(len(p))
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implements io.Closer
|
// Close implements io.Closer
|
||||||
func (s *Stream) Close() error {
|
func (s *stream) Close() error {
|
||||||
fmt.Printf("Closing stream %d\n", s.StreamID)
|
fmt.Printf("Closing stream %d\n", s.streamID)
|
||||||
return s.Session.QueueFrame(&frames.StreamFrame{
|
return s.session.QueueFrame(&frames.StreamFrame{
|
||||||
StreamID: s.StreamID,
|
StreamID: s.streamID,
|
||||||
Offset: s.WriteOffset,
|
Offset: s.writeOffset,
|
||||||
FinBit: true,
|
FinBit: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddStreamFrame adds a new stream frame
|
// AddStreamFrame adds a new stream frame
|
||||||
func (s *Stream) AddStreamFrame(frame *frames.StreamFrame) error {
|
func (s *stream) AddStreamFrame(frame *frames.StreamFrame) error {
|
||||||
s.StreamFrames <- frame
|
s.streamFrames <- frame
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterError is called by session to indicate that an error occured and the
|
// RegisterError is called by session to indicate that an error occured and the
|
||||||
// stream should be closed.
|
// stream should be closed.
|
||||||
func (s *Stream) RegisterError(err error) {
|
func (s *stream) RegisterError(err error) {
|
||||||
s.currentErr = err
|
s.currentErr = err
|
||||||
s.Session.closeStream(s.StreamID)
|
s.session.closeStream(s.streamID)
|
||||||
close(s.StreamFrames)
|
close(s.streamFrames)
|
||||||
}
|
}
|
||||||
|
|
152
stream_test.go
152
stream_test.go
|
@ -27,13 +27,13 @@ func (m *mockStreamHandler) closeStream(protocol.StreamID) {
|
||||||
|
|
||||||
var _ = Describe("Stream", func() {
|
var _ = Describe("Stream", func() {
|
||||||
var (
|
var (
|
||||||
stream *Stream
|
str *stream
|
||||||
handler *mockStreamHandler
|
handler *mockStreamHandler
|
||||||
)
|
)
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
handler = &mockStreamHandler{}
|
handler = &mockStreamHandler{}
|
||||||
stream = NewStream(handler, 1337)
|
str = newStream(handler, 1337)
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("reading", func() {
|
Context("reading", func() {
|
||||||
|
@ -42,9 +42,9 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
|
@ -55,13 +55,13 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
b := make([]byte, 2)
|
b := make([]byte, 2)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(2))
|
Expect(n).To(Equal(2))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD}))
|
||||||
n, err = stream.Read(b)
|
n, err = str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(2))
|
Expect(n).To(Equal(2))
|
||||||
Expect(b).To(Equal([]byte{0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xBE, 0xEF}))
|
||||||
|
@ -72,17 +72,17 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
b, err := stream.ReadByte()
|
b, err := str.ReadByte()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(b).To(Equal(byte(0xDE)))
|
Expect(b).To(Equal(byte(0xDE)))
|
||||||
b, err = stream.ReadByte()
|
b, err = str.ReadByte()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(b).To(Equal(byte(0xAD)))
|
Expect(b).To(Equal(byte(0xAD)))
|
||||||
b, err = stream.ReadByte()
|
b, err = str.ReadByte()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(b).To(Equal(byte(0xBE)))
|
Expect(b).To(Equal(byte(0xBE)))
|
||||||
b, err = stream.ReadByte()
|
b, err = str.ReadByte()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(b).To(Equal(byte(0xEF)))
|
Expect(b).To(Equal(byte(0xEF)))
|
||||||
})
|
})
|
||||||
|
@ -96,10 +96,10 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 2,
|
Offset: 2,
|
||||||
Data: []byte{0xBE, 0xEF},
|
Data: []byte{0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame1)
|
str.AddStreamFrame(&frame1)
|
||||||
stream.AddStreamFrame(&frame2)
|
str.AddStreamFrame(&frame2)
|
||||||
b := make([]byte, 6)
|
b := make([]byte, 6)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00}))
|
||||||
|
@ -114,10 +114,10 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 2,
|
Offset: 2,
|
||||||
Data: []byte{0xBE, 0xEF},
|
Data: []byte{0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame1)
|
str.AddStreamFrame(&frame1)
|
||||||
stream.AddStreamFrame(&frame2)
|
str.AddStreamFrame(&frame2)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
|
@ -130,10 +130,10 @@ var _ = Describe("Stream", func() {
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
}
|
}
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
}()
|
}()
|
||||||
b := make([]byte, 2)
|
b := make([]byte, 2)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(2))
|
Expect(n).To(Equal(2))
|
||||||
})
|
})
|
||||||
|
@ -147,10 +147,10 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame1)
|
str.AddStreamFrame(&frame1)
|
||||||
stream.AddStreamFrame(&frame2)
|
str.AddStreamFrame(&frame2)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
|
@ -169,17 +169,17 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 2,
|
Offset: 2,
|
||||||
Data: []byte{0xBE, 0xEF},
|
Data: []byte{0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame1)
|
str.AddStreamFrame(&frame1)
|
||||||
stream.AddStreamFrame(&frame2)
|
str.AddStreamFrame(&frame2)
|
||||||
stream.AddStreamFrame(&frame3)
|
str.AddStreamFrame(&frame3)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("discards unneeded stream frames", func() {
|
It("discards unneeded str frames", func() {
|
||||||
frame1 := frames.StreamFrame{
|
frame1 := frames.StreamFrame{
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
|
@ -192,11 +192,11 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 2,
|
Offset: 2,
|
||||||
Data: []byte{0xBE, 0xEF},
|
Data: []byte{0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame1)
|
str.AddStreamFrame(&frame1)
|
||||||
stream.AddStreamFrame(&frame2)
|
str.AddStreamFrame(&frame2)
|
||||||
stream.AddStreamFrame(&frame3)
|
str.AddStreamFrame(&frame3)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
|
@ -204,8 +204,8 @@ var _ = Describe("Stream", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("writing", func() {
|
Context("writing", func() {
|
||||||
It("writes stream frames", func() {
|
It("writes str frames", func() {
|
||||||
n, err := stream.Write([]byte("foobar"))
|
n, err := str.Write([]byte("foobar"))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(6))
|
Expect(n).To(Equal(6))
|
||||||
Expect(handler.frames).To(HaveLen(1))
|
Expect(handler.frames).To(HaveLen(1))
|
||||||
|
@ -215,11 +215,11 @@ var _ = Describe("Stream", func() {
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("writes multiple stream frames", func() {
|
It("writes multiple str frames", func() {
|
||||||
n, err := stream.Write([]byte("foo"))
|
n, err := str.Write([]byte("foo"))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(3))
|
Expect(n).To(Equal(3))
|
||||||
n, err = stream.Write([]byte("bar"))
|
n, err = str.Write([]byte("bar"))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(3))
|
Expect(n).To(Equal(3))
|
||||||
Expect(handler.frames).To(HaveLen(2))
|
Expect(handler.frames).To(HaveLen(2))
|
||||||
|
@ -235,7 +235,7 @@ var _ = Describe("Stream", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("closes", func() {
|
It("closes", func() {
|
||||||
err := stream.Close()
|
err := str.Close()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(handler.frames).To(HaveLen(1))
|
Expect(handler.frames).To(HaveLen(1))
|
||||||
Expect(handler.frames[0]).To(Equal(&frames.StreamFrame{
|
Expect(handler.frames[0]).To(Equal(&frames.StreamFrame{
|
||||||
|
@ -246,13 +246,13 @@ var _ = Describe("Stream", func() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("getting next stream frame", func() {
|
Context("getting next str frame", func() {
|
||||||
It("gets next frame", func() {
|
It("gets next frame", func() {
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
})
|
})
|
||||||
f, err := stream.getNextFrameInOrder(true)
|
f, err := str.getNextFrameInOrder(true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(f.Data).To(Equal([]byte{0xDE, 0xAD}))
|
Expect(f.Data).To(Equal([]byte{0xDE, 0xAD}))
|
||||||
})
|
})
|
||||||
|
@ -262,80 +262,80 @@ var _ = Describe("Stream", func() {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
b = true
|
b = true
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
f, err := stream.getNextFrameInOrder(true)
|
f, err := str.getNextFrameInOrder(true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(b).To(BeTrue())
|
Expect(b).To(BeTrue())
|
||||||
Expect(f.Data).To(Equal([]byte{0xDE, 0xAD}))
|
Expect(f.Data).To(Equal([]byte{0xDE, 0xAD}))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("queues non-matching stream frames", func() {
|
It("queues non-matching str frames", func() {
|
||||||
var b bool
|
var b bool
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 2,
|
Offset: 2,
|
||||||
Data: []byte{0xBE, 0xEF},
|
Data: []byte{0xBE, 0xEF},
|
||||||
})
|
})
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
b = true
|
b = true
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
f, err := stream.getNextFrameInOrder(true)
|
f, err := str.getNextFrameInOrder(true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(b).To(BeTrue())
|
Expect(b).To(BeTrue())
|
||||||
Expect(f.Data).To(Equal([]byte{0xDE, 0xAD}))
|
Expect(f.Data).To(Equal([]byte{0xDE, 0xAD}))
|
||||||
stream.ReadOffset += 2
|
str.readOffset += 2
|
||||||
f, err = stream.getNextFrameInOrder(true)
|
f, err = str.getNextFrameInOrder(true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(f.Data).To(Equal([]byte{0xBE, 0xEF}))
|
Expect(f.Data).To(Equal([]byte{0xBE, 0xEF}))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns nil if non-blocking", func() {
|
It("returns nil if non-blocking", func() {
|
||||||
Expect(stream.getNextFrameInOrder(false)).To(BeNil())
|
Expect(str.getNextFrameInOrder(false)).To(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns properly if non-blocking", func() {
|
It("returns properly if non-blocking", func() {
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
})
|
})
|
||||||
Expect(stream.getNextFrameInOrder(false)).ToNot(BeNil())
|
Expect(str.getNextFrameInOrder(false)).ToNot(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("dequeues 3rd frame after blocking on 1st", func() {
|
It("dequeues 3rd frame after blocking on 1st", func() {
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 4,
|
Offset: 4,
|
||||||
Data: []byte{0x23, 0x42},
|
Data: []byte{0x23, 0x42},
|
||||||
})
|
})
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 2,
|
Offset: 2,
|
||||||
Data: []byte{0xBE, 0xEF},
|
Data: []byte{0xBE, 0xEF},
|
||||||
})
|
})
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
stream.AddStreamFrame(&frames.StreamFrame{
|
str.AddStreamFrame(&frames.StreamFrame{
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
Expect(stream.getNextFrameInOrder(true)).ToNot(BeNil())
|
Expect(str.getNextFrameInOrder(true)).ToNot(BeNil())
|
||||||
stream.ReadOffset += 2
|
str.readOffset += 2
|
||||||
Expect(stream.getNextFrameInOrder(true)).ToNot(BeNil())
|
Expect(str.getNextFrameInOrder(true)).ToNot(BeNil())
|
||||||
stream.ReadOffset += 2
|
str.readOffset += 2
|
||||||
Expect(stream.getNextFrameInOrder(true)).ToNot(BeNil())
|
Expect(str.getNextFrameInOrder(true)).ToNot(BeNil())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("closing", func() {
|
Context("closing", func() {
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
Expect(stream.StreamFrames).To(BeClosed())
|
Expect(str.streamFrames).To(BeClosed())
|
||||||
Expect(handler.closedStream).To(BeTrue())
|
Expect(handler.closedStream).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -346,13 +346,13 @@ var _ = Describe("Stream", func() {
|
||||||
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
||||||
FinBit: true,
|
FinBit: true,
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).To(Equal(io.EOF))
|
Expect(err).To(Equal(io.EOF))
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
n, err = stream.Read(b)
|
n, err = str.Read(b)
|
||||||
Expect(n).To(BeZero())
|
Expect(n).To(BeZero())
|
||||||
Expect(err).To(Equal(io.EOF))
|
Expect(err).To(Equal(io.EOF))
|
||||||
})
|
})
|
||||||
|
@ -367,14 +367,14 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame1)
|
str.AddStreamFrame(&frame1)
|
||||||
stream.AddStreamFrame(&frame2)
|
str.AddStreamFrame(&frame2)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).To(Equal(io.EOF))
|
Expect(err).To(Equal(io.EOF))
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
n, err = stream.Read(b)
|
n, err = str.Read(b)
|
||||||
Expect(n).To(BeZero())
|
Expect(n).To(BeZero())
|
||||||
Expect(err).To(Equal(io.EOF))
|
Expect(err).To(Equal(io.EOF))
|
||||||
})
|
})
|
||||||
|
@ -385,9 +385,9 @@ var _ = Describe("Stream", func() {
|
||||||
Data: []byte{0xDE, 0xAD},
|
Data: []byte{0xDE, 0xAD},
|
||||||
FinBit: true,
|
FinBit: true,
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).To(Equal(io.EOF))
|
Expect(err).To(Equal(io.EOF))
|
||||||
Expect(n).To(Equal(2))
|
Expect(n).To(Equal(2))
|
||||||
Expect(b[:n]).To(Equal([]byte{0xDE, 0xAD}))
|
Expect(b[:n]).To(Equal([]byte{0xDE, 0xAD}))
|
||||||
|
@ -399,9 +399,9 @@ var _ = Describe("Stream", func() {
|
||||||
Data: []byte{},
|
Data: []byte{},
|
||||||
FinBit: true,
|
FinBit: true,
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(n).To(BeZero())
|
Expect(n).To(BeZero())
|
||||||
Expect(err).To(Equal(io.EOF))
|
Expect(err).To(Equal(io.EOF))
|
||||||
})
|
})
|
||||||
|
@ -415,14 +415,14 @@ var _ = Describe("Stream", func() {
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
Data: []byte{0xDE, 0xAD, 0xBE, 0xEF},
|
||||||
}
|
}
|
||||||
stream.AddStreamFrame(&frame)
|
str.AddStreamFrame(&frame)
|
||||||
stream.RegisterError(testErr)
|
str.RegisterError(testErr)
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 4)
|
||||||
n, err := stream.Read(b)
|
n, err := str.Read(b)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(n).To(Equal(4))
|
Expect(n).To(Equal(4))
|
||||||
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
Expect(b).To(Equal([]byte{0xDE, 0xAD, 0xBE, 0xEF}))
|
||||||
n, err = stream.Read(b)
|
n, err = str.Read(b)
|
||||||
Expect(n).To(BeZero())
|
Expect(n).To(BeZero())
|
||||||
Expect(err).To(Equal(testErr))
|
Expect(err).To(Equal(testErr))
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,6 +17,7 @@ type Stream interface {
|
||||||
io.Reader
|
io.Reader
|
||||||
io.ByteReader
|
io.ByteReader
|
||||||
io.Writer
|
io.Writer
|
||||||
|
io.Closer
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadUintN reads N bytes
|
// ReadUintN reads N bytes
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue