// FindStream looks up the given stream id and either waits for the // stream to be found or returns nil if the stream id is no longer // valid. func (s *Connection) FindStream(streamId uint32) *Stream { var stream *Stream var ok bool s.streamCond.L.Lock() stream, ok = s.streams[spdy.StreamId(streamId)] debugMessage("(%p) Found stream %d? %t", s, spdy.StreamId(streamId), ok) for !ok && streamId >= uint32(s.receivedStreamId) { s.streamCond.Wait() stream, ok = s.streams[spdy.StreamId(streamId)] } s.streamCond.L.Unlock() return stream }
func (s *Connection) addStreamFrame(frame *spdy.SynStreamFrame) { var parent *Stream if frame.AssociatedToStreamId != spdy.StreamId(0) { parent, _ = s.getStream(frame.AssociatedToStreamId) } stream := &Stream{ streamId: frame.StreamId, parent: parent, conn: s, startChan: make(chan error), headers: frame.Headers, finished: (frame.CFHeader.Flags & spdy.ControlFlagUnidirectional) != 0x00, replyCond: sync.NewCond(new(sync.Mutex)), dataChan: make(chan []byte), headerChan: make(chan http.Header), closeChan: make(chan bool), priority: frame.Priority, } if frame.CFHeader.Flags&spdy.ControlFlagFin != 0x00 { stream.closeRemoteChannels() } s.addStream(stream) }
func TestPriorityQueueOrdering(t *testing.T) { queue := NewPriorityFrameQueue(150) data1 := &spdy.DataFrame{} data2 := &spdy.DataFrame{} data3 := &spdy.DataFrame{} data4 := &spdy.DataFrame{} queue.Push(data1, 2) queue.Push(data2, 1) queue.Push(data3, 1) queue.Push(data4, 0) if queue.Pop() != data4 { t.Fatalf("Wrong order, expected data4 first") } if queue.Pop() != data2 { t.Fatalf("Wrong order, expected data2 second") } if queue.Pop() != data3 { t.Fatalf("Wrong order, expected data3 third") } if queue.Pop() != data1 { t.Fatalf("Wrong order, expected data1 fourth") } // Insert 50 Medium priority frames for i := spdy.StreamId(50); i < 100; i++ { queue.Push(&spdy.DataFrame{StreamId: i}, 1) } // Insert 50 low priority frames for i := spdy.StreamId(100); i < 150; i++ { queue.Push(&spdy.DataFrame{StreamId: i}, 2) } // Insert 50 high priority frames for i := spdy.StreamId(0); i < 50; i++ { queue.Push(&spdy.DataFrame{StreamId: i}, 0) } for i := spdy.StreamId(0); i < 150; i++ { frame := queue.Pop() if frame.(*spdy.DataFrame).StreamId != i { t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i) } } }
func (s *Connection) sendStream(stream *Stream, fin bool) error { var flags spdy.ControlFlags if fin { flags = spdy.ControlFlagFin stream.finished = true } var parentId spdy.StreamId if stream.parent != nil { parentId = stream.parent.streamId } streamFrame := &spdy.SynStreamFrame{ StreamId: spdy.StreamId(stream.streamId), AssociatedToStreamId: spdy.StreamId(parentId), Headers: stream.headers, CFHeader: spdy.ControlFrameHeader{Flags: flags}, } return s.framer.WriteFrame(streamFrame) }
func TestPriorityQueueSync(t *testing.T) { queue := NewPriorityFrameQueue(150) var wg sync.WaitGroup insertRange := func(start, stop spdy.StreamId, priority uint8) { for i := start; i < stop; i++ { queue.Push(&spdy.DataFrame{StreamId: i}, priority) } wg.Done() } wg.Add(3) go insertRange(spdy.StreamId(100), spdy.StreamId(150), 2) go insertRange(spdy.StreamId(0), spdy.StreamId(50), 0) go insertRange(spdy.StreamId(50), spdy.StreamId(100), 1) wg.Wait() for i := spdy.StreamId(0); i < 150; i++ { frame := queue.Pop() if frame.(*spdy.DataFrame).StreamId != i { t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i) } } }