forked from quic-go/quic-go
86 lines
2.0 KiB
Go
86 lines
2.0 KiB
Go
package quic
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/lucas-clemente/quic-go/frames"
|
|
"github.com/lucas-clemente/quic-go/protocol"
|
|
)
|
|
|
|
// streamFrameQueue is a Queue that handles StreamFrames
|
|
type streamFrameQueue struct {
|
|
prioFrames []*frames.StreamFrame
|
|
frames []*frames.StreamFrame
|
|
mutex sync.Mutex
|
|
}
|
|
|
|
// Push adds a new StreamFrame to the queue
|
|
func (q *streamFrameQueue) Push(frame *frames.StreamFrame, prio bool) {
|
|
q.mutex.Lock()
|
|
defer q.mutex.Unlock()
|
|
|
|
if prio {
|
|
q.prioFrames = append(q.prioFrames, frame)
|
|
} else {
|
|
q.frames = append(q.frames, frame)
|
|
}
|
|
}
|
|
|
|
// Len returns the total number of queued StreamFrames
|
|
func (q *streamFrameQueue) Len() int {
|
|
q.mutex.Lock()
|
|
defer q.mutex.Unlock()
|
|
|
|
return len(q.prioFrames) + len(q.frames)
|
|
}
|
|
|
|
// ByteLen returns the total number of bytes queued
|
|
func (q *streamFrameQueue) ByteLen() protocol.ByteCount {
|
|
q.mutex.Lock()
|
|
defer q.mutex.Unlock()
|
|
|
|
// TODO: improve performance
|
|
// This is a very unperformant implementation. However, the obvious solution of keeping track of the length on Push() and Pop() doesn't work, since the front frame can be split by the PacketPacker
|
|
|
|
var length protocol.ByteCount
|
|
for _, frame := range q.prioFrames {
|
|
length += protocol.ByteCount(len(frame.Data))
|
|
}
|
|
for _, frame := range q.frames {
|
|
length += protocol.ByteCount(len(frame.Data))
|
|
}
|
|
return length
|
|
}
|
|
|
|
// Pop returns the next element and deletes it from the queue
|
|
func (q *streamFrameQueue) Pop() *frames.StreamFrame {
|
|
q.mutex.Lock()
|
|
defer q.mutex.Unlock()
|
|
|
|
if len(q.prioFrames) > 0 {
|
|
frame := q.prioFrames[0]
|
|
q.prioFrames = q.prioFrames[1:]
|
|
return frame
|
|
}
|
|
if len(q.frames) > 0 {
|
|
frame := q.frames[0]
|
|
q.frames = q.frames[1:]
|
|
return frame
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Front returns the next element without modifying the queue
|
|
func (q *streamFrameQueue) Front() *frames.StreamFrame {
|
|
q.mutex.Lock()
|
|
defer q.mutex.Unlock()
|
|
|
|
if len(q.prioFrames) > 0 {
|
|
return q.prioFrames[0]
|
|
}
|
|
if len(q.frames) > 0 {
|
|
return q.frames[0]
|
|
}
|
|
return nil
|
|
}
|