summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/sctp/pending_queue.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pion/sctp/pending_queue.go')
-rw-r--r--vendor/github.com/pion/sctp/pending_queue.go138
1 files changed, 138 insertions, 0 deletions
diff --git a/vendor/github.com/pion/sctp/pending_queue.go b/vendor/github.com/pion/sctp/pending_queue.go
new file mode 100644
index 0000000..5f204d3
--- /dev/null
+++ b/vendor/github.com/pion/sctp/pending_queue.go
@@ -0,0 +1,138 @@
+package sctp
+
+import (
+ "github.com/pkg/errors"
+)
+
+// pendingBaseQueue
+
+type pendingBaseQueue struct {
+ queue []*chunkPayloadData
+}
+
+func newPendingBaseQueue() *pendingBaseQueue {
+ return &pendingBaseQueue{queue: []*chunkPayloadData{}}
+}
+
+func (q *pendingBaseQueue) push(c *chunkPayloadData) {
+ q.queue = append(q.queue, c)
+}
+
+func (q *pendingBaseQueue) pop() *chunkPayloadData {
+ if len(q.queue) == 0 {
+ return nil
+ }
+ c := q.queue[0]
+ q.queue = q.queue[1:]
+ return c
+}
+
+func (q *pendingBaseQueue) get(i int) *chunkPayloadData {
+ if len(q.queue) == 0 || i < 0 || i >= len(q.queue) {
+ return nil
+ }
+ return q.queue[i]
+}
+
+func (q *pendingBaseQueue) size() int {
+ return len(q.queue)
+}
+
+// pendingQueue
+
+type pendingQueue struct {
+ unorderedQueue *pendingBaseQueue
+ orderedQueue *pendingBaseQueue
+ nBytes int
+ selected bool
+ unorderedIsSelected bool
+}
+
+var (
+ errUnexpectedChuckPoppedUnordered = errors.New("unexpected chunk popped (unordered)")
+ errUnexpectedChuckPoppedOrdered = errors.New("unexpected chunk popped (ordered)")
+ errUnexpectedQState = errors.New("unexpected q state (should've been selected)")
+)
+
+func newPendingQueue() *pendingQueue {
+ return &pendingQueue{
+ unorderedQueue: newPendingBaseQueue(),
+ orderedQueue: newPendingBaseQueue(),
+ }
+}
+
+func (q *pendingQueue) push(c *chunkPayloadData) {
+ if c.unordered {
+ q.unorderedQueue.push(c)
+ } else {
+ q.orderedQueue.push(c)
+ }
+ q.nBytes += len(c.userData)
+}
+
+func (q *pendingQueue) peek() *chunkPayloadData {
+ if q.selected {
+ if q.unorderedIsSelected {
+ return q.unorderedQueue.get(0)
+ }
+ return q.orderedQueue.get(0)
+ }
+
+ if c := q.unorderedQueue.get(0); c != nil {
+ return c
+ }
+ return q.orderedQueue.get(0)
+}
+
+func (q *pendingQueue) pop(c *chunkPayloadData) error {
+ if q.selected {
+ var popped *chunkPayloadData
+ if q.unorderedIsSelected {
+ popped = q.unorderedQueue.pop()
+ if popped != c {
+ return errUnexpectedChuckPoppedUnordered
+ }
+ } else {
+ popped = q.orderedQueue.pop()
+ if popped != c {
+ return errUnexpectedChuckPoppedOrdered
+ }
+ }
+ if popped.endingFragment {
+ q.selected = false
+ }
+ } else {
+ if !c.beginningFragment {
+ return errUnexpectedQState
+ }
+ if c.unordered {
+ popped := q.unorderedQueue.pop()
+ if popped != c {
+ return errUnexpectedChuckPoppedUnordered
+ }
+ if !popped.endingFragment {
+ q.selected = true
+ q.unorderedIsSelected = true
+ }
+ } else {
+ popped := q.orderedQueue.pop()
+ if popped != c {
+ return errUnexpectedChuckPoppedOrdered
+ }
+ if !popped.endingFragment {
+ q.selected = true
+ q.unorderedIsSelected = false
+ }
+ }
+ }
+ q.nBytes -= len(c.userData)
+ return nil
+}
+
+func (q *pendingQueue) getNumBytes() int {
+ return q.nBytes
+}
+
+func (q *pendingQueue) size() int {
+ return q.unorderedQueue.size() + q.orderedQueue.size()
+}