make stream private

This commit is contained in:
Lucas Clemente 2016-04-25 17:50:35 +02:00
parent a79f7c4dc6
commit 23a1e08e90
7 changed files with 155 additions and 146 deletions

View file

@ -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)

View file

@ -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

View file

@ -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)
} }

View file

@ -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
View file

@ -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)
} }

View file

@ -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))
}) })

View file

@ -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